消毒机设备
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.

270 lines
7.1 KiB

3 weeks ago
1 month ago
1 month ago
1 month ago
3 weeks ago
3 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
  1. <script lang="ts" setup>
  2. import { sendCmd } from 'apis/system'
  3. import homeFinish from 'assets/images/home/home-finish.svg'
  4. import homeStart from 'assets/images/home/home-start.svg'
  5. import { startTimer, stopTimer } from 'libs/countdownTimer'
  6. import { deviceStateMap } from 'libs/utils'
  7. import { computed, ref, watchEffect } from 'vue'
  8. import { getDeviceStatus } from '@/libs/deviceComm'
  9. import { FtMessage } from '@/libs/message'
  10. import { FtMessageBox } from '@/libs/messageBox'
  11. import { useFormulaStore } from '@/stores/formulaStore'
  12. import { useHomeStore } from '@/stores/homeStore'
  13. import { useSystemStore } from '@/stores/systemStore'
  14. /**
  15. * 消毒操作控制组件
  16. * @description 负责处理消毒流程控制开始/结束状态监听及倒计时逻辑
  17. */
  18. // 状态管理
  19. const homeStore = useHomeStore()
  20. const formulaStore = useFormulaStore()
  21. const systemStore = useSystemStore()
  22. // 组件状态
  23. const curStateRemainTimeS = ref<string>('') // 当前状态剩余时间(字符串格式)
  24. const disinfectionState = ref(homeStore.disinfectionState) // 消毒状态
  25. const btnStyle = {
  26. width: '25vw',
  27. height: '7vh',
  28. textSize: '24px',
  29. borderRadius: '12px',
  30. textColor: '#FFFFFF',
  31. }
  32. let isDisinfection = false // 是否处于消毒中状态
  33. /**
  34. * @hook 响应式依赖监听
  35. * @description 监听消毒状态变化处理倒计时逻辑
  36. */
  37. watchEffect(() => {
  38. disinfectionState.value = homeStore.disinfectionState
  39. const time = disinfectionState.value.curStateRemainTimeS
  40. // 进入消毒状态且未启动倒计时时开始计时
  41. if (disinfectionState.value.state === 'disinfection' && !isDisinfection && time > 0) {
  42. isDisinfection = true
  43. startTimer(time * 1000, (times: string) => {
  44. homeStore.updateHomeRemainTime(times)
  45. curStateRemainTimeS.value = times
  46. })
  47. }
  48. })
  49. /**
  50. * @function 开始消毒操作
  51. * @desc 校验设备状态并发起消毒请求
  52. */
  53. const onStartDisinfect = () => {
  54. // 校验日志等级
  55. if (!formulaStore.loglevel) {
  56. FtMessage.warning('请选择消毒等级')
  57. return
  58. }
  59. FtMessageBox.warning('请确认是否开始消毒').then(() => {
  60. doStartDisinfect()
  61. })
  62. }
  63. const doStartDisinfect = async () => {
  64. // 校验设备状态
  65. const statusName = getDeviceStatus()
  66. if (statusName) {
  67. FtMessageBox.error(statusName)
  68. return
  69. }
  70. systemStore.updateLoading(true)
  71. try {
  72. // 使用选中配方或默认配置启动消毒
  73. if (formulaStore.selectedFormulaInfo && formulaStore.selectedFormulaInfo.formula_id) {
  74. await formulaStore.startDisinfectFormula(formulaStore.selectedFormulaInfo)
  75. const poll = setInterval(() => {
  76. if (!operationState.value) {
  77. systemStore.updateLoading(false)
  78. clearInterval(poll)
  79. }
  80. }, 100)
  81. }
  82. else {
  83. const startParams = {
  84. className: 'DisinfectionCtrlServiceExt',
  85. fnName: 'start',
  86. params: { loglevel: formulaStore.loglevel },
  87. }
  88. await sendCmd(startParams)
  89. const poll = setInterval(() => {
  90. if (!operationState.value) {
  91. systemStore.updateLoading(false)
  92. clearInterval(poll)
  93. }
  94. }, 100)
  95. }
  96. }
  97. catch (e) {
  98. console.log(e)
  99. systemStore.updateLoading(false)
  100. }
  101. }
  102. /**
  103. * @function 结束消毒操作
  104. * @desc 停止倒计时并发起结束消毒请求
  105. */
  106. const onFinishDisinfect = () => {
  107. FtMessageBox.warning('请确认是否结束消毒').then(() => {
  108. doStopDisinfect()
  109. })
  110. }
  111. const doStopDisinfect = async () => {
  112. stopTimer() // 停止倒计时
  113. systemStore.updateLoading(true)
  114. try {
  115. const stopParams = {
  116. className: 'DisinfectionCtrlServiceExt',
  117. fnName: 'stop',
  118. params: { loglevel: formulaStore.loglevel },
  119. }
  120. await sendCmd(stopParams)
  121. const poll = setInterval(() => {
  122. if (operationState.value) {
  123. systemStore.updateLoading(false)
  124. clearInterval(poll)
  125. }
  126. }, 100)
  127. }
  128. catch (e) {
  129. console.log(e)
  130. systemStore.updateLoading(false)
  131. }
  132. }
  133. /**
  134. * @computed 计算属性 - 操作状态判断
  135. * @returns {boolean} - 是否处于空闲或已完成状态
  136. * @desc 控制开始/结束按钮的显示逻辑
  137. */
  138. const operationState = computed(() => {
  139. return disinfectionState.value.state === 'idle' || disinfectionState.value.state === 'finished'
  140. })
  141. const startInjection = async () => {
  142. const stopParams = {
  143. className: 'DisinfectionCtrlServiceExt',
  144. fnName: 'setHandleStopPumpInjectionFlag',
  145. params: {},
  146. }
  147. await sendCmd(stopParams)
  148. FtMessage.success('操作成功')
  149. }
  150. const stopInjection = async () => {
  151. const stopParams = {
  152. className: 'DisinfectionCtrlServiceExt',
  153. fnName: 'clearHandleStopPumpInjectionFlag',
  154. params: {},
  155. }
  156. await sendCmd(stopParams)
  157. FtMessage.success('操作成功')
  158. }
  159. </script>
  160. <template>
  161. <div class="home-disinfect">
  162. <bt-button
  163. v-if="operationState"
  164. button-text="开始消毒"
  165. bg-color="#31CB7A"
  166. :text-color="btnStyle.textColor"
  167. :width="btnStyle.width"
  168. :height="btnStyle.height"
  169. :text-size="btnStyle.textSize"
  170. :border-radius="btnStyle.borderRadius"
  171. min-height="4rem"
  172. @click="onStartDisinfect"
  173. >
  174. <template #icon>
  175. <img :src="homeStart" alt="">
  176. </template>
  177. </bt-button>
  178. <bt-button
  179. v-else
  180. button-text="结束消毒"
  181. bg-color="#FF6767"
  182. :text-color="btnStyle.textColor"
  183. :width="btnStyle.width"
  184. :height="btnStyle.height"
  185. :text-size="btnStyle.textSize"
  186. :border-radius="btnStyle.borderRadius"
  187. min-height="4rem"
  188. @click="onFinishDisinfect"
  189. >
  190. <template #icon>
  191. <img :src="homeFinish" alt="">
  192. </template>
  193. </bt-button>
  194. </div>
  195. <div
  196. v-if="!operationState"
  197. style="width: 100%; display: flex; align-items: center; justify-content: center; margin-top: 10px"
  198. >
  199. <div style="margin-right: 10px">
  200. <span v-if="homeStore.disinfectionState.handlePumpStopFlag">已开启</span>
  201. <span v-else>已关闭</span>
  202. </div>
  203. <el-button type="primary" @click="startInjection">
  204. 开启喷液
  205. </el-button>
  206. <el-button type="danger" @click="stopInjection">
  207. 关闭喷液
  208. </el-button>
  209. </div>
  210. <!-- 开始消毒时显示剩余时间或状态 -->
  211. <div v-if="!operationState" class="home-remain-time">
  212. <div class="home-remaini-label">
  213. <span v-if="disinfectionState.state === 'disinfection'"> 预计剩余时间: </span>
  214. <span v-else> 消毒状态 </span>
  215. </div>
  216. <div v-if="disinfectionState.state === 'disinfection'" class="home-remaini-value">
  217. {{ curStateRemainTimeS }}
  218. </div>
  219. <div v-else>
  220. {{ deviceStateMap[disinfectionState.state] }}
  221. </div>
  222. </div>
  223. </template>
  224. <style lang="scss" scoped>
  225. .home-disinfect {
  226. display: flex;
  227. justify-content: center;
  228. margin-top: 20px;
  229. }
  230. .home-start {
  231. background: #31cb7a;
  232. }
  233. .home-end {
  234. background: #ff6767;
  235. }
  236. .home-remain-time {
  237. background: #f6fafe;
  238. margin-top: 1.5em;
  239. margin-left: 1rem;
  240. margin-right: 1rem;
  241. height: 8vh;
  242. border-radius: 12px;
  243. display: flex;
  244. align-items: center;
  245. justify-content: center;
  246. font-size: 24px;
  247. gap: 10px;
  248. .home-remaini-value {
  249. color: #2892f3;
  250. }
  251. }
  252. </style>