feat(calibration): 重构标定功能并添加新配置项

- 重新设计了标定页面布局和功能
- 添加了操作员编号输入字段
- 新增了标定中和标定后检测的配置项
- 优化了设备列表和日志的显示方式
- 重构了日志处理和设备信息更新的逻辑
- 新增了漏电检测相关的配置项
This commit is contained in:
fhysy 2025-07-08 17:00:43 +08:00
parent 9646a4ae8c
commit b71aaf4ff7
3 changed files with 375 additions and 232 deletions

View File

@ -1,10 +1,14 @@
module.exports = {
//打包配置
// url: 'http://127.0.0.1:8000',
// wsUrl: 'ws://127.0.0.1:8000',
// swichWsUrl: 'ws://127.0.0.1:8001',
// serialPortUrl: 'http://127.0.0.1:8000',
//开发配置
url: 'http://192.168.1.17:8000',
wsUrl: 'ws://192.168.1.17:8000',
swichWsUrl: 'ws://192.168.1.17:8001',

View File

@ -17,15 +17,15 @@
// }
export default {
url: 'http://127.0.0.1:8888',
wsUrl: 'ws://127.0.0.1:8888',
swichWsUrl: 'ws://127.0.0.1:8001',
serialPortUrl: 'http://127.0.0.1:8888',
// url: 'http://127.0.0.1:8000',
// wsUrl: 'ws://127.0.0.1:8000',
// swichWsUrl: 'ws://127.0.0.1:8001',
// serialPortUrl: 'http://127.0.0.1:8000',
// url: 'http://192.168.1.17:8000',
// wsUrl: 'ws://192.168.1.17:8000',
// swichWsUrl: 'ws://192.168.1.17:8001',
// serialPortUrl: 'http://192.168.1.17:8000',
url: 'http://192.168.1.17:8000',
wsUrl: 'ws://192.168.1.17:8000',
swichWsUrl: 'ws://192.168.1.17:8001',
serialPortUrl: 'http://192.168.1.17:8000',
// 远程连接串口使用
// serialPortUrl: 'http://120.77.172.42:7202',

View File

@ -6,7 +6,8 @@
<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>
<el-button icon="RemoveFilled" type="danger" :disabled="!playState" @click="stopExecution">停止</el-button>
<el-button icon="RemoveFilled" type="danger" @click="stopExecution">停止</el-button>
<el-input v-model="operatorCode" placeholder="请输入操作员编号" style="width: 200px; margin-left: 15px" />
</div>
<div class="header-right">
<el-button icon="RefreshRight" type="primary" :disabled="playState" @click="generateDeviceList">刷新列表</el-button>
@ -46,8 +47,25 @@
</div>
</template>
<div class="device-card-body">
<div :class="['iconfont', 'icon-icon_duanluqi', 'circuit-breaker', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : '']"></div>
<p>芯片ID: {{ device.deviceSN || '无' }}</p>
<div v-if="device.activeStep" class="process-status" :class="device.stepStatus === -1 ? 'color-red' : device.stepStatus === 1 ? 'color-green' : 'color-orange'">{{ device.activeStep }}</div>
<div
v-if="device.connectStatus === 1"
:class="[
'iconfont',
'icon-icon_duanluqi',
'circuit-breaker',
device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : device.stepStatus === -1 ? 'color-red' : device.stepStatus === 1 ? 'color-green' : 'color-orange'
]"
></div>
<div v-else :class="['iconfont', 'icon-icon_duanluqi', 'circuit-breaker', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : '']"></div>
<p>
芯片ID:
<span
><el-tooltip class="box-item" effect="dark" :content="device.cpuId" placement="top-start">
{{ device.cpuId || '无' }}
</el-tooltip></span
>
</p>
<p>设备端口: {{ device.devicePort || '无' }}</p>
<p>
标定结果:
@ -57,11 +75,12 @@
</p>
<p>
结果描述:
<span
<span v-if="device.resultTxt"
><el-tooltip class="box-item" effect="dark" :content="device.resultTxt" placement="top-start">
{{ device.resultTxt || '无' }}
</el-tooltip></span
>
<span v-else>{{ device.resultTxt || '' }}</span>
</p>
</div>
</el-card>
@ -70,23 +89,23 @@
<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">
<el-tooltip v-if="item.type == 'calibrate_error'" effect="light" content="错误信息" placement="top">
<span class="iconfont icon-bug-fill" style="color: #ff3b2b"></span>
</el-tooltip>
<el-tooltip v-else-if="item.type == 'calibrate_result_error'" effect="light" content="标定错误" placement="top">
<span class="iconfont icon-xwtubiaoku-15" style="color: #ff3b2b"></span>
</el-tooltip>
<el-tooltip v-else-if="item.type == 'calibrate_result_success'" effect="light" content="标定成功" placement="top">
<span class="iconfont icon-xwtubiaoku-13" style="color: #55e800"></span>
</el-tooltip>
<el-tooltip v-else effect="light" content="系统" placement="top">
<span class="iconfont icon-rizhi1"></span>
</el-tooltip>
<span class="log-item-txt">{{ item.time }} {{ item.msg }}</span>
</div>
</div>
<div class="log-list">
<div v-for="(item, index) in logs" :key="index" class="log-item">
<el-tooltip v-if="item.type == 'calibrate_error'" effect="light" content="错误信息" placement="top">
<span class="iconfont icon-bug-fill" style="color: #ff3b2b"></span>
</el-tooltip>
<el-tooltip v-else-if="item.type == 'calibrate_result_error'" effect="light" content="标定错误" placement="top">
<span class="iconfont icon-xwtubiaoku-15" style="color: #ff3b2b"></span>
</el-tooltip>
<el-tooltip v-else-if="item.type == 'calibrate_result_success'" effect="light" content="标定成功" placement="top">
<span class="iconfont icon-xwtubiaoku-13" style="color: #55e800"></span>
</el-tooltip>
<el-tooltip v-else effect="light" content="系统" placement="top">
<span class="iconfont icon-rizhi1"></span>
</el-tooltip>
<span class="log-item-txt">{{ item.time }} {{ item.msg }}</span>
</div>
</div>
</div>
<div class="calibration-footer-btn">
<div class="btn-box">
@ -150,12 +169,12 @@
<!-- 方案详情对话框 -->
<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 :model="currentScheme" label-width="100px">
<el-form-item label="方案名称">
<el-input v-model="currentScheme.schemeName" />
</el-form-item>
<el-row>
<el-col :span="8">
<el-col :span="5">
<el-form-item label="系列">
<el-select v-model="currentScheme.series" placeholder="请选择系列">
<el-option label="B7" value="B7" />
@ -163,14 +182,14 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-col :span="5">
<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-col :span="5">
<el-form-item label="断路器类型">
<el-select v-model="currentScheme.schemeType" placeholder="请选择断路器类型">
<el-option label="1p" value="1p" />
@ -180,6 +199,16 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="标定中检测">
<el-switch v-model="currentScheme.middleDetect" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="标定后检测">
<el-switch v-model="currentScheme.laterDetect" />
</el-form-item>
</el-col>
</el-row>
<el-divider>断路器校准参数</el-divider>
@ -197,9 +226,16 @@
</div> -->
<el-divider>校准精度(%)</el-divider>
<div class="accuracy-title">普通电流</div>
<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 v-for="(value, key) in currentScheme.errorRange.range" :key="key" label-width="auto" :label="accuracyType[key]">
<el-input-number v-model="currentScheme.errorRange.range[key]" style="width: 120px" :min="0" :max="100" :precision="2" />
</el-form-item>
</div>
<div class="accuracy-title">小电流</div>
<div class="accuracy-params">
<el-form-item v-for="(value, key) in currentScheme.errorRange.smallRange" :key="key" label-width="auto" :label="accuracyType[key]">
<el-input-number v-model="currentScheme.errorRange.smallRange[key]" style="width: 120px" :min="0" :max="100" :precision="2" />
</el-form-item>
</div>
@ -254,6 +290,31 @@
</el-table-column>
</el-table>
</div>
<!-- 新增漏电检测设置分组 -->
<el-divider>漏电检测设置</el-divider>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="漏电检测">
<el-switch v-model="currentScheme.iLeakDetectObj.iLeakDetect" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="检测电流(mA)">
<el-input-number v-model="currentScheme.iLeakDetectObj.detectInput" :min="0" :step="1" style="width: 120px" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="漏电保护">
<el-switch v-model="currentScheme.iLeakDetectObj.iLeakProtect" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="保护电流(mA)">
<el-input-number v-model="currentScheme.iLeakDetectObj.protectInput" :min="0" :step="1" style="width: 120px" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
@ -268,7 +329,7 @@
<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">芯片ID: {{ activeDeviceInfo.cpuId || '-' }}</div>
<div class="device-info-item">设备端口: {{ activeDeviceInfo.devicePort || '-' }}</div>
<div class="device-info-item">
标定结果:
@ -280,23 +341,58 @@
</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 === null?'': 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="center">
<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 :data="stepLogRows" style="width: 100%" size="small" scrollbar-always-on resizable empty-text="暂无日志">
<el-table-column prop="step" label="步骤" fixed align="center" />
<el-table-column v-for="col in logParamColumns" :key="col.key" :prop="'paramMap.' + col.valueKey + '.actualError'" :label="col.valueKey" align="center">
<template #header>
<el-tooltip effect="dark" :content="(col.valueName || col.valueKey) + (col.valueUnit ? ' [' + col.valueUnit + ']' : '')" placement="top">
<span>{{ col.valueKey }}</span>
</el-tooltip>
</template>
<template #default="scope">
<el-tooltip
effect="dark"
:content="
'差值百分比: ' +
(scope.row.paramMap[col.valueKey]?.actualError + '%' ?? '') +
'\n' +
'范围百分比: ' +
(scope.row.paramMap[col.valueKey]?.expectedError + '%' ?? '') +
'\n' +
'源输出值: ' +
(scope.row.paramMap[col.valueKey]?.outputValue ?? '') +
'\n' +
'范围最小值: ' +
(scope.row.paramMap[col.valueKey]?.ExpectedMin ?? '') +
'\n' +
'范围最大值: ' +
(scope.row.paramMap[col.valueKey]?.expectedMax ?? '') +
'\n' +
'读取值: ' +
(scope.row.paramMap[col.valueKey]?.actualValue ?? '')
"
placement="top"
>
<span :style="{ color: scope.row.paramMap[col.valueKey]?.result === 1 ? 'green' : 'red' }">
{{
typeof scope.row.paramMap[col.valueKey]?.actualError === 'number'
? Number(scope.row.paramMap[col.valueKey].actualError.toFixed(6)).toString()
: scope.row.paramMap[col.valueKey]?.actualError
}}<span v-if="scope.row.paramMap[col.valueKey]">%</span>
<template v-if="scope.row.paramMap[col.valueKey]">
<el-icon v-if="scope.row.paramMap[col.valueKey].actualValue > scope.row.paramMap[col.valueKey].expectedMax" style="color: red"><Top /></el-icon>
<el-icon v-else-if="scope.row.paramMap[col.valueKey].actualValue < scope.row.paramMap[col.valueKey].ExpectedMin" style="color: red"><Bottom /></el-icon>
</template>
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="result" fixed="right" label="结果" align="center" width="80">
<template #default="scope">
<span :style="{ color: scope.row.result === 1 ? 'green' : 'red' }">
{{ scope.row.result === 1 ? '成功' : '失败' }}
</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
@ -315,7 +411,7 @@ import dayjs from 'dayjs';
import axios from 'axios';
// import config from '@renderer/util/config.js';
const config = window.electron.readConfig();
console.log("当前获取config",config);
console.log('当前获取config', config);
import { logWebSocketStore } from '@renderer/stores/logWebSocket.js';
const webSocketStore = logWebSocketStore();
@ -327,9 +423,9 @@ const isScroll = ref(true);
const logs = ref([]);
const version = ref('V1.0.0');
const logTabActive = ref('log');
const operatorCode = ref('');
const loading = ref(true);
const fullscreenLoading = ref(false)
const isOpenLog = ref(false);
const logSocketStateHover = ref(false);
@ -342,7 +438,6 @@ const activeScheme = ref();
const accuracyType = ref({
voltage: '电压',
current: '电流',
smallCurrent: '小电流',
powerFactor: '功率因数',
activePower: '有功功率',
reactivePower: '无功功率',
@ -363,6 +458,13 @@ const defaultConfList = ref({
format: []
});
const defaultiLeakDetectObj = ref({
iLeakDetect: false,
detectInput: 100,
iLeakProtect: false,
protectInput: 100
});
const logVisible = ref(false);
const logList = ref([]);
@ -376,11 +478,13 @@ const activeDeviceIndex = ref(0);
const activeDeviceInfo = ref({
id: 0,
devicePort: '',
deviceSN: '',
cpuId: '',
connectStatus: 0,
switch: 0,
result: 0,
resultTxt: ''
resultTxt: '',
stepStatus: 0,
activeStep: ''
});
const defaultPropList = ref([]);
@ -390,20 +494,36 @@ const currentScheme = ref({
schemeType: '1p',
series: 'B7',
framework: '100ZS',
middleDetect: true,
laterDetect: false,
configParam: defaultConfList,
propertyParam: defaultPropList,
errorRange: {
voltage: 0.5,
current: 0.5,
smallCurrent: 1.0,
powerFactor: '0.5L',
activePower: 0.5,
reactivePower: 0.5,
apparentPower: 0.5
range: {
voltage: 0.5,
current: 0.5,
powerFactor: 0.5,
activePower: 0.5,
reactivePower: 0.5,
apparentPower: 0.5
},
smallRange: {
voltage: 1,
current: 1,
powerFactor: 1,
activePower: 1,
reactivePower: 1,
apparentPower: 1
}
},
steps: []
steps: [],
iLeakDetectObj: defaultiLeakDetectObj
});
// 1. step
const logParamColumns = ref([]); // [{ valueKey, valueName, valueUnit }]
const stepLogRows = ref([]); // [{ step, paramMap: { valueKey: item }, result: 0/1 }]
const logTabChange = (tab, event) => {
console.log(tab, event);
};
@ -412,7 +532,7 @@ const selectDevice = async (item, index) => {
activeDeviceInfo.value = item;
activeDeviceIndex.value = index;
//
await fetchDeviceLogs(item.id);
await fetchDeviceLogs(item.cpuId);
logVisible.value = true;
};
@ -421,7 +541,7 @@ const fetchDeviceLogs = async deviceId => {
logLoading.value = true;
try {
const response = await axios.get(config.url + '/master/calibrate/result', {
params: { devId: deviceId }
params: { cpuId: deviceId }
});
if (response.data.code === 0) {
@ -437,103 +557,60 @@ const fetchDeviceLogs = async deviceId => {
}
};
//
// processLogData
const processLogData = apiData => {
if (!apiData || !Array.isArray(apiData)) {
logList.value = [];
logParamColumns.value = [];
stepLogRows.value = [];
return;
}
// activeScheme.propertyParam
const paramMap = new Map();
apiData.forEach(item => {
let valueName = item.valueName || item.valueKey;
let valueUnit = item.valueUnit || '';
if (activeScheme.value && Array.isArray(activeScheme.value.propertyParam)) {
const found = activeScheme.value.propertyParam.find(param => param.key === item.valueKey);
if (found) {
valueName = found.name || valueName;
valueUnit = found.unit || valueUnit;
}
}
const key = item.valueKey + (valueUnit ? `(${valueUnit})` : '');
if (!paramMap.has(key)) {
paramMap.set(key, {
valueKey: item.valueKey,
valueName,
valueUnit,
key: key
});
}
});
logParamColumns.value = Array.from(paramMap.values());
//
// step
const stepGroups = {};
apiData.forEach(item => {
if (!stepGroups[item.step]) {
stepGroups[item.step] = [];
}
if (!stepGroups[item.step]) stepGroups[item.step] = [];
stepGroups[item.step].push(item);
});
//
const processedLogs = Object.keys(stepGroups).map(stepName => {
const stepData = stepGroups[stepName];
const dataList = stepData.map(item => {
// activeScheme.propertyParam
const paramInfo = activeScheme.value?.propertyParam?.find(param => param.key === item.valueKey || param.name === item.valueName);
// ExpectedMinexpectedMaxresult
const minValue = parseFloat(item.ExpectedMin);
const maxValue = parseFloat(item.expectedMax);
const outputValue = parseFloat(item.actualValue);
let result = 0; //
if (!isNaN(minValue) && !isNaN(maxValue) && !isNaN(outputValue)) {
// outputValue
if (outputValue >= minValue && outputValue <= maxValue) {
result = 1; //
} else if (outputValue > maxValue) {
result = 2; //
} else if (outputValue < minValue) {
result = 0; //
}
}
return {
id: item.id,
name: paramInfo?.name || item.valueName || item.valueKey,
value: item.actualValue,
unit: paramInfo?.unit || item.valueUnit,
accuracy: item.expectedError,
result: result,
minValue: item.ExpectedMin?.toString(),
maxValue: item.expectedMax?.toString()
};
//
stepLogRows.value = Object.entries(stepGroups).map(([step, arr]) => {
// paramMap: { valueKey: item }
const paramMapRow = {};
arr.forEach(item => {
paramMapRow[item.valueKey] = item;
});
//
const allOk = logParamColumns.value.every(col => paramMapRow[col.valueKey]?.result === 1);
return {
name: stepName,
dataList: dataList
step,
paramMap: paramMapRow,
result: allOk ? 1 : 0
};
});
logList.value = processedLogs;
};
// 便
const transposedLogList = computed(() => {
if (!logList.value.length) return [];
// valueKey
const allValueKeys = new Set();
logList.value.forEach(step => {
step.dataList.forEach(item => {
allValueKeys.add(item.valueKey || item.name);
});
});
// valueKey
const result = [];
allValueKeys.forEach(valueKey => {
// valueKey
const firstStepWithKey = logList.value.find(step =>
step.dataList.some(item => (item.valueKey || item.name) === valueKey)
);
const firstItem = firstStepWithKey?.dataList.find(item =>
(item.valueKey || item.name) === valueKey
);
const param = {
name: (firstItem?.name || valueKey) + (firstItem?.unit ? '(' + firstItem.unit + ')' : ''),
data: logList.value.map(step => {
// valueKey
const item = step.dataList.find(item => (item.valueKey || item.name) === valueKey);
return item || null; // null
})
};
result.push(param);
});
return result;
});
const schemeChange = e => {
if (e) {
const scheme = schemeList.value.filter(item => item.id === e);
@ -554,45 +631,44 @@ const tryParseJSON = data => {
//
const throttledScroll = throttle(() => {
logBoxRef.value.scrollTop = logBoxRef.value.scrollHeight;
}, 100);
}, 500);
const setDeviceInfo = msg => {
let deviceInfo = tryParseJSON(msg);
let type = false;
if(deviceInfo){
devices.value.forEach((item,index) => {
if (item.id === deviceInfo.id) {
// debugger
devices.value[index] = deviceInfo;
// item=deviceInfo;
if(deviceInfo.result === -1){
type = 'calibrate_result_error';
}else if (deviceInfo.result === 1){
type = 'calibrate_result_success';
}
}
})
}
return type;
let deviceInfo = tryParseJSON(msg);
let type = false;
if (deviceInfo) {
devices.value.forEach((item, index) => {
if (item.id === deviceInfo.id) {
// debugger
devices.value[index] = deviceInfo;
// item=deviceInfo;
if (deviceInfo.result === -1) {
type = 'calibrate_result_error';
} else if (deviceInfo.result === 1) {
type = 'calibrate_result_success';
}
}
});
}
return type;
};
const getSocketMeassage = message => {
// message = {data:{"msgType":"calibrate_result","data":"{\"id\":1,\"devicePort\":\"com3\",\"deviceSN\":\"SN\",\"connectStatus\":1,\"switch\":0,\"result\":-1,\"resultTxt\":\"\"}"}};
const msg = tryParseJSON(message.data);
console.log("msg",msg);
// message = {data:{"msgType":"calibrate_result","data":"{\"id\":1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"devicePort\":\"com3\",\"cpuId\":\"SN\",\"connectStatus\":1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"switch\":0,\"result\":-1,\"resultTxt\":\"\"}"}};
const msg = tryParseJSON(message.data);
console.log('msg', msg);
const newLog = {
time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
msg: msg.data ?? msg,
type: msg.msgType ?? null
};
if(msg.msgType === 'calibrate_result'){
let resultType = setDeviceInfo(msg.data);
if(resultType){
newLog.type = resultType;
}
}
if (msg.msgType === 'calibrate_result') {
let resultType = setDeviceInfo(msg.data);
if (resultType) {
newLog.type = resultType;
}
}
//
logs.value = [...logs.value.slice(-MAX_LOG_LENGTH + 1), newLog];
@ -649,13 +725,12 @@ onMounted(() => {
version.value = v;
});
}
// generateMockDevices();
getSchemeDefaultConf();
getSchemeDefaultProp();
generateDeviceList();
loadSchemes();
});
onUnmounted(() => {
@ -673,6 +748,12 @@ const startExecution = () => {
ElMessage.error('请先选择方案');
return;
}
if (operatorCode.value.trim() === '') {
ElMessage.error('请先输入操作员编号');
return;
}
// socket
reconnectSocket();
const scheme = schemeList.value.filter(item => item.id === selectedScheme.value);
console.log(scheme);
ElMessage.success('开始执行方案: ' + scheme[0].schemeName);
@ -681,10 +762,20 @@ const startExecution = () => {
// Add actual start logic here
};
const stopExecution = () => {
ElMessage.info('停止执行');
const stopExecution = async () => {
try {
const response = await axios.get(config.url + '/master/scheme/stop');
if (response.data.code === 0) {
// devices.value = response.data.data.result || [];
playState.value = false;
ElMessage.success('停止成功');
} else {
ElMessage.error(response.data.message || '停止失败');
}
} catch (error) {
ElMessage.error('停止失败');
}
playState.value = false;
// Add actual stop logic here
};
const openSettings = () => {
@ -757,18 +848,11 @@ const saveScheme = async () => {
Object.entries(accuracyType.value).forEach(([key, value]) => {
// 使
if (param.name.includes(value)) {
//
if (key === 'current') {
param.errorRange = {
bigRange: scheme.errorRange[key],
smallRange: scheme.errorRange.smallCurrent
};
} else {
// defaultRange
param.errorRange = {
defaultRange: scheme.errorRange[key]
};
}
// bigRangesmallRange
param.errorRange = {
bigRange: scheme.errorRange.range[key],
smallRange: scheme.errorRange.smallRange[key]
};
}
});
});
@ -826,18 +910,30 @@ const addScheme = () => {
schemeType: '1p',
series: 'B7',
framework: '100ZS',
middleDetect: true,
laterDetect: false,
configParam: defaultConfList,
propertyParam: defaultPropList,
errorRange: {
voltage: 0.5,
current: 0.5,
smallCurrent: 1.0,
powerFactor: '0.5L',
activePower: 0.5,
reactivePower: 0.5,
apparentPower: 0.5
range: {
voltage: 0.5,
current: 0.5,
powerFactor: 0.5,
activePower: 0.5,
reactivePower: 0.5,
apparentPower: 0.5
},
smallRange: {
voltage: 1,
current: 1,
powerFactor: 1,
activePower: 1,
reactivePower: 1,
apparentPower: 1
}
},
steps: []
steps: [],
iLeakDetectObj: defaultiLeakDetectObj
};
schemeDetailVisible.value = true;
};
@ -886,8 +982,8 @@ const generateDeviceList = async () => {
const response = await axios.get(config.url + '/master/device/list');
if (response.data.code === 0) {
devices.value = response.data.data.result || [];
//
// setDeviceInfo("{\"id\":1,\"devicePort\":\"com3\",\"deviceSN\":\"SN\",\"connectStatus\":1,\"switch\":0,\"result\":-1,\"resultTxt\":\"\"}")
//
// setDeviceInfo("{\"id\":1,\"devicePort\":\"com3\",\"cpuId\":\"SN\",\"connectStatus\":1,\"switch\":0,\"result\":-1,\"resultTxt\":\"\"}")
} else {
ElMessage.error(response.data.message || '刷新列表失败');
}
@ -899,15 +995,15 @@ const generateDeviceList = async () => {
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 + '&operatorCode=' + operatorCode.value);
if (response.data.code === 0) {
devices.value = response.data.data.result || [];
// devices.value = response.data.data.result || [];
} else {
ElMessage.error(response.data.message || '获取设备列表失败');
// ElMessage.error(response.data.message || '');
}
} catch (error) {
console.error('获取设备列表失败:', error);
ElMessage.error('获取设备列表失败');
// ElMessage.error('');
}
};
</script>
@ -969,7 +1065,7 @@ const playCalibration = async () => {
.calibration-main {
flex-grow: 1;
padding: 20px;
padding: 20px 10px;
overflow-y: auto;
}
@ -995,9 +1091,37 @@ const playCalibration = async () => {
font-size: 14px;
}
@keyframes dot-animation {
0% {
content: '.';
}
33% {
content: '..';
}
66% {
content: '...';
}
100% {
content: '.';
}
}
.device-card-body {
font-size: 12px;
text-align: center;
position: relative;
.process-status {
position: absolute;
top: -6px;
left: 0;
width: 100%;
&.color-orange {
&::after {
content: '...';
animation: dot-animation 1.5s infinite;
}
}
}
.device-result {
font-size: 14px;
font-weight: bold;
@ -1014,6 +1138,11 @@ const playCalibration = async () => {
/* Green for connected */
}
.color-orange {
color: #e6a23c;
/* Green for connected */
}
.color-red {
color: #f56c6c;
/* Red for disconnected */
@ -1052,7 +1181,6 @@ const playCalibration = async () => {
.log-box-main {
font-family: 'Courier New', Courier, monospace;
padding: 5px;
font-size: 10px;
white-space: pre-wrap;
flex-grow: 1;
@ -1061,30 +1189,34 @@ const playCalibration = async () => {
background-color: #202020;
color: #dcdcdc;
scroll-behavior: smooth;
.log-list{
// padding: 5px;
.log-item {
padding: 0 5px;
word-wrap: break-word;
word-break: break-all;
font-size: 12px;
line-height: 18px;
font-weight: 500;
.log-item {
word-wrap: break-word;
word-break: break-all;
font-size: 12px;
line-height: 18px;
font-weight: 500;
.iconfont {
font-size: 14px;
line-height: 18px;
&.icon-icon_fuzhi {
line-height: 26px;
margin-left: 8px;
font-size: 16px;
color: #0066cc;
cursor: pointer;
}
}
.iconfont {
font-size: 14px;
line-height: 18px;
&.icon-icon_fuzhi {
line-height: 26px;
margin-left: 8px;
font-size: 16px;
color: #0066cc;
cursor: pointer;
.log-item-txt {
margin-left: 5px;
}
}
.log-item-txt{
margin-left: 5px;
}
}
}
.calibration-footer-btn {
@ -1191,11 +1323,18 @@ const playCalibration = async () => {
gap: 5px;
}
.accuracy-title {
font-weight: bold;
margin-bottom: 10px;
font-size: 14px;
color: #000;
}
.device-params,
.accuracy-params {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
gap: 10px;
grid-template-columns: repeat(6, 1fr);
}
.calibration-steps {