Files
pqs-9100_client/frontend/src/views/home/components/preTest.vue

602 lines
20 KiB
Vue
Raw Normal View History

<template>
2024-12-05 11:07:54 +08:00
<div>
<el-tabs type="border-card">
<el-tab-pane label="预检测项目">
<div class="form-grid">
<el-checkbox v-for="(item, index) in detectionOptions" v-model="item.selected" :key="index"
2025-04-08 09:43:12 +08:00
:label="item.name" disabled></el-checkbox>
2024-12-05 11:07:54 +08:00
</div>
</el-tab-pane>
</el-tabs>
2024-12-05 11:07:54 +08:00
<div class="test-dialog">
<div class="dialog-left">
2025-08-11 11:14:20 +08:00
<el-steps direction="vertical" :active="activeIndex" finish-status="success">
<el-step :status="step1" title="源通讯校验"/>
<el-step :status="step2" title="设备通讯校验"/>
<el-step :status="step3" title="协议校验"/>
<el-step :status="step4" title="相序校验"/>
2025-04-08 09:43:12 +08:00
<el-step :status="step5" :title="ts === 'error'? '检测失败':ts === 'process'? '检测中':ts === 'success'? '检测成功':'待检测'"/>
2024-12-05 11:07:54 +08:00
</el-steps>
</div>
<div class="dialog-right">
<el-collapse v-model="collapseActiveName" accordion>
2024-12-05 11:07:54 +08:00
<el-collapse-item title="源通讯校验" name="1">
<div class="div-log">
<p v-for="(item, index) in step1InitLog" :key="index"
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
{{ item.log }} <br/>
2024-12-05 11:07:54 +08:00
</p>
</div>
</el-collapse-item>
<el-collapse-item title="设备通讯校验" name="2">
<div class="div-log">
<p v-for="(item, index) in step2InitLog" :key="index"
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
{{ item.log }} <br/>
2024-12-05 11:07:54 +08:00
</p>
</div>
</el-collapse-item>
<el-collapse-item title="协议校验" name="3">
<div class="div-log">
<p v-for="(item, index) in step3InitLog" :key="index"
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
{{ item.log }} <br/>
2024-12-05 11:07:54 +08:00
</p>
</div>
</el-collapse-item>
<el-collapse-item title="相序校验" name="4">
<div class="div-log">
<p v-for="(item, index) in step4InitLog" :key="index"
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
2025-01-15 19:27:33 +08:00
{{ item.log.split('&&')[0] }}
2025-01-15 21:08:07 +08:00
<br v-if="item.log.includes('&&')"/>
&nbsp;&nbsp;&nbsp;&nbsp;{{ item.log.split('&&')[1] }}
<br v-if="item.log.includes('&&')"/>
&nbsp;&nbsp;&nbsp;&nbsp;{{ item.log.split('&&')[2] }}
2025-01-15 19:27:33 +08:00
2024-12-05 11:07:54 +08:00
</p>
</div>
</el-collapse-item>
</el-collapse>
2024-12-05 11:07:54 +08:00
</div>
</div>
2024-12-05 11:07:54 +08:00
</div>
</template>
<script lang="tsx" setup name="preTest">
2025-08-11 11:14:20 +08:00
/**
* 预检测组件
* 负责电力设备检测中的预检测阶段包含4个步骤
* 1. 源通讯校验 - 验证源端通讯是否正常
* 2. 设备通讯校验 - 检查设备IP端口识别码密钥
* 3. 协议校验 - 进行ICD报告触发测试
* 4. 相序校验 - 判断装置接线是否正确
*/
import {ElMessage, ElMessageBox} from "element-plus";
2025-08-05 10:37:40 +08:00
import {defineExpose, ref, toRef, watch} from 'vue';
2025-08-11 11:14:20 +08:00
// ==================== 日志数据存储 ====================
// 各步骤的日志数据,用于在右侧折叠面板中显示实时日志
2024-11-21 23:02:43 +08:00
const step1InitLog = ref([
{
type: 'info',
2024-12-05 11:07:54 +08:00
log: '暂无数据,等待检测开始',
2024-11-21 23:02:43 +08:00
},
])
const step2InitLog = ref([
{
type: 'info',
2024-12-05 11:07:54 +08:00
log: '暂无数据,等待检测开始',
2024-11-21 23:02:43 +08:00
},
])
const step3InitLog = ref([
{
type: 'info',
2024-12-05 11:07:54 +08:00
log: '暂无数据,等待检测开始',
2024-11-21 23:02:43 +08:00
},
])
const step4InitLog = ref([
{
type: 'info',
2024-12-05 11:07:54 +08:00
log: '暂无数据,等待检测开始',
2024-11-21 23:02:43 +08:00
},
])
2025-08-11 11:14:20 +08:00
// ==================== 界面状态控制 ====================
const collapseActiveName = ref('1') // 当前展开的折叠面板
const activeIndex = ref(0) // 当前激活的步骤索引(用于步骤条高亮)
const activeTotalNum = ref(5) // 总步骤数
// ==================== 步骤状态管理 ====================
// 各步骤的执行状态wait/process/success/error
const step1 = ref('wait') // 源通讯校验状态
const step2 = ref('wait') // 设备通讯校验状态
const step3 = ref('wait') // 协议校验状态
const step4 = ref('wait') // 相序校验状态
const step5 = ref('wait') // 整体检测结果状态
// ==================== 预检测项目配置 ====================
// 定义预检测包含的检测项目顶部tabs显示用只读
const detectionOptions = ref([
{
id: 0,
name: "源通讯检测",//判断源通讯是否正常
selected: true,
},
{
id: 1,
name: "设备通讯检测",//判断设备的IP、Port、识别码、秘钥是否正常
selected: true,
},
{
id: 2,
name: "协议校验",//ICD报告触发测试
selected: true,
},
{
id: 3,
name: "相序校验",//判断装置的接线是否正确
selected: true,
2025-08-11 11:14:20 +08:00
}
]);
2025-08-11 11:14:20 +08:00
// ==================== 组件Props定义 ====================
2024-12-05 11:07:54 +08:00
const props = defineProps({
testStatus: {
type: String,
2025-08-11 11:14:20 +08:00
default: 'wait' // 从父组件接收的测试状态
2024-12-20 16:32:03 +08:00
},
webMsgSend: {
type: Object,
2025-08-11 11:14:20 +08:00
default: () => ({}) // 从父组件接收的WebSocket消息
}
})
2024-12-20 16:32:03 +08:00
2025-08-11 11:14:20 +08:00
// ==================== 响应式Props引用 ====================
const testStatus = toRef(props, 'testStatus');
2024-12-20 16:32:03 +08:00
const webMsgSend = toRef(props, 'webMsgSend');
2025-08-11 11:14:20 +08:00
const ts = ref(''); // 内部测试状态,用于向父组件同步
// ==================== 错误处理函数 ====================
/**
* 处理致命错误 - 会终止整个检测流程
* @param stepRef 当前步骤状态引用
* @param logRef 当前步骤日志引用
* @param message 错误消息
*/
function handleFatalError(stepRef: any, logRef: any, message: string) {
stepRef.value = 'error';
ts.value = 'error';
step5.value = 'error';
2025-08-26 10:58:29 +08:00
logRef.value.push({
2025-08-11 11:14:20 +08:00
type: 'error',
log: message
2025-08-26 10:58:29 +08:00
});
2025-08-11 11:14:20 +08:00
}
2025-08-11 11:14:20 +08:00
/**
* 处理警告错误 - 只标记当前步骤失败检测可继续
* @param stepRef 当前步骤状态引用
* @param logRef 当前步骤日志引用
* @param message 错误消息
*/
function handleWarningError(stepRef: any, logRef: any, message: string) {
stepRef.value = 'error';
logRef.value.push({
type: 'error',
log: message
});
}
// ==================== WebSocket消息处理 ====================
/**
* 监听WebSocket消息根据不同的requestId和operateCode处理各种检测状态
* 主要消息类型
* - yjc_ytxjy: 源通讯校验
* - yjc_sbtxjy: 设备通讯校验
* - yjc_xyjy: 协议校验
* - YJC_xujy: 相序校验
*/
watch(webMsgSend, function (newValue, oldValue) {
2025-04-14 13:22:46 +08:00
if (testStatus.value !== 'waiting') {
switch (newValue.requestId) {
case 'yjc_ytxjy':
switch (newValue.operateCode) {
case 'INIT_GATHER':
if (newValue.code == 10200) {
step1InitLog.value.push({
type: 'info',
log: '源初始化成功!',
})
activeIndex.value = 1
step1.value = 'success'
step2.value = 'process'
} else if (newValue.code == 10201) {
step1.value = 'process'
step1InitLog.value = [{
type: 'wait',
log: '正在进行源初始化!',
}];
} else if (newValue.code == 10552) {
ElMessage.error(newValue.code)
2025-08-11 11:14:20 +08:00
handleFatalError(step1, step1InitLog, '重复的初始化操作!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10523) {
2025-08-11 11:14:20 +08:00
handleFatalError(step1, step1InitLog, '源连接失败!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == -1) {
2025-08-11 11:14:20 +08:00
handleFatalError(step1, step1InitLog, '源未知异常!')
2025-04-14 13:22:46 +08:00
}
break;
}
break;
case 'yjc_sbtxjy':
switch (newValue.operateCode) {
case 'INIT_GATHER$01':
if (newValue.code == 10200) {
step2InitLog.value.push({
type: 'info',
log: newValue.data + '设备通讯校验成功!',
})
} else if (newValue.code == 10201) {
step2.value = 'process'
step2InitLog.value = [{
type: 'wait',
log: '正在进行设备通讯校验.....',
}];
} else if (newValue.code == 10550) {
2025-08-11 11:14:20 +08:00
handleWarningError(step2, step2InitLog, newValue.data + '设备连接异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10551) {
2025-08-11 11:14:20 +08:00
handleFatalError(step2, step2InitLog, newValue.data + '设备触发报告异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10552) {
2025-08-11 11:14:20 +08:00
handleFatalError(step2, step2InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 25001) {
activeIndex.value = 2
step2.value = 'success'
step3.value = 'process'
}
break;
}
break;
case 'yjc_xyjy':
switch (newValue.operateCode) {
case 'INIT_GATHER$01':
if (newValue.code == 10200) {
step3InitLog.value.push({
type: 'info',
log: '统计数据协议校验:' + newValue.data + '通讯协议校验成功!',
})
} else if (newValue.code == 10201) {
step3.value = 'process'
step3InitLog.value = [{
type: 'wait',
log: '正在进行通讯协议校验.....',
}];
} else if (newValue.code == 10550) {
2025-08-11 11:14:20 +08:00
handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10551) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10552) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测!')
2025-04-14 13:22:46 +08:00
}
break;
case 'INIT_GATHER$02':
if (newValue.code == 10200) {
step3InitLog.value.push({
type: 'info',
log: '实时数据协议校验:' + newValue.data + '通讯协议校验成功!',
})
} else if (newValue.code == 10201) {
step3.value = 'process'
step3InitLog.value = [{
type: 'wait',
log: '正在进行通讯协议校验.....',
}];
} else if (newValue.code == 10550) {
2025-08-11 11:14:20 +08:00
handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10551) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10552) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测!')
2025-04-14 13:22:46 +08:00
}
break;
case 'INIT_GATHER$03':
if (newValue.code == 10200) {
step3InitLog.value.push({
type: 'info',
log: '暂态数据协议校验:' + newValue.data + '通讯协议校验成功!',
})
} else if (newValue.code == 10201) {
step3.value = 'process'
} else if (newValue.code == 10550) {
2025-08-11 11:14:20 +08:00
handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10551) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10552) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测!')
2025-04-14 13:22:46 +08:00
}
break;
case 'VERIFY_MAPPING$01':
if (newValue.code == 25001) {
activeIndex.value = 3
step3.value = 'success'
step4.value = 'process'
2025-08-18 08:30:03 +08:00
} else if (newValue.code == 25002) {
2025-04-14 13:22:46 +08:00
let data = JSON.parse(newValue.data)
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, `脚本与icd检验失败! icd名称${data['icdType']} -> 校验项:${data['dataType']}`)
} else if (newValue.code == 10500) {
2025-08-11 11:14:20 +08:00
handleFatalError(step3, step3InitLog, '装置中未找到该icd')
2025-04-14 13:22:46 +08:00
}
break;
}
break;
case 'YJC_xujy':
switch (newValue.operateCode) {
case 'OPER_GATHER':
if (newValue.code == 10200) {
step4InitLog.value.push({
type: 'info',
log: '源参数下发成功,等待校验中.....',
})
} else if (newValue.code == 10201) {
step4.value = 'process'
2025-08-26 10:58:29 +08:00
step4InitLog.value.push({
2025-04-14 13:22:46 +08:00
type: 'wait',
log: '源参数下发中.....',
2025-08-26 10:58:29 +08:00
});
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10552) {
ElMessage.error("存在已经初始化步骤,已经自动关闭,请重新发起检测!")
2025-08-11 11:14:20 +08:00
handleFatalError(step4, step4InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 10520) {
2025-08-11 11:14:20 +08:00
handleFatalError(step4, step4InitLog, '解析报文异常')
2025-04-14 13:22:46 +08:00
}
break;
case 'DATA_REQUEST$02':
if (newValue.code == 10200) {
let type = 'info'
if (newValue.data.includes('不合格')) {
type = 'error'
}
newValue.data.split('<br/>')
step4InitLog.value.push({
type: type,
log: newValue.data,
})
} else if (newValue.code == 10201) {
step4.value = 'process'
2025-08-26 10:58:29 +08:00
step4InitLog.value.push({
2025-04-14 13:22:46 +08:00
type: 'wait',
log: '获取数据相序校验数据!',
2025-08-26 10:58:29 +08:00
});
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 25003) {
2025-08-11 11:14:20 +08:00
handleFatalError(step4, step4InitLog, '相序校验未通过!')
2025-04-14 13:22:46 +08:00
} else if (newValue.code == 25001) {
step4.value = 'success'
step5.value = 'success'
step4InitLog.value.push({
type: 'wait',
log: '相序校验成功!',
})
2025-04-18 11:07:04 +08:00
ts.value = 'success'
2025-04-14 13:22:46 +08:00
}
activeIndex.value = 5
console.log("@@@@", ts.value)
break
}
break;
case 'quit':
break;
case 'connect':
switch (newValue.operateCode) {
case "Source":
2025-08-11 11:14:20 +08:00
handleFatalError(step1, step1InitLog, '源服务端连接失败!')
2025-04-14 13:22:46 +08:00
break;
case "Dev":
2025-08-11 11:14:20 +08:00
handleFatalError(step2, step2InitLog, '设备服务端连接失败!')
2025-04-14 13:22:46 +08:00
break;
}
break;
case 'unknown_operate':
break;
case 'error_flow_end':
ElMessageBox.alert(`当前流程存在异常结束!`, '检测失败', {
2025-04-14 13:22:46 +08:00
confirmButtonText: '确定',
type: 'error',
})
2025-08-11 11:14:20 +08:00
// 根据当前步骤选择对应的日志记录
const currentStepLog = activeIndex.value === 0 ? step1InitLog :
activeIndex.value === 1 ? step2InitLog :
activeIndex.value === 2 ? step3InitLog : step4InitLog
const currentStep = activeIndex.value === 0 ? step1 :
activeIndex.value === 1 ? step2 :
activeIndex.value === 2 ? step3 : step4
handleFatalError(currentStep, currentStepLog, '设备连接异常,检测终止!')
2025-04-14 13:22:46 +08:00
break;
case 'socket_timeout':
ElMessageBox.alert(`设备连接异常,请检查设备连接情况!`, '检测失败', {
confirmButtonText: '确定',
type: 'error',
})
2025-08-11 11:14:20 +08:00
// 根据当前步骤选择对应的日志记录
const timeoutStepLog = activeIndex.value === 0 ? step1InitLog :
activeIndex.value === 1 ? step2InitLog :
activeIndex.value === 2 ? step3InitLog : step4InitLog
const timeoutStep = activeIndex.value === 0 ? step1 :
activeIndex.value === 1 ? step2 :
activeIndex.value === 2 ? step3 : step4
handleFatalError(timeoutStep, timeoutStepLog, 'Socket连接超时检测终止')
break;
case 'server_error':
ElMessageBox.alert('服务端主动关闭连接!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
2025-08-11 11:14:20 +08:00
// 根据当前步骤选择对应的日志记录
const serverStepLog = activeIndex.value === 0 ? step1InitLog :
activeIndex.value === 1 ? step2InitLog :
activeIndex.value === 2 ? step3InitLog : step4InitLog
const serverStep = activeIndex.value === 0 ? step1 :
activeIndex.value === 1 ? step2 :
activeIndex.value === 2 ? step3 : step4
handleFatalError(serverStep, serverStepLog, '服务端主动关闭连接!')
break;
2025-05-26 14:41:06 +08:00
case 'device_error':
ElMessageBox.alert('设备主动关闭连接!', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
2025-08-11 11:14:20 +08:00
// 根据当前步骤选择对应的日志记录
const deviceStepLog = activeIndex.value === 0 ? step1InitLog :
activeIndex.value === 1 ? step2InitLog :
activeIndex.value === 2 ? step3InitLog : step4InitLog
const deviceStep = activeIndex.value === 0 ? step1 :
activeIndex.value === 1 ? step2 :
activeIndex.value === 2 ? step3 : step4
handleFatalError(deviceStep, deviceStepLog, '设备主动关闭连接!')
2025-05-26 14:41:06 +08:00
break;
2025-04-14 13:22:46 +08:00
}
2024-12-20 16:32:03 +08:00
}
})
2025-08-11 11:14:20 +08:00
// ==================== 界面联动控制 ====================
/**
* 监听当前激活步骤自动展开对应的日志折叠面板
*/
watch(activeIndex, function (newValue, oldValue) {
if (newValue <= activeTotalNum.value - 2) {
collapseActiveName.value = (newValue + 1).toString()
} else {
2024-12-23 21:02:00 +08:00
collapseActiveName.value = (newValue - 1).toString()
2024-12-25 20:29:27 +08:00
}
})
2025-08-11 11:14:20 +08:00
/**
* 监听父组件传入的测试状态变化
* 处理测试开始和重置逻辑
*/
watch(testStatus, function (newValue, oldValue) {
ts.value = props.testStatus;
2024-12-05 11:07:54 +08:00
if (ts.value === 'start') {
ts.value = 'process'
} else if (ts.value === 'waiting') {
2024-12-20 16:32:03 +08:00
activeIndex.value = 0
step1InitLog.value = [
{
type: 'info',
log: '暂无数据,等待检测开始',
},
]
2024-12-23 21:02:00 +08:00
step1.value = 'finish'
step2.value = 'wait'
step3.value = 'wait'
step4.value = 'wait'
step5.value = 'wait'
}
})
2025-08-11 11:14:20 +08:00
// ==================== 父子组件通信 ====================
const emit = defineEmits(['update:testStatus']);
2025-08-11 11:14:20 +08:00
/**
* 监听内部测试状态变化同步给父组件
* 实现双向数据绑定
*/
watch(ts, function (newValue, oldValue) {
2024-12-05 11:07:54 +08:00
emit('update:testStatus', ts.value)
})
2024-12-23 21:02:00 +08:00
2025-08-11 11:14:20 +08:00
// ==================== 对外暴露方法 ====================
/**
* 初始化参数方法
* 由父组件调用用于重置所有步骤状态和日志
*/
2024-12-23 21:02:00 +08:00
function initializeParameters() {
activeIndex.value = 0
step1.value = 'process'
step2.value = 'wait'
step3.value = 'wait'
step4.value = 'wait'
step5.value = 'wait'
step1InitLog.value = [
{
type: 'info',
log: '暂无数据,等待检测开始',
},
]
step2InitLog.value = [
{
type: 'info',
log: '暂无数据,等待检测开始',
},
]
step3InitLog.value = [
{
type: 'info',
log: '暂无数据,等待检测开始',
},
]
step4InitLog.value = [
{
type: 'info',
log: '暂无数据,等待检测开始',
},
]
}
2025-08-11 11:14:20 +08:00
// 暴露方法给父组件使用
2024-12-23 21:02:00 +08:00
defineExpose({
initializeParameters,
});
</script>
2024-12-05 11:07:54 +08:00
<style scoped lang="scss">
.test-dialog {
height: 350px;
display: flex;
2024-12-05 11:07:54 +08:00
flex-direction: row;
/* 横向排列 */
margin-top: 20px;
}
2024-11-21 23:02:43 +08:00
2024-12-05 11:07:54 +08:00
.dialog-left {
width: 15%;
margin-left: 20px;
}
2024-11-21 23:02:43 +08:00
2024-12-05 11:07:54 +08:00
.dialog-right {
margin-left: 20px;
width: 80%;
height: 100%;
}
.dialog-right :deep(.el-collapse-item__header) {
font-size: 16px;
}
.div-log {
height: 145px;
overflow-y: auto;
padding-left: 10px;
p {
margin: 5px 0;
font-size: 14px;
}
}
</style>