Files
pqs-9100_client/frontend/src/views/home/components/factorTest.vue
2025-08-11 11:14:20 +08:00

969 lines
37 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="dialog" v-bind="dialogBig">
<div class="dialog-content">
<div class="right-title">
<!-- <div>系数校准表</div> -->
<div>{{ outputDsc }}</div>
<div>
<span style=" font-size: 18px;font-weight: 600;">
设备已合格 <span style="color: #91cc75">{{ qualified }}</span> / <span style="color: green">{{ total }}</span>
</span>
<!-- <el-button type="primary" loading
v-if="activeIndex > 0 && activeIndex < activeTotalNum">通道系数已校准3台/共3台</el-button>
<el-button type="primary" :disabled="true" v-if="activeIndex === activeTotalNum">通道系数已校准3台/共3台</el-button> -->
</div>
</div>
<div class="container">
<div class="dialog-left">
<el-steps direction="vertical" :active="active" :process-status="currentStepStatus" finish-status="success">
<el-step title="开始"/>
<el-step>
<template #title>
<span>大电压/电流系数下装</span><br/>
<span class="spanStyle">源输出为</span><br/>
<span class="spanStyle" v-if="active > 0">{{ big_V_Download }}</span><br/>
<span class="spanStyle" v-if="active > 0">{{ big_I_Download }}</span>
<el-icon v-if="active === 1 " class="loading-box">
<el-icon-loading/>
</el-icon>
</template>
</el-step>
<el-step>
<template #title>
<span>小电压/电流系数下装</span><br/>
<span class="spanStyle">源输出为</span><br/>
<span class="spanStyle" v-if="active > 1">{{ small_V_Download }}</span><br/>
<span class="spanStyle" v-if="active > 1">{{ small_I_Download }}</span>
<el-icon v-if="active === 2" class="loading-box">
<el-icon-loading/>
</el-icon>
</template>
</el-step>
<el-step>
<template #title>
<span>大电压/电流校准</span><br/>
<span class="spanStyle">源输出为</span><br/>
<span class="spanStyle" v-if="active > 2">{{ big_V_Adjust }}</span><br/>
<span class="spanStyle" v-if="active > 2">{{ big_I_Adjust }}</span>
<el-icon v-if="active === 3" class="loading-box">
<el-icon-loading/>
</el-icon>
</template>
</el-step>
<el-step>
<template #title>
<span>小电压/电流校准</span><br/>
<span class="spanStyle">源输出为</span><br/>
<span class="spanStyle" v-if="active > 3">{{ small_V_Adjust }}</span><br/>
<span class="spanStyle" v-if="active > 3">{{ small_I_Adjust }}</span>
<el-icon v-if="active === 4" class="loading-box">
<el-icon-loading/>
</el-icon>
</template>
</el-step>
<el-step title="结束"/>
</el-steps>
</div>
<div class="right-content">
<el-tabs type="border-card" v-model="editableTabsValue" :active-index="String(activeIndex)">
<el-tab-pane v-for="(device, index) in name" :key="index" :label="device">
<template #label>
<span class="custom-tabs-label">
<span>{{ device }}</span>
<el-icon v-if="errorStates[index]" class="icon-style">
<Failed/>
</el-icon>
</span>
</template>
<channelsTestTable
:tableData="getTableDataForChannel(index)"
:big_V_loading="big_V_loadingStates"
:curV="CurV">
</channelsTestTable>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</div>
</template>
<script lang="tsx" setup name="FactorTest">
/**
* 系数校准组件
*
* 功能概述:
* 1. 对电力设备进行系数校准,确保测量精度
* 2. 包含4个校准步骤大/小电压电流系数的下装和校准
* 3. 支持多设备并行校准,实时显示校准数据和结果
* 4. 校准完成后自动统计合格设备数量并通知父组件
*
* 校准流程:
* 第1步大电压/电流系数下装 - 向设备下发大幅值的系数参数
* 第2步小电压/电流系数下装 - 向设备下发小幅值的系数参数
* 第3步大电压/电流校准 - 使用大幅值进行校准测试
* 第4步小电压/电流校准 - 使用小幅值进行校准测试
*/
import {type Device} from '@/api/device/interface/device';
import {Failed} from '@element-plus/icons-vue'
import {onBeforeMount, type Ref, ref, toRef, watch} from 'vue'
import {dialogBig} from '@/utils/elementBind'
import {ElMessageBox} from 'element-plus';
import {getCoefficientCheck} from '@/api/home/channelsTest/index'
import type {ChannelsTest} from '@/api/home/interface/channelsTest';
import type {Plan} from '@/api/plan/interface';
import {useCheckStore} from "@/stores/modules/check";
import {useUserStore} from "@/stores/modules/user";
// ==================== 状态管理 ====================
const checkStore = useCheckStore()
const userStore = useUserStore()
// ==================== 界面控制变量 ====================
const activeIndex = ref(0) // 当前活跃的表格数据索引
const activeTotalNum = ref(4) // 总步骤数
const qualified = ref(0) // 已合格的设备数量
const outputDsc = ref('电压误差为±0.1Un% 电流误差为±0.5%') // 输出描述信息
const total = ref(0) // 设备总数
const dialogVisible = ref(false) // 弹窗显示状态
const active = ref(0) // 当前激活的校准步骤0-5
const editableTabsValue = ref('0') // 当前选中的标签页
// ==================== 定时器管理 ====================
let timer1: NodeJS.Timeout | null = null // 定时器1
let timer2: NodeJS.Timeout | null = null // 定时器2
// ==================== 设备信息管理 ====================
const name = ref<string[]>([]) // 系数校准所选设备名称数组
const channel = ref<number[]>([]) // 系数校准所选设备通道数量数组
const devIdArray = ref<string[]>([]) // 系数校准所选设备ID数组
const select_Plan = ref<Plan.ReqPlan>() // 选中的检测计划
const planId = ref('') // 计划ID
const CurV = ref<number>() // 额定电压值
// ==================== 状态控制变量 ====================
const isButtonDisabled = ref(false) // 按钮禁用状态
const errorStates = ref(new Array(name.value.length).fill(false)) // 各设备错误状态数组
// ==================== 加载状态管理 ====================
const big_V_loadingStates = ref(false) // 大电压大电流下装加载状态
const small_V_loadingStates = ref(false) // 小电压小电流下装加载状态
const big_V_loadingStates2 = ref(false) // 大电压大电流校准加载状态
const small_V_loadingStates2 = ref(false) // 小电压小电流校准加载状态
// ==================== 源输出参数显示 ====================
const big_V_Download = ref('') // 大电压下装时的电压输出显示
const big_I_Download = ref('') // 大电压下装时的电流输出显示
const small_V_Download = ref('') // 小电压下装时的电压输出显示
const small_I_Download = ref('') // 小电压下装时的电流输出显示
const big_V_Adjust = ref('') // 大电压校准时的电压输出显示
const big_I_Adjust = ref('') // 大电压校准时的电流输出显示
const small_V_Adjust = ref('') // 小电压校准时的电压输出显示
const small_I_Adjust = ref('') // 小电压校准时的电流输出显示
// ==================== 组件Props定义 ====================
const props = defineProps({
testStatus: {
type: String,
default: 'wait' // 从父组件接收的测试状态
},
webMsgSend: {
type: Object,
default: () => ({}) // 从父组件接收的WebSocket消息
},
})
// ==================== 响应式Props引用 ====================
const testStatus = toRef(props, 'testStatus');
const webMsgSend = toRef(props, 'webMsgSend');
// ==================== 数据管理 ====================
const tableDataMap = new Map<number, Ref<ChannelsTest.CoefficientVO[]>>([]); // 存储每个设备的表格数据映射
const currentStepStatus = ref<'error' | 'finish' | 'wait' | 'success' | 'process'>('finish'); // 当前步骤状态
// ==================== 组件生命周期 ====================
onBeforeMount(() => {
initData() // 组件挂载前初始化数据
})
/**
* 初始化组件数据
* 从store中获取设备信息初始化表格数据和状态变量
*/
const initData = () => {
// 获取设备基础信息
CurV.value = checkStore.devices[0]?.devVolt || 57.74; // 获取额定电压默认57.74V
isButtonDisabled.value = false; // 恢复按钮可用状态
select_Plan.value = checkStore.plan // 获取检测计划
planId.value = checkStore.devices[0]?.planId || ''; // 获取计划ID
// 提取设备信息数组
devIdArray.value = checkStore.devices.map(item => item.deviceId); // 设备ID数组
name.value = checkStore.devices.map(item => item.deviceName); // 设备名称数组
channel.value = checkStore.devices.map(item => item.chnNum); // 设备通道数量数组
// 设置界面状态
dialogVisible.value = true; // 显示弹窗
total.value = name.value.length; // 设置设备总数
// 初始化错误状态数组,所有设备初始状态为无错误
errorStates.value = new Array(checkStore.devices.length).fill(false);
// 为每个设备初始化表格数据
for (let i = 0; i < channel.value.length; i++) {
const currentTableData = initializeTableData(dataTemplates, i);
tableDataMap.set(i, currentTableData); // 将表格数据存储到Map中以设备索引为key
}
}
// ==================== 状态监听器 ====================
/**
* 监听父组件传入的测试状态变化
* 当父组件通知开始测试时,启动系数校准流程
*/
watch(testStatus, function (newValue, oldValue) {
if (newValue === 'start') {
// 父组件通知开始系数校准操作
handleSubmit()
}
})
/**
* 监听WebSocket消息处理系数校准过程中的各种响应
* 主要处理:
* 1. 错误代码的统一处理
* 2. 系数校准流程的各个步骤响应
* 3. 表格数据的实时更新
*/
watch(webMsgSend, function (newValue, oldValue) {
console.log('webMsgSend---code', newValue.code)
console.log('webMsgSend---requestId', newValue.requestId)
// 只有在非等待状态下才处理WebSocket消息
if (testStatus.value !== 'waiting') {
// ==================== 通用错误代码处理 ====================
if (newValue.code == 10520) {
// 报文解析异常
ElMessageBox.alert('报文解析异常!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10521) {
// 程控源参数有误
ElMessageBox.alert('程控源參数有误!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10522) {
// 测试项解析有误
ElMessageBox.alert('测试项解析有误!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10523) {
// 源连接失败
ElMessageBox.alert('源连接失败!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10524) {
// 获取源控制权失败
ElMessageBox.alert('获取源控制权失败!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10525) {
// 重置源失败
ElMessageBox.alert('重置源失败!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10527) {
// 源未进行初始化
ElMessageBox.alert('源未进行初始化!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10528) {
// 目标源有误(用户已控制其他源)
ElMessageBox.alert('目标源有误(该用户已控制其他源,在关闭前无法操作新的源)', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10529) {
// 源状态有误,无法响应报文
ElMessageBox.alert('源状态有误,无法响应报文(例如源处于输出状态,无法响应初始化报文)', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10550) {
// 设备连接异常
ElMessageBox.alert(`${newValue.data}设备连接异常!`, '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10551) {
// 设备触发报告异常
ElMessageBox.alert(`${newValue.data}设备触发报告异常!`, '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10552) {
// 存在已经初始化步骤,执行自动关闭
ElMessageBox.alert('存在已经初始化步骤,执行自动关闭,请重新发起检测', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else {
// ==================== 特定业务消息处理 ====================
console.log('显示东西code', newValue.code)
console.log('显示东西requestId', newValue.requestId)
switch (newValue.requestId) {
// 处理源通讯校验相关消息
case 'yjc_ytxjy':
switch (newValue.operateCode) {
case'INIT_GATHER':
if (newValue.code == -1) {
// 源未知异常
ElMessageBox.alert('源未知异常', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10523) {
// 源连接失败
ElMessageBox.alert('源连接失败', '源连接失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
}
break;
// 处理相序校验相关消息
case 'YJC_xujy':
switch (newValue.operateCode) {
case 'OPER_GATHER':
if (newValue.code == 10552) {
// 存在已经初始化步骤,执行自动关闭
ElMessageBox.alert('存在已经初始化步骤,执行自动关闭,请重新发起检测', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10520) {
// 解析报文异常
ElMessageBox.alert('解析报文异常,执行自动关闭,请重新发起检测', '解析报文异常', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
break;
case 'DATA_REQUEST$02':
if (newValue.code == 25003) {
// 相序校验未通过
ElMessageBox.alert('相序校验未通过,执行自动关闭,请重新发起检测', '相序校验未通过', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
break;
}
break;
// 处理设备通讯校验相关消息
case 'yjc_sbtxjy':
switch (newValue.operateCode) {
case 'INIT_GATHER$01':
if (newValue.code == 10550) {
// 设备连接异常
ElMessageBox.alert('设备连接异常', '设备连接异常', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10551) {
// 设备触发报告异常
ElMessageBox.alert('设备触发报告异常', '设备触发报告异常', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10552) {
// 存在已经初始化步骤,执行自动关闭
ElMessageBox.alert('存在已经初始化步骤,执行自动关闭,请重新发起检测', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
} else if (newValue.code == 10520) {
// 解析报文异常
ElMessageBox.alert('解析报文异常,执行自动关闭,请重新发起检测', '解析报文异常', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
break;
}
break;
// 处理协议校验相关消息
case 'yjc_xyjy':
switch (newValue.operateCode) {
case 'VERIFY_MAPPING$01':
if (newValue.code == 10200) {
// 脚本与ICD校验失败
let data = JSON.parse(newValue.data)
ElMessageBox.alert(`脚本与icd校验失败icd名称${data['icdType']} -> 校验项:${data['dataType']}`, '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
if (newValue.code == 10500) {
// 装置中未找到该ICD
ElMessageBox.alert(`装置中未找到该icd!`, '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
}
break;
}
break;
// ★★★ 处理系数校准核心业务消息 ★★★
case 'Coefficient_Check':
console.log("Coefficient_Checkactive", active.value);
// ==================== 第1阶段大电压/电流系数下装 ====================
switch (newValue.operateCode) {
case 'big_start':
// 大电压/电流系数下装开始,显示源输出参数
big_V_Download.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
big_I_Download.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
break;
case 'big_end':
// 大电压/电流系数下装完成,进入下一阶段
active.value++; // 步骤进度+1
tableLoading('small', '系数下装') // 开始小电压/电流下装的加载动画
break;
}
// ==================== 第2阶段小电压/电流系数下装 ====================
switch (newValue.operateCode) {
case 'small_start':
// 小电压/电流系数下装开始,显示源输出参数
small_V_Download.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
small_I_Download.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
break;
case 'small_end':
// 小电压/电流系数下装完成,进入校准阶段
active.value++; // 步骤进度+1
tableLoading('big', '系数校准') // 开始大电压/电流校准的加载动画
break;
}
// ==================== 第3阶段大电压/电流系数校准 ====================
switch (newValue.operateCode) {
case 'big_comp_start':
// 大电压/电流系数校准开始,显示源输出参数
big_V_Adjust.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
big_I_Adjust.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
break;
case 'big_comp_end':
// 大电压/电流系数校准完成,进入最后阶段
active.value++; // 步骤进度+1
tableLoading('small', '系数校准') // 开始小电压/电流校准的加载动画
break;
}
// ==================== 第4阶段小电压/电流系数校准(最终阶段)====================
switch (newValue.operateCode) {
case 'small_comp_start':
// 小电压/电流系数校准开始,显示源输出参数
small_V_Adjust.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
small_I_Adjust.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
break;
case 'small_comp_end':
// ★★★ 小电压/电流系数校准完成 - 整个系数校准流程结束 ★★★
active.value++; // 步骤进度+1
active.value++; // 再+1跳转到完成状态
// 统计所有设备的校准结果
for (let i = 0; i < name.value.length; i++) {
const currentDataRef = tableDataMap.get(i);
if (currentDataRef) {
const currentData = currentDataRef.value;
// 检查当前设备的校准数据是否合格
const hasError = checkForErrors(currentData);
if (!hasError) {
qualified.value++; // 合格设备计数+1
}
updateErrorState(i, hasError); // 更新设备错误状态显示
}
}
isButtonDisabled.value = false; // 恢复按钮可用状态
// ★★★ 通知父组件系数校准成功完成,触发自动步骤切换 ★★★
emit('update:testStatus', 'success')
break;
}
// ==================== 表格数据实时更新 ====================
switch (newValue.operateCode) {
case 'DATA_CHNFACTOR$02':
// 接收并更新表格中的系数校准数据
console.log('表格', name.value)
// 遍历所有设备,找到匹配的表格项并更新数据
for (let i = 0; i < name.value.length; i++) {
const targetArrayRef = tableDataMap.get(i);
if (targetArrayRef) {
const targetArray = targetArrayRef.value;
if (targetArray.length > 0) {
// 根据监测点号、类型、描述和设备名称找到对应的表格行
const firstCoefficientVO = targetArray.find(item =>
item.monitorNum === newValue.data.monitorNum &&
item.type === newValue.data.type &&
item.desc === newValue.data.desc &&
item.devName === newValue.data.devName);
if (firstCoefficientVO) {
// 更新A相电压数据和误差
firstCoefficientVO.aVuData = parseFloat(newValue.data.aVuData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.aVuXi)) && isFinite(newValue.data.aVuXi)) {
firstCoefficientVO.aVuXi = (parseFloat(newValue.data.aVuXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.aVuXi = newValue.data.aVuXi; // 可能是"不合格"等文本
}
// 更新B相电压数据和误差
firstCoefficientVO.bVuData = parseFloat(newValue.data.bVuData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.bVuXi)) && isFinite(newValue.data.bVuXi)) {
firstCoefficientVO.bVuXi = (parseFloat(newValue.data.bVuXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.bVuXi = newValue.data.bVuXi; // 可能是"不合格"等文本
}
// 更新C相电压数据和误差
firstCoefficientVO.cVuData = parseFloat(newValue.data.cVuData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.cVuXi)) && isFinite(newValue.data.cVuXi)) {
firstCoefficientVO.cVuXi = (parseFloat(newValue.data.cVuXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.cVuXi = newValue.data.cVuXi; // 可能是"不合格"等文本
}
// 更新A相电流数据和误差
firstCoefficientVO.aIeData = parseFloat(newValue.data.aIeData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.aIeXi)) && isFinite(newValue.data.aIeXi)) {
firstCoefficientVO.aIeXi = (parseFloat(newValue.data.aIeXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.aIeXi = newValue.data.aIeXi; // 可能是"不合格"等文本
}
// 更新B相电流数据和误差
firstCoefficientVO.bIeData = parseFloat(newValue.data.bIeData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.bIeXi)) && isFinite(newValue.data.bIeXi)) {
firstCoefficientVO.bIeXi = (parseFloat(newValue.data.bIeXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.bIeXi = newValue.data.bIeXi; // 可能是"不合格"等文本
}
// 更新C相电流数据和误差
firstCoefficientVO.cIeData = parseFloat(newValue.data.cIeData).toFixed(4);
if (!isNaN(parseFloat(newValue.data.cIeXi)) && isFinite(newValue.data.cIeXi)) {
firstCoefficientVO.cIeXi = (parseFloat(newValue.data.cIeXi) / 10000).toFixed(4);
} else {
firstCoefficientVO.cIeXi = newValue.data.cIeXi; // 可能是"不合格"等文本
}
// 更新三相电压和电流的原始值
firstCoefficientVO.aV = newValue.data.aV;
firstCoefficientVO.bV = newValue.data.bV;
firstCoefficientVO.cV = newValue.data.cV;
firstCoefficientVO.aI = newValue.data.aI;
firstCoefficientVO.bI = newValue.data.bI;
firstCoefficientVO.cI = newValue.data.cI;
console.log(newValue.data.devName + '对象:', firstCoefficientVO);
activeIndex.value++; // 更新活跃索引
} else {
console.log('未找到匹配的' + newValue.data.devName + '对象');
}
} else {
console.log(newValue.data.devName + '数组为空');
}
} else {
console.log('未找到' + newValue.data.devName + '对应的数组');
}
}
break;
}
break;
// 处理Socket连接超时
case 'socket_timeout':
switch (newValue.operateCode) {
case 'VOLTAGE':
// 电压连接超时
ElMessageBox.alert('连接超时!', '连接超时', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
break;
}
break;
// 处理连接失败
case 'connect':
switch (newValue.operateCode) {
case "Source":
// 源服务端连接失败
ElMessageBox.alert('源服务端连接失败', '源服务端连接失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
break;
case "Dev":
// 设备服务端连接失败
ElMessageBox.alert('设备服务端连接失败', '设备服务端连接失败', {
confirmButtonText: '确定',
type: 'error',
})
TableInit();
break;
}
break;
}
}
}
})
// ==================== 错误处理函数 ====================
/**
* 系数校准出错时的初始化处理
* 通知父组件检测失败,重置相关状态
*/
const TableInit = () => {
console.log("出错系数检测",active.value);
// 通知父组件系数校准失败
emit('update:testStatus', 'error')
}
// ==================== 界面动画控制 ====================
/**
* 控制表格中特定类型和描述的行显示加载动画
* @param type 类型:'big' | 'small'
* @param desc 描述:'系数下装' | '系数校准'
*/
const tableLoading = (type: string, desc: string) => {
console.log('转动',channel.value)
// 遍历所有设备
for (let i = 0; i < channel.value.length; i++) {
const targetArrayRef = tableDataMap.get(i);
if (targetArrayRef) {
const targetArray = targetArrayRef.value;
if (targetArray.length > 0) {
// 遍历当前设备的所有通道
for (let j = 0; j < channel.value[i]; j++) {
// 找到对应类型和描述的表格行
const firstCoefficientVO = targetArray.find(item =>
item.monitorNum === (j + 1).toString() &&
item.type === type &&
item.desc === desc);
if (firstCoefficientVO) {
firstCoefficientVO.loading = true; // 开启加载动画
}
}
}
} else {
console.log('不转了')
}
}
}
// ==================== 表格数据模板 ====================
/**
* 系数校准表格的数据模板
* 每个设备的每个通道都会根据这4个模板生成对应的表格行
*
* 模板说明:
* 1. 监测点1 - 大幅值系数下装
* 2. 监测点2 - 小幅值系数下装
* 3. 监测点3 - 大幅值系数校准
* 4. 监测点4 - 小幅值系数校准
*/
const dataTemplates: ChannelsTest.CoefficientVO[] = [
{
monitorNum: '1', // 监测点编号
desc: '系数下装', // 操作描述
type: 'big', // 幅值类型:大幅值
aVuData: '—', // A相电压测量值
aVuXi: '—', // A相电压误差
bVuData: '—', // B相电压测量值
bVuXi: '—', // B相电压误差
cVuData: '—', // C相电压测量值
cVuXi: '—', // C相电压误差
aIeData: '—', // A相电流测量值
aIeXi: '—', // A相电流误差
bIeData: '—', // B相电流测量值
bIeXi: '—', // B相电流误差
cIeData: '—', // C相电流测量值
cIeXi: '—', // C相电流误差
loading: false, // 加载状态
devName: '', // 设备名称(动态填充)
aV: '—', // A相电压原始值
bV: '—', // B相电压原始值
cV: '—', // C相电压原始值
aI: '—', // A相电流原始值
bI: '—', // B相电流原始值
cI: '—', // C相电流原始值
},
{
monitorNum: '2', // 监测点编号
desc: '系数下装', // 操作描述
type: 'small', // 幅值类型:小幅值
aVuData: '—',
aVuXi: '—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading: false,
devName: '',
aV: '—',
bV: '—',
cV: '—',
aI: '—',
bI: '—',
cI: '—',
},
{
monitorNum: '3', // 监测点编号
desc: '系数校准', // 操作描述
type: 'big', // 幅值类型:大幅值
aVuData: '—',
aVuXi: '—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading: false,
devName: '',
aV: '—',
bV: '—',
cV: '—',
aI: '—',
bI: '—',
cI: '—',
},
{
monitorNum: '4', // 监测点编号
desc: '系数校准', // 操作描述
type: 'small', // 幅值类型:小幅值
aVuData: '—',
aVuXi: '—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading: false,
devName: '',
aV: '—',
bV: '—',
cV: '—',
aI: '—',
bI: '—',
cI: '—',
},
];
// ==================== 工具函数 ====================
/**
* 更新设备错误状态显示
* @param index 设备索引
* @param hasError 是否有错误
*/
const updateErrorState = (index: number, hasError: boolean) => {
errorStates.value[index] = hasError;
};
/**
* 获取指定设备的表格数据
* @param index 设备索引
* @returns 返回对应设备的表格数据数组
*/
const getTableDataForChannel = (index: number): any[] => {
const data = tableDataMap.get(index);
return data ? data.value : [];
}
// ==================== 父子组件通信 ====================
const emit = defineEmits(['update:testStatus']);
// ==================== 界面状态监听 ====================
/**
* 监听活跃索引变化,更新界面描述信息
*/
watch(activeIndex, function (newValue, oldValue) {
if (activeIndex.value === 1) {
outputDsc.value = "电压误差为±0.1Un% 电流误差为±0.5%";
}
})
// ==================== 业务逻辑函数 ====================
/**
* 检查设备校准数据是否存在错误
* @param data 设备的校准数据数组
* @returns 返回是否存在不合格项
*/
const checkForErrors = (data: ChannelsTest.CoefficientVO[]): boolean => {
// 检查各相电压和电流的误差值是否为"不合格"
return data.some(item =>
item.aVuXi === '不合格' ||
item.bVuXi === '不合格' ||
item.cVuXi === '不合格' ||
item.aIeXi === '不合格' ||
item.bIeXi === '不合格' ||
item.cIeXi === '不合格'
);
};
/**
* 处理系数校准开始事件
* 由父组件通过状态监听触发
*/
const handleSubmit = async () => {
isButtonDisabled.value = true; // 禁用按钮,防止重复提交
tableLoading('big', '系数下装') // 开启大幅值系数下装的加载动画
active.value++; // 步骤进度+1进入第一个校准阶段
console.log('开始检测active.value', active.value)
};
/**
* 为指定设备初始化表格数据
* @param templates 数据模板数组
* @param index 设备索引
* @returns 返回初始化后的表格数据引用
*/
const initializeTableData = (templates: ChannelsTest.CoefficientVO[], index: number): Ref<ChannelsTest.CoefficientVO[]> => {
const currentTableData = ref<ChannelsTest.CoefficientVO[]>([]);
// 为当前设备的每个通道生成表格数据
for (let j = 0; j < channel.value[index]; j++) {
templates.forEach((template) => {
// 使用解构赋值复制模板,排除不需要的属性
const {devName, monitorNum: __, ...rest} = template;
currentTableData.value.push({
monitorNum: (j + 1).toString(), // 监测点号从1开始
devName: name.value[index], // 设置设备名称
...rest, // 其他模板属性
});
});
}
return currentTableData;
};
</script>
<style scoped lang="scss">
/* 确保 el-icon-loading 的动画效果没有被覆盖 */
.loading-box {
animation: rotate 2s linear infinite;
font-size: 30px; /* 增大图标的大小 */
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.right-title {
display: flex;
flex-direction: row;
/* 横向排列 */
justify-content: space-between;
margin-bottom: 10px;
}
.custom-tabs-label .el-icon {
vertical-align: middle;
}
.custom-tabs-label span {
vertical-align: middle;
margin-left: 4px;
}
.dialog-content {
height: 510px;
}
.el-tabs--border-card {
height: 470px;
}
/* .el-icon svg {
color: #ff7171;
} */
.icon-style {
color: #ff7171;
}
.container {
display: flex;
}
.dialog-left {
flex: 1;
}
.right-content {
flex: 6;
}
.spanStyle {
font-size: 14px;
}
</style>