diff --git a/frontend/src/api/check/interface/index.ts b/frontend/src/api/check/interface/index.ts index f48eed8..f7d2a25 100644 --- a/frontend/src/api/check/interface/index.ts +++ b/frontend/src/api/check/interface/index.ts @@ -136,6 +136,7 @@ export namespace CheckData { checkResult: number //检测结果 checkState?: number | null //检测状态 formalCheckTime?: number | null //正式检测耗时 + timeCheckResult?: number | null //守时检测结果(0:不合格,1:合格,2:未检,3:检测中/可续检) chnNumList: string[] //连线存储数据 } diff --git a/frontend/src/api/device/interface/device.ts b/frontend/src/api/device/interface/device.ts index 0b94bcc..614875b 100644 --- a/frontend/src/api/device/interface/device.ts +++ b/frontend/src/api/device/interface/device.ts @@ -75,7 +75,8 @@ export namespace Device { checkResult?: number | null //检测结果(0:不符合,1:符合,2:未检) reportState?: number | null //报告状态(0:未生成,1:已生成,2:未检) recheckNum: number //复检次数 - timeCheckResult?: number //守时检测结果(0:不符合1:符合) + timeCheckResult?: number | null //守时检测结果(0:不合格,1:合格,2:未检,3:检测中) + Time_Check_Result?: number | null //兼容后端原始字段:守时检测结果 factorCheckResult?: number //系数校准结果(0:不合格,1:合格,2:未检) realtimeResult?: number //实时数据结论(0:不符合,1:符合,2:未检) statisticsResult?: number //统计数据结论(0:不符合,1:符合,2:未检) diff --git a/frontend/src/stores/modules/check.ts b/frontend/src/stores/modules/check.ts index f0540ec..af028d5 100644 --- a/frontend/src/stores/modules/check.ts +++ b/frontend/src/stores/modules/check.ts @@ -22,6 +22,7 @@ export const useCheckStore = defineStore(CHECK_STORE_KEY, { chnNumList: [] as string[], //连线数据 nodesConnectable: true, //设置是能可以连线 resumeFormal: false, + resumeTimeCheck: false, restoringFormalProgress: false, formalProgressSnapshot: null as CheckData.FormalProgressVO | null }), @@ -40,6 +41,7 @@ export const useCheckStore = defineStore(CHECK_STORE_KEY, { const appSceneStore = useAppSceneStore() this.selectTestItems.preTest = true this.selectTestItems.timeTest = false + this.resumeTimeCheck = false if (appSceneStore.currentScene === '1') { this.selectTestItems.channelsTest = true } else { @@ -74,6 +76,9 @@ export const useCheckStore = defineStore(CHECK_STORE_KEY, { setResumeFormal(resumeFormal: boolean) { this.resumeFormal = resumeFormal }, + setResumeTimeCheck(resumeTimeCheck: boolean) { + this.resumeTimeCheck = resumeTimeCheck + }, setRestoringFormalProgress(restoring: boolean) { this.restoringFormalProgress = restoring }, diff --git a/frontend/src/views/home/components/selectTestItemPopup.vue b/frontend/src/views/home/components/selectTestItemPopup.vue index c63fb3c..f77d4a8 100644 --- a/frontend/src/views/home/components/selectTestItemPopup.vue +++ b/frontend/src/views/home/components/selectTestItemPopup.vue @@ -5,25 +5,45 @@
预检测 - +
-
- 守时检测 - +
+
+ 守时检测 + +
+
+ 守时检测是否续检 + +
系数校准 - +
-
- 正式检测 - +
+
+ 正式检测 + +
+
+ 正式检测是否续检 + +
@@ -43,7 +63,7 @@ import {dialogSmall} from "@/utils/elementBind"; import {reactive, ref} from "vue"; import {useCheckStore} from "@/stores/modules/check"; import type {CheckData} from "@/api/check/interface"; -import {ElMessageBox} from "element-plus"; +import {ElMessage, ElMessageBox} from "element-plus"; import {useAppSceneStore,useModeStore} from "@/stores/modules/mode"; @@ -56,10 +76,17 @@ const channelsTestShow = ref(false) const dialogVisible = ref(false) const formContent = reactive({preTest: true, timeTest: false, channelsTest: false, test: false}) +const resumeFormalChecked = ref(false) +const resumeFormalDisabled = ref(true) +const resumeTimeCheckChecked = ref(false) +const resumeTimeCheckDisabled = ref(true) +const submittedClose = ref(false) const open = async () => { resetFormContent() - checkStore.setSelectTestItems(formContent) + syncSelectTestItems() + checkStore.setResumeFormal(resumeFormalChecked.value) + checkStore.setResumeTimeCheck(false) dialogVisible.value = true if(modeStore.currentMode === '比对式'){ channelsTestShow.value = false @@ -76,6 +103,102 @@ const open = async () => { const resetFormContent = () => { let hasResult = checkStore.devices.some((device) => device.checkResult === 0) Object.assign(formContent, {preTest: !hasResult, channelsTest: false, timeTest: false, test: hasResult}) + resumeFormalChecked.value = formContent.test && allSelectedDevicesHaveFormalState(1) + resumeFormalDisabled.value = !allSelectedDevicesHaveFormalState(1) + resumeTimeCheckChecked.value = false + resumeTimeCheckDisabled.value = true +} + +const syncSelectTestItems = () => { + checkStore.setSelectTestItems({...formContent}) +} + +const normalizeNumber = (value: unknown) => { + if (value === null || value === undefined || value === '') { + return null + } + const num = Number(value) + return Number.isFinite(num) ? num : null +} + +const getTimeCheckResult = (device: CheckData.Device) => { + return normalizeNumber(device.timeCheckResult ?? (device as any).Time_Check_Result) +} + +const allSelectedDevicesHaveFormalState = (state: number) => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => normalizeNumber(device.checkState) === state) +} + +const allTimeCheckResultsAreNewRun = () => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => { + const result = getTimeCheckResult(device) + return result !== null && result <= 2 + }) +} + +const allTimeCheckResultsAreResumable = () => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => getTimeCheckResult(device) === 3) +} + +const hasMixedFormalCheckState = () => { + const checkStates = checkStore.devices.map(device => Number(device.checkState)) + const allCheckStatesEqual = new Set(checkStates).size <= 1 + const allCheckStatesKnown = checkStates.every(state => [0, 1, 2].includes(state)) + return !allCheckStatesEqual || !allCheckStatesKnown +} + +const handleSelectTestItemChange = () => { + syncSelectTestItems() +} + +const handleTimeTestChange = (value: string | number | boolean) => { + if (!Boolean(value)) { + resumeTimeCheckChecked.value = false + resumeTimeCheckDisabled.value = true + checkStore.setResumeTimeCheck(false) + syncSelectTestItems() + return + } + + if (!allTimeCheckResultsAreNewRun() && !allTimeCheckResultsAreResumable()) { + ElMessage.warning('守时检测中的设备不能与守时结果为符合、不符合、未检的设备混检') + formContent.timeTest = false + resumeTimeCheckChecked.value = false + resumeTimeCheckDisabled.value = true + checkStore.setResumeTimeCheck(false) + syncSelectTestItems() + return + } + + resumeTimeCheckChecked.value = allTimeCheckResultsAreResumable() + resumeTimeCheckDisabled.value = !allTimeCheckResultsAreResumable() + checkStore.setResumeTimeCheck(!resumeTimeCheckDisabled.value && resumeTimeCheckChecked.value) + syncSelectTestItems() +} + +const handleFormalTestChange = (value: string | number | boolean) => { + if (!Boolean(value)) { + resumeFormalChecked.value = false + resumeFormalDisabled.value = true + checkStore.setResumeFormal(false) + syncSelectTestItems() + return + } + + resumeFormalChecked.value = allSelectedDevicesHaveFormalState(1) + resumeFormalDisabled.value = !allSelectedDevicesHaveFormalState(1) + checkStore.setResumeFormal(!resumeFormalDisabled.value && resumeFormalChecked.value) + syncSelectTestItems() +} + +const handleResumeTimeCheckChange = (value: string | number | boolean) => { + resumeTimeCheckChecked.value = !resumeTimeCheckDisabled.value && Boolean(value) + checkStore.setResumeTimeCheck(formContent.timeTest && resumeTimeCheckChecked.value) +} + +const handleResumeFormalChange = (value: string | number | boolean) => { + resumeFormalChecked.value = !resumeFormalDisabled.value && Boolean(value) + checkStore.setResumeFormal(formContent.test && resumeFormalChecked.value) } const handleStart = async () => { @@ -88,6 +211,10 @@ const handleStart = async () => { if (count === 0) { ElMessage.warning('请选择测试内容!') } else { + if (formContent.test && hasMixedFormalCheckState()) { + ElMessage.warning('正式检测,所选设备检测状态不一致,请选择同一状态设备') + return + } if(formContent.channelsTest){ const factorFlagArray = ref([]) // 初始化为空数组 for (let i = 0; i < checkStore.devices.length; i++) { @@ -112,9 +239,12 @@ const handleStart = async () => { } checkStore.setCheckType(0) checkStore.setSelectTestItems({...formContent}) + checkStore.setResumeFormal(formContent.test && !resumeFormalDisabled.value && resumeFormalChecked.value) + checkStore.setResumeTimeCheck(formContent.timeTest && !resumeTimeCheckDisabled.value && resumeTimeCheckChecked.value) + submittedClose.value = true handleClose() emit('openTestDialog',checkStore.selectTestItems.test) @@ -126,6 +256,12 @@ const handleClose = () => { dialogVisible.value = false // 清空dialogForm中的值 resetFormContent() + if (!submittedClose.value) { + syncSelectTestItems() + checkStore.setResumeFormal(resumeFormalChecked.value) + checkStore.setResumeTimeCheck(false) + } + submittedClose.value = false dialogFormRef.value?.resetFields() } @@ -143,11 +279,25 @@ defineExpose({open}) white-space: nowrap; } +.test-item-row { + display: flex; + align-items: center; + column-gap: 80px; + width: 330px; +} + +.resume-checkbox { + display: inline-flex; + align-items: center; + justify-content: space-between; + min-width: 150px; + white-space: nowrap; +} + .select-test-form { display: grid; - grid-template-columns: repeat(2, 120px); + grid-template-columns: 330px; justify-content: center; - column-gap: 70px; row-gap: 22px; padding: 12px 0 18px; diff --git a/frontend/src/views/home/components/table.vue b/frontend/src/views/home/components/table.vue index c71b07e..35248a6 100644 --- a/frontend/src/views/home/components/table.vue +++ b/frontend/src/views/home/components/table.vue @@ -508,6 +508,25 @@ const columns = reactive[]>([ return '' } }, + { + prop: 'timeCheckResult', + label: '守时检测结果', + minWidth: 130, + sortable: true, + render: scope => { + const timeCheckResult = scope.row.timeCheckResult ?? scope.row.Time_Check_Result + if (timeCheckResult === 0) { + return '不合格' + } else if (timeCheckResult === 1) { + return '合格' + } else if (timeCheckResult === 2) { + return '未检' + } else if (timeCheckResult === 3) { + return '检测中' + } + return '' + } + }, { prop: 'reportState', label: '报告状态', @@ -592,7 +611,8 @@ const handleSelectionChange = (selection: any[]) => { factorFlag: item.factorFlag, checkResult: item.checkResult, checkState: item.checkState, - formalCheckTime: item.formalCheckTime + formalCheckTime: item.formalCheckTime, + timeCheckResult: item.timeCheckResult ?? item.Time_Check_Result } }) @@ -922,22 +942,18 @@ const handleTest = async (val: string) => { // 处理检测相关操作 if (val === '手动检测' || val === '一键检测' || val === '系数校准') { - const hasCheckingDevice = channelsSelection.value.some(item => Number(item.checkState) === 1) - const hasNonCheckingDevice = channelsSelection.value.some(item => Number(item.checkState) !== 1) - if (hasCheckingDevice && hasNonCheckingDevice) { - ElMessage.warning('检测中的设备不能和未检、检测完成的设备同时检测') - return + if (val !== '手动检测') { + // 检查选中设备的检测状态是否一致 + const checkStates = channelsSelection.value.map(item => Number(item.checkState)) + const allCheckStatesEqual = new Set(checkStates).size <= 1 + const allCheckStatesKnown = checkStates.every(state => [0, 1, 2].includes(state)) + if (!allCheckStatesEqual || !allCheckStatesKnown) { + ElMessage.warning('正式检测,所选设备检测状态不一致,请选择同一状态设备') + return + } } checkStore.setResumeFormal(false) - // 检查选中设备的检测状态是否一致 - const checkStates = channelsSelection.value.map(item => item.checkState) - const allCheckStatesEqual = new Set(checkStates).size <= 1 - - // 如果检测状态不一致,设置为复检模式 - if (!allCheckStatesEqual) { - checkStore.setReCheckType(1) - } // 限制每次检测最多12个通道 if (devChannelsNum > 12) { ElMessageBox.confirm('每次检测最多只能检测12个设备通道,请重新选择', '提示', { diff --git a/frontend/src/views/home/components/writeTHPopup.vue b/frontend/src/views/home/components/writeTHPopup.vue index 2bed63c..fa55ad1 100644 --- a/frontend/src/views/home/components/writeTHPopup.vue +++ b/frontend/src/views/home/components/writeTHPopup.vue @@ -8,11 +8,21 @@ - - + + - - + +
+ +
+ 守时检测是否续检 + +
+
@@ -30,7 +40,8 @@ import { dialogSmall } from '@/utils/elementBind' import { reactive, Ref, ref } from 'vue' import type { Device } from '@/api/device/interface/device.ts' -import { ElMessageBox, FormItemRule } from 'element-plus' +import { ElMessage } from 'element-plus' +import type { FormItemRule } from 'element-plus' import { useCheckStore } from '@/stores/modules/check' const emit = defineEmits(['openTestDialog2']) @@ -39,47 +50,170 @@ const dialogFormRef = ref() const dialogVisible = ref(false) const formContent = reactive({ temperature: 0, humidity: 0 }) -const hasCheckingDevice = ref(false) const resumeFormalChecked = ref(false) +const resumeFormalDisabled = ref(true) +const showTimeCheck = ref(false) const timeTestChecked = ref(false) +const resumeTimeCheckChecked = ref(false) +const resumeTimeCheckDisabled = ref(true) +const submittedClose = ref(false) const checkStore = useCheckStore() const open = async () => { resetFormContent() - syncResumeFormalSelection() - timeTestChecked.value = Boolean(checkStore.selectTestItems.timeTest) + if (!syncPopupSelectionState()) { + return + } dialogVisible.value = true } // 清空表单内容 -const resetFormContent = () => { +const resetFormContent = (resetStore = false) => { Object.assign(formContent, { temperature: '22', humidity: '50' }) - hasCheckingDevice.value = false resumeFormalChecked.value = false + resumeFormalDisabled.value = true + showTimeCheck.value = false timeTestChecked.value = false + resumeTimeCheckChecked.value = false + resumeTimeCheckDisabled.value = true + if (resetStore) { + checkStore.setResumeFormal(false) + checkStore.setResumeTimeCheck(false) + checkStore.setSelectTestItems({ + ...checkStore.selectTestItems, + timeTest: false, + }) + } +} + +const syncResumeTimeCheckSelection = (selected: boolean) => { + const normalizedSelected = showTimeCheck.value && timeTestChecked.value && !resumeTimeCheckDisabled.value && selected + resumeTimeCheckChecked.value = normalizedSelected + checkStore.setResumeTimeCheck(normalizedSelected) } const syncTimeTestSelection = (selected: boolean) => { - timeTestChecked.value = selected + const normalizedSelected = showTimeCheck.value && selected + timeTestChecked.value = normalizedSelected checkStore.setSelectTestItems({ ...checkStore.selectTestItems, - timeTest: selected, + timeTest: normalizedSelected, + }) + if (!normalizedSelected) { + syncResumeTimeCheckSelection(false) + } +} + +const normalizeNumber = (value: unknown) => { + if (value === null || value === undefined || value === '') { + return null + } + const num = Number(value) + return Number.isFinite(num) ? num : null +} + +const allSelectedDevicesHaveState = (state: number) => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => normalizeNumber(device.checkState) === state) +} + +const hasOnlyKnownFormalStates = () => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => [0, 1, 2].includes(normalizeNumber(device.checkState) as number)) +} + +const hasMixedFormalStates = () => { + const states = checkStore.devices.map(device => normalizeNumber(device.checkState)) + return new Set(states).size > 1 +} + +const allTimeCheckResultsAreNewRun = () => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => { + const result = normalizeNumber(device.timeCheckResult) + return result !== null && result <= 2 }) } -const syncResumeFormalSelection = () => { - hasCheckingDevice.value = checkStore.devices.some(device => Number(device.checkState) === 1) - resumeFormalChecked.value = hasCheckingDevice.value - checkStore.setResumeFormal(hasCheckingDevice.value) +const allTimeCheckResultsAreResumable = () => { + return checkStore.devices.length > 0 && checkStore.devices.every(device => normalizeNumber(device.timeCheckResult) === 3) +} + +const syncPopupSelectionState = () => { + if (!hasOnlyKnownFormalStates() || hasMixedFormalStates()) { + ElMessage.warning('正式检测,所选设备检测状态不一致,请选择同一状态设备') + return false + } + + const planTimeCheckEnabled = normalizeNumber(checkStore.plan.timeCheck) === 1 + + if (allSelectedDevicesHaveState(1)) { + resumeFormalChecked.value = true + resumeFormalDisabled.value = false + checkStore.setResumeFormal(true) + } else { + resumeFormalChecked.value = false + resumeFormalDisabled.value = true + checkStore.setResumeFormal(false) + } + + showTimeCheck.value = planTimeCheckEnabled + if (!showTimeCheck.value) { + syncTimeTestSelection(false) + syncResumeTimeCheckSelection(false) + return true + } + + if (allTimeCheckResultsAreNewRun()) { + syncTimeTestSelection(false) + resumeTimeCheckDisabled.value = true + syncResumeTimeCheckSelection(false) + return true + } + + if (allTimeCheckResultsAreResumable()) { + syncTimeTestSelection(true) + resumeTimeCheckDisabled.value = false + syncResumeTimeCheckSelection(true) + return true + } + + syncTimeTestSelection(false) + resumeTimeCheckDisabled.value = true + syncResumeTimeCheckSelection(false) + return true +} + +const handleTimeTestChange = (value: string | number | boolean) => { + const selected = Boolean(value) + if (!selected) { + syncTimeTestSelection(false) + resumeTimeCheckDisabled.value = true + syncResumeTimeCheckSelection(false) + return + } + + if (!allTimeCheckResultsAreNewRun() && !allTimeCheckResultsAreResumable()) { + ElMessage.warning('守时检测中的设备不能与守时结果为符合、不符合、未检的设备混检') + syncTimeTestSelection(false) + resumeTimeCheckDisabled.value = true + syncResumeTimeCheckSelection(false) + return + } + + syncTimeTestSelection(true) + resumeTimeCheckDisabled.value = !allTimeCheckResultsAreResumable() + if (resumeTimeCheckDisabled.value) { + syncResumeTimeCheckSelection(false) + } else { + syncResumeTimeCheckSelection(true) + } } const handleResumeFormalChange = (value: string | number | boolean) => { - const selected = hasCheckingDevice.value && Boolean(value) + const selected = !resumeFormalDisabled.value && Boolean(value) resumeFormalChecked.value = selected checkStore.setResumeFormal(selected) } -const handleTimeTestChange = (value: string | number | boolean) => { - syncTimeTestSelection(Boolean(value)) +const handleResumeTimeCheckChange = (value: string | number | boolean) => { + syncResumeTimeCheckSelection(Boolean(value)) } @@ -109,9 +243,11 @@ const handleStart = () => { if (valid) { checkStore.setTemperature(formContent.temperature) checkStore.setHumidity(formContent.humidity) - checkStore.setResumeFormal(hasCheckingDevice.value && resumeFormalChecked.value) + checkStore.setResumeFormal(!resumeFormalDisabled.value && resumeFormalChecked.value) + checkStore.setResumeTimeCheck(showTimeCheck.value && !resumeTimeCheckDisabled.value && resumeTimeCheckChecked.value) emit('openTestDialog2') - handleClose() + submittedClose.value = true + dialogVisible.value = false } }) } catch (err) { @@ -124,7 +260,8 @@ const handleStart = () => { const handleClose = () => { dialogVisible.value = false // 清空dialogForm中的值 - resetFormContent() + resetFormContent(!submittedClose.value) + submittedClose.value = false dialogFormRef.value?.resetFields() } @@ -134,4 +271,21 @@ defineExpose({ open })