feat(renderer): 优化日志功能和界面布局
- 更新 iconfont 文件,添加新的图标 - 重构日志显示逻辑,支持不同类型的消息 - 添加方案详情展示区域 - 优化方案编辑界面布局 - 实现日志滚动和展开/收缩功能 - 添加版本号动态显示 - 优化 WebSocket 连接管理
This commit is contained in:
parent
2764645590
commit
82a578fc5c
|
@ -2,8 +2,12 @@ import { resolve } from 'path'
|
|||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import VueDevTools from 'vite-plugin-vue-devtools';
|
||||
import pkg from './package.json'
|
||||
|
||||
export default defineConfig({
|
||||
define: {
|
||||
'import.meta.env.VITE_APP_VERSION': JSON.stringify(pkg.version)
|
||||
},
|
||||
main: {
|
||||
plugins: [externalizeDepsPlugin()]
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "calibration-pc",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.9",
|
||||
"description": "谷云开发部开发的断路器标定软件",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "example.com",
|
||||
|
@ -21,12 +21,10 @@
|
|||
"@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",
|
||||
"file-saver": "^2.0.5",
|
||||
"gateway-app": "file:",
|
||||
"pinia": "^2.1.7",
|
||||
"vue-router": "^4.4.0",
|
||||
"xlsx": "^0.18.5"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4622943 */
|
||||
src: url('iconfont.woff2?t=1743060096253') format('woff2'),
|
||||
url('iconfont.woff?t=1743060096253') format('woff'),
|
||||
url('iconfont.ttf?t=1743060096253') format('truetype');
|
||||
src: url('iconfont.woff2?t=1750322442953') format('woff2'),
|
||||
url('iconfont.woff?t=1750322442953') format('woff'),
|
||||
url('iconfont.ttf?t=1750322442953') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
|
@ -13,6 +13,46 @@
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-rizhi:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
|
||||
.icon-bug:before {
|
||||
content: "\e725";
|
||||
}
|
||||
|
||||
.icon-caozuorizhi:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.icon-rizhishenji:before {
|
||||
content: "\e666";
|
||||
}
|
||||
|
||||
.icon-chenggong:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
.icon-rizhi1:before {
|
||||
content: "\e613";
|
||||
}
|
||||
|
||||
.icon-chenggong1:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.icon-bug-fill:before {
|
||||
content: "\e773";
|
||||
}
|
||||
|
||||
.icon-bug-line:before {
|
||||
content: "\e774";
|
||||
}
|
||||
|
||||
.icon-kongtiaoguizhuduanluqiAA:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.icon--_saomaqiang:before {
|
||||
content: "\e640";
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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">
|
||||
<el-select v-model="selectedScheme" placeholder="选择方案" 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>
|
||||
|
@ -13,6 +13,20 @@
|
|||
<el-button icon="Setting" :disabled="playState" @click="openSettings">设置</el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
<div class="scheme-list" v-if="activeScheme && activeScheme.series">
|
||||
<span class="scheme-item"
|
||||
>系列: <span class="scheme-value">{{ activeScheme.series }}</span></span
|
||||
>
|
||||
<span class="scheme-item"
|
||||
>框架: <span class="scheme-value">{{ activeScheme.framework }}</span></span
|
||||
>
|
||||
<span class="scheme-item"
|
||||
>类型: <span class="scheme-value">{{ activeScheme.schemeType }}</span></span
|
||||
>
|
||||
<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
|
||||
>
|
||||
</div>
|
||||
|
||||
<el-main class="calibration-main">
|
||||
<div class="device-grid">
|
||||
|
@ -46,16 +60,42 @@
|
|||
</div>
|
||||
</el-main>
|
||||
|
||||
<el-footer class="calibration-footer">
|
||||
<el-footer class="calibration-footer" :class="isOpenLog ? 'open-log' : ''">
|
||||
<div id="log-box-main" class="log-box-main">
|
||||
<div class="log-list">
|
||||
<div v-for="(item, index) in logs" :key="index" class="log-item">
|
||||
{{ item }}
|
||||
<el-tooltip v-if="item.type == 'subscribe'" effect="light" content="订阅" placement="top">
|
||||
<span class="iconfont icon-icon_shanghang" style="color: #00a73c"></span>
|
||||
</el-tooltip>
|
||||
<el-tooltip v-else-if="item.type == 'calibrate_error'" effect="light" content="错误信息" placement="top">
|
||||
<span class="iconfont icon-bug-fill" style="color: #ff3b2b"></span>
|
||||
</el-tooltip>
|
||||
<!-- <el-tooltip-->
|
||||
<!-- effect="light"-->
|
||||
<!-- content="消息"-->
|
||||
<!-- placement="top"-->
|
||||
<!-- v-else-if="item.type == 'calibrate_info'"-->
|
||||
<!-- >-->
|
||||
<!-- <span class="iconfont icon-rizhi1" style="color: #0066cc"></span>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<el-tooltip v-else effect="light" content="系统" placement="top">
|
||||
<span class="iconfont icon-rizhi1"></span>
|
||||
</el-tooltip>
|
||||
{{ item.time }} {{ item.msg }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calibration-footer-btn">
|
||||
<div class="btn-box">
|
||||
<view class="log-box-operate-item">
|
||||
<div>日志状态:</div>
|
||||
<div v-if="socketStatus" style="color: #00a73c; display: flex; align-items: center">连接</div>
|
||||
<div v-else style="color: #ff3b2b; display: flex; align-items: center" @click="initSocket">
|
||||
<el-tooltip class="box-item" content="重新连接" effect="dark" placement="bottom">
|
||||
<div style="display: flex; align-items: center">断连<span class="iconfont icon-icon_gengxin"></span></div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</view>
|
||||
<view class="log-box-operate-item" @click="toggleIsScroll">
|
||||
<el-tooltip v-if="isScroll" class="box-item" content="关闭滚动" effect="dark" placement="bottom">
|
||||
<span class="iconfont icon-unlock"></span>
|
||||
|
@ -64,6 +104,14 @@
|
|||
<span class="iconfont icon-icon_suoding"></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>
|
||||
</el-tooltip>
|
||||
<el-tooltip v-else class="box-item" content="展开日志" effect="dark" placement="bottom">
|
||||
<span class="iconfont icon-shousuoshangjiantou"></span>
|
||||
</el-tooltip>
|
||||
</view>
|
||||
</div>
|
||||
<div class="version-info">{{ version }}</div>
|
||||
</div>
|
||||
|
@ -96,14 +144,33 @@
|
|||
<el-form-item label="方案名称">
|
||||
<el-input v-model="currentScheme.schemeName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="断路器类型">
|
||||
<el-select v-model="currentScheme.schemeType">
|
||||
<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-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">
|
||||
|
@ -121,7 +188,7 @@
|
|||
|
||||
<el-divider>校准精度(%)</el-divider>
|
||||
<div class="accuracy-params">
|
||||
<el-form-item label-width="80px" v-for="(value, key) in currentScheme.errorRange" :key="key" :label="accuracyType[key]">
|
||||
<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>
|
||||
|
@ -132,21 +199,26 @@
|
|||
<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="step" label="步骤" width="80" /> -->
|
||||
<el-table-column prop="step" align="center" label="步骤">
|
||||
<!-- <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="0" />
|
||||
<el-input-number v-model="scope.row.step" :min="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="voltage" align="center" label="电压(V)">
|
||||
<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="电流(A)">
|
||||
<el-table-column prop="current" align="center" label="电流Ib(%)">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.current" :min="0" :precision="3" />
|
||||
<el-input-number v-model="scope.row.current" :min="0" :precision="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="powerFactor" align="center" label="功率因数">
|
||||
|
@ -160,11 +232,11 @@
|
|||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="riseFirst" align="center" label="先升后标" width="120">
|
||||
<el-table-column prop="isILeak" align="center" label="检测漏电" width="120">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.riseFirst" />
|
||||
<el-switch v-model="scope.row.isILeak" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link @click="deleteCalibrationStep(scope.$index)">删除</el-button>
|
||||
|
@ -186,24 +258,33 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, computed, onUnmounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import dayjs from 'dayjs';
|
||||
import axios from 'axios';
|
||||
import config from '@renderer/util/config.js';
|
||||
|
||||
import { logWebSocketStore } from '@renderer/stores/logWebSocket.js';
|
||||
const webSocketStore = logWebSocketStore();
|
||||
|
||||
const selectedScheme = ref('');
|
||||
const playState = ref(false);
|
||||
const devices = ref([]);
|
||||
const isScroll = ref(true);
|
||||
const logs = ref(['14:44:10.482 添加条码 GE 2', '14:44:10.487 连接失败 127.0.0.1:8821 0000 未将对象引用设置到对象的实例。']);
|
||||
const logs = ref([]);
|
||||
const version = ref('V1.0.0');
|
||||
// 直接使用环境变量
|
||||
// const versionTxt = import.meta.env.VITE_APP_VERSION || 'dev';
|
||||
// version.value = versionTxt;
|
||||
|
||||
const loading = ref(true);
|
||||
const isOpenLog = ref(false);
|
||||
|
||||
// 方案配置相关
|
||||
const schemeDrawerVisible = ref(false);
|
||||
const schemeDetailVisible = ref(false);
|
||||
const schemeList = ref([]);
|
||||
const activeScheme = ref();
|
||||
|
||||
const accuracyType = ref({
|
||||
voltage: '电压',
|
||||
|
@ -234,6 +315,8 @@ const defaultPropList = ref([]);
|
|||
const currentScheme = ref({
|
||||
schemeName: '',
|
||||
schemeType: '1p',
|
||||
series: 'B7',
|
||||
framework: '100ZS',
|
||||
configParam: defaultConfList,
|
||||
propertyParam: defaultPropList,
|
||||
errorRange: {
|
||||
|
@ -265,7 +348,7 @@ const generateMockDevices = () => {
|
|||
|
||||
const playCalibration = async () => {
|
||||
try {
|
||||
const response = await axios.get(config.url + '/master/scheme/start?schemeId='+ selectedScheme.value);
|
||||
const response = await axios.get(config.url + '/master/scheme/start?schemeId=' + selectedScheme.value);
|
||||
if (response.data.code === 0) {
|
||||
devices.value = response.data.data.result || [];
|
||||
} else {
|
||||
|
@ -291,6 +374,15 @@ const generateDeviceList = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const schemeChange = e => {
|
||||
if (e) {
|
||||
const scheme = schemeList.value.filter(item => item.id === e);
|
||||
activeScheme.value = scheme[0];
|
||||
} else {
|
||||
activeScheme.value = {};
|
||||
}
|
||||
};
|
||||
|
||||
const generateRandomLog = () => {
|
||||
// 获取当前时间 HH:MM:SS.ms
|
||||
const now = new Date();
|
||||
|
@ -330,13 +422,58 @@ const generateLogs = () => {
|
|||
}
|
||||
};
|
||||
|
||||
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 initSocket = () => {
|
||||
webSocketStore.init(getSocketMeassage);
|
||||
};
|
||||
|
||||
// socket连接状态
|
||||
const socketStatus = computed(() => {
|
||||
return webSocketStore.socket_open;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initSocket();
|
||||
getSchemeDefaultConf();
|
||||
getSchemeDefaultProp();
|
||||
generateDeviceList();
|
||||
loadSchemes();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (webSocketStore) {
|
||||
webSocketStore.close();
|
||||
}
|
||||
});
|
||||
|
||||
const toggleIsScroll = () => {
|
||||
isScroll.value = !isScroll.value;
|
||||
};
|
||||
|
@ -404,6 +541,7 @@ const loadSchemes = async () => {
|
|||
schemeList.value = response.data.data.schemes || [];
|
||||
if (!selectedScheme.value && schemeList.value.length > 0) {
|
||||
selectedScheme.value = schemeList.value[0].id;
|
||||
activeScheme.value = schemeList.value[0];
|
||||
}
|
||||
ElMessage.success('获取方案列表成功');
|
||||
} else {
|
||||
|
@ -496,13 +634,15 @@ const addScheme = () => {
|
|||
currentScheme.value = {
|
||||
schemeName: `方案${schemeList.value.length + 1}`,
|
||||
schemeType: '1p',
|
||||
series: 'B7',
|
||||
framework: '100ZS',
|
||||
configParam: defaultConfList,
|
||||
propertyParam: defaultPropList,
|
||||
errorRange: {
|
||||
voltage: 0.5,
|
||||
current: 0.5,
|
||||
smallCurrent: 1.0,
|
||||
powerFactor: "0.5L",
|
||||
powerFactor: '0.5L',
|
||||
activePower: 0.5,
|
||||
reactivePower: 0.5,
|
||||
apparentPower: 0.5
|
||||
|
@ -526,21 +666,25 @@ const viewScheme = scheme => {
|
|||
// 添加标定步骤
|
||||
const addCalibrationStep = () => {
|
||||
currentScheme.value.steps.push({
|
||||
id: currentScheme.value.steps.length + 1,
|
||||
step: currentScheme.value.steps.length + 1,
|
||||
voltage: 220,
|
||||
current: 10,
|
||||
powerFactor: "0.5L",
|
||||
// riseFirst: true
|
||||
voltage: 100,
|
||||
current: 100,
|
||||
powerFactor: '0.5L',
|
||||
isILeak: false
|
||||
});
|
||||
};
|
||||
const toggleOpenLog = () => {
|
||||
isOpenLog.value = !isOpenLog.value;
|
||||
};
|
||||
|
||||
// 删除标定步骤
|
||||
const deleteCalibrationStep = index => {
|
||||
currentScheme.value.steps.splice(index, 1);
|
||||
// 重新编号
|
||||
// currentScheme.value.steps.forEach((step, idx) => {
|
||||
// step.step = idx + 1;
|
||||
// });
|
||||
currentScheme.value.steps.forEach((step, idx) => {
|
||||
step.id = idx + 1;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -562,6 +706,23 @@ const deleteCalibrationStep = index => {
|
|||
color: white;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.scheme-list {
|
||||
background: #ccc;
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.scheme-item {
|
||||
margin-left: 10px;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.scheme-value {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-left,
|
||||
.header-center,
|
||||
|
@ -627,6 +788,9 @@ const deleteCalibrationStep = index => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
&.open-log {
|
||||
height: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
.log-output {
|
||||
|
@ -680,6 +844,19 @@ const deleteCalibrationStep = index => {
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue