feat(main): 添加获取应用版本功能并优化日志功能
- 在主进程中添加 get-app-version 的 IPC 处理程序,返回应用版本号 - 在预加载脚本中暴露 getAppVersion 方法给渲染进程 - 在 calibration 页面中添加版本信息显示 - 优化日志显示功能,增加日志转置和分页显示 - 添加清空日志功能 - 调整设备卡片样式,增加选中状态
This commit is contained in:
parent
cd708e9eb9
commit
4d0d6c2ab9
|
@ -8,7 +8,10 @@ directories:
|
|||
# 定义要包含或排除在构建输出中的文件
|
||||
files:
|
||||
- '!**/.vscode/*' # 排除VSCode配置文件
|
||||
- '!**/.cursor/*' # 排除cursor配置文件
|
||||
- '!**/.idea/*' # 排除idea配置文件
|
||||
- '!src/*' # 排除源代码目录
|
||||
- '!**/*.log' # 排除日志文件
|
||||
- '!electron.vite.config.{js,ts,mjs,cjs}' # 排除Electron构建配置文件
|
||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' # 排除开发和文档文件
|
||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml,*.zip,app.log}' # 排除环境和包管理配置文件
|
||||
|
|
|
@ -91,9 +91,9 @@ if (!gotTheLock) {
|
|||
}
|
||||
});
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
//当Electron完成时,将调用此方法
|
||||
//初始化并准备创建浏览器窗口。
|
||||
//某些API只能在此事件发生后使用。
|
||||
const { spawn } = require('child_process');
|
||||
let child = null;
|
||||
let exePluginsExeList = [];
|
||||
|
@ -220,5 +220,10 @@ if (!gotTheLock) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
// In this file you can include the rest of your app"s specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
ipcMain.handle('get-app-version', () => {
|
||||
return app.getVersion();
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { contextBridge, ipcRenderer } from 'electron'
|
||||
import { contextBridge, ipcRenderer } from 'electron'
|
||||
import { electronAPI } from '@electron-toolkit/preload'
|
||||
|
||||
// Custom APIs for renderer
|
||||
|
@ -16,6 +16,10 @@ import { electronAPI } from '@electron-toolkit/preload'
|
|||
// return result;
|
||||
// }
|
||||
// }
|
||||
// // 暴露获取版本号的方法
|
||||
// ipcMain.handle('get-app-version', () => {
|
||||
// return app.getVersion(); // 返回当前应用版本(来自 package.json)
|
||||
// });
|
||||
|
||||
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
// renderer only if context isolation is enabled, otherwise
|
||||
|
@ -23,12 +27,22 @@ import { electronAPI } from '@electron-toolkit/preload'
|
|||
// 使用contextBridge将Electron API和自定义的主进程方法API暴露给渲染进程页面。
|
||||
if (process.contextIsolated) {
|
||||
try {
|
||||
contextBridge.exposeInMainWorld('electron', electronAPI)
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
...electronAPI,
|
||||
getAppVersion: async () => {
|
||||
return await ipcRenderer.invoke('get-app-version');
|
||||
}
|
||||
})
|
||||
// contextBridge.exposeInMainWorld('api', api)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
} else {
|
||||
window.electron = electronAPI
|
||||
window.electron = {
|
||||
...electronAPI,
|
||||
getAppVersion: async () => {
|
||||
return await ipcRenderer.invoke('get-app-version');
|
||||
}
|
||||
}
|
||||
// window.api = api
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<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" @change="schemeChange">
|
||||
<el-select v-model="selectedScheme" placeholder="选择方案" :disabled="playState" style="width: 200px; margin-right: 15px" @change="schemeChange">
|
||||
<el-option v-for="(item, index) in schemeList" :key="index" :label="item.schemeName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-button icon="CaretRight" type="primary" :disabled="playState" @click="startExecution">开始执行</el-button>
|
||||
|
@ -10,10 +10,10 @@
|
|||
</div>
|
||||
<div class="header-right">
|
||||
<el-button icon="RefreshRight" type="primary" :disabled="playState" @click="generateDeviceList">刷新列表</el-button>
|
||||
<el-button icon="Setting" :disabled="playState" @click="openSettings">设置</el-button>
|
||||
<el-button icon="Setting" :disabled="playState" @click="openSettings">配置方案</el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
<div class="scheme-list" v-if="activeScheme && activeScheme.series">
|
||||
<div v-if="activeScheme && activeScheme.series" class="scheme-list list-one">
|
||||
<span class="scheme-item"
|
||||
>系列: <span class="scheme-value">{{ activeScheme.series }}</span></span
|
||||
>
|
||||
|
@ -21,8 +21,13 @@
|
|||
>框架: <span class="scheme-value">{{ activeScheme.framework }}</span></span
|
||||
>
|
||||
<span class="scheme-item"
|
||||
>类型: <span class="scheme-value">{{ activeScheme.schemeType }}</span></span
|
||||
>P位: <span class="scheme-value">{{ activeScheme.schemeType }}</span></span
|
||||
>
|
||||
<span class="scheme-item"
|
||||
>额定电流(A): <span class="scheme-value">{{ activeScheme.configParam.format[2].value }}</span></span
|
||||
>
|
||||
</div>
|
||||
<div v-if="activeScheme && activeScheme.series" class="scheme-list list-two">
|
||||
<span v-for="(item, index) in activeScheme.configParam.format" :key="index" class="scheme-item"
|
||||
>{{ item.unit ? item.name + '(' + item.unit + ')' : item.name }}: <span class="scheme-value">{{ item.value }}</span></span
|
||||
>
|
||||
|
@ -30,25 +35,25 @@
|
|||
|
||||
<el-main class="calibration-main">
|
||||
<div class="device-grid">
|
||||
<el-card v-for="(device, index) in devices" :key="device.id" class="device-card">
|
||||
<el-card v-for="(device, index) in devices" :key="device.id" class="device-card" :class="activeDeviceIndex === index ? 'active' : ''" @click="selectDevice(device, index)">
|
||||
<template #header>
|
||||
<div class="device-card-header">
|
||||
<!-- <span>{{ device.code }}</span>-->
|
||||
<span>设备{{ device.id }}</span>
|
||||
<el-tag :type="device.status === 1 ? 'success' : 'info'" size="small">
|
||||
{{ device.status === 1 ? '已连接' : '未连接' }}
|
||||
<el-tag :type="device.connectStatus === 1 ? 'success' : 'info'" size="small">
|
||||
{{ device.connectStatus === 1 ? '已连接' : '未连接' }}
|
||||
</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.deviceSN || '无' }}</p>
|
||||
<p>芯片ID: {{ device.deviceSN || '无' }}</p>
|
||||
<p>设备端口: {{ device.devicePort || '无' }}</p>
|
||||
<p>
|
||||
标定结果: <span :class="['device-result', device.result === '成功' ? 'color-green' : device.result === '失败' ? 'color-red' : '']">{{ device.result || '无' }}</span>
|
||||
</p>
|
||||
<p>
|
||||
失败描述:
|
||||
结果描述:
|
||||
<span
|
||||
><el-tooltip class="box-item" effect="dark" :content="device.resultTxt" placement="top-start">
|
||||
{{ device.resultTxt || '无' }}
|
||||
|
@ -104,6 +109,11 @@
|
|||
<span class="iconfont icon-icon_suoding"></span>
|
||||
</el-tooltip>
|
||||
</view>
|
||||
<view class="log-box-operate-item" @click="clearLog">
|
||||
<el-tooltip class="box-item" content="清空日志" effect="dark" placement="bottom">
|
||||
<span class="iconfont icon-icon_shanchu"></span>
|
||||
</el-tooltip>
|
||||
</view>
|
||||
<view class="log-box-operate-item" @click="toggleOpenLog">
|
||||
<el-tooltip v-if="isOpenLog" class="box-item" content="收缩日志" effect="dark" placement="bottom">
|
||||
<span class="iconfont icon-up-arrow"></span>
|
||||
|
@ -113,153 +123,192 @@
|
|||
</el-tooltip>
|
||||
</view>
|
||||
</div>
|
||||
<div class="version-info">{{ version }}</div>
|
||||
<div class="version-info">V{{ version }}</div>
|
||||
</div>
|
||||
</el-footer>
|
||||
|
||||
<!-- 方案配置抽屉 -->
|
||||
<el-drawer v-model="schemeDrawerVisible" title="方案配置" size="80%" :destroy-on-close="true">
|
||||
<div class="scheme-drawer-content">
|
||||
<div class="scheme-list">
|
||||
<div class="scheme-list-header">
|
||||
<el-button type="primary" @click="addScheme">新增方案</el-button>
|
||||
<el-button type="primary" @click="loadSchemes">刷新</el-button>
|
||||
<div class="scheme-list-header">
|
||||
<el-button type="primary" @click="addScheme">新增方案</el-button>
|
||||
<el-button type="primary" @click="loadSchemes">刷新</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="schemeList" style="width: 100%">
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="schemeName" label="方案名称" />
|
||||
<el-table-column prop="schemeType" label="断路器类型"></el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="viewScheme(scope.row)">修改</el-button>
|
||||
<el-button type="danger" link @click="deleteScheme(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 方案详情对话框 -->
|
||||
<el-dialog v-model="schemeDetailVisible" :title="currentScheme.schemeName" width="95%" :destroy-on-close="true" align-center :close-on-click-modal="false">
|
||||
<el-form :model="currentScheme" label-width="120px">
|
||||
<el-form-item label="方案名称">
|
||||
<el-input v-model="currentScheme.schemeName" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="系列">
|
||||
<el-select v-model="currentScheme.series" placeholder="请选择系列">
|
||||
<el-option label="B7" value="B7" />
|
||||
<el-option label="B7L" value="B7L" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="框架">
|
||||
<el-select v-model="currentScheme.framework" placeholder="请选择框架">
|
||||
<el-option label="100ZS" value="100ZS" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="断路器类型">
|
||||
<el-select v-model="currentScheme.schemeType" placeholder="请选择断路器类型">
|
||||
<el-option label="1p" value="1p" />
|
||||
<el-option label="2p" value="2p" />
|
||||
<el-option label="3p" value="3p" />
|
||||
<el-option label="4p" value="4p" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider>断路器校准参数</el-divider>
|
||||
<div class="calibrate-params">
|
||||
<el-form-item v-for="(item, index) in defaultConfList.format" :key="item.key" :label="item.unit ? item.name + '(' + item.unit + ')' : item.name" :label-width="140">
|
||||
<el-input v-model="currentScheme.configParam.format[index].value"> </el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- <el-divider>断路器类型参数</el-divider>
|
||||
<div class="device-params">
|
||||
<div v-for="item in currentScheme.propertyParam" :key="item.id" class="device-param-item">
|
||||
<span class="param-label">{{ item.unit ? item.name + '(' + item.unit + ')' : item.name }}</span>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<el-divider>校准精度(%)</el-divider>
|
||||
<div class="accuracy-params">
|
||||
<el-form-item v-for="(value, key) in currentScheme.errorRange" :key="key" label-width="80px" :label="accuracyType[key]">
|
||||
<el-input-number v-model="currentScheme.errorRange[key]" :min="0" :max="100" :precision="2" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-divider>标定步骤</el-divider>
|
||||
<div class="calibration-steps">
|
||||
<div class="steps-header">
|
||||
<el-button type="primary" @click="addCalibrationStep">添加步骤</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="schemeList" style="width: 100%">
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="schemeName" label="方案名称" />
|
||||
<el-table-column prop="schemeType" label="断路器类型"></el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<el-table :data="currentScheme.steps" style="width: 100%">
|
||||
<!-- <el-table-column type="index" width="50" />-->
|
||||
<el-table-column prop="id" align="center" label="排序" width="80" />
|
||||
<!-- <el-table-column prop="id" align="center" label="步骤值">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-input-number v-model="scope.row.id" :min="0" />-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="step" align="center" label="步骤值">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="viewScheme(scope.row)">修改</el-button>
|
||||
<el-button type="danger" link @click="deleteScheme(scope.row)">删除</el-button>
|
||||
<el-input-number v-model="scope.row.step" :min="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="voltage" align="center" label="电压Un(%)">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.voltage" :min="0" :precision="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="current" align="center" label="电流Ib(%)">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.current" :min="0" :precision="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="powerFactor" align="center" label="功率因数">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.powerFactor">
|
||||
<el-option label="0.5L" value="0.5L" />
|
||||
<el-option label="0.8L" value="0.8L" />
|
||||
<el-option label="1" value="1" />
|
||||
<el-option label="0.5C" value="0.5C" />
|
||||
<el-option label="0.8C" value="0.8C" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isILeak" align="center" label="检测漏电" width="120">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.isILeak" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link @click="deleteCalibrationStep(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="schemeDetailVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveScheme">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 方案详情对话框 -->
|
||||
<el-dialog v-model="schemeDetailVisible" :title="currentScheme.schemeName" width="95%" :destroy-on-close="true" align-center :close-on-click-modal="false">
|
||||
<el-form :model="currentScheme" label-width="120px">
|
||||
<el-form-item label="方案名称">
|
||||
<el-input v-model="currentScheme.schemeName" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="系列">
|
||||
<el-select v-model="currentScheme.series" placeholder="请选择系列">
|
||||
<el-option label="B7" value="B7" />
|
||||
<el-option label="B7L" value="B7L" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="框架">
|
||||
<el-select v-model="currentScheme.framework" placeholder="请选择框架">
|
||||
<el-option label="100ZS" value="100ZS" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="断路器类型">
|
||||
<el-select v-model="currentScheme.schemeType" placeholder="请选择断路器类型">
|
||||
<el-option label="1p" value="1p" />
|
||||
<el-option label="2p" value="2p" />
|
||||
<el-option label="3p" value="3p" />
|
||||
<el-option label="4p" value="4p" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 方案配置抽屉 -->
|
||||
<el-drawer v-model="logVisible" title="设备日志" size="80%" :destroy-on-close="true">
|
||||
<div class="scheme-drawer-content log-content">
|
||||
<div class="device-info">
|
||||
<div class="device-info-item">设备: {{ activeDeviceInfo.id || '-' }}</div>
|
||||
<div class="device-info-item">芯片ID: {{ activeDeviceInfo.deviceSN || '-' }}</div>
|
||||
<div class="device-info-item">设备端口: {{ activeDeviceInfo.devicePort || '-' }}</div>
|
||||
<div class="device-info-item">标定结果: {{ activeDeviceInfo.result || '-' }}</div>
|
||||
<div class="device-info-item">结果描述: {{ activeDeviceInfo.resultTxt || '-' }}</div>
|
||||
</div>
|
||||
<el-tabs v-model="logTabActive" class="demo-tabs" @tab-click="logTabChange">
|
||||
<el-tab-pane label="标定日志" name="log">
|
||||
<el-table :data="transposedLogList" style="width: 100%" size="small" scrollbar-always-on resizable empty-text="暂无日志">
|
||||
<el-table-column prop="name" label="参数" fixed align="center" />
|
||||
<el-table-column v-for="(item, index) in logList" :key="index" :label="item.name" align="center">
|
||||
<el-table-column prop="name" label="结果" align="center" min-width="80">
|
||||
<template #default="scope">
|
||||
<span :style="{ color: scope.row.data[index].result != 1 ? 'red' : 'green' }">{{ scope.row.data[index].value || '-' }}</span>
|
||||
<el-icon v-if="scope.row.data[index].result === 2" style="color: red"><Top /></el-icon>
|
||||
<el-icon v-if="scope.row.data[index].result === 0" style="color: red"><Bottom /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="范围" align="errLog">
|
||||
<template #default="scope">
|
||||
<span style="margin-left: 8px; color: #888; font-size: 12px">{{
|
||||
scope.row.data[index].minValue && scope.row.data[index].maxValue ? scope.row.data[index].minValue + ' ~ ' + scope.row.data[index].maxValue : '-'
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="错误日志" name="second">
|
||||
错误日志
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-divider>断路器校准参数</el-divider>
|
||||
<div class="calibrate-params">
|
||||
<el-form-item v-for="(item, index) in defaultConfList.format" :key="item.key" :label="item.unit ? item.name + '(' + item.unit + ')' : item.name" :label-width="140">
|
||||
<el-input v-model="currentScheme.configParam.format[index].value"> </el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- <el-divider>断路器类型参数</el-divider>
|
||||
<div class="device-params">
|
||||
<div v-for="item in currentScheme.propertyParam" :key="item.id" class="device-param-item">
|
||||
<span class="param-label">{{ item.unit ? item.name + '(' + item.unit + ')' : item.name }}</span>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<el-divider>校准精度(%)</el-divider>
|
||||
<div class="accuracy-params">
|
||||
<el-form-item v-for="(value, key) in currentScheme.errorRange" :key="key" label-width="80px" :label="accuracyType[key]">
|
||||
<el-input-number v-model="currentScheme.errorRange[key]" :min="0" :max="100" :precision="2" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-divider>标定步骤</el-divider>
|
||||
<div class="calibration-steps">
|
||||
<div class="steps-header">
|
||||
<el-button type="primary" @click="addCalibrationStep">添加步骤</el-button>
|
||||
</div>
|
||||
<el-table :data="currentScheme.steps" style="width: 100%">
|
||||
<!-- <el-table-column type="index" width="50" />-->
|
||||
<el-table-column prop="id" align="center" label="排序" width="80" />
|
||||
<!-- <el-table-column prop="id" align="center" label="步骤值">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-input-number v-model="scope.row.id" :min="0" />-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="step" align="center" label="步骤值">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.step" :min="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="voltage" align="center" label="电压Un(%)">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.voltage" :min="0" :precision="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="current" align="center" label="电流Ib(%)">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.current" :min="0" :precision="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="powerFactor" align="center" label="功率因数">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.powerFactor">
|
||||
<el-option label="0.5L" value="0.5L" />
|
||||
<el-option label="0.8L" value="0.8L" />
|
||||
<el-option label="1" value="1" />
|
||||
<el-option label="0.5C" value="0.5C" />
|
||||
<el-option label="0.8C" value="0.8C" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isILeak" align="center" label="检测漏电" width="120">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.isILeak" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link @click="deleteCalibrationStep(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="schemeDetailVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveScheme">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, onUnmounted } from 'vue';
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { throttle } from 'lodash-es';
|
||||
import dayjs from 'dayjs';
|
||||
import axios from 'axios';
|
||||
import config from '@renderer/util/config.js';
|
||||
|
@ -273,6 +322,7 @@ const devices = ref([]);
|
|||
const isScroll = ref(true);
|
||||
const logs = ref([]);
|
||||
const version = ref('V1.0.0');
|
||||
const logTabActive = ref('log')
|
||||
|
||||
const loading = ref(true);
|
||||
const isOpenLog = ref(false);
|
||||
|
@ -307,6 +357,236 @@ const defaultConfList = ref({
|
|||
format: []
|
||||
});
|
||||
|
||||
const logVisible = ref(false);
|
||||
|
||||
const logList = ref([
|
||||
{
|
||||
name: '标定1',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 0,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 5,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 0,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 1,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 2,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '标定1重复1',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 10,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 0,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '标定2',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 10,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 0,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '标定3',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 10,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 0,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '标定4',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 10,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 0,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '标定5',
|
||||
dataList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '电压',
|
||||
value: 220,
|
||||
unit: 'V',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '210',
|
||||
maxValue: '230'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '电流',
|
||||
value: 10,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '7.5',
|
||||
maxValue: '12.5'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '漏电流',
|
||||
value: 0,
|
||||
unit: 'A',
|
||||
accuracy: 1,
|
||||
result: 1,
|
||||
minValue: '0',
|
||||
maxValue: '0'
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
const logBoxRef = ref(null);
|
||||
const MAX_LOG_LENGTH = 800;
|
||||
|
||||
const activeDeviceIndex = ref(0);
|
||||
|
||||
const activeDeviceInfo = ref({
|
||||
id: 0,
|
||||
devicePort: '',
|
||||
deviceSN: '',
|
||||
connectStatus: 0,
|
||||
switch: 0,
|
||||
result: 0,
|
||||
resultTxt: ''
|
||||
});
|
||||
|
||||
const defaultPropList = ref([]);
|
||||
|
||||
const currentScheme = ref({
|
||||
|
@ -328,16 +608,29 @@ const currentScheme = ref({
|
|||
steps: []
|
||||
});
|
||||
|
||||
const logTabChange = (tab, event) => {
|
||||
console.log(tab, event)
|
||||
}
|
||||
|
||||
const selectDevice = (item, index) => {
|
||||
activeDeviceInfo.value = item;
|
||||
activeDeviceIndex.value = index;
|
||||
// 添加日志到日志列表
|
||||
// logList.value = [];
|
||||
logVisible.value = true;
|
||||
};
|
||||
|
||||
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
|
||||
deviceSN: Math.floor(1000000000000 + Math.random() * 9000000000000).toString(),
|
||||
devicePort: `192.168.1.${i}`,
|
||||
connectStatus: i % 3 === 0 ? 1 : 0,
|
||||
result: i % 3 !== 0 ? (i % 2 === 0 ? '' : '成功') : '失败',
|
||||
resultTxt: i % 3 !== 0 ? (i % 2 === 0 ? '' : '成功') : '失败'
|
||||
});
|
||||
}
|
||||
devices.value = mockDevices;
|
||||
|
@ -419,33 +712,58 @@ const generateLogs = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// 安全解析 JSON
|
||||
const tryParseJSON = data => {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
// 节流滚动
|
||||
const throttledScroll = throttle(() => {
|
||||
logBoxRef.value.scrollTop = logBoxRef.value.scrollHeight;
|
||||
}, 100);
|
||||
|
||||
const getSocketMeassage = message => {
|
||||
let msg = JSON.parse(message.data);
|
||||
if (msg.msgType !== undefined) {
|
||||
if (logs.value.length > 400) {
|
||||
logs.value.shift();
|
||||
}
|
||||
logs.value.push({
|
||||
time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
msg: msg.data,
|
||||
type: msg.msgType
|
||||
});
|
||||
} else {
|
||||
if (logs.value.length > 400) {
|
||||
logs.value.shift();
|
||||
}
|
||||
logs.value.push({
|
||||
time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
msg,
|
||||
type: null
|
||||
});
|
||||
}
|
||||
if (isScroll.value) {
|
||||
setTimeout(() => {
|
||||
let div = document.querySelector('#log-box-main');
|
||||
div.scrollTop = div.scrollHeight;
|
||||
}, 200);
|
||||
}
|
||||
const msg = tryParseJSON(message.data);
|
||||
const newLog = {
|
||||
time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
msg: msg.data ?? msg,
|
||||
type: msg.msgType ?? null
|
||||
};
|
||||
|
||||
// 批量更新日志数组
|
||||
logs.value = [...logs.value.slice(-MAX_LOG_LENGTH + 1), newLog];
|
||||
|
||||
// 按需触发滚动
|
||||
if (isScroll.value) throttledScroll();
|
||||
|
||||
// let msg = JSON.parse(message.data);
|
||||
// if (msg.msgType !== undefined) {
|
||||
// if (logs.value.length > 400) {
|
||||
// logs.value.shift();
|
||||
// }
|
||||
// logs.value.push({
|
||||
// time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
// msg: msg.data,
|
||||
// type: msg.msgType
|
||||
// });
|
||||
// } else {
|
||||
// if (logs.value.length > 400) {
|
||||
// logs.value.shift();
|
||||
// }
|
||||
// logs.value.push({
|
||||
// time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
// msg,
|
||||
// type: null
|
||||
// });
|
||||
// }
|
||||
// if (isScroll.value) {
|
||||
// requestAnimationFrame(() => {
|
||||
// logBoxRef.value.scrollTop = logBoxRef.value.scrollHeight;
|
||||
// });
|
||||
// }
|
||||
};
|
||||
|
||||
const initSocket = () => {
|
||||
|
@ -458,7 +776,14 @@ const socketStatus = computed(() => {
|
|||
});
|
||||
|
||||
onMounted(() => {
|
||||
logBoxRef.value = document.querySelector('#log-box-main');
|
||||
initSocket();
|
||||
if (window.electron && typeof window.electron.getAppVersion === 'function') {
|
||||
window.electron.getAppVersion().then(v => {
|
||||
version.value = v;
|
||||
});
|
||||
}
|
||||
// generateMockDevices();
|
||||
getSchemeDefaultConf();
|
||||
getSchemeDefaultProp();
|
||||
generateDeviceList();
|
||||
|
@ -675,6 +1000,10 @@ const toggleOpenLog = () => {
|
|||
isOpenLog.value = !isOpenLog.value;
|
||||
};
|
||||
|
||||
const clearLog = () => {
|
||||
logs.value = [];
|
||||
};
|
||||
|
||||
// 删除标定步骤
|
||||
const deleteCalibrationStep = index => {
|
||||
currentScheme.value.steps.splice(index, 1);
|
||||
|
@ -683,6 +1012,22 @@ const deleteCalibrationStep = index => {
|
|||
step.id = idx + 1;
|
||||
});
|
||||
};
|
||||
|
||||
// 设备日志转置,便于表格渲染
|
||||
const transposedLogList = computed(() => {
|
||||
if (!logList.value.length) return [];
|
||||
// 假设每个dataList参数顺序一致
|
||||
const paramCount = logList.value[0].dataList.length;
|
||||
const result = [];
|
||||
for (let i = 0; i < paramCount; i++) {
|
||||
const param = {
|
||||
name: logList.value[0].dataList[i].name + (logList.value[0].dataList[i].unit ? '(' + logList.value[0].dataList[i].unit + ')' : ''),
|
||||
data: logList.value.map(log => log.dataList[i])
|
||||
};
|
||||
result.push(param);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -709,7 +1054,9 @@ const deleteCalibrationStep = index => {
|
|||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
&.list-two {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.scheme-item {
|
||||
margin-left: 10px;
|
||||
&:first-child {
|
||||
|
@ -719,6 +1066,12 @@ const deleteCalibrationStep = index => {
|
|||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
&.list-one {
|
||||
padding-bottom: 0;
|
||||
.scheme-item {
|
||||
margin-right: 55px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-left,
|
||||
|
@ -745,7 +1098,12 @@ const deleteCalibrationStep = index => {
|
|||
}
|
||||
|
||||
.device-card {
|
||||
cursor: pointer;
|
||||
/* background-color: #ffffff; */ /* Default card color is fine */
|
||||
border: 1px solid #e6e6e6;
|
||||
&.active {
|
||||
border: 1px solid #67c23a;
|
||||
}
|
||||
}
|
||||
|
||||
.device-card-header {
|
||||
|
@ -770,11 +1128,13 @@ const deleteCalibrationStep = index => {
|
|||
}
|
||||
|
||||
.color-green {
|
||||
color: #67c23a; /* Green for connected */
|
||||
color: #67c23a;
|
||||
/* Green for connected */
|
||||
}
|
||||
|
||||
.color-red {
|
||||
color: #f56c6c; /* Red for disconnected */
|
||||
color: #f56c6c;
|
||||
/* Red for disconnected */
|
||||
}
|
||||
|
||||
.calibration-footer {
|
||||
|
@ -785,6 +1145,7 @@ const deleteCalibrationStep = index => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.open-log {
|
||||
height: 350px;
|
||||
}
|
||||
|
@ -795,7 +1156,8 @@ const deleteCalibrationStep = index => {
|
|||
overflow-y: auto;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap; /* Ensures logs wrap and preserve formatting */
|
||||
white-space: pre-wrap;
|
||||
/* Ensures logs wrap and preserve formatting */
|
||||
border: 1px solid #555;
|
||||
padding: 5px;
|
||||
background-color: #202020;
|
||||
|
@ -805,6 +1167,7 @@ const deleteCalibrationStep = index => {
|
|||
margin: 2px 0;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.log-box-main {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
padding: 5px;
|
||||
|
@ -816,6 +1179,7 @@ const deleteCalibrationStep = index => {
|
|||
background-color: #202020;
|
||||
color: #dcdcdc;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
.log-item {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
|
@ -824,6 +1188,7 @@ const deleteCalibrationStep = index => {
|
|||
line-height: 18px;
|
||||
font-weight: 500;
|
||||
margin-left: 8px;
|
||||
|
||||
.iconfont {
|
||||
&.icon-icon_fuzhi {
|
||||
line-height: 26px;
|
||||
|
@ -835,26 +1200,31 @@ const deleteCalibrationStep = index => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.calibration-footer-btn {
|
||||
font-size: 12px;
|
||||
padding-top: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.log-box-operate-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
.icon-icon_gengxin {
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.version-info {
|
||||
text-align: right;
|
||||
color: #888;
|
||||
|
@ -862,34 +1232,34 @@ const deleteCalibrationStep = index => {
|
|||
|
||||
/* 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-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-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-main-padding: 20px;
|
||||
/* Adjust if necessary */
|
||||
}
|
||||
|
||||
.el-select .el-input__inner {
|
||||
background-color: #555; /* Darker input fields */
|
||||
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(.log-content .el-table .cell) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.device-grid .el-card__header) {
|
||||
padding: 10px 5px;
|
||||
|
@ -903,6 +1273,17 @@ const deleteCalibrationStep = index => {
|
|||
|
||||
.scheme-drawer-content {
|
||||
padding: 20px;
|
||||
.device-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background: #ddd;
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
align-items: center;
|
||||
.device-info-item {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scheme-list-header {
|
||||
|
|
Loading…
Reference in New Issue