Files
pqs-9100_client/frontend/src/views/home/components/compareTestPopup.vue
2025-08-15 08:37:35 +08:00

535 lines
16 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 :title="dialogTitle" width="1550px" :model-value="dialogVisible" :before-close="beforeClose" @close="handleClose" height="1000px" draggable>
<div class="steps-container">
<el-steps v-if="showSteps" class="test-head-steps" simple :active="stepsActiveIndex" process-status="finish" finish-status="success">
<el-step v-if="preTestSelected" title="预检测" :icon="stepsActive > 1 || stepsActiveIndex > stepsTotalNum - 1? SuccessFilled : Edit" @click="handleStepClick(1)"/>
<el-step v-if="testSelected" title="正式检测" :icon="stepsActive > 2 || stepsActiveIndex > stepsTotalNum - 1? SuccessFilled : Coin" @click="handleStepClick(2)"/>
<el-step title="检测完成" :icon="stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Key"/>
</el-steps>
</div>
<keep-alive>
<ComparePreTest v-if="preTestSelected && stepsActiveView==1" ref="preTestRef" v-model:testStatus="preTestStatus"
:webMsgSend="webMsgSend" :mapping = "channelMapping"/>
</keep-alive>
<keep-alive>
<CompareTest v-if="testSelected && stepsActiveView==2" ref="testRef" v-model:testStatus="TestStatus"
:stepsActive="stepsActive"/>
</keep-alive>
<template #footer>
<div>
<el-button type="primary" :icon="VideoPlay" v-if="ActiveStatue === 'waiting'" @click="handleSubmitFast">开始检测</el-button>
<el-button type="primary" v-if="TestStatus === 'test_init'" disabled>
<el-icon class="loading-box" style="color: #fff;margin-right: 8px;">
<component :is="Refresh"/>
</el-icon>
初始化中
</el-button>
<el-button
type="primary"
v-if="TestStatus=='process'"
:icon="VideoPause"
@click="handlePause()">停止检测
</el-button>
<el-button type="warning" v-if="TestStatus === 'paused_ing'" disabled>
<el-icon class="loading-box" style="color: #fff;margin-right: 8px;">
<component :is="Refresh"/>
</el-icon>
暂停中
</el-button>
<el-button
type="warning"
v-if="(TestStatus =='paused')"
:icon="VideoPlay"
@click="sendResume"
>继续检测
</el-button>
<el-button type="warning" :icon="VideoPlay"
v-if="nextStepText !== '下一步' && (ActiveStatue === 'success'||ActiveStatue==='error'||ActiveStatue==='test_init_fail'||ActiveStatue==='connect_timeout'||ActiveStatue==='pause_timeout')"
@click="handleSubmitAgain">重新检测
</el-button>
<el-button :type="ActiveStatue==='success'?'primary':'danger'" :icon="Right"
v-if="nextStepText !== '下一步' && (ActiveStatue === 'success'||ActiveStatue==='error'||ActiveStatue==='test_init_fail'||ActiveStatue==='connect_timeout'||ActiveStatue==='pause_timeout')"
@click="nextStep">
{{ nextStepText }}
</el-button>
<el-button type="primary" @click="handleQuit" v-else>
退出检测
</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="tsx" setup name="testPopup">
import {nextTick, reactive, ref, watch} from 'vue';
import {ElMessage, ElMessageBox} from 'element-plus'
import {Coin, Edit, Key, Odometer, Refresh, Right, SuccessFilled, UploadFilled, VideoPause, VideoPlay} from '@element-plus/icons-vue'
import ComparePreTest from './comparePreTest.vue'
import CompareTest from './compareTest.vue'
import socketClient from '@/utils/webSocketClient';
import {useCheckStore} from "@/stores/modules/check";
import {pauseTest, resumeTest, startPreTest,contrastTest,getContrastTestNumInfo} from '@/api/socket/socket'
import {useUserStore} from "@/stores/modules/user";
import {JwtUtil} from "@/utils/jwtUtil";
const userStore = useUserStore()
const checkStore = useCheckStore();
const nextStepText = ref('下一步');
const dialogVisible = ref(false)
const showSteps = ref(false)
const stepsTotalNum = ref(-1);//步骤总数
const stepsActiveIndex = ref(1); //当前正在执行的步骤索引
const stepsActiveView = ref(1); //当前正在执行的步骤在(预处理、守时校验、系数校准、正式检测)中的排序,仅用于页面显示
const stepsActive = ref(-1); //当前正在执行的步骤在(预处理、守时校验、系数校准、正式检测)中的排序,实际记录步骤的状态,用于切换步骤
const ActiveStatue = ref('waiting');//当前步骤状态
const preTestStatus = ref('waiting');//预检测执行状态
const TestStatus = ref('waiting');//正式检测执行状态
const webMsgSend = ref();//webSocket推送的数据
const dialogTitle = ref('')
const showComponent = ref(true)
const preTestRef = ref<InstanceType<typeof ComparePreTest> | null>(null)
const testRef = ref(null)
const dataSocket = reactive({
socketServe: socketClient.Instance,
});
// 勾选的检测内容
const preTestSelected = ref(true)
const testSelected = ref(false)
const initOperate = () => {
ActiveStatue.value = 'waiting'
preTestStatus.value = 'waiting'
TestStatus.value = 'waiting'
stepsActiveIndex.value = 1
showComponent.value = true
// 初始化勾选的检测内容
preTestSelected.value = checkStore.selectTestItems.preTest
testSelected.value = checkStore.selectTestItems.test
let count = 0
for (let key in checkStore.selectTestItems) {
if (checkStore.selectTestItems[key]) {
count++
}
}
stepsTotalNum.value = count + 1
if (preTestSelected.value) {
stepsActiveView.value = 1
stepsActive.value = 1
return
}
if (testSelected.value) {
stepsActiveView.value = 2
stepsActive.value = 2
return
}
}
const channelMapping = ref<Record<string, Record<string, string>>>({})
const planId = ref('')
const loginName = ref('')
const devIds = ref<[]>()
const standardDevIds = ref<[]>()
const pairs = ref<any>()
const testAgain = ref(false)//重新检测按钮是否显示
const checkNumber = ref(0)//检测次数
const open = async (title: string,mapping:any,plan: string,login: string,devIdsArray: [],standardDevIdsArray: [],pair:any) => {
if(checkStore.selectTestItems.preTest && !checkStore.selectTestItems.test){
testAgain.value = true
}
channelMapping.value = mapping
planId.value = plan
loginName.value = login
devIds.value = devIdsArray
standardDevIds.value = standardDevIdsArray
pairs.value = pair
showSteps.value = true
initOperate()
dialogTitle.value = title;
dialogVisible.value = true;
// 等待组件渲染完成
await nextTick();
if (preTestRef.value) {
preTestRef.value.initializeParameters();
}
//开始创建webSocket客户端
socketClient.Instance.connect();
dataSocket.socketServe = socketClient.Instance;
dataSocket.socketServe.registerCallBack('aaa', (res: { code: number; }) => {
console.log('Received message:', res)
// 处理来自服务器的消息
if (res.code === 20000) {
//ElMessage.error(message.message)
// loading.close()
} else {
webMsgSend.value = res
}
});
}
//预检测-重新检测
const handleSubmitAgain = async () => {
stepsActiveIndex.value = 1
stepsActiveView.value = 1
stepsActive.value = 1
let count = 0
for (let key in checkStore.selectTestItems) {
if (checkStore.selectTestItems[key]) {
count++
}
}
stepsTotalNum.value = count + 1
// 通知子组件清空并重新初始化
if (preTestRef.value) {
preTestRef.value.initializeParameters();
}
// 重置状态
ActiveStatue.value = 'waiting'
preTestStatus.value = 'waiting'
const checkNum = await mapValue()
await contrastTest({
planId: planId.value,
loginName: loginName.value,
devIds: devIds.value,
standardDevIds: standardDevIds.value,
pairs:pairs.value,
testItemList:[checkStore.selectTestItems.preTest,false,checkStore.selectTestItems.test],
num: checkNum
})
preTestStatus.value = 'start'
};
//开始检测
const handleSubmitFast = async () => {
if (!dataSocket.socketServe.connected) {
ElMessage.error('webSocket连接中断')
return
}
const checkNum = await mapValue()
switch (stepsActive.value) {
case 1:
if (preTestStatus.value == 'waiting') {
if (checkStore.selectTestItems.preTest) {
await contrastTest({
planId: planId.value,
loginName: loginName.value,
devIds: devIds.value,
standardDevIds: standardDevIds.value,
pairs:pairs.value,
testItemList:[checkStore.selectTestItems.preTest,false,checkStore.selectTestItems.test],
num: checkNum
})
preTestStatus.value = 'start'
}
}
break;
case 2:
if (TestStatus.value == "waiting") {
// 如果没有预检测,直接进行正式检测需要先初始化
if (!checkStore.selectTestItems.preTest && checkStore.selectTestItems.test) {
await contrastTest({
planId: planId.value,
loginName: loginName.value,
devIds: devIds.value,
standardDevIds: standardDevIds.value,
pairs:pairs.value,
testItemList:[checkStore.selectTestItems.preTest,false,checkStore.selectTestItems.test],
num: checkNum
})
}
TestStatus.value = 'start'
} else if (TestStatus.value == 'paused') {
// 发送继续指令
//sendResume()
}
break;
default:
break;
}
}
const mapValue = (async () => {
const data = await getContrastTestNumInfo(checkStore.plan.id)
// 解析返回的数据,现在是 map 类型 {99: 1}
const dataMap = data.data as Record<string, number>
// 获取键值对
const entries = Object.entries(dataMap)
// 获取第一对键值
const [key, value] = entries[0]
return value
})
const emit = defineEmits<{
(e: 'quitClicked'): void;
}>();
watch(preTestStatus, function (newValue, oldValue) {
console.log('预检测状态',newValue, oldValue);
ActiveStatue.value = newValue
})
watch(TestStatus, function (newValue, oldValue) {
console.log('正式检测状态',newValue, oldValue);
ActiveStatue.value = newValue
})
watch(stepsActiveIndex, function (newValue, oldValue) {
console.log('步骤索引',newValue, oldValue);
})
watch(ActiveStatue, function (newValue, oldValue) {
console.log('当前步骤状态-----',newValue);
console.log('stepsActiveIndex-----',stepsActiveIndex.value);
console.log('stepsTotalNum----',stepsTotalNum.value);
if (newValue === 'error') {
stepsActiveIndex.value = stepsTotalNum.value + 1
nextStepText.value = '检测失败'
}
if (newValue === 'success' && stepsActiveIndex.value === stepsTotalNum.value - 1) {
stepsActiveIndex.value += 2
nextStepText.value = '检测完成'
}
if (newValue === 'test_init_fail') {
stepsActiveIndex.value += 2
nextStepText.value = '初始化失败'
}
if (newValue === 'connect_timeout') {
stepsActiveIndex.value += 2
nextStepText.value = '连接超时'
}
if (newValue === 'pause_timeout') {
stepsActiveIndex.value += 2
// nextStepText.value = '结束测试'
nextStepText.value = '暂停超时'
}
if (newValue === 'success' && stepsActiveIndex.value < stepsTotalNum.value - 1) {
nextStep() // 实现自动点击,进入下一个测试内容
//handleSubmitFast()
}
})
const handleQuit = () => {
console.log('handleQuit', ActiveStatue.value)
if (ActiveStatue.value !== 'success' && ActiveStatue.value !== 'waiting' && ActiveStatue.value !== 'paused' && ActiveStatue.value !== 'test_init_fail' && ActiveStatue.value !== 'connect_timeout' && ActiveStatue.value !== 'pause_timeout') {
beforeClose(() => {
})
} else {
handleClose()
}
}
const handlePause = () => {
sendPause()
testRef.value?.handlePause()
}
const sendPause = () => {
console.log('发起暂停请求')
TestStatus.value = 'paused_ing'
pauseTest()
}
const sendResume = () => {
console.log('发起继续检测请求')
resumeTest({
userPageId: "cdf",
devIds: checkStore.devices.map((item) => item.deviceId),
planId: checkStore.plan.id,
reCheckType: '2', // 0:'系数校验''1'为预检测、2为正式检测、'8'为不合格项复检
userId: userStore.userInfo.id,
temperature: checkStore.temperature,
humidity: checkStore.humidity
})
Object.assign(webMsgSend.value, {
requestId: 'Resume_Success'
})
}
const sendReCheck = () => {
console.log('发送重新检测指令')
startPreTest({
userPageId: JwtUtil.getLoginName(),
devIds: checkStore.devices.map((item) => item.deviceId),
planId: checkStore.plan.id,
reCheckType: '2', // 0:'系数校验''1'为预检测、2为正式检测、'8'为不合格项复检
userId: userStore.userInfo.id,
temperature: checkStore.temperature,
humidity: checkStore.humidity,
testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test]
}).then(res => {
console.log(res)
if (res.code === 'A001014') {
ElMessageBox.alert('装置配置异常', '初始化失败', {
confirmButtonText: '确定',
type: 'error',
})
TestStatus.value = 'test_init_fail'
}
})
TestStatus.value = 'start'
}
const closeWebSocket = () => {
dataSocket.socketServe.closeWs()
}
const nextStep = () => {
if (stepsActiveIndex.value == stepsTotalNum.value + 1 || ActiveStatue.value === 'error' || ActiveStatue.value === 'test_init_fail' || ActiveStatue.value === 'connect_timeout' || ActiveStatue.value === 'pause_timeout') {
handleClose()
return
}
if (ActiveStatue.value != 'error') {
ActiveStatue.value = 'waiting'
let tempStep = stepsActiveIndex.value
let idx = -1
stepsActiveIndex.value++
for (let selectTestItemsKey in checkStore.selectTestItems) {
if (tempStep == 0 && checkStore.selectTestItems[selectTestItemsKey]) {
console.log('selectTestItemsKey1')
stepsActiveView.value = idx
stepsActive.value = idx
console.log('stepsActiveView.value999', stepsActiveView.value)
return
}
if (checkStore.selectTestItems[selectTestItemsKey] && tempStep != 0) {
console.log('selectTestItemsKey2')
tempStep--
}
console.log('selectTestItemsKey3',idx)
idx++
}
}
}
const handleStepClick = (step: number) => {
if (step > stepsActive.value) {
return
} else {
stepsActiveView.value = step
}
}
function clearData() {
stepsTotalNum.value = -1
stepsActiveIndex.value = 1
stepsActiveView.value = -1
preTestStatus.value = "waiting"
TestStatus.value = "waiting"
ActiveStatue.value = "waiting"
nextStepText.value = "下一步"
}
const beforeClose = (done: () => void) => {
if (stepsActiveIndex.value < stepsTotalNum.value && ActiveStatue.value != 'error') {
ElMessageBox.confirm('检测未完成,是否退出当前检测流程?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
handleClose()
})
} else {
handleClose()
}
}
const handleClose = () => {
showSteps.value = false
dataSocket.socketServe.closeWs()
dialogVisible.value = false;
clearData()
showComponent.value = false;
emit('quitClicked'); // 触发事件
}
// 对外映射
defineExpose({open})
</script>
<style scoped lang="scss">
.test-head-steps {
::v-deep .el-step {
.el-step__head.is-success {
color: #91cc75;
}
.el-step__title.is-success {
color: #91cc75;
}
}
}
:deep(.dialog-big .el-dialog__body) {
max-height: 840px !important;
}
.steps-container :deep(.test-head-steps) {
height: 80px;
margin-bottom: 10px;
}
.steps-container :deep(.el-step__title) {
font-size: 20px !important; /* 设置标题字体大小 */
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
}
.steps-container :deep(.el-step__icon-inner) {
font-size: 18px !important;
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
}
.steps-container :deep(.el-step__icon) {
font-size: 18px !important;
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
}
.loading-box {
animation: loading 1.5s linear infinite;
}
@keyframes loading {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>