refactor(layout): 重构整体布局并移除未使用的组件和页面,调整应用配置,添加断路器标定页面
- 删除了 无用组件和页面 - 调整了 Layout 组件的样式 - 更新了路由配置,重定向到新的 calibration 页面 - 调整应用配置 - 添加断路器标定页面
This commit is contained in:
parent
e97b8516ae
commit
57cf6523ef
|
@ -1,7 +1,7 @@
|
|||
# 应用程序的唯一标识符
|
||||
appId: com.electron.app
|
||||
appId: gy.calibration.pc
|
||||
# 应用程序的名称
|
||||
productName: 谷云工具
|
||||
productName: 谷云标定工具
|
||||
# 定义构建资源和输出文件的目录
|
||||
directories:
|
||||
buildResources: build
|
||||
|
@ -50,7 +50,7 @@ linux:
|
|||
- AppImage
|
||||
- snap
|
||||
- deb
|
||||
maintainer: electronjs.org # 维护者信息
|
||||
maintainer: GuyunDevelopment # 维护者信息
|
||||
category: Utility # 应用程序类别
|
||||
icon: resources/icon.png # 应用程序图标路径
|
||||
# 针对AppImage包的配置
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gateway-app",
|
||||
"version": "1.0.9",
|
||||
"description": "An Electron application with Vue",
|
||||
"name": "calibration-pc",
|
||||
"version": "1.0.0",
|
||||
"description": "谷云开发部开发的断路器标定软件",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "example.com",
|
||||
"homepage": "https://electron-vite.org",
|
||||
|
@ -21,6 +21,7 @@
|
|||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"axios": "^1.7.2",
|
||||
"calibration-pc": "file:",
|
||||
"dayjs": "^1.11.13",
|
||||
"electron-updater": "^6.1.7",
|
||||
"element-plus": "^2.7.6",
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>谷云工具</title>
|
||||
<title>谷云标定工具</title>
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<link rel="stylesheet" href="/src/assets/iconfont/iconfont.css">
|
||||
<!-- <meta-->
|
||||
<!-- http-equiv="Content-Security-Policy"-->
|
||||
<!-- content="default-src 'self'; connect-src 'self' *; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"-->
|
||||
<!-- />-->
|
||||
<script type="text/javascript" src="/videoplayer/EasyPlayer-element.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<cross-domain-policy>
|
||||
<allow-access-from domain="*"/>
|
||||
</cross-domain-policy>
|
|
@ -31,7 +31,8 @@ code {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
margin-bottom: 80px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
<script setup>
|
||||
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/videoplayer"><span class="iconfont icon-icon_jiankong"></span> 视频监控</el-menu-item>-->
|
||||
<el-menu-item index="/system/serialport"><span class="iconfont icon-chuankou2"></span> 设备参数读写</el-menu-item>
|
||||
<el-menu-item index="/system/devicestandard"><span class="iconfont icon-qianzhaoyiqibiaoding"></span> 断路器标定</el-menu-item>
|
||||
<el-menu-item index="/system/scancodewrite"><span class="iconfont icon--_saomaqiang"></span> 扫码录入</el-menu-item>
|
||||
<!-- <el-menu-item index="/gateway/southdirection"><span class="iconfont icon-icon_chajian"></span> 南向采集配置</el-menu-item>-->
|
||||
<!-- <el-menu-item index="/gateway/northboundtask"><span class="iconfont icon-icon_chajian"></span> 北向任务配置</el-menu-item>-->
|
||||
<!-- <el-menu-item index="/gateway/collectdatamonitor"><span class="iconfont icon-icon_chajian"></span> 采集数据监视</el-menu-item>-->
|
||||
<!-- <el-menu-item index="/system/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: 6px;
|
||||
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>
|
|
@ -1,160 +0,0 @@
|
|||
<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-item index="/gateway">网关</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 = () => {
|
||||
// 为了避免频繁触发导致页面卡顿,使用定时器
|
||||
if (!timer.value) {
|
||||
if (domWidth.value != document.body.clientWidth) {
|
||||
domWidth.value = document.body.clientWidth;
|
||||
menuWidth.value = document.body.clientWidth - 363;
|
||||
}
|
||||
timer.value = true;
|
||||
setTimeout(function () {
|
||||
timer.value = false;
|
||||
}, 500);
|
||||
}
|
||||
})
|
||||
);
|
||||
</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>
|
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
<el-container direction="vertical" style="min-height: 100vh; min-width: 100vw; overflow: hidden">
|
||||
<Header></Header>
|
||||
<el-container direction="vertical" style="height: 100%; width: 100%; ">
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive>
|
||||
|
@ -13,7 +12,6 @@
|
|||
|
||||
<script setup>
|
||||
// 组件注册
|
||||
import Header from '@renderer/layout/Header.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -30,6 +28,6 @@ import Header from '@renderer/layout/Header.vue';
|
|||
/*height: 100vh;*/
|
||||
overflow-x: hidden;
|
||||
background: #fff;
|
||||
padding-right: 10px;
|
||||
/*padding-right: 10px;*/
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import Layout from '@renderer/layout/index.vue';
|
||||
import systenLayout from '@renderer/views/system/index.vue';
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
|
@ -9,119 +8,22 @@ const router = createRouter({
|
|||
path: '/',
|
||||
component: Layout,
|
||||
meta: { title: '整体页面布局' },
|
||||
redirect: '/system',
|
||||
redirect: '/calibration',
|
||||
children: [
|
||||
{
|
||||
path: '/system',
|
||||
name: 'system',
|
||||
component: systenLayout,
|
||||
redirect: { name: 'switch' },
|
||||
children: [
|
||||
{
|
||||
path: 'switch',
|
||||
name: 'switch',
|
||||
component: () => import('@renderer/views/system/switch/index.vue'),
|
||||
meta: {
|
||||
menu: 'switch',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'videoplayer',
|
||||
name: 'videoplayer',
|
||||
component: () => import('@renderer/views/system/videoplayer/index.vue'),
|
||||
meta: {
|
||||
menu: 'videoplayer',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'serialport',
|
||||
name: 'serialport',
|
||||
component: () => import('@renderer/views/system/serialport/index.vue'),
|
||||
meta: {
|
||||
menu: 'serialport',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'scancodewrite',
|
||||
name: 'scancodewrite',
|
||||
component: () => import('@renderer/views/system/scancodewrite/index.vue'),
|
||||
meta: {
|
||||
menu: 'scancodewrite',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'devicestandard',
|
||||
name: 'devicestandard',
|
||||
component: () => import('@renderer/views/system/serialport/devicestandard.vue'),
|
||||
meta: {
|
||||
menu: 'devicestandard',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
name: 'about',
|
||||
component: () => import('@renderer/views/AboutView.vue'),
|
||||
meta: {
|
||||
menu: 'about',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'test',
|
||||
name: 'test',
|
||||
component: () => import('@renderer/views/test.vue'),
|
||||
meta: {
|
||||
menu: 'test',
|
||||
keepAlive: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/gateway',
|
||||
name: 'gateway',
|
||||
component: systenLayout,
|
||||
redirect: { name: 'southdirection' },
|
||||
children: [
|
||||
{
|
||||
path: 'southdirection',
|
||||
name: 'southdirection',
|
||||
component: () => import('@renderer/views/gateway/southdirection.vue'),
|
||||
meta: {
|
||||
menu: 'southdirection',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'northboundtask',
|
||||
name: 'northboundtask',
|
||||
component: () => import('@renderer/views/gateway/northboundtask.vue'),
|
||||
meta: {
|
||||
menu: 'northboundtask',
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'collectdatamonitor',
|
||||
name: 'collectdatamonitor',
|
||||
component: () => import('@renderer/views/gateway/collectdatamonitor.vue'),
|
||||
meta: {
|
||||
menu: 'collectdatamonitor',
|
||||
keepAlive: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
path: 'calibration',
|
||||
name: 'calibration',
|
||||
component: () => import('@renderer/views/calibration/index.vue'),
|
||||
meta: {
|
||||
menu: 'calibration',
|
||||
keepAlive: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/', // 这个是根路由,现在我们让它重定向到 /system
|
||||
redirect: '/system'
|
||||
redirect: '/calibration'
|
||||
},
|
||||
{ path: '/:pathMatch(.*)', redirect: '/' }
|
||||
]
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.about {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,258 @@
|
|||
<template>
|
||||
<div class="calibration-page">
|
||||
<el-header class="calibration-header">
|
||||
<div class="header-left">
|
||||
<el-select v-model="selectedScheme" placeholder="选择方案" style="width: 200px; margin-right: 15px">
|
||||
<el-option v-for="item in schemes" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-button icon="CaretRight" type="primary" :disabled="playState" @click="startExecution">开始执行</el-button>
|
||||
<el-button icon="RemoveFilled" type="danger" :disabled="!playState" @click="stopExecution">停止</el-button>
|
||||
</div>
|
||||
<!-- <div class="header-center">-->
|
||||
<!-- <el-button type="primary" size="small" @click="startExecution">开始执行</el-button>-->
|
||||
<!-- <el-button type="danger" size="small" @click="stopExecution">停止</el-button>-->
|
||||
<!-- </div>-->
|
||||
<div class="header-right">
|
||||
<el-button icon="Setting" :disabled="playState" @click="openSettings">设置</el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
|
||||
<el-main class="calibration-main">
|
||||
<div class="device-grid">
|
||||
<el-card v-for="device in devices" :key="device.id" class="device-card">
|
||||
<template #header>
|
||||
<div class="device-card-header">
|
||||
<span>{{ device.code }}</span>
|
||||
<el-tag :type="device.status === 'connected' ? 'success' : 'info'" size="small">
|
||||
{{ device.status === 'connected' ? '已连接' : '未连接' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<div class="device-card-body">
|
||||
<div :class="['iconfont', 'icon-icon_duanluqi', 'circuit-breaker', device.result === '成功' ? 'color-green' : device.result === '失败' ? 'color-red' : '']"></div>
|
||||
<p>设备码: {{ device.deviceCode || '无' }}</p>
|
||||
<p>设备地址: {{ device.address || '无' }}</p>
|
||||
<p>
|
||||
标定结果: <span :class="['device-result', device.result === '成功' ? 'color-green' : device.result === '失败' ? 'color-red' : '']">{{ device.result || '无' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-main>
|
||||
|
||||
<el-footer class="calibration-footer">
|
||||
<div class="log-output">
|
||||
<pre v-for="(log, index) in logs" :key="index">{{ log }}</pre>
|
||||
</div>
|
||||
<div class="version-info">{{ version }}</div>
|
||||
</el-footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const selectedScheme = ref('scheme1');
|
||||
const playState = ref(false);
|
||||
const devices = ref([]);
|
||||
const schemes = ref([
|
||||
{
|
||||
value: 'scheme1',
|
||||
label: '方案1'
|
||||
},
|
||||
{
|
||||
value: 'scheme2',
|
||||
label: '方案2'
|
||||
}
|
||||
]);
|
||||
const logs = ref(['14:44:10.482 添加条码 GE 2', '14:44:10.487 连接失败 127.0.0.1:8821 0000 未将对象引用设置到对象的实例。']);
|
||||
const version = ref('V1.0.0'); // Or dynamically get this
|
||||
|
||||
const generateMockDevices = () => {
|
||||
const mockDevices = [];
|
||||
for (let i = 1; i <= 16; i++) {
|
||||
mockDevices.push({
|
||||
id: i,
|
||||
code: `设备 ${i}`,
|
||||
deviceCode: Math.floor(1000000000000 + Math.random() * 9000000000000).toString(),
|
||||
address: `192.168.1.${i}`,
|
||||
status: i % 3 === 0 ? 'disconnected' : 'connected', // Mock status
|
||||
result: i % 3 !== 0 ? (i % 2 === 0 ? '' : '成功') : '失败' // Mock result
|
||||
});
|
||||
}
|
||||
devices.value = mockDevices;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
generateMockDevices();
|
||||
});
|
||||
|
||||
const startExecution = () => {
|
||||
ElMessage.info('开始执行');
|
||||
playState.value = true;
|
||||
// Add actual start logic here
|
||||
};
|
||||
|
||||
const stopExecution = () => {
|
||||
ElMessage.info('停止执行');
|
||||
playState.value = false;
|
||||
// Add actual stop logic here
|
||||
};
|
||||
|
||||
const openSettings = () => {
|
||||
ElMessage.info('打开设置');
|
||||
// Add settings opening logic here
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.calibration-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
|
||||
.calibration-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
height: 60px;
|
||||
background-color: #404040; /* Dark grey similar to image */
|
||||
color: white;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-left,
|
||||
.header-center,
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-center .el-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.calibration-main {
|
||||
flex-grow: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.device-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.device-card {
|
||||
/* background-color: #ffffff; */ /* Default card color is fine */
|
||||
}
|
||||
|
||||
.device-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.device-card-body {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
.device-result {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.circuit-breaker {
|
||||
font-size: 70px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
|
||||
.color-green {
|
||||
color: #67c23a; /* Green for connected */
|
||||
}
|
||||
|
||||
.color-red {
|
||||
color: #f56c6c; /* Red for disconnected */
|
||||
}
|
||||
|
||||
.calibration-footer {
|
||||
height: 200px; /* Fixed height for logs */
|
||||
background-color: #303030; /* Darker grey for logs */
|
||||
color: #a7a7a7; /* Light grey text for logs */
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.log-output {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap; /* Ensures logs wrap and preserve formatting */
|
||||
border: 1px solid #555;
|
||||
padding: 5px;
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.log-output pre {
|
||||
margin: 2px 0;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.version-info {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
padding-top: 5px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/* Element Plus component overrides if needed */
|
||||
.el-header {
|
||||
--el-header-padding: 0 20px; /* Adjust if necessary */
|
||||
--el-header-height: 60px; /* Ensure this matches fixed height */
|
||||
}
|
||||
|
||||
.el-footer {
|
||||
--el-footer-padding: 0px; /* Adjust if necessary */
|
||||
--el-footer-height: 200px; /* Ensure this matches fixed height */
|
||||
}
|
||||
|
||||
.el-main {
|
||||
--el-main-padding: 20px; /* Adjust if necessary */
|
||||
}
|
||||
|
||||
.el-select .el-input__inner {
|
||||
background-color: #555; /* Darker input fields */
|
||||
color: white;
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
//.el-button--primary {
|
||||
// background-color: #007bff; /* Example primary button color */
|
||||
// border-color: #007bff;
|
||||
//}
|
||||
//
|
||||
//.el-button--danger {
|
||||
// background-color: #dc3545; /* Example danger button color */
|
||||
// border-color: #dc3545;
|
||||
//}
|
||||
|
||||
:deep(.device-grid .el-card__header) {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
:deep(.device-grid .el-card__body) {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Ensure select dropdowns are also styled if needed */
|
||||
</style>
|
|
@ -1,240 +0,0 @@
|
|||
<template>
|
||||
<div id="southdirection-box">
|
||||
<div class="device-config">
|
||||
<h2>设备状态</h2>
|
||||
<div class="btn-list">
|
||||
<div class="btn-list-left"></div>
|
||||
<div class="btn-list-right">
|
||||
<el-button type="primary" @click="getDeviceList">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<el-table
|
||||
ref="deviceConfigTableRef"
|
||||
highlight-current-row
|
||||
:data="deviceList"
|
||||
border
|
||||
height="187"
|
||||
:style="{ width: tabelBox + 'px', background: '#f2f2f2' }"
|
||||
empty-text="配置为空"
|
||||
@row-click="deviceConfigClick"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" width="60" />
|
||||
<el-table-column prop="equipId" label="设备ID" align="center" />
|
||||
<el-table-column prop="quality" label="通讯质量" align="center" />
|
||||
<el-table-column prop="status" label="运行状态" align="center" />
|
||||
<el-table-column prop="status" label="开启状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.status" :before-change="handleBeforeChange.bind(this, scope.$index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-config">
|
||||
<h2>数据源配置 {{ activeDeviceConfig.equipId || '' }}</h2>
|
||||
<div class="btn-list">
|
||||
<div class="btn-list-left"></div>
|
||||
<div class="btn-list-right">
|
||||
<el-button type="primary" @click="getDeviceConfig">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<el-table ref="deviceDataTableRef" :data="activeDeviceConfig.result" border size="small" height="100%" :style="{ width: tabelBox + 'px' }" empty-text="配置为空">
|
||||
<el-table-column type="index" label="序号" align="center" width="60" fixed />
|
||||
<el-table-column prop="id" label="设备ID_数据ID" align="center">
|
||||
<template #default="scope">
|
||||
{{ activeDeviceConfig.equipId + '_' + scope.row.id }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dataName" label="数据名" align="center" />
|
||||
<el-table-column prop="dataValue" label="当前值" align="center" />
|
||||
<el-table-column prop="dataUnit" label="单位" align="center" />
|
||||
<el-table-column prop="time" label="时间" align="center" />
|
||||
<!-- <el-table-column label="操作" width="55" fixed="right" align="center">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button link type="danger" size="small" @click.stop="delDeviceDataConfig(scope.$index)">删除</el-button>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import axios from 'axios';
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
const deviceConfigTableRef = ref();
|
||||
const deviceDataTableRef = ref();
|
||||
const tabelBox = ref(884);
|
||||
const deviceList = ref([]);
|
||||
|
||||
//当选中索引
|
||||
const ActiveRowIndex = ref(0);
|
||||
|
||||
const activeDeviceConfig = ref({
|
||||
equipId: '',
|
||||
status: false,
|
||||
result: []
|
||||
});
|
||||
|
||||
const getDeviceDataList = id => {
|
||||
// console.log('获取设备列表')
|
||||
axios
|
||||
.get(config.url + '/data/collect?equipId=' + id, {})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
if (response.data.code == 0) {
|
||||
//缓存上下行主题
|
||||
activeDeviceConfig.value = {
|
||||
equipId: response.data.data.equipId || '',
|
||||
status: response.data.data.status || false,
|
||||
result: response.data.data.result || []
|
||||
};
|
||||
// activeDeviceResult.value = response.data.data.result || []
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
console.error(error); // 打印错误信息
|
||||
ElMessage.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
const getDeviceList = () => {
|
||||
// console.log('获取设备列表')
|
||||
axios
|
||||
.get(config.url + '/data/equip/list', {})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
if (response.data.code == 0) {
|
||||
//缓存上下行主题
|
||||
deviceList.value = response.data.data.equips || [];
|
||||
if (deviceList.value.length > ActiveRowIndex.value) {
|
||||
getDeviceDataList(deviceList.value[ActiveRowIndex.value].equipId);
|
||||
} else if (deviceList.value.length > 0) {
|
||||
getDeviceDataList(deviceList.value[0].equipId);
|
||||
} else {
|
||||
activeDeviceConfig.value = {
|
||||
equipId: '',
|
||||
starus: false,
|
||||
result: []
|
||||
};
|
||||
// activeDeviceResult.value = []
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
console.error(error); // 打印错误信息
|
||||
ElMessage.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
const getDeviceConfig = () => {
|
||||
getDeviceDataList(deviceList.value[ActiveRowIndex.value].equipId);
|
||||
};
|
||||
|
||||
const handleBeforeChange = index => {
|
||||
console.log('e', index);
|
||||
return new Promise((resolve, reject) => {
|
||||
let deviceObj = deviceList.value[index];
|
||||
console.log('deviceObj', deviceObj.status);
|
||||
let url = config.url + '/data/collect/start?equipId=' + deviceObj.equipId;
|
||||
if (deviceObj.status) {
|
||||
url = config.url + '/data/collect/end?taskId=' + deviceObj.equipId;
|
||||
}
|
||||
// 发送 axios.get 请求
|
||||
axios
|
||||
.get(url)
|
||||
.then(response => {
|
||||
console.log('response', response);
|
||||
if (response.data.code === 0) {
|
||||
// 请求成功且状态为 ok,允许改变开关状态
|
||||
if (deviceObj.status) {
|
||||
ElMessage.success('关闭成功');
|
||||
} else {
|
||||
ElMessage.success('开启成功');
|
||||
}
|
||||
deviceList.value[index].status = !deviceList.value[index].status;
|
||||
getDeviceList();
|
||||
resolve();
|
||||
} else {
|
||||
// 请求成功但状态不为 ok,阻止改变开关状态
|
||||
ElMessage.error(response.data.message);
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 请求失败,阻止改变开关状态
|
||||
ElMessage.error(error.data.message);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//选择设备配置
|
||||
const deviceConfigClick = e => {
|
||||
getDeviceDataList(e.equipId);
|
||||
deviceConfigTableRef.value.toggleRowSelection(e);
|
||||
ActiveRowIndex.value = deviceList.value.indexOf(e);
|
||||
};
|
||||
|
||||
//更新表格宽度
|
||||
const handleResize = () => {
|
||||
deviceDataTableRef.value.doLayout();
|
||||
tabelBox.value = window.innerWidth - 180 - 10;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', handleResize);
|
||||
getDeviceList();
|
||||
handleResize();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-table .double-clicked-row {
|
||||
background-color: #f0f9eb;
|
||||
}
|
||||
:deep(.el-table .el-scrollbar) {
|
||||
background: #fff;
|
||||
}
|
||||
#southdirection-box {
|
||||
height: 100%;
|
||||
.btn-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.device-config {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.data-config {
|
||||
position: relative;
|
||||
height: calc(100% - 278px);
|
||||
.table-box {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(100% - 162px);
|
||||
}
|
||||
}
|
||||
.table-box {
|
||||
//position: absolute;
|
||||
//width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,656 +0,0 @@
|
|||
<template>
|
||||
<div id="southdirection-box">
|
||||
<div class="plat-config">
|
||||
<h2>平台配置</h2>
|
||||
<div class="btn-list">
|
||||
<div class="btn-list-left">
|
||||
<el-button type="primary" @click="addDeviceConfig">新增配置</el-button>
|
||||
<!-- <el-button type="danger" @click="getDeviceConfig">删除</el-button>-->
|
||||
</div>
|
||||
<div class="btn-list-right">
|
||||
<!-- <el-button type="primary" @click="getDeviceConfig">导出</el-button>-->
|
||||
<!-- <el-button type="primary" @click="getDeviceConfig">导入</el-button>-->
|
||||
<el-button type="primary" @click="getDeviceConfig">获取配置</el-button>
|
||||
<el-button type="primary" @click="setDeviceConfig">设置配置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<el-table
|
||||
ref="platConfigTableRef"
|
||||
highlight-current-row
|
||||
:data="platConfigList"
|
||||
border
|
||||
height="187"
|
||||
:row-class-name="tableRowClassName"
|
||||
:style="{ width: tabelBox + 'px',background:'#f2f2f2' }"
|
||||
empty-text="配置为空"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" width="60" />
|
||||
<el-table-column prop="PlatformIp" label="平台地址" >
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.PlatformIp" placeholder="请输入平台地址" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="上报格式" >
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.type" placeholder="请选择上报格式">
|
||||
<el-option
|
||||
v-for="item in uploadType"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mqtt.user" label="用户名" >
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.mqtt.user" placeholder="请输入用户名" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mqtt.passwd" label="密码" >
|
||||
<template #default="scope">
|
||||
<el-input type="password" show-password v-model="scope.row.mqtt.passwd" placeholder="请输入密码" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mqtt.isUseSsl" label="ssl" >
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.mqtt.isUseSsl" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mqtt.isUseSslConf" label="ssl文件" >
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.mqtt.isUseSslConf" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="pushConf.isUseResumeBrokenTransfer" label="断点续存" >
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.pushConf.isUseResumeBrokenTransfer" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="tasks" label="任务ID" >
|
||||
<template #default="scope">
|
||||
{{scope.row.tasks?scope.row.tasks.join():''}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="openCollectionModel(scope.row)">加解密配置</el-button>
|
||||
<el-button link type="danger" size="small" @click="delDeviceConfig(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plat-config">
|
||||
<h2>任务配置</h2>
|
||||
<div class="table-box">
|
||||
<el-table
|
||||
ref="platConfigTableRef"
|
||||
highlight-current-row
|
||||
:data="taskList"
|
||||
border
|
||||
height="187"
|
||||
:row-class-name="tableRowClassName"
|
||||
@row-click="taskConfigClick"
|
||||
:style="{ width: tabelBox + 'px',background:'#f2f2f2' }"
|
||||
empty-text="配置为空"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" width="60" />
|
||||
<el-table-column prop="taskId" label="任务ID" align="center">
|
||||
<template #default="scope">
|
||||
{{scope.row.taskId}}
|
||||
<!-- <el-input v-model="scope.row.taskId" placeholder="请输入任务ID" />-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="uploadMode" label="上报策略" >
|
||||
<template #default="scope">
|
||||
<el-autocomplete
|
||||
v-model="scope.row.uploadMode"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="请选择上报策略"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-config">
|
||||
<h2>上报测点 {{activeDeviceConfig.taskId}}</h2>
|
||||
<div class="table-box">
|
||||
<el-table
|
||||
:data="activeDeviceConfig.dataIdEntire"
|
||||
border
|
||||
size="small"
|
||||
height="100%"
|
||||
ref="deviceDataTableRef"
|
||||
:style="{ width: tabelBox + 'px' }"
|
||||
empty-text="配置为空"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" width="60" fixed />
|
||||
<el-table-column prop="equipId" label="设备ID" align="center"/>
|
||||
<el-table-column prop="idInfo[0].id" label="数据ID" align="center"/>
|
||||
<el-table-column prop="idInfo[0].uploadMode" label="上报策略" align="center"/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="collectionModelShow"
|
||||
title="加解密配置"
|
||||
width="500"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<el-form ref="collectionRef" :model="collectionForm" label-width="auto" status-icon>
|
||||
<h3>加密算法配置</h3>
|
||||
<el-form-item label="启动">
|
||||
<el-switch v-model="collectionForm.encrypt_1.enable" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="加密算法">
|
||||
<el-select v-model="collectionForm.encrypt_1.algorithm" placeholder="选择加密算法">
|
||||
<el-option label="AES" value="AES" />
|
||||
<el-option label="DES" value="DES" />
|
||||
<el-option label="SM4" value="SM4" />
|
||||
<el-option label="RSA" value="RSA" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-center">
|
||||
<el-form-item label="加密key值">
|
||||
<el-input v-model="collectionForm.encrypt_1.param.key" placeholder="请输入加密key值" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="加密模式">
|
||||
<el-select v-model="collectionForm.encrypt_1.mode" placeholder="选择加密模式">
|
||||
<el-option label="ECB" value="ECB" />
|
||||
<el-option label="CBC" value="CBC" />
|
||||
<el-option label="CTR" value="CTR" />
|
||||
<el-option label="CFB" value="CFB" />
|
||||
<el-option label="CFB1" value="CFB1" />
|
||||
<el-option label="CFB8" value="CFB8" />
|
||||
<el-option label="CFB128" value="CFB128" />
|
||||
<el-option label="OFB" value="OFB" />
|
||||
<el-option label="OFB128" value="OFB128" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-center">
|
||||
<el-form-item label="加密向量表">
|
||||
<el-input v-model="collectionForm.encrypt_1.param.ivec" placeholder="请输入加密向量表" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="加密位数">
|
||||
<el-select v-model="collectionForm.encrypt_1.bits" placeholder="选择加密位数">
|
||||
<el-option label="128" value="128" />
|
||||
<el-option label="192" value="192" />
|
||||
<el-option label="256" value="256" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<h3>解密算法配置</h3>
|
||||
<el-form-item label="启动">
|
||||
<el-switch v-model="collectionForm.decrypt_1.enable" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="加密算法">
|
||||
<el-select v-model="collectionForm.decrypt_1.algorithm" placeholder="选择加密算法">
|
||||
<el-option label="AES" value="AES" />
|
||||
<el-option label="DES" value="DES" />
|
||||
<el-option label="SM4" value="SM4" />
|
||||
<el-option label="RSA" value="RSA" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-center">
|
||||
<el-form-item label="加密key值">
|
||||
<el-input v-model="collectionForm.decrypt_1.param.key" placeholder="请输入加密key值" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="加密模式">
|
||||
<el-select v-model="collectionForm.decrypt_1.mode" placeholder="选择加密模式">
|
||||
<el-option label="ECB" value="ECB" />
|
||||
<el-option label="CBC" value="CBC" />
|
||||
<el-option label="CTR" value="CTR" />
|
||||
<el-option label="CFB" value="CFB" />
|
||||
<el-option label="CFB1" value="CFB1" />
|
||||
<el-option label="CFB8" value="CFB8" />
|
||||
<el-option label="CFB128" value="CFB128" />
|
||||
<el-option label="OFB" value="OFB" />
|
||||
<el-option label="OFB128" value="OFB128" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-center">
|
||||
<el-form-item label="加密向量表">
|
||||
<el-input v-model="collectionForm.decrypt_1.param.ivec" placeholder="请输入加密向量表" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="加密位数">
|
||||
<el-select v-model="collectionForm.decrypt_1.bits" placeholder="选择加密位数">
|
||||
<el-option label="128" value="128" />
|
||||
<el-option label="192" value="192" />
|
||||
<el-option label="256" value="256" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="collectionModelShow = false">取消</el-button>
|
||||
<el-button type="primary" @click="editCollection">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted, onUnmounted, computed, watch } from "vue"
|
||||
import { ElMessage, ElMessageBox } from "element-plus"
|
||||
import axios from "axios"
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
//上报策略
|
||||
const uploadModeList = ref([
|
||||
{ value: 'timer 10', link: 'timer 10' },
|
||||
{ value: 'change 10', link: 'change 10' },
|
||||
{ value: 'timer 10 || change 10', link: 'timer 10 || change 10' },
|
||||
{ value: 'label LD200 up', link: 'label LD200 up' },
|
||||
])
|
||||
|
||||
const querySearch = (queryString, cb) => {
|
||||
const results = queryString
|
||||
? uploadModeList.value.filter(createFilter(queryString))
|
||||
: uploadModeList.value
|
||||
// call callback function to return suggestions
|
||||
cb(results)
|
||||
}
|
||||
const createFilter = (queryString) => {
|
||||
return (restaurant) => {
|
||||
return (
|
||||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
)
|
||||
}
|
||||
}
|
||||
//北向任务列表(后面换请求获取)
|
||||
const taskList = ref([
|
||||
]);
|
||||
const platConfigTableRef = ref();
|
||||
const deviceDataTableRef = ref();
|
||||
const tabelBox = ref(884)
|
||||
const platConfigList = ref([])
|
||||
|
||||
const uploadType = ref([
|
||||
{ label: 'DT-MQTT-DEFAULT', value: 'DT-MQTT-DEFAULT'},
|
||||
{ label: 'DT-MQTT-DEBUG', value: 'DT-MQTT-DEBUG'},
|
||||
{ label: 'HN-MQTT-BJ', value: 'HN-MQTT-BJ'},
|
||||
{ label: 'SC-MQTT-DEFAULT', value: 'SC-MQTT-DEFAULT'},
|
||||
{ label: 'WG-MQTT-PuPu', value: 'WG-MQTT-PuPu'},
|
||||
{ label: 'WG-MQTT-TengSheng', value: 'WG-MQTT-TengSheng'},
|
||||
])
|
||||
//新增配置
|
||||
const addDeviceConfig = () => {
|
||||
let newDeviceConfig = {
|
||||
"PlatformIp": "",
|
||||
"tasks": ["T1", "T2", "T3", "T4", "T5"],
|
||||
"type": "",
|
||||
"mqtt": {
|
||||
"user": "",
|
||||
"passwd": "",
|
||||
"isUseSsl": false,
|
||||
"isUseSslConf": false,
|
||||
"sslConf": {
|
||||
"localCertificate_file": "/etc/custom/sslConf/pupu_core_3501000001.pem",
|
||||
"privateKey_file": "/etc/custom/sslConf/pupu_core_3501000001.prv"
|
||||
}
|
||||
},
|
||||
"pushConf": {
|
||||
"isRun": true,
|
||||
"isUseResumeBrokenTransfer": false,
|
||||
"broken": {
|
||||
"resume": { "intervalTime_ms": 1000 },
|
||||
"filter": {
|
||||
"filter_s": 600,
|
||||
"relevanceTaskId": ["T1", "T2", "T3", "T4", "T5"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"encrypt_decrypt": {
|
||||
"encrypt_1": {
|
||||
"algorithm": "AES",
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
"enable": false
|
||||
},
|
||||
"decrypt_1": {
|
||||
"algorithm": "AES",
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
};
|
||||
console.log("platConfigList.value",platConfigTableRef.value)
|
||||
platConfigList.value.push(newDeviceConfig);
|
||||
}
|
||||
|
||||
//删除配置
|
||||
const delDeviceConfig = (index) => {
|
||||
console.log("当前点击的行号", index);
|
||||
ElMessageBox.confirm(
|
||||
'确认要删除该设备配置吗?',
|
||||
'告警',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
platConfigList.value.splice(index, 1);
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功',
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '取消删除',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const getDeviceConfig = () => {
|
||||
console.log('获取配置')
|
||||
axios
|
||||
.get(config.url + '/config/platform/query', {})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log(response); // 打印响应数据
|
||||
if (response.data.code == 0) {
|
||||
//缓存上下行主题
|
||||
platConfigList.value = response.data.data.PlatformPar || [];
|
||||
|
||||
taskList.value = response.data.data.tasks.map(item=>{
|
||||
if(item.dataIdEntire!=[]){
|
||||
let dataIdEntireList = [];
|
||||
item.dataIdEntire.forEach(val=>{
|
||||
val.idInfo.forEach(info=>{
|
||||
dataIdEntireList.push({
|
||||
equipId: val.equipId,
|
||||
idInfo:[info]
|
||||
})
|
||||
})
|
||||
})
|
||||
item.dataIdEntire = dataIdEntireList;
|
||||
}
|
||||
return item;
|
||||
}) || [];
|
||||
// taskList.value = taskDataList;
|
||||
console.log("格式化后数据",taskList.value)
|
||||
if(!platConfigList.value.length){
|
||||
addDeviceConfig()
|
||||
}
|
||||
if(platConfigList.value.length){
|
||||
if(platConfigList.value.length>ActiveRowIndex.value){
|
||||
activeDeviceConfig.value = platConfigList.value[ActiveRowIndex.value];
|
||||
}else{
|
||||
activeDeviceConfig.value = platConfigList.value[0];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
console.error(error); // 打印错误信息
|
||||
ElMessage.error(error);
|
||||
});
|
||||
}
|
||||
const setDeviceConfig = () => {
|
||||
console.log('提交配置',platConfigList.value)
|
||||
axios
|
||||
.post(config.url + '/config/platform/add', {PlatformPar: platConfigList.value,tasks:taskList.value})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log(response); // 打印响应数据
|
||||
if (response.data.code == 0) {
|
||||
ElMessage.success('保存成功');
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
console.error(error); // 打印错误信息
|
||||
ElMessage.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
//当选中索引
|
||||
const ActiveRowIndex = ref(0);
|
||||
|
||||
const collectionModelShow = ref(false);
|
||||
const collectionRef = ref();
|
||||
const collectionForm = ref({
|
||||
// 加密配置
|
||||
"encrypt_1": {
|
||||
// 加密算法
|
||||
"algorithm": "AES",
|
||||
// 加密参数
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
// 是否启用加密
|
||||
"enable": false
|
||||
},
|
||||
// 解密配置
|
||||
"decrypt_1": {
|
||||
// 解密算法
|
||||
"algorithm": "AES",
|
||||
// 解密参数
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
// 是否启用解密
|
||||
"enable": false
|
||||
}
|
||||
})
|
||||
//打开采集配置弹窗
|
||||
const openCollectionModel = (row) => {
|
||||
console.log("当前采集",row)
|
||||
collectionForm.value = {
|
||||
"encrypt_1": row.encrypt_decrypt.encrypt_1,
|
||||
"decrypt_1": row.encrypt_decrypt.decrypt_1
|
||||
};
|
||||
collectionModelShow.value = true;
|
||||
}
|
||||
|
||||
const editCollection = () => {
|
||||
platConfigList.value[ActiveRowIndex.value].encrypt_decrypt.encrypt_1 = collectionForm.value.encrypt_1;
|
||||
platConfigList.value[ActiveRowIndex.value].encrypt_decrypt.decrypt_1 = collectionForm.value.decrypt_1;
|
||||
collectionModelShow.value = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const activeDeviceConfig = ref({
|
||||
"PlatformIp": "",
|
||||
"tasks": ["T1", "T2", "T3", "T4", "T5"],
|
||||
"type": "",
|
||||
"mqtt": {
|
||||
"user": "",
|
||||
"passwd": "",
|
||||
"isUseSsl": false,
|
||||
"isUseSslConf": false,
|
||||
"sslConf": {
|
||||
"localCertificate_file": "/etc/custom/sslConf/pupu_core_3501000001.pem",
|
||||
"privateKey_file": "/etc/custom/sslConf/pupu_core_3501000001.prv"
|
||||
}
|
||||
},
|
||||
"pushConf": {
|
||||
"isRun": true,
|
||||
"isUseResumeBrokenTransfer": false,
|
||||
"broken": {
|
||||
"resume": { "intervalTime_ms": 1000 },
|
||||
"filter": {
|
||||
"filter_s": 600,
|
||||
"relevanceTaskId": ["T1", "T2", "T3", "T4", "T5"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"encrypt_decrypt": {
|
||||
"encrypt_1": {
|
||||
"algorithm": "AES",
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
"enable": false
|
||||
},
|
||||
"decrypt_1": {
|
||||
"algorithm": "AES",
|
||||
"param": {
|
||||
"mode": "CBC",
|
||||
"key": "0123456789abcdef",
|
||||
"ivec": "0123456789abcdef",
|
||||
"bits": 128
|
||||
},
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
watch(
|
||||
() => ({ ...activeDeviceConfig.value }),
|
||||
(newVal) => {
|
||||
console.log("数据变化",newVal)
|
||||
platConfigList.value[ActiveRowIndex.value] = newVal;
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
|
||||
// const saveDeviceDataConfig = () => {
|
||||
// platConfigList.value[ActiveRowIndex.value] = activeDeviceConfig.value;
|
||||
// }
|
||||
const tableRowClassName = ({ row, rowIndex }) => {
|
||||
if (rowIndex === ActiveRowIndex.value) {
|
||||
return 'selected-row';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
//选择设备配置
|
||||
const taskConfigClick = (e) => {
|
||||
console.log(`current page:`,e)
|
||||
activeDeviceConfig.value = e;
|
||||
platConfigTableRef.value.toggleRowSelection(e);
|
||||
|
||||
ActiveRowIndex.value = platConfigList.value.indexOf(e);
|
||||
// e.isDoubleClicked = !e.isDoubleClicked;
|
||||
}
|
||||
|
||||
|
||||
//更新表格宽度
|
||||
const handleResize = () => {
|
||||
deviceDataTableRef.value.doLayout();
|
||||
tabelBox.value = window.innerWidth - 180 - 10 ;
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', handleResize);
|
||||
getDeviceConfig()
|
||||
handleResize()
|
||||
// if(platConfigList.value[0]){
|
||||
// activeDeviceConfig.value = platConfigList.value[0];
|
||||
// platConfigTableRef.value.toggleRowSelection(platConfigList.value[0]);
|
||||
// ActiveRowIndex.value = 0;
|
||||
// }
|
||||
|
||||
});
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-table .double-clicked-row {
|
||||
background-color: #f0f9eb;
|
||||
}
|
||||
:deep(.el-table .el-scrollbar) {
|
||||
background: #fff;
|
||||
}
|
||||
#southdirection-box{
|
||||
height: 100%;
|
||||
.btn-list{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.plat-config{
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.data-config{
|
||||
position: relative;
|
||||
height: calc(100% - 278px - 226px);
|
||||
.table-box{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(100% - 120px);
|
||||
}
|
||||
}
|
||||
.table-box{
|
||||
//position: absolute;
|
||||
//width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
.selected-row {
|
||||
background-color: #55e800;
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,35 +0,0 @@
|
|||
<template>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 组件注册
|
||||
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>
|
|
@ -1,796 +0,0 @@
|
|||
<template>
|
||||
<div class="scanner-container">
|
||||
<el-upload
|
||||
v-model:file-list="fileList"
|
||||
class="upload-demo"
|
||||
:action="config.serialPortUrl + '/importDevice'"
|
||||
multiple
|
||||
ref="upload"
|
||||
name="excelFile"
|
||||
:before-remove="beforeRemove"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
>
|
||||
<el-button type="primary"><el-icon><Upload /></el-icon>导入设备表</el-button>
|
||||
<!-- <template #tip>-->
|
||||
<!-- <div class="el-upload__tip">-->
|
||||
<!-- xls 文件.-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
</el-upload>
|
||||
|
||||
<!-- Device Code Section -->
|
||||
<div class="input-section">
|
||||
<div class="label">设备序列号</div>
|
||||
<el-input
|
||||
ref="snInputRef"
|
||||
v-model="deviceAttrList[1].inputValue"
|
||||
placeholder="请输入或扫描设备序列号"
|
||||
size="large"
|
||||
clearable
|
||||
class="device-code-input"
|
||||
@focus="handleSnInputFocus"
|
||||
@blur="handleSnInputBlur"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Main and Sub Model Section -->
|
||||
<div class="model-section">
|
||||
<div class="model-inputs">
|
||||
<div class="model-input-group">
|
||||
<div class="label">主型号</div>
|
||||
<el-input v-model="deviceAttrList[2].inputValue" :disabled="inputStatus" size="large" placeholder="请输入主型号" @input="saveCache($event,2)" />
|
||||
</div>
|
||||
<div class="model-input-group">
|
||||
<div class="label">次型号</div>
|
||||
<el-input v-model="deviceAttrList[3].inputValue" :disabled="inputStatus" size="large" placeholder="请输入次型号" @input="saveCache($event,3)" />
|
||||
</div>
|
||||
<el-button size="large" type="primary" @click="toggleInput">{{inputStatus?'解锁':'锁定'}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Information Display Section -->
|
||||
<div class="info-section">
|
||||
<span class="info-time">{{infoTime ? '时间:' + $dayjs(infoTime).format('YYYY-MM-DD HH:mm:ss') : ''}}</span>
|
||||
<el-tag type="info" class="status-tag" v-if="deviceAttrList[1].outputValue==''">-</el-tag>
|
||||
<el-tag type="success" class="status-tag" v-else-if="getContrastStatus()">比对成功</el-tag>
|
||||
<el-tag type="danger" class="status-tag" v-else>比对失败</el-tag>
|
||||
<div class="info-card">
|
||||
<div class="info-title">设备序列号</div>
|
||||
<div class="info-content">{{ deviceAttrList[1].outputValue || '-' }}</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-title"></div>
|
||||
<div class="info-content"></div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-title">主型号</div>
|
||||
<div class="info-content">{{ deviceAttrList[2].outputValue || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<div class="info-title">次型号</div>
|
||||
<div class="info-content">{{ deviceAttrList[3].outputValue || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div id="serialport-box">-->
|
||||
<!-- <div id="serialport-main" class="serialport-main">-->
|
||||
<!-- <el-collapse v-model="activeFold" @change="foldChange">-->
|
||||
<!-- <el-collapse-item name="3" title="设备参数">-->
|
||||
<!-- <div class="device-attr-list">-->
|
||||
<!-- <div v-for="(item, index) in deviceAttrList" :key="item.id" class="device-attr-item">-->
|
||||
<!-- <div class="device-attr-item-name">{{ item.name }}</div>-->
|
||||
<!-- <div class="device-attr-item-value">-->
|
||||
<!-- <el-input v-model="item.outputValue" class="device-attr-input" disabled />-->
|
||||
<!-- <el-button type="primary" :loading="item.outputLoadingStatus" @click="sendDeviceAttr(item, 'output', index)">读取</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="device-attr-item-value">-->
|
||||
<!-- <el-input v-model="item.inputValue"-->
|
||||
<!-- v-if="item.name === '设备序列号(SN)'"-->
|
||||
<!-- ref="snInputRef"-->
|
||||
<!-- class="device-attr-input"-->
|
||||
<!-- :disabled="item.inputDisable"-->
|
||||
<!-- @focus="handleSnInputFocus"-->
|
||||
<!-- @blur="handleSnInputBlur"-->
|
||||
<!-- @keyup.enter="handleSnEnter(item, index)"-->
|
||||
<!-- placeholder="扫码输入"/>-->
|
||||
<!-- <el-input v-model="item.inputValue" :disabled="item.inputDisable" class="device-attr-input" v-else/>-->
|
||||
<!-- <el-button type="primary" :disabled="item.inputDisable" :loading="item.inputLoadingStatus" @click="sendDeviceAttr(item, 'input', index)">写入</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="btn-box">-->
|
||||
<!-- <el-button type="primary" @click="allReadDeviceAttr">一键读取</el-button>-->
|
||||
<!-- <el-button type="primary" @click="allWriteDeviceAttr">一键写入</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-collapse-item>-->
|
||||
<!-- </el-collapse>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import axios from 'axios'; // 引入axios
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
import { reactive, ref, onMounted, onUnmounted, watch, computed, nextTick, onDeactivated, onActivated } from 'vue';
|
||||
import { ElMessage,ElMessageBox,genFileId } from 'element-plus';
|
||||
import { buildHead, hexToString, hexToVersion, rearrangeHexStr, versionToHex } from '../serialport/js/fun';
|
||||
import { useSerialPortStore } from '@renderer/stores/seralPort.js';
|
||||
|
||||
|
||||
const useseralPortStore = useSerialPortStore();
|
||||
|
||||
const upload = ref()
|
||||
|
||||
//连接状态
|
||||
const connectionState = ref(false);
|
||||
const inputStatus = ref(false);
|
||||
|
||||
const snInputRef = ref(null); // 引用SN输入框
|
||||
|
||||
const serialportForm = computed(() => {
|
||||
return useseralPortStore.serialport;
|
||||
});
|
||||
|
||||
const infoTime = ref('');
|
||||
|
||||
// 扫码枪相关功能
|
||||
const isScannerInput = ref(false);
|
||||
const lastScanTime = ref(0);
|
||||
const scanTimeout = ref(null);
|
||||
|
||||
const toggleInput = () => {
|
||||
inputStatus.value = !inputStatus.value;
|
||||
ElMessage.success(inputStatus.value?'已锁定':'已解锁');
|
||||
}
|
||||
|
||||
const fileList = ref([])
|
||||
|
||||
const handleExceed = () => {
|
||||
ElMessage.error(
|
||||
`只能上传一个设备表、请先删除设备表再上传`
|
||||
);
|
||||
}
|
||||
|
||||
const beforeAvatarUpload = (rawFile) => {
|
||||
console.log("rawFile",rawFile)
|
||||
if (rawFile.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' && rawFile.type !== 'application/vnd.ms-excel') {
|
||||
ElMessage.error('请上传xls或者xlsx格式文件!')
|
||||
fileList.value = [];
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const beforeRemove = (uploadFile, uploadFiles) => {
|
||||
return ElMessageBox.confirm(
|
||||
`确认要删除 ${uploadFile.name} 吗?`, "告警", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
fileList.value = [];
|
||||
return true;
|
||||
},
|
||||
() => false
|
||||
)
|
||||
}
|
||||
|
||||
// 处理SN输入框获得焦点
|
||||
const handleSnInputFocus = () => {
|
||||
isScannerInput.value = true;
|
||||
};
|
||||
|
||||
// 处理SN输入框失去焦点
|
||||
const handleSnInputBlur = () => {
|
||||
isScannerInput.value = false;
|
||||
};
|
||||
|
||||
// 处理扫码完成后的回车事件
|
||||
const generateDerivedSerialNumbers = serialNumber => {
|
||||
if (!serialNumber || serialNumber.length === 0) return;
|
||||
|
||||
// Get the first digit and the rest of the string
|
||||
const firstDigit = parseInt(serialNumber.charAt(0));
|
||||
const restOfString = serialNumber.substring(1);
|
||||
|
||||
// Generate motherboard serial number (first digit + 1)
|
||||
const motherboardFirstDigit = (firstDigit + 1) % 10; // Use modulo to handle 9 -> 0
|
||||
const motherboardSN = motherboardFirstDigit + restOfString;
|
||||
|
||||
// Generate 69 serial number (first digit + 2)
|
||||
const sn69FirstDigit = (firstDigit + 2) % 10; // Use modulo to handle 8 -> 0, 9 -> 1
|
||||
const sn69 = sn69FirstDigit + restOfString;
|
||||
|
||||
// Find and update the motherboard serial number field
|
||||
const motherboardIndex = deviceAttrList.value.findIndex(item => item.name === '主板序列号');
|
||||
if (motherboardIndex !== -1) {
|
||||
deviceAttrList.value[motherboardIndex].inputValue = motherboardSN;
|
||||
}
|
||||
|
||||
// Find and update the 69 serial number field
|
||||
const sn69Index = deviceAttrList.value.findIndex(item => item.name === '69序列号');
|
||||
if (sn69Index !== -1) {
|
||||
deviceAttrList.value[sn69Index].inputValue = sn69;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理扫码完成后的回车事件
|
||||
const handleSnEnter = (item, index) => {
|
||||
console.log("item",item.inputValue)
|
||||
if (item.inputValue && item.inputValue.trim() !== '') {
|
||||
// 查询产品密钥
|
||||
queryProductKey(item.inputValue);
|
||||
|
||||
// 可选:自动写入SN
|
||||
// sendDeviceAttr(item, 'input', index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const JudgeInput = () => {
|
||||
|
||||
if(deviceAttrList.value[2].inputValue === '' || deviceAttrList.value[3].inputValue === ''){
|
||||
ElMessage.error('主型号和次型号不能为空');
|
||||
}else if(deviceAttrList.value[1].inputValue === ''){
|
||||
ElMessage.error('设备序列号不能为空');
|
||||
}else if(deviceAttrList.value[4].inputValue === ''){
|
||||
ElMessage.error('产品密钥不能为空');
|
||||
}else if(deviceAttrList.value[5].inputValue === ''){
|
||||
ElMessage.error('主板序列号不能为空');
|
||||
}else if(deviceAttrList.value[6].inputValue === ''){
|
||||
ElMessage.error('69序列号不能为空');
|
||||
}else if (!serialportForm.value.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
}else{
|
||||
allWriteDeviceAttr()
|
||||
}
|
||||
}
|
||||
|
||||
// 查询产品密钥API
|
||||
const queryProductKey = async serialNumber => {
|
||||
try {
|
||||
// 显示加载状态
|
||||
const keyIndex = deviceAttrList.value.findIndex(item => item.name === '产品密钥');
|
||||
if (keyIndex !== -1) {
|
||||
deviceAttrList.value[keyIndex].inputLoadingStatus = true;
|
||||
}
|
||||
|
||||
// 调用API查询密钥
|
||||
const response = await axios.get(`${config.serialPortUrl}/importDeviceSearch`, {
|
||||
params: { devKey: serialNumber }
|
||||
});
|
||||
if (response.data.code === 0 && response.data.data.Result) {
|
||||
// 找到产品密钥输入框并填入值
|
||||
if (keyIndex !== -1) {
|
||||
deviceAttrList.value[keyIndex].inputValue = response.data.data.Result.devSecret;
|
||||
generateDerivedSerialNumbers(serialNumber);
|
||||
JudgeInput()
|
||||
// ElMessage.success('密钥查询成功');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('未找到对应密钥,请检查设备序列号和设备表内设备序列号是否正确');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查询密钥失败:', error);
|
||||
ElMessage.error('查询密钥失败');
|
||||
} finally {
|
||||
// 清除加载状态
|
||||
const keyIndex = deviceAttrList.value.findIndex(item => item.name === '产品密钥');
|
||||
if (keyIndex !== -1) {
|
||||
deviceAttrList.value[keyIndex].inputLoadingStatus = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 自动聚焦SN输入框
|
||||
const focusSnInput = () => {
|
||||
if (snInputRef.value) {
|
||||
// 找到SN输入框的索引
|
||||
const snIndex = deviceAttrList.value.findIndex(item => item.name === '设备序列号(SN)');
|
||||
if (snIndex !== -1) {
|
||||
// 清空之前的输入
|
||||
deviceAttrList.value[snIndex].inputValue = '';
|
||||
// 聚焦输入框
|
||||
nextTick(() => {
|
||||
snInputRef.value.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const deviceAttrCommonList = ref({
|
||||
input: {
|
||||
//数据长度类型
|
||||
datalentype: '00',
|
||||
//目标ID
|
||||
remote_id: '0',
|
||||
//本地ID
|
||||
local_id: '0',
|
||||
//指令码
|
||||
cmd: '0100',
|
||||
//设备类型
|
||||
devtype: '00',
|
||||
//数据类型
|
||||
datatype: '00'
|
||||
},
|
||||
output: {
|
||||
//数据长度类型
|
||||
datalentype: '00',
|
||||
//目标ID
|
||||
remote_id: '0',
|
||||
//本地ID
|
||||
local_id: '0',
|
||||
//指令码
|
||||
cmd: '0011',
|
||||
//设备类型
|
||||
devtype: '00',
|
||||
//数据类型
|
||||
datatype: '00'
|
||||
}
|
||||
});
|
||||
|
||||
const deviceAttrList = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '芯片ID',
|
||||
startValue: 0,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'hex',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '设备序列号(SN)',
|
||||
startValue: 4,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '产品主型号',
|
||||
startValue: 12,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '产品次型号',
|
||||
startValue: 16,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '产品密钥',
|
||||
startValue: 20,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '主板序列号',
|
||||
startValue: 28,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '69序列号',
|
||||
startValue: 36,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
const saveCache = (e,index) => {
|
||||
console.log("e,index",e,index)
|
||||
if(index === 2){
|
||||
localStorage.setItem('mainModel', e);
|
||||
}else if(index === 3){
|
||||
localStorage.setItem('secondaryModel', e);
|
||||
}
|
||||
}
|
||||
|
||||
//解码
|
||||
const analysisData = (hexData, data) => {
|
||||
if (hexData.length < 28) {
|
||||
console.log('返回hex小于28个字符串', hexData);
|
||||
return '';
|
||||
} else {
|
||||
// let head = hexData.substring(0,8);
|
||||
// let startAddr = hexData.substring(8,16);
|
||||
// let len = hexData.substring(16,24);
|
||||
let hexValue = hexData.substring(24, data.lengthValue * 4 * 2 + 24);
|
||||
// let crc = hexData.substring(hexData.length - 4);
|
||||
if (data.dataType === 'str') {
|
||||
let str = hexToString(hexValue).trim();
|
||||
return str;
|
||||
} else if (data.dataType === 'hex') {
|
||||
let str = rearrangeHexStr(hexValue);
|
||||
return str;
|
||||
}
|
||||
// else if(data.dataType === 'firmware'){
|
||||
// let str = hexToVersion(hexValue);
|
||||
// return str;
|
||||
// }
|
||||
else {
|
||||
return hexValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const sendDeviceAttr = (data, type, index) => {
|
||||
if (!serialportForm.value.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
console.log('readDeviceAttr', data);
|
||||
|
||||
let head = buildHead(
|
||||
deviceAttrCommonList.value[type].datalentype,
|
||||
deviceAttrCommonList.value[type].remote_id,
|
||||
deviceAttrCommonList.value[type].local_id,
|
||||
deviceAttrCommonList.value[type].cmd,
|
||||
deviceAttrCommonList.value[type].devtype,
|
||||
deviceAttrCommonList.value[type].datatype,
|
||||
data.startValue,
|
||||
data.lengthValue,
|
||||
data.inputValue,
|
||||
data
|
||||
);
|
||||
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = true;
|
||||
// head = head + 'd240';
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = true;
|
||||
}
|
||||
axios
|
||||
.post(
|
||||
config.serialPortUrl + '/serial/response',
|
||||
{
|
||||
port: serialportForm.value.port,
|
||||
data: head,
|
||||
hex: 1,
|
||||
crc: 1,
|
||||
flush: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log('串口请求', response); // 打印响应数据
|
||||
if (response.data.code === 0) {
|
||||
ElMessage.success('操作成功');
|
||||
if (type === 'output') {
|
||||
deviceAttrList.value[index].outputValue = analysisData(response.data.data.hex || '', data);
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = false;
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('error', error);
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = false;
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = false;
|
||||
}
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allReadDeviceAttr = () => {
|
||||
console.log('serialportForm', serialportForm.value);
|
||||
if (!serialportForm.value.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
|
||||
let head = buildHead(
|
||||
deviceAttrCommonList.value['output'].datalentype,
|
||||
deviceAttrCommonList.value['output'].remote_id,
|
||||
deviceAttrCommonList.value['output'].local_id,
|
||||
deviceAttrCommonList.value['output'].cmd,
|
||||
deviceAttrCommonList.value['output'].devtype,
|
||||
deviceAttrCommonList.value['output'].datatype,
|
||||
0,
|
||||
46,
|
||||
''
|
||||
);
|
||||
|
||||
axios
|
||||
.post(
|
||||
config.serialPortUrl + '/serial/response',
|
||||
{
|
||||
port: serialportForm.value.port,
|
||||
data: head,
|
||||
hex: 1,
|
||||
crc: 1,
|
||||
flush: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log('串口请求', response); // 打印响应数据
|
||||
if (response.data.code === 0) {
|
||||
if(response.data.data.hex!==''){
|
||||
ElMessage.success('操作成功');
|
||||
let hexValue = response.data.data.hex.substring(24, 392);
|
||||
let startValue = 0;
|
||||
deviceAttrList.value.forEach((item, index) => {
|
||||
if (startValue === 0) {
|
||||
startValue = item.startValue;
|
||||
}
|
||||
let value = hexValue.substring(startValue, item.lengthValue * 4 * 2 + startValue);
|
||||
startValue = startValue + item.lengthValue * 4 * 2;
|
||||
console.log('value', value);
|
||||
infoTime.value = new Date().getTime();
|
||||
if (item.dataType === 'str') {
|
||||
deviceAttrList.value[index].outputValue = hexToString(value).trim();
|
||||
// deviceAttrList.value[index].inputValue = hexToString(value).trim();
|
||||
} else if (item.dataType === 'hex') {
|
||||
deviceAttrList.value[index].outputValue = rearrangeHexStr(value);
|
||||
// deviceAttrList.value[index].inputValue = rearrangeHexStr(value);
|
||||
} else {
|
||||
deviceAttrList.value[index].outputValue = value;
|
||||
// deviceAttrList.value[index].inputValue = value;
|
||||
}
|
||||
});
|
||||
}else{
|
||||
ElMessage.error('获取数据为空');
|
||||
}
|
||||
|
||||
// deviceAttrList.value[index].outputValue = analysisData(response.data.data.hex || '', data);
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('error', error);
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allWriteDeviceAttr = () => {
|
||||
if (!serialportForm.value.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
deviceAttrList.value.forEach((item, index) => {
|
||||
setTimeout(() => {
|
||||
if(index === 1 || index === 2 || index === 3 || index === 4 || index === 5 || index === 6 ){
|
||||
sendDeviceAttr(item, 'input', index);
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
setTimeout(() => {
|
||||
allReadDeviceAttr();
|
||||
},1000)
|
||||
};
|
||||
|
||||
const getKeyboardWriter = e => {
|
||||
// 如果当前焦点在SN输入框上
|
||||
if (isScannerInput.value) {
|
||||
const now = Date.now();
|
||||
|
||||
// 如果是扫码枪输入(扫码枪通常输入速度很快)
|
||||
if (now - lastScanTime.value > 3000) {
|
||||
// 如果间隔大于500ms,可能是新的扫码开始,清空输入
|
||||
const snIndex = deviceAttrList.value.findIndex(item => item.name === '设备序列号(SN)');
|
||||
if (snIndex !== -1) {
|
||||
deviceAttrList.value[snIndex].inputValue = '';
|
||||
}
|
||||
}
|
||||
|
||||
lastScanTime.value = now;
|
||||
|
||||
// 清除之前的超时
|
||||
if (scanTimeout.value) {
|
||||
clearTimeout(scanTimeout.value);
|
||||
}
|
||||
|
||||
// 设置新的超时,如果50ms内没有新输入,认为扫码完成
|
||||
scanTimeout.value = setTimeout(() => {
|
||||
// 扫码完成,检查是否有回车键
|
||||
if (e.key === 'Enter') {
|
||||
const snIndex = deviceAttrList.value.findIndex(item => item.name === '设备序列号(SN)');
|
||||
if (snIndex !== -1 && deviceAttrList.value[snIndex].inputValue) {
|
||||
handleSnEnter(deviceAttrList.value[snIndex], snIndex);
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
};
|
||||
const getContrastStatus = () => {
|
||||
let flag = true;
|
||||
if(deviceAttrList.value[1].outputValue && deviceAttrList.value[1].outputValue !== deviceAttrList.value[1].inputValue){
|
||||
flag = false;
|
||||
}
|
||||
if(deviceAttrList.value[2].outputValue && deviceAttrList.value[2].outputValue !== deviceAttrList.value[2].inputValue){
|
||||
flag = false;
|
||||
}
|
||||
if(deviceAttrList.value[3].outputValue && deviceAttrList.value[3].outputValue !== deviceAttrList.value[3].inputValue){
|
||||
flag = false;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
// 生命周期钩子
|
||||
onMounted(() => {
|
||||
// getSerialPortList(false);
|
||||
deviceAttrList.value[2].inputValue = localStorage.getItem('mainModel');
|
||||
deviceAttrList.value[3].inputValue = localStorage.getItem('secondaryModel');
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
console.log('页面重新打开(从缓存恢复)');
|
||||
console.log("serialportForm",serialportForm.value)
|
||||
allReadDeviceAttr();
|
||||
// 这里可以刷新数据
|
||||
// 组件挂载后自动聚焦SN输入框
|
||||
nextTick(() => {
|
||||
focusSnInput();
|
||||
});
|
||||
|
||||
// 添加键盘事件监听器,用于检测扫码枪的输入
|
||||
window.addEventListener('keydown', getKeyboardWriter);
|
||||
});
|
||||
|
||||
// 页面离开但被缓存时触发
|
||||
onDeactivated(() => {
|
||||
console.log('页面离开(进入缓存)');
|
||||
// 移除事件监听器
|
||||
window.removeEventListener('keydown', getKeyboardWriter);
|
||||
|
||||
// 清除超时
|
||||
if (scanTimeout.value) {
|
||||
clearTimeout(scanTimeout.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.scanner-container {
|
||||
padding: 20px;
|
||||
height: calc(100% - 80px);
|
||||
background: #f2f2f2;
|
||||
border-radius: 10px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.import-btn {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.device-code-input {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
//.input-section,
|
||||
.model-section,
|
||||
.info-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.model-inputs {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.model-input-group {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 15px;
|
||||
background-color: #f8f8f8;
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.info-title {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
}
|
||||
.info-time{
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 10px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,956 +0,0 @@
|
|||
<template>
|
||||
<div id="serialport-box">
|
||||
<div id="serialport-main" class="serialport-main">
|
||||
<el-collapse v-model="activeFold" @change="foldChange">
|
||||
<el-collapse-item name="1" title="串口设置">
|
||||
<el-form ref="serialportFormRef" :model="serialportForm" :rules="serialportRules" class="demo-serialportForm" label-width="auto" status-icon>
|
||||
<el-form-item label="端口" prop="port" required>
|
||||
<el-select v-model="serialportForm.port" :disabled="connectionState" placeholder="选择端口" style="flex: 1">
|
||||
<el-option v-for="(item, index) in serialportList" :key="index" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-button style="margin-left: 10px" type="primary" @click="getSerialPortList">获取端口列表</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="波特率" prop="baudrate" required>
|
||||
<el-select v-model="serialportForm.baudrate" :disabled="connectionState" placeholder="选择波特率">
|
||||
<el-option label="4800" :value="4800" />
|
||||
<el-option label="9600" :value="9600" />
|
||||
<el-option label="19200" :value="19200" />
|
||||
<el-option label="43000" :value="43000" />
|
||||
<el-option label="56000" :value="56000" />
|
||||
<el-option label="115200" :value="115200" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据位" prop="databits" required>
|
||||
<el-select v-model="serialportForm.databits" :disabled="connectionState" placeholder="选择数据位">
|
||||
<el-option label="5" :value="5" />
|
||||
<el-option label="6" :value="6" />
|
||||
<el-option label="7" :value="7" />
|
||||
<el-option label="8" :value="8" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="校验位" prop="parity" required>
|
||||
<el-select v-model="serialportForm.parity" :disabled="connectionState" placeholder="选择校验位">
|
||||
<el-option label="None" :value="0" />
|
||||
<el-option label="Odd" :value="1" />
|
||||
<el-option label="Even" :value="2" />
|
||||
<el-option label="Mark" :value="3" />
|
||||
<el-option label="Space" :value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="停止位" prop="stopbits" required>
|
||||
<el-select v-model="serialportForm.stopbits" :disabled="connectionState" placeholder="选择停止位">
|
||||
<el-option label="1" :value="0" />
|
||||
<el-option label="1.5" :value="1" />
|
||||
<el-option label="2" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="btn-box">
|
||||
<el-button type="danger" @click="disconnSerialPort">关闭 </el-button>
|
||||
<el-button type="primary" @click="connectSerialPort(serialportFormRef)">{{ connectionState ? '已打开' : '打开' }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="2" title="通用调试">
|
||||
<el-form ref="commonDebuggerFormRef" :model="commonDebuggerForm" :rules="commonDebuggerRules" class="demo-serialportForm" label-width="auto" status-icon>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="本地ID" prop="localId">
|
||||
<el-input v-model="commonDebuggerForm.localId" placeholder="请输入本地ID" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="目标ID" prop="remoteId">
|
||||
<el-input v-model="commonDebuggerForm.remoteId" placeholder="请输入目标ID" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备类型" prop="devType" required>
|
||||
<el-select v-model="commonDebuggerForm.devType" placeholder="选择设备类型" style="flex: 1">
|
||||
<el-option v-for="(item, index) in devTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="数据类型" prop="dataType" required>
|
||||
<el-select v-model="commonDebuggerForm.dataType" placeholder="选择数据类型" style="flex: 1">
|
||||
<el-option v-for="(item, index) in dataTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="指令码" prop="cmd" required>
|
||||
<el-select v-model="commonDebuggerForm.cmd" placeholder="选择指令码" style="flex: 1">
|
||||
<el-option v-for="(item, index) in cmdList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="数据长度类型" prop="dataLenType" required>
|
||||
<el-select v-model="commonDebuggerForm.dataLenType" placeholder="选择数据长度类型" style="flex: 1">
|
||||
<el-option v-for="(item, index) in dataLenTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="commonDebuggerForm.cmd === '0100' || commonDebuggerForm.cmd === '0011'">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="起始地址" prop="writeStart" required>
|
||||
<el-input v-model="commonDebuggerForm.writeStart" type="number" placeholder="请输入起始地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="长度" prop="writeLength" required>
|
||||
<el-input v-model="commonDebuggerForm.writeLength" type="number" placeholder="请输入长度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item v-if="commonDebuggerForm.cmd === '0100'" label="数据" prop="writeData">
|
||||
<el-input v-model="commonDebuggerForm.writeData" type="textarea" :rows="2" placeholder="请输入数据" />
|
||||
</el-form-item>
|
||||
<el-form-item label="发送包" prop="dataStr">
|
||||
<el-input v-model="commonDebuggerForm.dataStr" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="返回包" prop="hexStr">
|
||||
<el-input v-model="commonDebuggerForm.hexStr" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item class="btn-box">
|
||||
<el-button type="primary" :loading="sendCommonDebuggerState" @click="sendCommonDebugger(commonDebuggerFormRef)">发送</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="3" title="设备基础参数">
|
||||
<div class="device-attr-list">
|
||||
<div v-for="(item, index) in deviceAttrList" :key="item.id" class="device-attr-item">
|
||||
<div class="device-attr-item-name">{{ item.name }}</div>
|
||||
<div class="device-attr-item-value">
|
||||
<el-input v-model="item.outputValue" class="device-attr-input" disabled />
|
||||
<el-button type="primary" :loading="item.outputLoadingStatus" @click="sendDeviceAttr(item, 'output', index)">读取</el-button>
|
||||
</div>
|
||||
<div class="device-attr-item-value">
|
||||
<el-input v-model="item.inputValue" :disabled="item.inputDisable" class="device-attr-input" />
|
||||
<el-button type="primary" :disabled="item.inputDisable" :loading="item.inputLoadingStatus" @click="sendDeviceAttr(item, 'input', index)">写入</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<el-button type="primary" @click="allReadDeviceAttr">一键读取</el-button>
|
||||
<el-button type="primary" @click="allWriteDeviceAttr">一键写入</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import axios from 'axios'; // 引入axios
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
import { reactive, ref, onMounted, onUnmounted, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { buildHead, hexToString, hexToVersion, rearrangeHexStr, versionToHex } from './js/fun';
|
||||
import { useSerialPortStore } from '@renderer/stores/seralPort.js';
|
||||
|
||||
const useseralPortStore = useSerialPortStore();
|
||||
const activeFold = ref(['1', '2', '3']);
|
||||
|
||||
//连接状态
|
||||
const connectionState = ref(false);
|
||||
|
||||
const serialportFormRef = ref();
|
||||
|
||||
const serialportList = ref([]);
|
||||
|
||||
const serialportForm = reactive({
|
||||
port: '',
|
||||
baudrate: 115200,
|
||||
databits: 8,
|
||||
parity: 0,
|
||||
stopbits: 0
|
||||
});
|
||||
|
||||
// 监听 serialportForm 的变化
|
||||
watch(
|
||||
() => ({ ...serialportForm }),
|
||||
newVal => {
|
||||
// 将新的值存储到 localStorage 中
|
||||
newVal.port = newVal.port.toLowerCase();
|
||||
useseralPortStore.setSerialport(newVal);
|
||||
// localStorage.setItem('serialportForm', newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const serialportRules = reactive({
|
||||
port: [{ required: true, message: '请选择端口', trigger: 'change' }],
|
||||
baudrate: [{ required: true, message: '请选择波特率', trigger: 'change' }],
|
||||
databits: [{ required: true, message: '请选择port', trigger: 'change' }],
|
||||
parity: [{ required: true, message: '请选择userName', trigger: 'change' }],
|
||||
stopbits: [{ required: true, message: '请选择passWord', trigger: 'change' }]
|
||||
});
|
||||
|
||||
//获取端口列表
|
||||
const getSerialPortList = (msgShow = true) => {
|
||||
axios
|
||||
.get(config.serialPortUrl + '/serial/list', {})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
if (response.data.code === 0) {
|
||||
serialportList.value = response.data.data.List || [];
|
||||
if (msgShow) {
|
||||
ElMessage.success('获取端口列表成功');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
ElMessage.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
//打开
|
||||
const connectSerialPort = formEl => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(valid => {
|
||||
if (valid) {
|
||||
serialportForm.port = serialportForm.port.toLowerCase();
|
||||
axios
|
||||
.post(config.serialPortUrl + '/serial/open', serialportForm)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log(response); // 打印响应数据
|
||||
if (response.data.code === 0) {
|
||||
ElMessage.success('打开成功');
|
||||
connectionState.value = true;
|
||||
} else {
|
||||
if (response.data.code === 60) {
|
||||
connectionState.value = false;
|
||||
}
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//关闭串口
|
||||
const disconnSerialPort = () => {
|
||||
serialportForm.port = serialportForm.port.toLowerCase();
|
||||
axios
|
||||
.get(config.serialPortUrl + '/serial/close', {
|
||||
params: {
|
||||
port: serialportForm.port
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
if (response.data.code === 0) {
|
||||
connectionState.value = false;
|
||||
ElMessage.success('关闭成功');
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
ElMessage.error(error);
|
||||
});
|
||||
};
|
||||
const deviceAttrCommonList = ref({
|
||||
input: {
|
||||
//数据长度类型
|
||||
datalentype: '00',
|
||||
//目标ID
|
||||
remote_id: '0',
|
||||
//本地ID
|
||||
local_id: '0',
|
||||
//指令码
|
||||
cmd: '0100',
|
||||
//设备类型
|
||||
devtype: '00',
|
||||
//数据类型
|
||||
datatype: '00'
|
||||
},
|
||||
output: {
|
||||
//数据长度类型
|
||||
datalentype: '00',
|
||||
//目标ID
|
||||
remote_id: '0',
|
||||
//本地ID
|
||||
local_id: '0',
|
||||
//指令码
|
||||
cmd: '0011',
|
||||
//设备类型
|
||||
devtype: '00',
|
||||
//数据类型
|
||||
datatype: '00'
|
||||
}
|
||||
});
|
||||
|
||||
const deviceAttrList = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '芯片ID',
|
||||
startValue: 0,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'hex',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '设备序列号(SN)',
|
||||
startValue: 4,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '产品主型号',
|
||||
startValue: 12,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '产品次型号',
|
||||
startValue: 16,
|
||||
lengthValue: 4,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '产品密钥',
|
||||
startValue: 20,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '主板序列号',
|
||||
startValue: 28,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '69序列号',
|
||||
startValue: 36,
|
||||
lengthValue: 8,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'str',
|
||||
inputDisable: false
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '通信版本号',
|
||||
startValue: 44,
|
||||
lengthValue: 1,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'firmware',
|
||||
inputDisable: true
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '软件固件号',
|
||||
startValue: 45,
|
||||
lengthValue: 1,
|
||||
inputValue: '',
|
||||
inputLoadingStatus: false,
|
||||
outputValue: '',
|
||||
outputLoadingStatus: false,
|
||||
dataType: 'firmware',
|
||||
inputDisable: true
|
||||
}
|
||||
]);
|
||||
|
||||
//解码
|
||||
const analysisData = (hexData, data) => {
|
||||
if (hexData.length < 28) {
|
||||
console.log('返回hex小于28个字符串', hexData);
|
||||
return '';
|
||||
} else {
|
||||
// let head = hexData.substring(0,8);
|
||||
// let startAddr = hexData.substring(8,16);
|
||||
// let len = hexData.substring(16,24);
|
||||
let hexValue = hexData.substring(24, data.lengthValue * 4 * 2 + 24);
|
||||
// let crc = hexData.substring(hexData.length - 4);
|
||||
if (data.dataType === 'str') {
|
||||
let str = hexToString(hexValue).trim();
|
||||
return str;
|
||||
} else if (data.dataType === 'hex') {
|
||||
let str = rearrangeHexStr(hexValue);
|
||||
return str;
|
||||
}
|
||||
// else if(data.dataType === 'firmware'){
|
||||
// let str = hexToVersion(hexValue);
|
||||
// return str;
|
||||
// }
|
||||
else {
|
||||
return hexValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const sendDeviceAttr = (data, type, index) => {
|
||||
if (!serialportForm.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
console.log('readDeviceAttr', data);
|
||||
|
||||
let head = buildHead(
|
||||
deviceAttrCommonList.value[type].datalentype,
|
||||
deviceAttrCommonList.value[type].remote_id,
|
||||
deviceAttrCommonList.value[type].local_id,
|
||||
deviceAttrCommonList.value[type].cmd,
|
||||
deviceAttrCommonList.value[type].devtype,
|
||||
deviceAttrCommonList.value[type].datatype,
|
||||
data.startValue,
|
||||
data.lengthValue,
|
||||
data.inputValue,
|
||||
data
|
||||
);
|
||||
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = true;
|
||||
// head = head + 'd240';
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = true;
|
||||
}
|
||||
axios
|
||||
.post(
|
||||
config.serialPortUrl + '/serial/response',
|
||||
{
|
||||
port: serialportForm.port,
|
||||
data: head,
|
||||
hex: 1,
|
||||
crc: 1,
|
||||
flush: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log('串口请求', response); // 打印响应数据
|
||||
if (response.data.code === 0) {
|
||||
ElMessage.success('操作成功');
|
||||
if (type === 'output') {
|
||||
deviceAttrList.value[index].outputValue = analysisData(response.data.data.hex || '', data);
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = false;
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('error', error);
|
||||
if (type === 'input') {
|
||||
deviceAttrList.value[index].inputLoadingStatus = false;
|
||||
} else {
|
||||
deviceAttrList.value[index].outputLoadingStatus = false;
|
||||
}
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allReadDeviceAttr = () => {
|
||||
if (!serialportForm.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
|
||||
let head = buildHead(
|
||||
deviceAttrCommonList.value['output'].datalentype,
|
||||
deviceAttrCommonList.value['output'].remote_id,
|
||||
deviceAttrCommonList.value['output'].local_id,
|
||||
deviceAttrCommonList.value['output'].cmd,
|
||||
deviceAttrCommonList.value['output'].devtype,
|
||||
deviceAttrCommonList.value['output'].datatype,
|
||||
0,
|
||||
46,
|
||||
''
|
||||
);
|
||||
|
||||
axios
|
||||
.post(
|
||||
config.serialPortUrl + '/serial/response',
|
||||
{
|
||||
port: serialportForm.port,
|
||||
data: head,
|
||||
hex: 1,
|
||||
crc: 1,
|
||||
flush: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log('串口请求', response); // 打印响应数据
|
||||
if (response.data.code === 0) {
|
||||
if (response.data.data.hex !== '') {
|
||||
ElMessage.success('操作成功');
|
||||
let hexValue = response.data.data.hex.substring(24, 392);
|
||||
let startValue = 0;
|
||||
deviceAttrList.value.forEach((item, index) => {
|
||||
if (startValue === 0) {
|
||||
startValue = item.startValue;
|
||||
}
|
||||
let value = hexValue.substring(startValue, item.lengthValue * 4 * 2 + startValue);
|
||||
startValue = startValue + item.lengthValue * 4 * 2;
|
||||
console.log('value', value);
|
||||
if (item.dataType === 'str') {
|
||||
deviceAttrList.value[index].outputValue = hexToString(value).trim();
|
||||
deviceAttrList.value[index].inputValue = hexToString(value).trim();
|
||||
} else if (item.dataType === 'hex') {
|
||||
deviceAttrList.value[index].outputValue = rearrangeHexStr(value);
|
||||
deviceAttrList.value[index].inputValue = rearrangeHexStr(value);
|
||||
} else {
|
||||
deviceAttrList.value[index].outputValue = value;
|
||||
deviceAttrList.value[index].inputValue = value;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ElMessage.error('获取数据为空');
|
||||
}
|
||||
|
||||
// deviceAttrList.value[index].outputValue = analysisData(response.data.data.hex || '', data);
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('error', error);
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allWriteDeviceAttr = () => {
|
||||
if (!serialportForm.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
deviceAttrList.value.forEach((item, index) => {
|
||||
setTimeout(() => {
|
||||
sendDeviceAttr(item, 'input', index);
|
||||
}, 50);
|
||||
});
|
||||
|
||||
// let head = buildHead(
|
||||
// deviceAttrCommonList.value['input'].datalentype,
|
||||
// deviceAttrCommonList.value['input'].remote_id,
|
||||
// deviceAttrCommonList.value['input'].local_id,
|
||||
// deviceAttrCommonList.value['input'].cmd,
|
||||
// deviceAttrCommonList.value['input'].devtype,
|
||||
// deviceAttrCommonList.value['input'].datatype,
|
||||
// 0,
|
||||
// 46,
|
||||
// ''
|
||||
// );
|
||||
//
|
||||
// axios
|
||||
// .post(
|
||||
// config.serialPortUrl + '/serial/response',
|
||||
// {
|
||||
// port: serialportForm.port,
|
||||
// data: head,
|
||||
// hex: 1,
|
||||
// crc: 1
|
||||
// },
|
||||
// {
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/x-www-form-urlencoded'
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// .then(response => {
|
||||
// // 成功响应后的处理
|
||||
// console.log('串口请求', response); // 打印响应数据
|
||||
// if (response.data.code === 0) {
|
||||
// ElMessage.success('操作成功');
|
||||
// let hexValue = response.data.data.hex.substring(24, 392);
|
||||
// let startValue = 0;
|
||||
// deviceAttrList.value.forEach((item, index) => {
|
||||
// if(startValue === 0){
|
||||
// startValue = item.startValue;
|
||||
// }
|
||||
// let value = hexValue.substring(startValue, item.lengthValue * 4 * 2 + startValue);
|
||||
// startValue = startValue + item.lengthValue * 4 * 2;
|
||||
// console.log("value",value)
|
||||
// if (item.dataType === 'str') {
|
||||
// deviceAttrList.value[index].outputValue = hexToString(value).trim();
|
||||
// deviceAttrList.value[index].inputValue = hexToString(value).trim();
|
||||
// }else{
|
||||
// deviceAttrList.value[index].outputValue = value;
|
||||
// deviceAttrList.value[index].inputValue = value;
|
||||
// }
|
||||
// })
|
||||
// // deviceAttrList.value[index].outputValue = analysisData(response.data.data.hex || '', data);
|
||||
// } else {
|
||||
// ElMessage.error(response.data.message);
|
||||
// }
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.log('error', error);
|
||||
// // 错误处理
|
||||
// if (error.response.data.message) {
|
||||
// ElMessage.error(error.response.data.message);
|
||||
// } else {
|
||||
// ElMessage.error(error);
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
const commonDebuggerFormRef = ref();
|
||||
|
||||
const sendCommonDebuggerState = ref(false);
|
||||
|
||||
const commonDebuggerForm = ref({
|
||||
localId: '',
|
||||
remoteId: '',
|
||||
devType: '00',
|
||||
dataType: '00',
|
||||
cmd: '0011',
|
||||
dataLenType: '00',
|
||||
writeStart: 0,
|
||||
writeLength: 0,
|
||||
writeData: '',
|
||||
dataStr: '',
|
||||
hexStr: ''
|
||||
});
|
||||
|
||||
const devTypeList = ref([
|
||||
{
|
||||
label: '配套通信工具',
|
||||
value: '00'
|
||||
},
|
||||
{
|
||||
label: '网关',
|
||||
value: '01'
|
||||
},
|
||||
{
|
||||
label: '设备',
|
||||
value: '10'
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: '11'
|
||||
}
|
||||
]);
|
||||
|
||||
const dataTypeList = ref([
|
||||
{
|
||||
label: '紧急',
|
||||
value: '00'
|
||||
},
|
||||
{
|
||||
label: '应答',
|
||||
value: '01'
|
||||
},
|
||||
{
|
||||
label: '发送',
|
||||
value: '10'
|
||||
},
|
||||
{
|
||||
label: '广播',
|
||||
value: '11'
|
||||
}
|
||||
]);
|
||||
|
||||
const cmdList = ref([
|
||||
{
|
||||
label: '特殊指令',
|
||||
value: '0000'
|
||||
},
|
||||
{
|
||||
label: '事件指令',
|
||||
value: '0001'
|
||||
},
|
||||
{
|
||||
label: '连接指令',
|
||||
value: '0010'
|
||||
},
|
||||
{
|
||||
label: '地址读指令',
|
||||
value: '0011'
|
||||
},
|
||||
{
|
||||
label: '地址写指令',
|
||||
value: '0100'
|
||||
},
|
||||
{
|
||||
label: '文件读指令',
|
||||
value: '0101'
|
||||
},
|
||||
{
|
||||
label: '文件写指令',
|
||||
value: '0110'
|
||||
},
|
||||
{
|
||||
label: '文件控制指令',
|
||||
value: '0111'
|
||||
},
|
||||
{
|
||||
label: 'OTA升级指令',
|
||||
value: '1000'
|
||||
},
|
||||
{
|
||||
label: '控制台通道',
|
||||
value: '1001'
|
||||
}
|
||||
]);
|
||||
|
||||
const dataLenTypeList = ref([
|
||||
{
|
||||
label: '单帧数据',
|
||||
value: '00'
|
||||
},
|
||||
{
|
||||
label: '多帧数据起始帧',
|
||||
value: '01'
|
||||
},
|
||||
{
|
||||
label: '多帧数据中间帧',
|
||||
value: '10'
|
||||
},
|
||||
{
|
||||
label: '多帧数据结束帧',
|
||||
value: '11'
|
||||
}
|
||||
]);
|
||||
|
||||
const commonDebuggerRules = reactive({
|
||||
devType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
dataType: [{ required: true, message: '请选择数据类型', trigger: 'change' }],
|
||||
cmd: [{ required: true, message: '请选择指令码', trigger: 'change' }],
|
||||
dataLenType: [{ required: true, message: '请选择数据长度类型', trigger: 'change' }],
|
||||
writeStart: [{ required: true, message: '请输入起始地址', trigger: 'blur' }],
|
||||
writeLength: [{ required: true, message: '请输入长度', trigger: 'blur' }]
|
||||
});
|
||||
|
||||
//打开
|
||||
const sendCommonDebugger = formEl => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(valid => {
|
||||
if (valid) {
|
||||
if (!serialportForm.port) {
|
||||
ElMessage.error('请先打开串口');
|
||||
return '';
|
||||
}
|
||||
let head = buildHead(
|
||||
commonDebuggerForm.value.dataLenType,
|
||||
commonDebuggerForm.value.remoteId,
|
||||
commonDebuggerForm.value.localId,
|
||||
commonDebuggerForm.value.cmd,
|
||||
commonDebuggerForm.value.devType,
|
||||
commonDebuggerForm.value.dataType,
|
||||
commonDebuggerForm.value.writeStart,
|
||||
commonDebuggerForm.value.writeLength,
|
||||
commonDebuggerForm.value.writeData,
|
||||
commonDebuggerForm.value
|
||||
);
|
||||
sendCommonDebuggerState.value = true;
|
||||
axios
|
||||
.post(
|
||||
config.serialPortUrl + '/serial/response',
|
||||
{
|
||||
port: serialportForm.port,
|
||||
data: head,
|
||||
hex: 1,
|
||||
crc: 1,
|
||||
flush: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log('串口请求', response); // 打印响应数据
|
||||
sendCommonDebuggerState.value = false;
|
||||
if (response.data.code === 0) {
|
||||
ElMessage.success('请求成功');
|
||||
commonDebuggerForm.value.dataStr = head;
|
||||
commonDebuggerForm.value.hexStr = response.data.data.hex;
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
sendCommonDebuggerState.value = false;
|
||||
console.log('error', error);
|
||||
// 错误处理
|
||||
if (error.response.data.message) {
|
||||
ElMessage.error(error.response.data.message);
|
||||
} else {
|
||||
ElMessage.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 生命周期钩子
|
||||
onMounted(() => {
|
||||
getSerialPortList(false);
|
||||
});
|
||||
|
||||
onUnmounted(() => {});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/* 样式可以在这里定义 */
|
||||
#serialport-box {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
padding-bottom: 5px;
|
||||
.serialport-main {
|
||||
height: calc(100% - 60px);
|
||||
overflow-y: auto;
|
||||
border-radius: 10px;
|
||||
background: #f2f2f2;
|
||||
&.open-log {
|
||||
height: calc(50% - 42px);
|
||||
}
|
||||
}
|
||||
.device-attr-list {
|
||||
padding: 20px 10px;
|
||||
.device-attr-item {
|
||||
display: flex;
|
||||
.device-attr-item-name {
|
||||
width: 120px;
|
||||
}
|
||||
.device-attr-item-value {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 5px;
|
||||
.device-attr-input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-form) {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
|
||||
:deep(.el-tabs--border-card > .el-tabs__content) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.el-collapse-item__header) {
|
||||
//height: 42px;
|
||||
//line-height: 42px;
|
||||
}
|
||||
|
||||
:deep(.el-collapse-item__content) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
background: #e6e6e6;
|
||||
&.is-active {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.log-box-search .el-input__wrapper) {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
:deep(.log-box-search .el-select__wrapper) {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
:deep(.el-form-item__content) {
|
||||
justify-content: end;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,149 +0,0 @@
|
|||
<template>
|
||||
<el-form ref="formRef" :model="form" class="demo-form" :rules="formRules" label-width="auto" status-icon>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备号" prop="deviceSN" required>
|
||||
<el-input v-model="form.deviceSN" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备类型" prop="deviceType" required>
|
||||
<el-select v-model="form.deviceType" placeholder="选择设备类型">
|
||||
<el-option v-for="(item, index) in deviceTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="升级包地址" prop="url" required>
|
||||
<el-input v-model="form.url" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="版本号" prop="codeVer" required>
|
||||
<el-input v-model="form.codeVer" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="包大小(字节)" prop="size" required>
|
||||
<el-input v-model="form.size" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="签名类型" prop="signType" required>
|
||||
<el-select v-model="form.signType" placeholder="选择签名类型">
|
||||
<el-option v-for="(item, index) in signTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="签名" prop="sign" required>
|
||||
<el-input v-model="form.sign" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="包加密类型" prop="scType" required>
|
||||
<el-select v-model="form.scType" placeholder="选择包加密类型">
|
||||
<el-option v-for="(item, index) in scTypeList" :key="index" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备型号" prop="productKey" required>
|
||||
<el-input v-model="form.productKey" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item class="btn-box">
|
||||
<el-button type="primary" @click="updateForm(formRef)">更新</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import axios from 'axios';
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const form = reactive({
|
||||
deviceSN: '',
|
||||
deviceType: 'device',
|
||||
url: '', //升级包路径
|
||||
codeVer: '', //升级包版本号
|
||||
size: '', //1024", //10进制字符串
|
||||
signType: 'md5',
|
||||
sign: '', //升级包md5
|
||||
scType: 'crc32', //包加密类型
|
||||
productKey: '' //设备型号
|
||||
});
|
||||
// const form = reactive({
|
||||
// "deviceSN": "D000000000000001",
|
||||
// "deviceType": "device",
|
||||
// "url": "http://111.bin",
|
||||
// "size": 1024,
|
||||
// "codeVer": "1.1.1.1.1.1.1.1",
|
||||
// "signType": "md5",
|
||||
// "sign": "sa51ear16a1er",
|
||||
// "scType": "crc32",
|
||||
// "productKey": "B7L-NET-G1(4G)"
|
||||
// });
|
||||
|
||||
const deviceTypeList = [
|
||||
{ value: 'device', label: '设备' },
|
||||
{ value: 'gateway', label: '网关' }
|
||||
];
|
||||
const signTypeList = [{ value: 'md5', label: 'md5' }];
|
||||
const scTypeList = [{ value: 'crc32', label: 'crc32' }];
|
||||
|
||||
const formRules = reactive({
|
||||
deviceSN: [{ required: true, message: '设备编号不能为空', trigger: 'blur' }],
|
||||
deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }],
|
||||
url: [{ required: true, message: '升级包路径不能为空', trigger: 'blur' }],
|
||||
codeVer: [{ required: true, message: '升级包版本号不能为空', trigger: 'blur' }],
|
||||
size: [{ required: true, message: '升级包大小不能为空', trigger: 'blur' }],
|
||||
signType: [{ required: true, message: '签名类型不能为空', trigger: 'blur' }],
|
||||
sign: [{ required: true, message: '签名不能为空', trigger: 'blur' }],
|
||||
scType: [{ required: true, message: '包加密类型不能为空', trigger: 'blur' }],
|
||||
productKey: [{ required: true, message: '设备型号不能为空', trigger: 'blur' }]
|
||||
});
|
||||
|
||||
const updateForm = formEl => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(valid => {
|
||||
if (valid) {
|
||||
axios
|
||||
.post(config.url + '/otaUpgrade',form)
|
||||
.then(response => {
|
||||
// 成功响应后的处理
|
||||
console.log(response); // 打印响应数据
|
||||
if (response.data.code == 0) {
|
||||
//缓存上下行主题
|
||||
ElMessage.success('固件更新成功');
|
||||
} else {
|
||||
if (response.data.code == 60) {
|
||||
}
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 错误处理
|
||||
console.error(error); // 打印错误信息
|
||||
ElMessage.error(error);
|
||||
});
|
||||
} else {
|
||||
console.log('error submit!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.btn-box {
|
||||
:deep(.el-form-item__content) {
|
||||
justify-content: end;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,62 +0,0 @@
|
|||
<template>
|
||||
<div id="video-player-box">
|
||||
<easy-player id="EasyPlayer" ref="vVideoPlayerRef" live muted autoplay :has-audio="videoOption.hasAudio" :video-url="videoOption.videoUrl"></easy-player>
|
||||
<div class="operation-box">
|
||||
<div>
|
||||
<el-checkbox v-model="videoOption.hasAudio" label="音频(音频有问题,请设置成false,仅支持flv)" size="large" />
|
||||
</div>
|
||||
<div>
|
||||
<span>视频地址:</span>
|
||||
<el-input v-model="videoOption.videoUrl" style="width: 500px; margin-right: 10px" placeholder="请输入视频地址" />
|
||||
<el-button type="primary" @click="initPlay">初始化</el-button>
|
||||
<el-button v-if="videoOption.status" type="primary" @click="switchVideo">播放</el-button>
|
||||
<el-button v-else @click="switchVideo">暂停</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const videoOption = ref({
|
||||
//视频地址
|
||||
videoUrl: '',
|
||||
//是否静音
|
||||
hasAudio: false,
|
||||
status: true
|
||||
});
|
||||
const vVideoPlayerRef = ref(null);
|
||||
|
||||
const initPlay = () => {
|
||||
let player = vVideoPlayerRef.value.getVueInstance();
|
||||
player.destroyPlayer();
|
||||
player.initPlayer();
|
||||
};
|
||||
|
||||
const switchVideo = () => {
|
||||
let player = vVideoPlayerRef.value.getVueInstance();
|
||||
player.switchVideo();
|
||||
videoOption.value.status = !player.pause;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#video-player-box {
|
||||
height: 100%;
|
||||
//position: relative;
|
||||
//padding-bottom: 5px;
|
||||
}
|
||||
#EasyPlayer {
|
||||
display: inline-block;
|
||||
width: 100% !important;
|
||||
height: 500px !important;
|
||||
margin: 0 auto;
|
||||
}
|
||||
:deep(.easy-player-loading .logo) {
|
||||
display: none;
|
||||
}
|
||||
:deep(.easy-player-right-menu) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -1,13 +0,0 @@
|
|||
<template>
|
||||
<div>测试test</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'test'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue