feat(断路器): 调整样式、更换插件socket

This commit is contained in:
fhysy 2024-07-22 10:37:55 +08:00
parent 8567ec8c2e
commit 57d766fab0
18 changed files with 672 additions and 94 deletions

View File

@ -34,7 +34,7 @@ function createWindow() {
// 禁用同源策略,允许跨域请求 // 禁用同源策略,允许跨域请求
webSecurity: false, webSecurity: false,
contextIsolation: false, contextIsolation: false,
csp: "default-src 'self'; connect-src 'self' http://127.0.0.1:8000 http://192.168.1.17:8000 ws://192.168.1.17:8000 ws://127.0.0.1:8000", csp: "default-src 'self'; connect-src 'self' *",
// 禁止build环境使用DevTool // 禁止build环境使用DevTool
// devTools: is.dev ? true : false // devTools: is.dev ? true : false
devTools: true devTools: true

View File

@ -2,11 +2,12 @@
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Electron</title> <title>谷云工具</title>
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<link rel="stylesheet" href="/src/assets/iconfont/iconfont.css">
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; connect-src 'self' http://127.0.0.1:8000 http://192.168.1.17:8000 ws://192.168.1.17:8000 ws://127.0.0.1:8000; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" content="default-src 'self'; connect-src 'self' *; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
/> />
</head> </head>

View File

@ -1,12 +1,18 @@
<script setup> <script setup>
import { RouterView } from "vue-router" import { RouterView } from 'vue-router'
</script> </script>
<template> <template>
<RouterView></RouterView> <RouterView></RouterView>
</template> </template>
<style> <style lang="scss">
:root {
--el-input-height: 36px;
--el-color-primary: #0066cc;
--el-fill-color-blank: #e6e6e6;
--el-disabled-bg-color: #f7f7f7;
}
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 5px; width: 5px;
} }
@ -20,4 +26,27 @@ import { RouterView } from "vue-router"
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
width: 5px; width: 5px;
} }
/*全局覆盖样式*/
.el-collapse-item {
color: #333333;
.el-collapse-item__header {
font-family: Source Han Sans CN;
background: #e6e6e6;
padding: 0 30px;
color: #333333;
font-size: 16px;
height: 42px;
line-height: 42px;
font-weight: 500;
&.is-active {
color: #0066cc;
}
}
.el-collapse-item__wrap {
background-color: #f2f2f2 !important;
}
.el-input__wrapper {
background: #e6e6e6;
}
}
</style> </style>

View File

