消毒机设备
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

251 lines
6.5 KiB

<script lang="ts" setup>
import { sendCmd, subscribeEvent } from 'apis/system'
import homeFinish from 'assets/images/home/home-finish.svg'
import homeStart from 'assets/images/home/home-start.svg'
import { startTimer, stopTimer } from 'libs/countdownTimer'
import { deviceStateMap } from 'libs/utils'
import { computed, onMounted, ref, watchEffect } from 'vue'
import { getDeviceStatus } from '@/libs/deviceComm'
import { FtMessage } from '@/libs/message'
import { FtMessageBox } from '@/libs/messageBox'
import { useFormulaStore } from '@/stores/formulaStore'
import { useHomeStore } from '@/stores/homeStore'
import { useSystemStore } from '@/stores/systemStore'
/**
* 消毒操作控制组件
* @description 负责处理消毒流程控制(开始/结束)、状态监听及倒计时逻辑
*/
// 状态管理
const homeStore = useHomeStore()
const formulaStore = useFormulaStore()
const systemStore = useSystemStore()
// 组件状态
const curStateRemainTimeS = ref<string>('') // 当前状态剩余时间(字符串格式)
const disinfectionState = ref(homeStore.disinfectionState) // 消毒状态
const btnStyle = {
width: '25vw',
height: '7vh',
textSize: '24px',
borderRadius: '12px',
textColor: '#FFFFFF',
}
let isDisinfection = false // 是否处于消毒中状态
/**
* @hook 响应式依赖监听
* @description 监听消毒状态变化,处理倒计时逻辑
*/
watchEffect(() => {
disinfectionState.value = homeStore.disinfectionState
const time = disinfectionState.value.curStateRemainTimeS
// 进入消毒状态且未启动倒计时时开始计时
if (disinfectionState.value.state === 'disinfection' && !isDisinfection && time > 0) {
isDisinfection = true
startTimer(time * 1000, (times: string) => {
homeStore.updateHomeRemainTime(times)
curStateRemainTimeS.value = times
})
}
})
/**
* @hook 生命周期钩子 - 组件挂载完成时执行
* @description 订阅消毒状态更新事件
*/
onMounted(async () => {
await systemStore.subscribeDisinfectEvent() // 订阅状态更新
subscribeEvent('stateUpdate', handleDisinfectState)
})
/**
* @function 处理消毒状态更新事件
* @param {Socket.WebSocketResponse<Home.DisinfectState>} report - 状态更新报告
* @desc 接收并更新消毒状态数据
*/
const handleDisinfectState = (report: Socket.WebSocketResponse<Home.DisinfectState>) => {
if (report.fromClass === 'DisinfectionCtrlServiceExt') {
homeStore.updateHomeDisinfectionState(report.rely)
}
}
/**
* @function 开始消毒操作
* @desc 校验设备状态并发起消毒请求
*/
const onStartDisinfect = () => {
// 校验日志等级
if (!formulaStore.loglevel) {
FtMessage.warning('请选择消毒等级')
return
}
FtMessageBox.warning('请确认是否开始消毒').then(() => {
doStartDisinfect()
})
}
const doStartDisinfect = async () => {
// 校验设备状态
const statusName = getDeviceStatus()
if (statusName) {
FtMessageBox.error(statusName)
return
}
systemStore.updateLoading(true)
try {
// 使用选中配方或默认配置启动消毒
if (formulaStore.selectedFormulaInfo && formulaStore.selectedFormulaInfo.formula_id) {
await formulaStore.startDisinfectFormula(formulaStore.selectedFormulaInfo)
}
else {
const startParams = {
className: 'DisinfectionCtrlServiceExt',
fnName: 'start',
params: { loglevel: formulaStore.loglevel },
}
await sendCmd(startParams)
}
}
finally {
systemStore.updateLoading(false)
}
}
/**
* @function 结束消毒操作
* @desc 停止倒计时并发起结束消毒请求
*/
const onFinishDisinfect = () => {
FtMessageBox.warning('请确认是否结束消毒').then(() => {
doStopDisinfect()
})
}
const doStopDisinfect = async () => {
stopTimer() // 停止倒计时
systemStore.updateLoading(true)
try {
const stopParams = {
className: 'DisinfectionCtrlServiceExt',
fnName: 'stop',
params: { loglevel: formulaStore.loglevel },
}
await sendCmd(stopParams)
}
finally {
systemStore.updateLoading(false)
}
}
/**
* @computed 计算属性 - 操作状态判断
* @returns {boolean} - 是否处于空闲或已完成状态
* @desc 控制开始/结束按钮的显示逻辑
*/
const operationState = computed(() => {
return disinfectionState.value.state === 'idle' || disinfectionState.value.state === 'finished'
})
</script>
<template>
<div class="home-disinfect">
<bt-button
v-if="operationState"
button-text="开始消毒"
bg-color="#31CB7A"
:text-color="btnStyle.textColor"
:width="btnStyle.width"
:height="btnStyle.height"
:text-size="btnStyle.textSize"
:border-radius="btnStyle.borderRadius"
min-height="4rem"
@click="onStartDisinfect"
>
<template #icon>
<img :src="homeStart" alt="">
</template>
</bt-button>
<bt-button
v-else
button-text="结束消毒"
bg-color="#FF6767"
:text-color="btnStyle.textColor"
:width="btnStyle.width"
:height="btnStyle.height"
:text-size="btnStyle.textSize"
:border-radius="btnStyle.borderRadius"
min-height="4rem"
@click="onFinishDisinfect"
>
<template #icon>
<img :src="homeFinish" alt="">
</template>
</bt-button>
</div>
<!-- 开始消毒时显示剩余时间或状态 -->
<div v-if="!operationState" class="home-remain-time">
<div class="home-remaini-label">
<span v-if="disinfectionState.state === 'disinfection'">
预计剩余时间:
</span>
<span v-else>
消毒状态:
</span>
</div>
<div v-if="disinfectionState.state === 'disinfection'" class="home-remaini-value">
{{ curStateRemainTimeS }}
</div>
<div v-else>
{{ deviceStateMap[disinfectionState.state] }}
</div>
</div>
</template>
<style lang="scss" scoped>
.home-disinfect{
display: flex;
justify-content: center;
margin-top: 5vh;
}
.home-disinfect-btn{
width: 27vw;
height: 8vh;
border-radius: 12px;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
gap: 10px;
}
.home-start{
background: #31CB7A;
}
.home-end{
background: #FF6767;
}
.home-remain-time{
background: #F6FAFE;
margin-top: 6rem;
width: 27vw;
height: 8vh;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
gap: 10px;
margin-left: 1rem;
.home-remaini-value{
color: #2892F3;
}
}
</style>