feat(calibration): 重构标定功能并添加新配置项
- 重新设计了标定页面布局和功能 - 添加了操作员编号输入字段 - 新增了标定中和标定后检测的配置项 - 优化了设备列表和日志的显示方式 - 重构了日志处理和设备信息更新的逻辑 - 新增了漏电检测相关的配置项
This commit is contained in:
parent
67b005f77c
commit
a9a580ad29
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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>
|
||||
|
@ -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,24 +341,59 @@
|
|||
</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">
|
||||
<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">
|
||||
<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>
|
||||
<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 label="范围" align="center">
|
||||
<el-table-column prop="result" fixed="right" label="结果" align="center" width="80">
|
||||
<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>
|
||||
<span :style="{ color: scope.row.result === 1 ? 'green' : 'red' }">
|
||||
{{ scope.row.result === 1 ? '成功' : '失败' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="错误日志" name="second"> 错误日志 </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: {
|
||||
range: {
|
||||
voltage: 0.5,
|
||||
current: 0.5,
|
||||
smallCurrent: 1.0,
|
||||
powerFactor: '0.5L',
|
||||
powerFactor: 0.5,
|
||||
activePower: 0.5,
|
||||
reactivePower: 0.5,
|
||||
apparentPower: 0.5
|
||||
},
|
||||
steps: []
|
||||
smallRange: {
|
||||
voltage: 1,
|
||||
current: 1,
|
||||
powerFactor: 1,
|
||||
activePower: 1,
|
||||
reactivePower: 1,
|
||||
apparentPower: 1
|
||||
}
|
||||
},
|
||||
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);
|
||||
|
||||
// 根据ExpectedMin和expectedMax计算result值
|
||||
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; // 超出最小值
|
||||
}
|
||||
}
|
||||
|
||||
// 生成每行数据
|
||||
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 {
|
||||
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()
|
||||
step,
|
||||
paramMap: paramMapRow,
|
||||
result: allOk ? 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
name: stepName,
|
||||
dataList: dataList
|
||||
};
|
||||
});
|
||||
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,46 +631,45 @@ 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 (deviceInfo) {
|
||||
devices.value.forEach((item, index) => {
|
||||
if (item.id === deviceInfo.id) {
|
||||
// debugger
|
||||
devices.value[index] = deviceInfo;
|
||||
// item=deviceInfo;
|
||||
if(deviceInfo.result === -1){
|
||||
if (deviceInfo.result === -1) {
|
||||
type = 'calibrate_result_error';
|
||||
}else if (deviceInfo.result === 1){
|
||||
} 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\":\"\"}"}};
|
||||
// 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);
|
||||
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'){
|
||||
if (msg.msgType === 'calibrate_result') {
|
||||
let resultType = setDeviceInfo(msg.data);
|
||||
if(resultType){
|
||||
if (resultType) {
|
||||
newLog.type = resultType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量更新日志数组
|
||||
logs.value = [...logs.value.slice(-MAX_LOG_LENGTH + 1), newLog];
|
||||
|
||||
|
@ -655,7 +731,6 @@ onMounted(() => {
|
|||
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') {
|
||||
// 为每个参数设置bigRange和smallRange
|
||||
param.errorRange = {
|
||||
bigRange: scheme.errorRange[key],
|
||||
smallRange: scheme.errorRange.smallCurrent
|
||||
bigRange: scheme.errorRange.range[key],
|
||||
smallRange: scheme.errorRange.smallRange[key]
|
||||
};
|
||||
} else {
|
||||
// 其他参数直接赋值defaultRange
|
||||
param.errorRange = {
|
||||
defaultRange: scheme.errorRange[key]
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -826,18 +910,30 @@ const addScheme = () => {
|
|||
schemeType: '1p',
|
||||
series: 'B7',
|
||||
framework: '100ZS',
|
||||
middleDetect: true,
|
||||
laterDetect: false,
|
||||
configParam: defaultConfList,
|
||||
propertyParam: defaultPropList,
|
||||
errorRange: {
|
||||
range: {
|
||||
voltage: 0.5,
|
||||
current: 0.5,
|
||||
smallCurrent: 1.0,
|
||||
powerFactor: '0.5L',
|
||||
powerFactor: 0.5,
|
||||
activePower: 0.5,
|
||||
reactivePower: 0.5,
|
||||
apparentPower: 0.5
|
||||
},
|
||||
steps: []
|
||||
smallRange: {
|
||||
voltage: 1,
|
||||
current: 1,
|
||||
powerFactor: 1,
|
||||
activePower: 1,
|
||||
reactivePower: 1,
|
||||
apparentPower: 1
|
||||
}
|
||||
},
|
||||
steps: [],
|
||||
iLeakDetectObj: defaultiLeakDetectObj
|
||||
};
|
||||
schemeDetailVisible.value = true;
|
||||
};
|
||||
|
@ -887,7 +983,7 @@ const generateDeviceList = async () => {
|
|||
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,8 +1189,10 @@ 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;
|
||||
|
@ -1081,10 +1211,12 @@ const playCalibration = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
.log-item-txt{
|
||||
.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 {
|
||||
|
|
Loading…
Reference in New Issue