@ -0,0 +1,83 @@
@font-face {
font-family: "iconfont"; /* Project id 4622943 */
src: url('iconfont.woff2?t=1721353754291') format('woff2'),
url('iconfont.woff?t=1721353754291') format('woff'),
url('iconfont.ttf?t=1721353754291') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-shousuoshangjiantou:before {
content: "\e9b6";
}
.icon-up-arrow:before {
content: "\e9c1";
}
.icon-unlock:before {
content: "\e882";
}
.icon-gexinghuabobao:before {
content: "\e66d";
}
.icon-icon_suoding:before {
content: "\e76c";
}
.icon-icon_shanchu:before {
content: "\e76d";
}
.icon-icon_shanghang:before {
content: "\e76e";
}
.icon-icon_xiahang:before {
content: "\e76f";
}
.icon-icon_shezhi:before {
content: "\e770";
}
.icon-icon_xitong:before {
content: "\e771";
}
.icon-icon_jiankong:before {
content: "\e772";
}
.icon-icon_caid:before {
content: "\e75f";
}
.icon-icon_chajian:before {
content: "\e767";
}
.icon-icon_xiaoxi:before {
content: "\e768";
}
.icon-icon_gengxin:before {
content: "\e769";
}
.icon-icon_fuzhi:before {
content: "\e76a";
}
.icon-icon_duanluqi:before {
content: "\e76b";
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,71 @@
<script setup>
import { ref } from 'vue'
const settings = defineProps({
collapse: Boolean,
width: String
})
</script>
<template>
<el-aside :width="settings.width">
<el-scrollbar>
<el-menu
default-active="/system/switch"
:collapse="settings.collapse"
:router="true"
>
<el-menu-item index="/system/switch"> <span class="iconfont icon-icon_duanluqi"></span> 断路器调试</el-menu-item>
<!-- <el-menu-item index="/system/about"><span class="iconfont icon-icon_jiankong"></span> 视频监控</el-menu-item>-->
<!-- <el-menu-item index="/test"><el-icon> <Menu /> </el-icon></el-menu-item>-->
</el-menu>
</el-scrollbar>
</el-aside>
</template>
<style scoped lang="less">
.el-aside {
height: 100vh;
overflow: hidden;
}
.el-menu{
padding: 0 10px;
background: #fff;
}
.el-menu-item{
border-radius: 10px;
background: #f2f2f2;
margin-bottom: 12px;
align-items: center;
padding: 0;
padding-left: 26px !important;
color: #333;
font-size: 16px;
.iconfont{
margin-right: 10px;
color: #999;
font-size: 22px;
}
}
.el-menu-item.is-active{
background: #4c94db;
border-radius: 10px;
/*margin: 0 10px;*/
color: #fff;
.iconfont{
color: #fff;
}
}
.el-scrollbar {
height: 100vh;
overflow: hidden;
/*background-color: #1a1c1e;*/
}
.el-menu {
border-right: none;
}
</style>

View File

@ -0,0 +1,170 @@
<template>
<div>
<el-header style="display: flex; font-size: 16px">
<div class='header-left'>
<img :src="logo" alt="">
</div>
<div class='haeder-menu' :style="{width:menuWidth + 'px'}">
<el-menu
default-active="/system"
mode="horizontal"
router="true"
>
<el-menu-item index="/system">系统模板</el-menu-item>
</el-menu>
</div>
<div class="haeder-right">
<div class="block" style="margin-right: 25px">
<el-icon size="24" color="#80b3e6"><BellFilled /></el-icon>
</div>
<div class="user-name" style="margin-right: 10px">
admin
</div>
<el-dropdown trigger="click">
<div class="el-dropdown-link avatar-box" style="cursor: pointer">
<img :src="avatar" alt="">
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>admin</el-dropdown-item>
<!-- <el-dropdown-item @click="LogOut">退出登录</el-dropdown-item>-->
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-header>
</div>
</template>
<script setup>
import { ref, watch } from "vue"
import logo from '@renderer/assets/image/logo.png'
import avatar from '@renderer/assets/image/avatar.png'
const screenWidth = ref(document.documentElement.clientWidth || document.body.clientWidth)
const timer = ref(false);
const domWidth = ref(document.body.clientWidth);
const menuWidth = ref(document.body.clientWidth - 363);
watch(
(screenWidth.value = () => {
console.log("页面变化",document.body.clientWidth)
// 使
if (!timer.value) {
if(domWidth.value != document.body.clientWidth){
console.log("更新页面")
domWidth.value = document.body.clientWidth
menuWidth.value = document.body.clientWidth - 363
}
timer.value = true;
setTimeout(function () {
timer.value = false
}, 200)
}
})
);
</script>
<style scoped lang="scss">
.el-header {
width: 100%;
background-color: #0066cc;
color: var(--el-text-color-primary);
justify-content: space-between;
padding: 0;
}
.header-left{
display: flex;
justify-content: center;
align-items: center;
width: 180px;
img{
width: 154px;
height: 37px;
}
}
.haeder-menu{
width: calc(100% - 180px - 183px);
overflow: hidden;
:deep(.el-scrollbar__bar.is-vertical) {
display: none;
}
:deep(a) {
width: 100%;
}
.el-menu.el-menu--horizontal {
display: flex;
height: 100%;
width: 100%;
box-sizing: border-box;
background: #0066cc;
border-bottom: none;
.el-menu-item{
color: #fff !important;
width: 124px;
font-size: 16px;
border: none;
text-indent: 10px;
&.is-active{
background: #267dd4;
position: relative;
&:after{
content: "";
position: absolute;
top: 22px;
left: 20px;
width: 5px;
height: 16px;
background: #fff;
border-radius: 2px;
}
}
&:not(.is-disabled):hover{
background: #4c94db;
}
}
}
}
.haeder-right{
display: flex;
align-items: center;
width: 165px;
margin-right: 18px;
.user-name{
font-family: Source Han Sans CN;
font-weight: 400;
font-size: 12px;
color: #FFFFFF;
}
.avatar-box{
img{
width: 54px;
height: 54px;
margin-bottom: -2px;
}
}
}
.toolbar {
display: inline-flex;
align-items: center;
justify-content: center;
height: 100%;
right: 20px;
text-align: right;
}
.el-dropdown-menu__item {
width: 120px;
}
.icon-color {
color: white;
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<el-container direction="vertical" style="min-height: 100vh;min-width: 100vw;overflow: hidden;">
<Header></Header>
<el-container style="padding: 10px 0">
<Aside width="180px"></Aside>
<el-main>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</el-main>
</el-container>
</el-container>
</template>
<script setup>
//
import Header from '@renderer/layout/Header.vue'
import Aside from '@renderer/layout/Aside.vue'
</script>
<style scoped>
body{
background-color: #eee;
max-width: 100vw;
}
.el-container{
/*padding: 10px 0;*/
}
.el-main {
width: 100%;
padding: 0;
height: 100vh;
overflow-x: hidden;
background: #fff;
padding-right: 10px;
}
</style>

View File

@ -1,13 +1,13 @@
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@renderer/views/HomeView.vue' import Layout from '@renderer/layout/index.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: [ routes: [
{ {
path: '/', path: '/system',
name: 'home', name: 'system',
component: HomeView, component: Layout,
redirect: {name: 'switch'}, redirect: {name: 'switch'},
children:[ children:[
{ {
@ -37,8 +37,13 @@ const router = createRouter({
keepAlive: true, keepAlive: true,
} }
}, },
] ]
}, },
{
path: '/', // 这个是根路由,现在我们让它重定向到 /system
redirect: '/system',
},
{ path: '/:pathMatch(.*)', redirect: '/' }, { path: '/:pathMatch(.*)', redirect: '/' },
] ]
}) })

