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

770 lines
27 KiB
Vue
Raw Normal View History

<template>
2025-10-10 13:23:40 +08:00
<!-- 检测流程弹窗容器 -->
<el-dialog
:title="dialogTitle"
width="1550px"
:model-value="dialogVisible"
:before-close="beforeClose"
@close="handleClose"
height="1000px"
draggable
>
<!-- 步骤指示器容器 -->
<div class="steps-container">
<!-- 检测步骤进度条根据选择的检测项动态显示步骤 -->
<!-- 注意Element Plus的active属性从0开始但业务逻辑从1开始所以需要减1 -->
<el-steps
v-if="showSteps"
class="test-head-steps"
simple
:active="stepsActiveIndex - 1"
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="timeTestSelected"
title="守时检测"
:icon="stepsActive > 2 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : UploadFilled"
@click="handleStepClick(2)"
/>
<!-- 系数校准步骤 -->
<el-step
v-if="channelsTestSelected"
title="系数校准"
:icon="stepsActive > 3 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Odometer"
@click="handleStepClick(3)"
/>
<!-- 正式检测步骤 -->
<el-step
v-if="testSelected"
title="正式检测"
:icon="stepsActive > 4 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Coin"
@click="handleStepClick(4)"
/>
<!-- 检测完成步骤 -->
<el-step title="检测完成" :icon="stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Key" />
</el-steps>
</div>
<!-- 检测组件容器 - 根据当前步骤显示对应的检测组件 -->
<!-- 预检测组件 -->
<preTest
v-if="showComponent && preTestSelected"
v-show="preTestSelected && stepsActiveView == 1"
ref="preTestRef"
v-model:testStatus="preTestStatus"
:webMsgSend="webMsgSend"
/>
<!-- 守时检测组件 -->
<timeTest
v-if="showComponent && timeTestSelected"
v-show="timeTestSelected && stepsActiveView == 2"
v-model:testStatus="timeTestStatus"
/>
<!-- 系数校准检测组件 -->
<factorTest
v-if="showComponent && channelsTestSelected"
v-show="channelsTestSelected && stepsActiveView == 3"
v-model:testStatus="channelsTestStatus"
:webMsgSend="webMsgSend"
/>
<!-- 正式检测组件 -->
<test
v-if="showComponent && testSelected"
ref="testRef"
v-show="testSelected && stepsActiveView == 4"
v-model:testStatus="TestStatus"
:webMsgSend="webMsgSend"
@update:webMsgSend="webMsgSend = $event"
@sendPause="sendPause"
@sendResume="sendResume"
@closeWebSocket="closeWebSocket"
:stepsActive="stepsActive"
/>
<!-- 弹窗底部操作按钮区域 -->
<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="ActiveStatue === 'success' ? 'primary' : 'danger'"
:icon="Right"
v-if="
nextStepText !== '下一步' &&
(ActiveStatue === 'success' ||
ActiveStatue === 'error' ||
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>
2025-01-07 19:47:38 +08:00
2025-10-10 13:23:40 +08:00
<script lang="tsx" setup name="testPopup">
2025-08-07 15:44:17 +08:00
// ====================== 导入依赖 ======================
2025-10-10 13:23:40 +08:00
import { onBeforeUnmount, reactive, ref, watch } from 'vue'
2025-08-11 11:14:20 +08:00
import { ElMessage, ElMessageBox } from 'element-plus'
import {
2025-10-10 13:23:40 +08:00
Coin,
Edit,
Key,
Odometer,
Refresh,
Right,
SuccessFilled,
UploadFilled,
VideoPause,
VideoPlay
2025-08-11 11:14:20 +08:00
} from '@element-plus/icons-vue'
2025-01-07 19:47:38 +08:00
import preTest from './preTest.vue'
import timeTest from './timeTest.vue'
import factorTest from './factorTest.vue'
import test from './test.vue'
2025-08-11 11:14:20 +08:00
import socketClient from '@/utils/webSocketClient'
import { useCheckStore } from '@/stores/modules/check'
import { pauseTest, resumeTest, startPreTest } from '@/api/socket/socket'
import { useUserStore } from '@/stores/modules/user'
import { JwtUtil } from '@/utils/jwtUtil'
2025-08-07 15:44:17 +08:00
// ====================== 状态管理 ======================
2025-03-28 09:31:46 +08:00
const userStore = useUserStore()
2025-08-11 11:14:20 +08:00
const checkStore = useCheckStore()
2024-12-27 14:29:21 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 基础状态变量 ======================
2025-08-11 11:14:20 +08:00
const nextStepText = ref('下一步') // 下一步按钮文本
2025-08-07 15:44:17 +08:00
const dialogVisible = ref(false) // 弹窗显示状态
const dialogTitle = ref('') // 弹窗标题
const showComponent = ref(true) // 是否显示检测组件
2025-08-12 10:26:30 +08:00
const preTestRef = ref<{ initializeParameters: () => void } | null>(null) // 预检测组件引用
const testRef = ref<{ handlePause: () => void } | null>(null) // 正式检测组件引用
2025-08-07 15:44:17 +08:00
// ====================== 步骤控制相关变量 ======================
const showSteps = ref(false) // 是否显示步骤条
const stepsTotalNum = ref(-1) // 步骤总数(选中的检测项数量 + 1个完成步骤
const stepsActiveIndex = ref(1) // 当前正在执行的步骤索引用于UI显示高亮
const stepsActiveView = ref(-1) // 当前显示的检测组件步骤序号控制v-show显示哪个组件
const stepsActive = ref(-1) // 当前实际执行的业务步骤序号(控制业务逻辑分支)
// ====================== 状态管理变量 ======================
const ActiveStatue = ref('waiting') // 当前步骤的整体状态waiting/start/process/success/error等
const preTestStatus = ref('waiting') // 预检测执行状态
2025-10-10 13:23:40 +08:00
const timeTestStatus = ref('waiting') // 守时校验执行状态
2025-08-07 15:44:17 +08:00
const channelsTestStatus = ref('waiting') // 通道系数校准执行状态
const TestStatus = ref('waiting') // 正式检测执行状态
const webMsgSend = ref() // webSocket推送的数据用于组件间通信
// ====================== WebSocket 相关 ======================
2025-08-12 10:26:30 +08:00
const dataSocket = reactive<{
2025-10-10 13:23:40 +08:00
socketServe: typeof socketClient.Instance | null
2025-08-12 10:26:30 +08:00
}>({
2025-10-10 13:23:40 +08:00
socketServe: socketClient.Instance // WebSocket客户端实例
2025-08-11 11:14:20 +08:00
})
2024-12-23 15:08:14 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 检测项选择状态 ======================
// 根据用户勾选的检测内容动态显示对应的检测步骤和组件
const preTestSelected = ref(false) // 是否选择预检测
const timeTestSelected = ref(false) // 是否选择守时检测
const channelsTestSelected = ref(false) // 是否选择系数校准
const testSelected = ref(false) // 是否选择正式检测
// ====================== 初始化操作 ======================
/**
* 初始化操作 - 重置所有状态并根据用户选择的检测项设置初始步骤
*/
const initOperate = () => {
2025-10-10 13:23:40 +08:00
// 重置所有状态为等待状态
ActiveStatue.value = 'waiting'
preTestStatus.value = 'waiting'
timeTestStatus.value = 'waiting'
channelsTestStatus.value = 'waiting'
TestStatus.value = 'waiting'
// 重置步骤和组件显示状态
stepsActiveIndex.value = 1
showComponent.value = true
// 从store中获取用户勾选的检测内容
preTestSelected.value = checkStore.selectTestItems.preTest
timeTestSelected.value = checkStore.selectTestItems.timeTest
channelsTestSelected.value = checkStore.selectTestItems.channelsTest
testSelected.value = checkStore.selectTestItems.test
// 计算总步骤数(选中的检测项 + 1个完成步骤
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 (timeTestSelected.value) {
stepsActiveView.value = 2 // 显示守时检测组件
stepsActive.value = 2 // 业务逻辑设为守时检测
return
}
if (channelsTestSelected.value) {
stepsActiveView.value = 3 // 显示系数校准组件
stepsActive.value = 3 // 业务逻辑设为系数校准
return
}
if (testSelected.value) {
stepsActiveView.value = 4 // 显示正式检测组件
stepsActive.value = 4 // 业务逻辑设为正式检测
return
}
}
2025-08-07 15:44:17 +08:00
// ====================== 弹窗开启方法 ======================
/**
* 打开检测弹窗
* @param title 弹窗标题
*/
2025-02-25 13:46:01 +08:00
const open = (title: string) => {
2025-10-10 13:23:40 +08:00
showSteps.value = true // 显示步骤条
initOperate() // 初始化所有状态和步骤
dialogTitle.value = title // 设置弹窗标题
dialogVisible.value = true // 显示弹窗
// 如果预检测组件存在,初始化其参数
if (preTestRef.value) {
preTestRef.value?.initializeParameters()
}
// 改进:无论什么状态,都先清理再重新建立连接
try {
// 先强制清理现有连接
if (dataSocket.socketServe) {
if (dataSocket.socketServe.connected) {
dataSocket.socketServe.closeWs()
}
// 清理回调
dataSocket.socketServe.unRegisterCallBack?.('aaa')
}
// 重新建立连接
socketClient.Instance.connect()
dataSocket.socketServe = socketClient.Instance
// 注册新的回调
dataSocket.socketServe.registerCallBack('aaa', res => {
// 将接收到的数据传递给子组件
webMsgSend.value = res
})
} catch (error) {
console.error('WebSocket连接处理失败:', error)
ElMessage.error('连接建立失败,请重试')
2025-08-12 10:26:30 +08:00
}
2025-01-07 19:47:38 +08:00
}
2024-12-30 14:41:34 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 开始检测处理 ======================
/**
* 快速开始检测 - 根据当前步骤执行对应的检测逻辑
*/
2025-06-20 12:11:57 +08:00
const handleSubmitFast = () => {
2025-10-10 13:23:40 +08:00
// 获取设备ID列表和计划ID
let deviceIds = checkStore.devices.map(item => item.deviceId)
let planId = checkStore.plan.id
// 检查WebSocket连接状态
if (!dataSocket.socketServe.connected) {
ElMessage.error('webSocket连接中断')
return
}
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
// 根据当前激活的步骤执行对应的检测逻辑
switch (stepsActive.value) {
case 1: // 预检测步骤
if (preTestStatus.value == 'waiting') {
if (checkStore.selectTestItems.preTest) {
// 启动预检测
startPreTest({
userPageId: JwtUtil.getLoginName(),
devIds: deviceIds,
planId: planId,
reCheckType: checkStore.reCheckType == 1 ? '1' : '2', // 操作类型1为预检测2为正式检测
userId: userStore.userInfo.id,
temperature: checkStore.temperature,
humidity: checkStore.humidity,
testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => {
if (res.code !== 'A0000') {
ElMessageBox.alert('预检测失败', '检测失败', {
confirmButtonText: '确定',
type: 'error'
})
preTestStatus.value = 'error'
}
})
preTestStatus.value = 'start'
}
}
2025-10-10 13:23:40 +08:00
break
case 2: // 守时检测步骤
timeTestStatus.value = 'start'
break
case 3: // 系数校准步骤
if (channelsTestStatus.value == 'waiting') {
// 如果没有预检测且有系数校准,需要先进行初始化
if (!checkStore.selectTestItems.preTest && checkStore.selectTestItems.channelsTest) {
startPreTest({
userPageId: JwtUtil.getLoginName(),
devIds: deviceIds,
planId: planId,
reCheckType: checkStore.reCheckType == 1 ? '1' : '2',
userId: userStore.userInfo.id,
temperature: checkStore.temperature,
humidity: checkStore.humidity,
testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => {
if (res.code !== 'A0000') {
ElMessageBox.alert('系数校准失败', '检测失败', {
confirmButtonText: '确定',
type: 'error'
})
channelsTestStatus.value = 'error'
}
})
}
channelsTestStatus.value = 'start'
}
2025-10-10 13:23:40 +08:00
break
case 4: // 正式检测步骤
if (TestStatus.value == 'waiting') {
// 如果没有预检测和系数校准,直接进行正式检测需要先初始化
if (
!checkStore.selectTestItems.preTest &&
!checkStore.selectTestItems.channelsTest &&
checkStore.selectTestItems.test
) {
startPreTest({
userPageId: JwtUtil.getLoginName(),
devIds: deviceIds,
planId: planId,
reCheckType: checkStore.reCheckType == 1 ? '1' : '2',
userId: userStore.userInfo.id,
temperature: checkStore.temperature,
humidity: checkStore.humidity,
testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => {
if (res.code !== 'A0000') {
ElMessageBox.alert('正式检测失败', '检测失败', {
confirmButtonText: '确定',
type: 'error'
})
TestStatus.value = 'error'
}
})
}
TestStatus.value = 'start'
} else if (TestStatus.value == 'paused') {
// 如果是暂停状态,发送继续指令
sendResume()
2025-06-25 09:21:58 +08:00
}
2025-10-10 13:23:40 +08:00
break
default:
break
}
2025-06-20 12:11:57 +08:00
}
2025-08-07 15:44:17 +08:00
// ====================== 事件定义 ======================
2025-01-13 21:06:24 +08:00
const emit = defineEmits<{
2025-10-10 13:23:40 +08:00
(e: 'quitClicked'): void // 退出检测事件
2025-08-11 11:14:20 +08:00
}>()
2025-01-13 21:06:24 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 状态监听器 ======================
// 监听各个检测步骤的状态变化,并同步到总体状态
2025-10-10 13:23:40 +08:00
watch(preTestStatus, function (newValue, oldValue) {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
ActiveStatue.value = newValue // 同步到总体状态
2025-01-07 19:47:38 +08:00
})
2025-10-10 13:23:40 +08:00
watch(timeTestStatus, function (newValue, oldValue) {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
ActiveStatue.value = newValue // 同步到总体状态
2025-01-07 19:47:38 +08:00
})
2025-10-10 13:23:40 +08:00
watch(channelsTestStatus, function (newValue, oldValue) {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
ActiveStatue.value = newValue // 同步到总体状态
2025-01-07 19:47:38 +08:00
})
2025-10-10 13:23:40 +08:00
watch(TestStatus, function (newValue, oldValue) {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
ActiveStatue.value = newValue // 同步到总体状态
2025-01-07 19:47:38 +08:00
})
2025-08-07 15:44:17 +08:00
// 监听总体状态变化,处理步骤切换和错误状态
2025-10-10 13:23:40 +08:00
watch(ActiveStatue, function (newValue, oldValue) {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
// 处理错误状态
if (newValue === 'error') {
stepsActiveIndex.value = stepsTotalNum.value + 1 // 跳到最后一步
nextStepText.value = '检测失败'
}
// 处理成功完成状态(已到达最后一个检测步骤)
if (newValue === 'success' && stepsActiveIndex.value === stepsTotalNum.value - 1) {
stepsActiveIndex.value += 2 // 跳到完成状态
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
nextStepText.value = '检测完成'
}
// 处理连接超时状态
if (newValue === 'connect_timeout') {
stepsActiveIndex.value += 2 // 跳过当前步骤
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
nextStepText.value = '连接超时'
}
// 处理暂停超时状态
if (newValue === 'pause_timeout') {
stepsActiveIndex.value += 2 // 跳过当前步骤
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
nextStepText.value = '暂停超时'
}
// 处理成功状态的自动步骤切换(还有后续步骤时)
if (newValue === 'success' && stepsActiveIndex.value < stepsTotalNum.value - 1) {
nextStep() // 自动进入下一个测试步骤
handleSubmitFast() // 自动开始下一步检测
}
2025-01-07 19:47:38 +08:00
})
2024-11-21 23:02:43 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 退出和暂停恢复处理 ======================
/**
* 处理退出检测
*/
2025-03-17 13:24:35 +08:00
const handleQuit = () => {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
// 可以直接关闭的安全状态:未检测、检测完成、检测失败或异常情况
const safeExitStates = [
'waiting', // 未开始检测
'success', // 检测完成
'error', // 检测失败
'connect_timeout', // 连接超时
'pause_timeout' // 暂停超时
]
// 需要确认退出的状态:所有进行中、暂停中等状态
const needConfirmStates = [
'start', // 开始检测
'process', // 检测进行中
'test_init', // 初始化中
'paused', // 已暂停(用户可能想要继续)
'paused_ing' // 暂停中
]
if (safeExitStates.includes(ActiveStatue.value)) {
handleClose() // 安全状态直接关闭
} else {
beforeClose() // 需要确认的状态
}
2025-03-17 13:24:35 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 处理暂停检测
*/
2025-06-25 09:21:58 +08:00
const handlePause = () => {
2025-10-10 13:23:40 +08:00
sendPause() // 发送暂停指令
testRef.value?.handlePause() // 调用正式检测组件的暂停方法
2025-03-17 13:24:35 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 发送暂停指令
*/
2025-01-07 19:47:38 +08:00
const sendPause = () => {
2025-10-15 08:49:11 +08:00
2025-08-11 11:14:20 +08:00
2025-10-10 13:23:40 +08:00
TestStatus.value = 'paused_ing' // 设置为暂停中状态
pauseTest() // 调用暂停API
2025-01-07 19:47:38 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 发送继续检测指令
*/
2025-01-07 19:47:38 +08:00
const sendResume = () => {
2025-10-15 08:49:11 +08:00
2025-10-10 13:23:40 +08:00
// 调用继续检测API
resumeTest({
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
})
// 发送继续成功消息给子组件
Object.assign(webMsgSend.value, {
requestId: 'Resume_Success'
})
2025-01-07 19:47:38 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 关闭WebSocket连接
*/
2025-05-26 14:41:06 +08:00
const closeWebSocket = () => {
2025-10-10 13:23:40 +08:00
try {
if (dataSocket.socketServe) {
// 先清理回调
dataSocket.socketServe.unRegisterCallBack?.('aaa')
// 再关闭连接
if (dataSocket.socketServe.connected) {
dataSocket.socketServe.closeWs()
}
// 清空引用
dataSocket.socketServe = null
}
} catch (error) {
console.error('WebSocket关闭失败:', error)
// 强制清空引用,确保下次能正常重新连接
dataSocket.socketServe = null
2025-08-12 10:26:30 +08:00
}
2025-05-26 14:41:06 +08:00
}
2025-08-07 15:44:17 +08:00
// ====================== 步骤切换处理 ======================
/**
* 进入下一步检测 - 复杂的步骤切换逻辑
*/
2025-01-07 19:47:38 +08:00
const nextStep = () => {
2025-10-10 13:23:40 +08:00
// 如果已到最后或遇到错误状态,直接关闭弹窗
if (
stepsActiveIndex.value == stepsTotalNum.value + 1 ||
ActiveStatue.value === 'error' ||
ActiveStatue.value === 'connect_timeout' ||
ActiveStatue.value === 'pause_timeout'
) {
handleClose()
return
}
2025-10-10 13:23:40 +08:00
// 如果不是错误状态,进行步骤切换
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 as keyof typeof checkStore.selectTestItems]
) {
// 找到下一个要执行的检测项
stepsActiveView.value = idx // 设置显示的组件
stepsActive.value = idx // 设置业务逻辑步骤
return
}
if (
checkStore.selectTestItems[selectTestItemsKey as keyof typeof checkStore.selectTestItems] &&
tempStep != 0
) {
tempStep-- // 跳过已选择的检测项
}
idx++
}
}
}
2025-08-07 15:44:17 +08:00
/**
* 处理步骤点击 - 允许点击回到之前已完成的步骤
* @param step 点击的步骤序号
*/
const handleStepClick = (step: number) => {
2025-10-10 13:23:40 +08:00
if (step > stepsActive.value) {
return // 不能点击未完成的步骤
} else {
stepsActiveView.value = step // 切换到点击的步骤显示
}
}
2025-01-07 19:47:38 +08:00
2025-08-07 15:44:17 +08:00
// ====================== 数据清理和关闭处理 ======================
/**
* 清理所有数据状态
*/
2025-01-07 19:47:38 +08:00
function clearData() {
2025-10-10 13:23:40 +08:00
stepsTotalNum.value = -1
stepsActiveIndex.value = 1
stepsActiveView.value = -1
preTestStatus.value = 'waiting'
timeTestStatus.value = 'waiting'
channelsTestStatus.value = 'waiting'
TestStatus.value = 'waiting'
ActiveStatue.value = 'waiting'
nextStepText.value = '下一步'
2025-01-07 19:47:38 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 关闭前确认处理
*/
2025-08-11 11:14:20 +08:00
const beforeClose = () => {
2025-10-10 13:23:40 +08:00
// 如果检测未完成且不是错误状态,需要用户确认
if (stepsActiveIndex.value < stepsTotalNum.value && ActiveStatue.value != 'error') {
ElMessageBox.confirm('检测未完成,是否退出当前检测流程?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
handleClose() // 用户确认后关闭
})
} else {
handleClose() // 直接关闭
}
2024-11-29 13:45:48 +08:00
}
2025-08-07 15:44:17 +08:00
/**
* 关闭弹窗并清理资源
*/
const handleClose = () => {
2025-10-10 13:23:40 +08:00
showSteps.value = false // 隐藏步骤条
closeWebSocket() // 统一通过closeWebSocket函数关闭连接避免重复关闭
dialogVisible.value = false // 隐藏弹窗
clearData() // 清理所有状态数据
showComponent.value = false // 隐藏检测组件
2025-01-16 15:57:29 +08:00
2025-10-10 13:23:40 +08:00
emit('quitClicked') // 触发退出事件通知父组件
}
2025-01-07 19:47:38 +08:00
2025-08-11 11:14:20 +08:00
// ====================== 生命周期处理 ======================
/**
* 组件卸载前的清理工作
* 确保路由切换或组件销毁时正确关闭WebSocket连接
*/
onBeforeUnmount(() => {
2025-10-10 13:23:40 +08:00
closeWebSocket() // 组件销毁前关闭WebSocket连接
2025-08-11 11:14:20 +08:00
})
2025-08-07 15:44:17 +08:00
// ====================== 对外暴露的方法 ======================
2025-08-11 11:14:20 +08:00
defineExpose({ open }) // 只暴露open方法供父组件调用
2025-01-07 19:47:38 +08:00
</script>
2025-10-10 13:23:40 +08:00
<style scoped lang="scss">
2025-03-17 13:24:35 +08:00
.test-head-steps {
2025-10-10 13:23:40 +08:00
:deep(.el-step) {
.el-step__head.is-success {
color: #91cc75;
}
2025-06-25 09:21:58 +08:00
2025-10-10 13:23:40 +08:00
.el-step__title.is-success {
color: #91cc75;
}
2025-03-17 13:24:35 +08:00
}
}
2025-01-07 19:47:38 +08:00
:deep(.dialog-big .el-dialog__body) {
2025-10-10 13:23:40 +08:00
max-height: 840px !important;
2024-11-22 10:46:10 +08:00
}
2025-01-07 19:47:38 +08:00
.steps-container :deep(.test-head-steps) {
2025-10-10 13:23:40 +08:00
height: 80px;
margin-bottom: 10px;
2025-01-07 19:47:38 +08:00
}
2025-01-07 19:47:38 +08:00
.steps-container :deep(.el-step__title) {
2025-10-10 13:23:40 +08:00
font-size: 20px !important; /* 设置标题字体大小 */
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
}
2025-01-07 19:47:38 +08:00
.steps-container :deep(.el-step__icon-inner) {
2025-10-10 13:23:40 +08:00
font-size: 18px !important;
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
2025-01-07 19:47:38 +08:00
}
2025-01-07 19:47:38 +08:00
.steps-container :deep(.el-step__icon) {
2025-10-10 13:23:40 +08:00
font-size: 18px !important;
vertical-align: baseline !important;
display: inline-block; /* 确保文字和图标在同一行 */
line-height: 1; /* 调整行高以确保底部对齐 */
2024-11-25 21:11:10 +08:00
}
2025-01-07 19:47:38 +08:00
.loading-box {
2025-10-10 13:23:40 +08:00
animation: loading 1.5s linear infinite;
2025-01-07 19:47:38 +08:00
}
@keyframes loading {
2025-10-10 13:23:40 +08:00
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
2025-01-07 19:47:38 +08:00
}
</style>