Files
pqs-9100_client/frontend/src/views/home/components/channelsTest.vue
2025-01-08 11:40:12 +08:00

709 lines
23 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
<el-dialog v-model='dialogVisible' title="系数校准" v-bind="dialogBig" width="1500px" @close="handleCancel">
<div class="test-dialog" >
<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: #67C23A">{{ 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">
</channelsTestTable>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit" :disabled="isButtonDisabled">开始系数校准</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="tsx" setup name="channelsTest">
import { type Device } from '@/api/device/interface/device';
import { SuccessFilled, Failed, Message, MessageBox } from '@element-plus/icons-vue'
import { type Ref, ref, toRef, watch } from 'vue'
import {dialogBig} from '@/utils/elementBind'
import { ElMessage, ElMessageBox, TabsPaneContext } 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';
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)
let timer1: NodeJS.Timeout | null = null; // 声明并初始化 timer1
let timer2: NodeJS.Timeout | null = null; // 同样声明并初始化 timer2
const name = ref<string[]>([])//系数校准所选设备名字数组
const channel = ref<number[]>([])//系数校准所选设备通道数组
const devIdArray = ref<string[]>([])//系数校准所选设备ID数组
const select_Plan = ref<Plan.ReqPlan>()
const planId = ref('')
const isButtonDisabled = ref(false);
// 在 setup 函数中
const errorStates = ref(new Array(name.value.length).fill(false));
//const loadingStates = ref(new Array(name.value.length).fill(false)); // 初始化 loading 状态
const big_V_loadingStates = ref(false); // 初始化 大电压大电流下装loading 状态
const small_V_loadingStates = ref(false); // 初始化 小电压小电流下装loading 状态
const big_V_loadingStates2 = ref(false); // 初始化 大电压大电流校准loading 状态
const small_V_loadingStates2 = ref(false); // 初始化 小电压小电流校准loading 状态
const editableTabsValue = ref('0')
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('')
const props = defineProps({
webMsgSend: {
type: Object,
default: () => ({})
}
})
const tableDataMap = new Map<number, Ref<ChannelsTest.CoefficientVO[]>>([]);
const currentStepStatus = ref<'error' | 'finish' | 'wait' | 'success' | 'process'>('finish');
const webMsgSend = toRef(props, 'webMsgSend');
watch(webMsgSend,function (newValue,oldValue){
switch (newValue.requestId){
case 'yjc_sbtxjy':
switch (newValue.operateCode) {
case 'INIT_GATHER$01':
if (newValue.code == 10550) {
ElMessageBox.alert('设备连接异常', '设备连接异常', {
confirmButtonText: '确定',
type: 'error',
})
}else if (newValue.code == 10551) {
ElMessageBox.alert('设备触发报告异常', '设备触发报告异常', {
confirmButtonText: '确定',
type: 'error',
})
} else if (newValue.code == 10552) {
ElMessageBox.alert('存在已经初始化步骤,执行自动关闭,请重新发起检测', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
}
break;
}
break;
case 'Coefficient_Check':
switch (newValue.operateCode){
case 'big_end'://大电压,电流下装
active.value++;
big_V_Download.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
big_I_Download.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
tableLoading('small','系数下装')
break;
}
switch (newValue.operateCode){
case 'small_end'://小电压,电流下装
active.value++;
small_V_Download.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
small_I_Download.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
tableLoading('big','系数校准')
break;
}
switch (newValue.operateCode){
case 'big_comp_end'://大电压,电流校准
active.value++;
big_V_Adjust.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
big_I_Adjust.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
tableLoading('small','系数校准')
break;
}
switch (newValue.operateCode){
case 'small_comp_end'://小电压,电流校准
active.value++;
small_V_Adjust.value = 'Ua=Ub=Uc=' + newValue.data.devVolt + 'V';
small_I_Adjust.value = 'Ia=Ib=Ic=' + newValue.data.devCurr + 'A';
active.value++;
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) {
} else {
qualified.value++;
}
updateErrorState(i, hasError);
}
}
//editableTabsValue.value = (tabNumber.value).toString();//显示下一个tab
isButtonDisabled.value = false; // 恢复按钮
break;
}
switch (newValue.operateCode){
case 'DATA_CHNFACTOR$02'://表格
// 输出 key 为 0 的数组中的第一条 ChannelsTest.CoefficientVO 对象
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) { // 检查 firstCoefficientVO 是否存在
firstCoefficientVO.aVuData = parseFloat(newValue.data.aVuData).toFixed(4);;
firstCoefficientVO.aVuXi = newValue.data.aVuXi;
firstCoefficientVO.bVuData = parseFloat(newValue.data.bVuData).toFixed(4);
firstCoefficientVO.bVuXi = newValue.data.bVuXi;
firstCoefficientVO.cVuData = parseFloat(newValue.data.cVuData).toFixed(4);
firstCoefficientVO.cVuXi = newValue.data.cVuXi;
firstCoefficientVO.aIeData = parseFloat(newValue.data.aIeData).toFixed(4);
firstCoefficientVO.aIeXi = newValue.data.aIeXi;
firstCoefficientVO.bIeData = parseFloat(newValue.data.bIeData).toFixed(4);
firstCoefficientVO.bIeXi = newValue.data.bIeXi;
firstCoefficientVO.cIeData = parseFloat(newValue.data.cIeData).toFixed(4);
firstCoefficientVO.cIeXi = newValue.data.cIeXi;
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;
case 'socket_timeout':
switch(newValue.operateCode){
case 'VOLTAGE':
ElMessageBox.alert('连接超时!', '连接超时', {
confirmButtonText: '确定',
type: 'error',
})
break;
}
break;
case 'connect':
switch (newValue.operateCode){
case "Source":
ElMessageBox.alert('源服务端连接失败', '源服务端连接失败', {
confirmButtonText: '确定',
type: 'error',
})
break;
case "Dev":
ElMessageBox.alert('设备服务端连接失败', '设备服务端连接失败', {
confirmButtonText: '确定',
type: 'error',
})
break;
}
break;
}
})
//按行图标转动
const tableLoading = (type: string, desc: string) => {
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;
}
}
}
}
}
}
const dataTemplates : ChannelsTest.CoefficientVO[]= [
{
monitorNum: '1',
desc: '系数下装',
type:'big',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading:false,
devName:''
},
{
monitorNum: '2',
desc: '系数下装',
type:'small',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading:false,
devName:''
},
{
monitorNum: '3',
desc: '系数校准',
type:'big',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading:false,
devName:''
},
{
monitorNum: '4',
desc: '系数校准',
type:'small',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
loading:false,
devName:''
},
];
const dataTemplates2 : ChannelsTest.CoefficientVO[]= [
{
monitorNum: '1',
desc: '系数下装',
type:'big',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
},
{
monitorNum: '2',
desc: '系数下装',
type:'small',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
},
{
monitorNum: '3',
desc: '系数校准',
type:'big',
aVuData: '—',
aVuXi:'不合格',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
},
{
monitorNum: '4',
desc: '系数校准',
type:'small',
aVuData: '—',
aVuXi:'—',
bVuData: '—',
bVuXi: '—',
cVuData: '—',
cVuXi: '—',
aIeData: '—',
aIeXi: '—',
bIeData: '—',
bIeXi: '—',
cIeData: '—',
cIeXi: '—',
},
];
// 更新错误状态的方法
const updateErrorState = (index: number, hasError: boolean) => {
errorStates.value[index] = hasError;
};
// 打开弹窗,可能是新增,也可能是编辑
const open = (selection: Device.ResPqDev[],plan:Plan.ReqPlan) => {
const checkStates = selection.map(item => item.checkState);
const allCheckStatesEqual = new Set(checkStates).size <= 1;
if (!allCheckStatesEqual) {
ElMessageBox.confirm(
'所勾选设备检测状态不一致,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
return
}
isButtonDisabled.value = false; // 恢复按钮
select_Plan.value = plan
planId.value = selection[0]?.planId || '';
devIdArray.value = selection.map(item => item.id);
name.value = selection.map(item => item.name)
channel.value = selection.map(item => item.devChns)
dialogVisible.value = true;
total.value = name.value.length
// 初始化 loadingStates 为 false
// loadingStates.value = new Array(selection.length).fill(false);
errorStates.value = new Array(selection.length).fill(false);
for (let i = 0; i < channel.value.length; i++) {
const currentTableData = initializeTableData(dataTemplates, i);
tableDataMap.set(i,currentTableData)
}
console.log('tableDataMap',tableDataMap);
}
const handleCancel=() => {
// 清空 name, channel, total
name.value = [];
channel.value = [];
total.value = 0;
activeIndex.value = 0
qualified.value = 0
active.value = 0
dialogVisible.value = false
editableTabsValue.value = '0'
}
const getTableDataForChannel = (index: number): any[] => {
const data = tableDataMap.get(index);
return data ? data.value : [];
}
watch(activeIndex, function (newValue, oldValue) {
if(activeIndex.value === 1)
{
outputDsc.value = "电压误差为±0.1Un% 电流误差为±0.5%";
// 当前源输出为Ua=Ub=Uc=57.74V Ia=Ib=Ic=1A"
}
})
// 示例的 checkForErrors 函数,根据实际需求进行调整
const checkForErrors = (data: ChannelsTest.CoefficientVO[]): boolean => {
// 这里假设不合格字段的标准是 status 为 '不合格' 或 isValid 为 false
return data.some(item =>
item.aVuXi === '不合格' ||
item.bVuXi === '不合格' ||
item.cVuXi === '不合格' ||
item.aIeXi === '不合格' ||
item.bIeXi === '不合格' ||
item.cIeXi === '不合格'
);
};
const handleSubmit = async () => {
isButtonDisabled.value = true; // 禁用按钮
tableLoading('big','系数下装')
await getCoefficientCheck({
userPageId: "cdf",
devIds: devIdArray.value,
planId:planId.value,
errorSysId: select_Plan.value?.errorSysId,
     scriptId: select_Plan.value?.scriptId,
operateType:'0' // '0'为预检测、1为正式检测
})
active.value++;
// 初始化 loadingStates 为 true
// loadingStates.value = new Array(name.value.length).fill(true);
return;
// 初始化 currentTableData
let isTimer2Completed = false;
//"80b4b4f52a4c4064a18319525f8ac13c",
for (let i = 0; i < channel.value.length; i++) {
// 重置状态变量
active.value = 0;
//activeIndex.value = 0;
editableTabsValue.value = i.toString();
// 初始化并填充 currentTableData
const currentTableData = initializeTableData(dataTemplates2, i);
tableDataMap.set(i, currentTableData);
//activeIndex.value++;
// 清除之前的 timer1
clearInterval(timer1);
// 启动 timer1
timer1 = setInterval(() => {
active.value++;
if (active.value > 5) {
clearInterval(timer1);
}
}, 3000);
// 清除之前的 timer2
clearInterval(timer2);
// 启动 timer2
timer2 = setInterval(() => {
// 初始化并填充 currentTableData
const currentTableData = initializeTableData(i > 0 ? dataTemplates2 : dataTemplates2, i);
tableDataMap.set(i, currentTableData);
activeIndex.value++;
clearInterval(timer2);
const currentDataRef = tableDataMap.get(i);
if (currentDataRef) {
const currentData = currentDataRef.value;
// 检查当前数据中有无不合格字段
const hasError = checkForErrors(currentData);
if (hasError) {
} else {
qualified.value++;
}
updateErrorState(i, hasError);
}
// 设置标志变量为 true表示 timer2 已经完成
isTimer2Completed = true;
}, 3000);
// 等待 timer2 完成
while (!isTimer2Completed) {
// 这里可以添加一个短暂的等待,避免死循环
await new Promise(resolve => setTimeout(resolve, 100));
}
// 重置标志变量
isTimer2Completed = false;
}
};
// 提取初始化并填充 currentTableData 的函数
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) => {
// 使用解构赋值排除 id 和 MonitorIdx 属性
const { devName,monitorNum: __, ...rest } = template;
currentTableData.value.push({
monitorNum: (j + 1).toString(),
devName: name.value[index],
...rest,
});
});
}
return currentTableData;
};
// 对外映射
defineExpose({ open })
</script>
<style scoped>
/* 确保 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>