View File

@ -0,0 +1,96 @@
import { defineStore } from 'pinia'
import config from '@renderer/util/config.js'
// 定义一个名为logWebSocketStore的store用于管理WebSocket连接的状态和操作
export const logWebSocketStore = defineStore('websocket', {
state: () => ({
websocket: null, // WebSocket实例
connectURL: config.wsUrl + '/ws/log', // WebSocket连接的URL
socket_open: false, // 标记WebSocket是否连接
hearbeat_timer: null, // 心跳检测的定时器
hearbeat_interval: 2 * 1000, // 心跳检测的间隔时间
is_reonnect: true, // 是否尝试重新连接
reconnect_count: 3, // 最大重连次数
reconnect_current: 1, // 当前重连次数
reconnect_timer: null, // 重连定时器
reconnect_interval: 5 * 1000, // 重连间隔时间
}),
actions: {
// 初始化WebSocket连接
init(overrideReceiveMessage) {
let receiveMessage = overrideReceiveMessage || (() => {})
// 检查浏览器是否支持WebSocket
if (!('WebSocket' in window)) {
this.$router.push({ name: 'ErrorPage', params: { error: '浏览器不支持WebSocket' } })
return null
}
// 创建WebSocket实例并设置事件处理函数
this.websocket = new WebSocket(this.connectURL)
this.websocket.onmessage = (e) => {
receiveMessage(e)
}
this.websocket.onclose = () => {
console.log('socket连接关闭----------------------')
this.socket_open = false
// 尝试重新连接
if (this.is_reonnect) {
this.reconnect_timer = setTimeout(() => {
if (this.reconnect_current > this.reconnect_count) {
clearTimeout(this.reconnect_timer)
this.is_reonnect = false
return
}
console.log('socket重连次数' + this.reconnect_current)
this.reconnect_current++
this.reconnect()
}, this.reconnect_interval)
}
}
this.websocket.onopen = () => {
this.socket_open = true
this.is_reonnect = true
// this.heartbeat()
}
this.websocket.onerror = () => {}
},
// 发送心跳包
heartbeat() {
this.hearbeat_timer && clearInterval(this.hearbeat_timer)
this.hearbeat_timer = setInterval(() => {
let data = {}
this.send(data)
}, this.hearbeat_interval)
},
// 发送数据
send(data, callback = null) {
// 如果WebSocket连接已建立则发送数据
if (this.websocket.readyState === this.websocket.OPEN) {
this.websocket.send(JSON.stringify(data))
callback && callback()
} else {
// 如果WebSocket连接断开则跳转到错误页面
clearInterval(this.hearbeat_timer)
this.$router.push({ name: 'ErrorPage', params: { error: 'socket链接已断开' } })
}
},
// 关闭WebSocket连接
close() {
this.is_reonnect = false
this.websocket.close()
},
// 重新连接WebSocket
reconnect() {
// 如果已存在WebSocket实例且不尝试重新连接则关闭连接
if (this.websocket && !this.is_reonnect) {
this.close()
}
// 初始化WebSocket连接
this.init()
},
},
})

