Files
pqs-9100_client/frontend/src/views/home/components/channelsTest.vue
2024-12-30 14:43:13 +08:00

831 lines
22 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>
<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>源输出为</span><br/>
<span v-if="active > 0">Ua=Ub=Uc=57.74V</span><br/>
<span v-if="active > 0">Ia=Ib=Ic=10A</span>
</template>
</el-step>
<el-step>
<template #title>
<span>小电压/电流系数下装</span><br/>
<span>源输出为</span><br/>
<span v-if="active > 1">Ua=Ub=Uc=5.774V</span><br/>
<span v-if="active > 1">Ia=Ib=Ic=1A</span>
</template>
</el-step>
<el-step>
<template #title>
<span>大电压/电流校准</span><br/>
<span>源输出为</span><br/>
<span v-if="active > 2">Ua=Ub=Uc=57.74V</span><br/>
<span v-if="active > 2">Ia=Ib=Ic=10A</span>
</template>
</el-step>
<el-step>
<template #title>
<span>小电压/电流校准</span><br/>
<span>源输出为</span><br/>
<span v-if="active > 3">Ua=Ub=Uc=5.774V</span><br/>
<span v-if="active > 3">Ia=Ib=Ic=1A</span>
</template>
</el-step>
<el-step title="结束"/>
</el-steps>
</div>
<div class="right-content">
<el-tabs type="border-card">
<div >
<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]">
<Failed />
</el-icon>
</span>
</template>
<channelsTestTable :tableData="getTableDataForChannel(index)" :loading="loadingStates[index]"></channelsTestTable>
</el-tab-pane>
</div>
<el-empty description="暂无数据,等待检测开始" v-if="activeIndex === 0" />
</el-tabs>
<!-- <el-tabs type="border-card">
<el-empty description="暂无数据,等待检测开始" v-if="activeIndex === 0" />
<el-tab-pane label="240001" v-if="activeIndex > 0">
<template #label>
<span class="custom-tabs-label">
<span>240001</span>
<el-icon>
<Failed />
</el-icon>
</span>
</template>
<channelsTestTable :tableData="tableData1"></channelsTestTable>
</el-tab-pane>
<el-tab-pane label="240002" v-if="activeIndex > 1">
<template #label>
<span class="custom-tabs-label">
<span>240002</span>
<el-icon>
<Failed />
</el-icon>
</span>
</template>
<channelsTestTable :tableData="tableData2"></channelsTestTable>
</el-tab-pane>
<el-tab-pane label="240003" v-if="activeIndex > 2">
<channelsTestTable :tableData="tableData3"></channelsTestTable>
</el-tab-pane>
<el-tab-pane label="240004" v-if="activeIndex > 3">
<channelsTestTable :tableData="tableData4"></channelsTestTable>
</el-tab-pane>
</el-tabs> -->
</div>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit">开始系数校准</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 } from 'element-plus';
import { el } from 'element-plus/es/locale';
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 intervalId: NodeJS.Timeout | null = null;
const name = ref<string[]>([])//系数校准所选设备名字数组
const channel = ref<number[]>([])//系数校准所选设备通道数组
// 在 setup 函数中
const errorStates = ref(new Array(name.value.length).fill(false));
const loadingStates = ref(new Array(name.value.length).fill(false)); // 初始化 loading 状态
// 定义 TableDataItem 接口
interface TableDataItem {
id: string;
deviceName?: string;
MonitorIdx: number;
UaData?: number | string;
UaChannel?: number | string;
UbData?: number | string;
UbChannel?: number | string;
UcData?: number | string;
UcChannel?: number | string;
IaData?: number | string;
IaChannel?: number | string;
IbData?: number | string;
IbChannel?: number | string;
IcData?: number | string;
IcChannel?: number | string;
Result?: string | string;
updateTime?: string;
}
const dataTemplates3 = [
{
deviceName: '系数下装',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
{
deviceName: '系数下装',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
{
deviceName: '系数校准',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
{
deviceName: '系数校准',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
];
const dataTemplates4 = [
{
deviceName: '系数下装',
UaData: 57.74,
UaChannel: 1.0003,
UbData: 57.74,
UbChannel: 1.0003,
UcData: 57.74,
UcChannel: 1.0003,
IaData: 10,
IaChannel: 1.0001,
IbData: 10,
IbChannel: 1.0001,
IcData: 10,
IcChannel: 1.0001,
},
{
deviceName: '系数下装',
UaData: 5.774,
UaChannel: 1.0003,
UbData: 5.774,
UbChannel: 1.0003,
UcData: 5.774,
UcChannel: 1.0003,
IaData: 1,
IaChannel: 1.0001,
IbData: 1,
IbChannel: 1.0001,
IcData: 1,
IcChannel: 1.0001,
},
{
deviceName: '系数校准',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
{
deviceName: '系数校准',
UaData: '—',
UaChannel:'—',
UbData: '—',
UbChannel: '—',
UcData: '—',
UcChannel: '—',
IaData: '—',
IaChannel: '—',
IbData: '—',
IbChannel: '—',
IcData: '—',
IcChannel: '—',
},
];
const dataTemplates5 = [
{
deviceName: '系数下装',
UaData: 57.74,
UaChannel: 1.0003,
UbData: 57.74,
UbChannel: 1.0003,
UcData: 57.74,
UcChannel: 1.0003,
IaData: 10,
IaChannel: 1.0001,
IbData: 10,
IbChannel: 1.0001,
IcData: 10,
IcChannel: 1.0001,
},
{
deviceName: '系数下装',
UaData: 5.774,
UaChannel: 1.0003,
UbData: 5.774,
UbChannel: 1.0003,
UcData: 5.774,
UcChannel: 1.0003,
IaData: 1,
IaChannel: 1.0001,
IbData: 1,
IbChannel: 1.0001,
IcData: 1,
IcChannel: 1.0001,
},
{
deviceName: '系数校准',
UaData: 57.74,
UaChannel: '不合格',
UbData: 57.74,
UbChannel: '合格',
UcData: 57.74,
UcChannel: '合格',
IaData: 10,
IaChannel: '合格',
IbData: 10,
IbChannel: '合格',
IcData: 10,
IcChannel: '合格',
},
{
deviceName: '系数校准',
UaData: 5.774,
UaChannel: '不合格',
UbData: 5.774,
UbChannel: '合格',
UcData: 5.774,
UcChannel: '合格',
IaData: 1,
IaChannel: '合格',
IbData: 1,
IbChannel: '合格',
IcData: 1,
IcChannel: '合格',
},
];
const dataTemplates6 = [
{
deviceName: '系数下装',
UaData: 57.74,
UaChannel: 1.0003,
UbData: 57.74,
UbChannel: 1.0003,
UcData: 57.74,
UcChannel: 1.0003,
IaData: 10,
IaChannel: 1.0001,
IbData: 10,
IbChannel: 1.0001,
IcData: 10,
IcChannel: 1.0001,
},
{
deviceName: '系数下装',
UaData: 5.774,
UaChannel: 1.0003,
UbData: 5.774,
UbChannel: 1.0003,
UcData: 5.774,
UcChannel: 1.0003,
IaData: 1,
IaChannel: 1.0001,
IbData: 1,
IbChannel: 1.0001,
IcData: 1,
IcChannel: 1.0001,
},
{
deviceName: '系数校准',
UaData: 57.74,
UaChannel: '合格',
UbData: 57.74,
UbChannel: '合格',
UcData: 57.74,
UcChannel: '合格',
IaData: 10,
IaChannel: '合格',
IbData: 10,
IbChannel: '合格',
IcData: 10,
IcChannel: '合格',
},
{
deviceName: '系数校准',
UaData: 5.774,
UaChannel: '合格',
UbData: 5.774,
UbChannel: '合格',
UcData: 5.774,
UcChannel: '合格',
IaData: 1,
IaChannel: '合格',
IbData: 1,
IbChannel: '合格',
IcData: 1,
IcChannel: '合格',
},
];
// 更新错误状态的方法
const updateErrorState = (index: number, hasError: boolean) => {
errorStates.value[index] = hasError;
};
const activities = [
{
content: '开始检测',
timestamp: '2018-04-12 20:46',
size: 'large',
color: '#0bbd87',
icon: SuccessFilled,
},
{
content: 'GPS上送时刻',
timestamp: '2018-04-03 20:46',
hollow: true,
},
{
content: '设备最早上送时刻',
timestamp: '2018-04-03 20:46',
hollow: true,
},
{
content: '设备最晚上送时刻',
timestamp: '2018-04-03 20:46',
hollow: true,
},
{
content: '检测结束',
timestamp: '2018-04-03 20:46',
hollow: true,
},
]
const tableDataMap = new Map<number, Ref<TableDataItem[]>>([
// [0, tableData1],
// [1, tableData2],
// [2, tableData3],
// [3, tableData1],
// [4, tableData1],
// [5, tableData1],
]);
const currentStepStatus = ref<'error' | 'finish' | 'wait' | 'success' | 'process'>('finish');
// 打开弹窗,可能是新增,也可能是编辑
const open = (selection: Device.ResPqDev[]) => {
const checkStates = selection.map(item => item.checkState);
const allCheckStatesEqual = new Set(checkStates).size <= 1;
if (!allCheckStatesEqual) {
ElMessageBox.confirm(
'所勾选设备检测状态不一致,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
return
}
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 = ref<TableDataItem[]>([]);
// 随机选择 dataTemplates 或 dataTemplates2
const selectedTemplates = dataTemplates3;
for(let j = 0; j < channel.value[i]; j++){
const id = (j + 1).toString();
selectedTemplates.forEach((template) => {
currentTableData.value.push({
id: id,
MonitorIdx: j + 1,
...template,
});
});
}
tableDataMap.set(i,currentTableData)
}
// // 循环生成数据
// for (let i = 0; i < channel.value.length; i++) {
// const currentTableData = ref<TableDataItem[]>([]);
// // 随机选择 dataTemplates 或 dataTemplates2
// const selectedTemplates = Math.random() < 0.5 ? dataTemplates : dataTemplates2;
// for(let j = 0; j < channel.value[i]; j++){
// const id = (j + 1).toString();
// selectedTemplates.forEach((template) => {
// currentTableData.value.push({
// id: id,
// MonitorIdx: j + 1,
// ...template,
// });
// });
// }
// tableDataMap.set(i,currentTableData)
// }
}
const handleCancel=() => {
// 清空 name, channel, total
name.value = [];
channel.value = [];
total.value = 0;
activeIndex.value = 0
qualified.value = 0
active.value = 0
dialogVisible.value = false
}
const getTableDataForChannel = (index: number): any[] => {
const data = tableDataMap.get(index);
// console.log('index',index)
// console.log('data',data)
return data ? data.value : [];
}
// const props = defineProps({
// testStatus: {
// type: String,
// default: 'wait'
// }
// })
// const testStatus = toRef(props, 'testStatus');
// const ts = ref('');
// //监听goods_sn的变化
// watch(testStatus, function (newValue, oldValue) {
// ts.value = props.testStatus;
// if (ts.value === 'start') {
// ts.value = 'process'
// let timer = setInterval(() => {
// if (activeIndex.value < activeTotalNum.value) {
// activeIndex.value++
// if(activeIndex.value > 1)
// qualified.value = activeIndex.value -1;//演示效果,实际运行时使用后端传来的真实数据即可
// else
// qualified.value = activeIndex.value;
// }
// else if (activeIndex.value === activeTotalNum.value) {
// clearInterval(timer)
// ts.value = 'success'
// }
// else {
// clearInterval(timer)
// ts.value = 'success'
// }
// total.value = activeTotalNum.value
// }, 1000);
// }
// })
// const emit = defineEmits(['update:testStatus']);
// //监听sn
// watch(ts, function (newValue, oldValue) {
// //修改父组件
// emit('update:testStatus', ts.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: TableDataItem[]): boolean => {
// 这里假设不合格字段的标准是 status 为 '不合格' 或 isValid 为 false
return data.some(item =>
item.UaChannel === '不合格' ||
item.UbChannel === '不合格' ||
item.UcChannel === '不合格' ||
item.IaChannel === '不合格' ||
item.IbChannel === '不合格' ||
item.IcChannel === '不合格'
);
};
const handleSubmit = async () => {
if (intervalId !== null) {
clearInterval(intervalId);
}
// 初始化 currentTableData
let isTimer2Completed = false;
// 设置 loading 状态为 true
// 初始化 loadingStates 为 true
loadingStates.value = new Array(name.value.length).fill(true);
for (let i = 0; i < channel.value.length; i++) {
console.log('channel', channel.value[i]);
console.log('activeIndex', activeIndex.value);
const currentTableData = ref<TableDataItem[]>([]);
const selectedTemplates = dataTemplates4;
for (let j = 0; j < channel.value[i]; j++) {
const id = (j + 1).toString();
selectedTemplates.forEach((template) => {
currentTableData.value.push({
id: id,
MonitorIdx: j + 1,
...template,
});
});
}
tableDataMap.set(i, currentTableData);
console.log('tableDataMap after set', tableDataMap);
activeIndex.value++;
// 启动 timer2
let timer2 = setInterval(() => {
// 初始化 currentTableData
const currentTableData = ref<TableDataItem[]>([]);
if(i > 0){
const selectedTemplates = dataTemplates6;
for (let j = 0; j < channel.value[i]; j++) {
const id = (j + 1).toString();
selectedTemplates.forEach((template) => {
currentTableData.value.push({
id: id,
MonitorIdx: j + 1,
...template,
});
});
}
}else{
const selectedTemplates = dataTemplates5;
for (let j = 0; j < channel.value[i]; j++) {
const id = (j + 1).toString();
selectedTemplates.forEach((template) => {
currentTableData.value.push({
id: id,
MonitorIdx: j + 1,
...template,
});
});
}
}
tableDataMap.set(i, currentTableData);
clearInterval(timer2);
const currentDataRef = tableDataMap.get(activeIndex.value - 1);
console.log('activeIndex.value',activeIndex.value);
console.log('tableDataMap',tableDataMap);
console.log('currentDataRef',currentDataRef);
if (currentDataRef) {
const currentData = currentDataRef.value;
// 检查当前数据中有无不合格字段
const hasError = checkForErrors(currentData);
if (hasError) {
} else {
qualified.value++;
}
updateErrorState(activeIndex.value - 1, hasError);
}
activeIndex.value++;
// 设置标志变量为 true表示 timer2 已经完成
isTimer2Completed = true;
}, 3000);
// 等待 timer2 完成
while (!isTimer2Completed) {
// 这里可以添加一个短暂的等待,避免死循环
await new Promise(resolve => setTimeout(resolve, 100));
}
// 重置标志变量
isTimer2Completed = false;
}
// 启动 timer1
let timer1 = setInterval(() => {
active.value++;
if (active.value > 5) {
clearInterval(timer1);
}
}, 1000);
};
const handleSubmit2 = () => {
if (intervalId !== null) {
clearInterval(intervalId);
}
intervalId = setInterval(() => {
if (activeIndex.value < name.value.length) {
activeIndex.value++;
// 获取当前活动索引对应的 tableData
const currentDataRef = tableDataMap.get(activeIndex.value - 1);
if (currentDataRef) {
const currentData = currentDataRef.value;
// 检查当前数据中有无不合格字段
const hasError = checkForErrors(currentData);
if (hasError) {
}else{
qualified.value++;
}
updateErrorState(activeIndex.value - 1, hasError);
}
} else {
clearInterval(intervalId!); // 停止定时器
}
}, 1000); // 每隔3秒显示下一个tab
// let timer = setInterval(() => {
// if (activeIndex.value < activeTotalNum.value) {
// activeIndex.value++
// if(activeIndex.value > 1)
// qualified.value = activeIndex.value -1;//演示效果,实际运行时使用后端传来的真实数据即可
// else
// qualified.value = activeIndex.value;
// }
// else if (activeIndex.value === activeTotalNum.value) {
// clearInterval(timer)
// }
// else {
// clearInterval(timer)
// }
// total.value = activeTotalNum.value
// }, 1000);
let timer2 = setInterval(() => {
active.value++
if (active.value++ > 5) {
clearInterval(timer2)
}
}, 1000);
};
// 对外映射
defineExpose({ open })
</script>
<style scoped>
.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;
}
.container {
display: flex;
}
.dialog-left {
flex: 1;
}
.right-content {
flex: 5;
}
</style>