View File

@ -1,7 +1,8 @@
// // 手动配置的地址 // // // 手动配置的地址
// window.config = { // window.config = {
// url: 'http://192.168.1.17:8000', // url: 'http://192.168.1.17:8000',
// wsUrl: 'ws://192.168.1.17:8000', // wsUrl: 'ws://192.168.1.17:8000',
// ws1Url: 'ws://192.168.1.17:8001',
// } // }
// 手动配置的地址 // 手动配置的地址
@ -10,7 +11,21 @@
// wsUrl: 'ws://127.0.0.1:8000', // wsUrl: 'ws://127.0.0.1:8000',
// } // }
// export default {
// url: 'http://127.0.0.1:8000',
// wsUrl: 'ws://127.0.0.1:8000'
// }
export default { export default {
url: 'http://127.0.0.1:8000', url: 'http://127.0.0.1:8000',
wsUrl: 'ws://127.0.0.1:8000' wsUrl: 'ws://127.0.0.1:8000',
swichWsUrl: 'ws://127.0.0.1:8001',
} }
// 手动配置的地址
// export default {
// url: 'http://192.168.1.17:8000',
// wsUrl: 'ws://192.168.1.17:8000',
// swichWsUrl: 'ws://192.168.1.17:8001',
// }

View File

@ -5,7 +5,7 @@ let receiveMessage = null
import { reactive } from 'vue' import { reactive } from 'vue'
const socket = reactive({ const socket = reactive({
websocket: null, websocket: null,
connectURL: config.wsUrl + '/ws/log', connectURL: config.swichWsUrl + '/ws/log',
// 开启标识 // 开启标识
socket_open: false, socket_open: false,
// 心跳timer // 心跳timer

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="switch-box"> <div id="switch-box">
<div class="switch-main"> <div class="switch-main" id="switch-main" :class="isOpenLog?'open-log':''">
<el-collapse v-model="activeFold" @change="foldChange"> <el-collapse v-model="activeFold" @change="foldChange">
<el-collapse-item name="1" title="Mqtt设置"> <el-collapse-item name="1" title="Mqtt设置">
<el-form <el-form
@ -103,13 +103,12 @@
<el-input v-model="attrReadForm.deviceSN" /> <el-input v-model="attrReadForm.deviceSN" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="10" class="text-center"> <el-col :span="10" :offset="1" class="text-center">
<el-form-item label="属性"> <el-form-item label="属性">
<el-select <el-select
v-model="attrReadForm.attrName" v-model="attrReadForm.attrName"
multiple multiple
placeholder="选择属性" placeholder="选择属性"
style="width: 240px"
@change="attrReadChange" @change="attrReadChange"
> >
<el-option <el-option
@ -121,7 +120,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="4" style="text-align: right"> <el-col :span="3" style="text-align: right">
<el-button type="primary" @click="addReadAttr">新增属性</el-button> <el-button type="primary" @click="addReadAttr">新增属性</el-button>
</el-col> </el-col>
</el-row> </el-row>
@ -163,13 +162,12 @@
<el-input v-model="attrWriteForm.deviceSN" /> <el-input v-model="attrWriteForm.deviceSN" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="10" class="text-center"> <el-col :span="10" :offset="1" class="text-center">
<el-form-item label="属性"> <el-form-item label="属性">
<el-select <el-select
v-model="attrWriteForm.attrName" v-model="attrWriteForm.attrName"
multiple multiple
placeholder="选择属性" placeholder="选择属性"
style="width: 240px"
@change="attrWriteChange" @change="attrWriteChange"
> >
<el-option <el-option
@ -181,7 +179,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="4" style="text-align: right"> <el-col :span="3" style="text-align: right">
<el-button type="primary" @click="addWriteAttr">新增属性</el-button> <el-button type="primary" @click="addWriteAttr">新增属性</el-button>
</el-col> </el-col>
</el-row> </el-row>
@ -202,7 +200,7 @@
<el-input v-model="item.len" /> <el-input v-model="item.len" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="6">
<el-form-item label="data"> <el-form-item label="data">
<el-input v-model="item.data" /> <el-input v-model="item.data" />
</el-form-item> </el-form-item>
@ -284,42 +282,66 @@
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</div> </div>
<div class="log-box"> <div class="log-box" id="log-box" :class="isOpenLog?'open-log':''">
<div class="log-box-header"> <div class="log-box-header">
<div class="log-box-title">日志</div> <div class="log-box-title">日志</div>
<div class="log-box-operate"> <div class="log-box-operate">
<view class="log-box-operate-item"> <view class="log-box-operate-item">
<div>mqtt状态</div> <div>mqtt状态</div>
<div v-if="connectionState" style="color: #00ff78; display: flex; align-items: center"> <div v-if="connectionState" style="color: #00A73C; display: flex; align-items: center">
连接 连接
</div> </div>
<div <div
v-else v-else
style="color: red; display: flex; align-items: center" style="color: #FF3B2B; display: flex; align-items: center"
@click="runMqtt(mqttFormRef)" @click="runMqtt(mqttFormRef)"
> >
断连 断连
<el-icon> <span class="iconfont icon-icon_gengxin"></span>
<Refresh />
</el-icon>
</div> </div>
</view> </view>
<view class="log-box-operate-item"> <view class="log-box-operate-item">
<div>日志状态</div> <div>日志状态</div>
<div v-if="socketStatus" style="color: #00ff78; display: flex; align-items: center"> <div v-if="socketStatus" style="color: #00A73C; display: flex; align-items: center">
连接 连接
</div> </div>
<div <div
v-else v-else
style="color: #ff0000; display: flex; align-items: center" style="color: #FF3B2B; display: flex; align-items: center"
@click="initSocket" @click="initSocket"
> >
断连 断连
<el-icon> <span class="iconfont icon-icon_gengxin"></span>
<Refresh />
</el-icon>
</div> </div>
</view> </view>
<!-- <view class="log-box-operate-item">-->
<!-- <div>断路器状态</div>-->
<!-- <div v-if="switchSocketStatus" style="color: #00A73C; display: flex; align-items: center">-->
<!-- 连接-->
<!-- </div>-->
<!-- <div-->
<!-- v-else-->
<!-- style="color: #FF3B2B; display: flex; align-items: center"-->
<!-- @click="initSwitchSocket"-->
<!-- >-->
<!-- 断连-->
<!-- <span class="iconfont icon-icon_gengxin"></span>-->
<!-- </div>-->
<!-- </view>-->
<view class="log-box-operate-item" @click="toggleOpenLog">
<el-tooltip
v-if="isOpenLog"
class="box-item"
content="收缩日志"
effect="dark"
placement="bottom"
>
<span class="iconfont icon-up-arrow"></span>
</el-tooltip>
<el-tooltip v-else class="box-item" content="展开日志" effect="dark" placement="bottom">
<span class="iconfont icon-shousuoshangjiantou"></span>
</el-tooltip>
</view>
<view class="log-box-operate-item" @click="toggleIsScroll"> <view class="log-box-operate-item" @click="toggleIsScroll">
<el-tooltip <el-tooltip
v-if="isScroll" v-if="isScroll"
@ -328,47 +350,27 @@
effect="dark" effect="dark"
placement="bottom" placement="bottom"
> >
<el-icon> <span class="iconfont icon-unlock"></span>
<Unlock />
</el-icon>
</el-tooltip> </el-tooltip>
<el-tooltip v-else class="box-item" content="开启滚动" effect="dark" placement="bottom"> <el-tooltip v-else class="box-item" content="开启滚动" effect="dark" placement="bottom">
<el-icon> <span class="iconfont icon-icon_suoding"></span>
<Lock />
</el-icon>
</el-tooltip> </el-tooltip>
</view> </view>
<view class="log-box-operate-item" @click="clearLog"> <view class="log-box-operate-item" @click="clearLog">
<el-icon> <span class="iconfont icon-icon_shanchu"></span>
<DeleteFilled />
</el-icon>
</view> </view>
</div> </div>
</div> </div>
<div id="log-box-main" class="log-box-main"> <div id="log-box-main" class="log-box-main">
<div class="log-list"> <div class="log-list">
<div v-for="(item, index) in logList" :key="index" class="log-item"> <div v-for="(item, index) in logList" :key="index" class="log-item">
<p>{{ item.time }}</p> <span v-if="item.type == 'subscribe'" class="iconfont icon-icon_shanghang"></span>
<el-icon <span v-else-if="item.type == 'publish'" class="iconfont icon-icon_xiahang"></span>
v-if="item.type == 'subscribe'" <span v-else-if="item.type == 'system'" class="iconfont icon-icon_xitong"></span>
style="color: #00ff78; font-weight: bold; margin-right: 8px" <span v-else class="iconfont icon-icon_xiaoxi"></span>
> &nbsp;&nbsp;{{ item.time }}&nbsp;&nbsp;&nbsp;&nbsp; {{ item.msg }}
<Top />
</el-icon>
<el-icon
v-else-if="item.type == 'publish'"
style="color: red; font-weight: bold; margin-right: 8px"
>
<Bottom />
</el-icon>
<el-icon v-else-if="item.type == 'system'" style="font-weight: bold; margin-right: 8px">
<Message />
</el-icon>
<p>{{ item.msg }}</p>
<el-tooltip class="box-item" content="复制" effect="dark" placement="bottom"> <el-tooltip class="box-item" content="复制" effect="dark" placement="bottom">
<el-icon style="font-weight: bold; cursor: pointer" @click="copyMsg(item.msg)"> <span class="iconfont icon-icon_fuzhi" @click="copyMsg(item.msg)"></span>
<DocumentCopy />
</el-icon>
</el-tooltip> </el-tooltip>
</div> </div>
</div> </div>
@ -384,9 +386,11 @@ import config from '@renderer/util/config.js'
import { reactive, ref, onMounted, computed, watch, onUnmounted } from 'vue' import { reactive, ref, onMounted, computed, watch, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import socket from '@renderer/util/socket.js' import switchSocket from '@renderer/util/socket.js'
import { logWebSocketStore } from '@renderer/stores/logWebSocket.js'
const webSocketStore = logWebSocketStore()
const activeFold = ref(['1']) const activeFold = ref(['1','3','4'])
const logList = ref([]) const logList = ref([])
// //
const connectionState = ref(false) const connectionState = ref(false)
@ -399,6 +403,7 @@ const getGuid = () => {
}) })
} }
const isScroll = ref(true) const isScroll = ref(true)
const isOpenLog = ref(false)
const mqttFormRef = ref() const mqttFormRef = ref()
// const mqttForm = reactive({ // const mqttForm = reactive({
// clientId: '', // clientId: '',
@ -661,6 +666,7 @@ const testMqtt = (formEl) => {
} }
}) })
} }
// //
const runMqtt = (formEl) => { const runMqtt = (formEl) => {
if (!formEl) return if (!formEl) return
@ -676,6 +682,10 @@ const runMqtt = (formEl) => {
console.log(response) // console.log(response) //
if (response.data.code == 0) { if (response.data.code == 0) {
ElMessage.success('连接成功') ElMessage.success('连接成功')
if(!switchSocketStatus.value){
initSwitchSocket()
}
// //
localStorage.setItem('mqttForm', JSON.stringify(mqttForm)) localStorage.setItem('mqttForm', JSON.stringify(mqttForm))
connectionState.value = true connectionState.value = true
@ -720,6 +730,11 @@ const updateGateway = (formEl) => {
// //
localStorage.setItem('gatewayForm', JSON.stringify(gatewayForm)) localStorage.setItem('gatewayForm', JSON.stringify(gatewayForm))
ElMessage.success('更新成功') ElMessage.success('更新成功')
activeFold.value = activeFold.value.filter((item) => item !== '2')
if (!activeFold.value.includes('3')) {
// 1
activeFold.value.unshift('3')
}
} else { } else {
if (response.data.code == 60) { if (response.data.code == 60) {
connectionState.value = false connectionState.value = false
@ -996,7 +1011,6 @@ const getSocketMeassage = (message) => {
if (isScroll.value) { if (isScroll.value) {
setTimeout(() => { setTimeout(() => {
let div = document.querySelector('#log-box-main') let div = document.querySelector('#log-box-main')
console.log('div.scrollHeight', div.scrollHeight)
div.scrollTop = div.scrollHeight div.scrollTop = div.scrollHeight
}, 200) }, 200)
} }
@ -1017,18 +1031,32 @@ const toggleIsScroll = () => {
isScroll.value = !isScroll.value isScroll.value = !isScroll.value
} }
const toggleOpenLog = () => {
isOpenLog.value = !isOpenLog.value
}
const initSocket = () => { const initSocket = () => {
socket.init(getSocketMeassage) webSocketStore.init(getSocketMeassage)
}
const initSwitchSocket = () => {
switchSocket.init(getSocketMeassage)
} }
// socket // socket
const socketStatus = computed(() => { const socketStatus = computed(() => {
return socket.socket_open return webSocketStore.socket_open
})
// socket
const switchSocketStatus = computed(() => {
return switchSocket.socket_open
}) })
// //
onMounted(() => { onMounted(() => {
initSocket() initSocket()
const storedMqttForm = localStorage.getItem('mqttForm') const storedMqttForm = localStorage.getItem('mqttForm')
if (storedMqttForm) { if (storedMqttForm) {
Object.assign(mqttForm, JSON.parse(storedMqttForm)) Object.assign(mqttForm, JSON.parse(storedMqttForm))
@ -1040,7 +1068,8 @@ onMounted(() => {
}) })
onUnmounted(() => { onUnmounted(() => {
socket.close() webSocketStore.close()
switchSocket.close()
}) })
</script> </script>
@ -1049,28 +1078,41 @@ onUnmounted(() => {
#switch-box { #switch-box {
height: 100%; height: 100%;
position: relative; position: relative;
padding-bottom: 5px;
.switch-main { .switch-main {
height: calc(100% - 200px - 60px); height: calc(100% - 188px - 60px);
overflow-y: auto; overflow-y: auto;
border-radius: 10px;
background: #f2f2f2;
&.open-log{
height: calc(50% - 42px);
}
} }
.log-box { .log-box {
height: 200px; border-radius: 10px;
background: #0066cc; height: 160px;
border: 1px solid #2d1ca9; margin-top: 10px;
color: #fff; //border: 1px solid #2d1ca9;
color: #333;
overflow: hidden;
display: flex;
flex-direction: column;
&.open-log{
height: calc(50% - 42px);
}
.log-box-header { .log-box-header {
height: 28px; height: 42px;
padding: 0 10px; padding: 0 30px;
border-bottom: 1px solid #fff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
font-size: 18px; font-size: 16px;
font-weight: bold; font-weight: 500;
line-height: 28px; line-height: 28px;
background: #e6e6e6;
font-family: Source Han Sans CN;
color: #333333;
.log-box-operate { .log-box-operate {
display: flex; display: flex;
@ -1087,19 +1129,40 @@ onUnmounted(() => {
} }
.log-box-main { .log-box-main {
padding: 10px; padding: 10px 30px;
height: 169px; //height: 118px;
flex: 1;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box;
background: #f2f2f2;
line-height: 26px;
.log-item { .log-item {
font-size: 13px; font-size: 13px;
user-select: text; user-select: text;
display: flex; //display: flex;
align-items: center; //align-items: center;
flex-wrap: wrap; //flex-wrap: wrap;
line-height: 26px;
font-weight: 500;
margin-left: 8px;
//.log-txt {
// font-weight: 500;
// margin-left: 8px;
// display: inline-block;
// word-wrap: break-word;
// overflow-wrap: break-word;
//}
.iconfont{
&.icon-icon_fuzhi{
line-height: 26px;
margin-left: 8px;
font-size: 16px;
color: #0066cc;
cursor: pointer;
}
> p {
margin-right: 8px;
} }
} }
} }
@ -1114,18 +1177,22 @@ onUnmounted(() => {
} }
:deep(.el-collapse-item__header) { :deep(.el-collapse-item__header) {
background-color: #0066cc; //height: 42px;
color: #fff; //line-height: 42px;
font-size: 18px;
font-weight: bold;
text-indent: 10px;
height: 40px;
line-height: 40px;
} }
:deep(.el-collapse-item__content) { :deep(.el-collapse-item__content) {
padding-bottom: 0; padding-bottom: 0;
} }
:deep(.el-tabs__content) {
background: #f2f2f2;
}
:deep(.el-tabs__item){
background: #e6e6e6;
&.is-active{
background: #f2f2f2;
}
}
.btn-box { .btn-box {
:deep(.el-form-item__content) { :deep(.el-form-item__content) {