管道式消毒机
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.

784 lines
17 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div class="progress_container">
  3. <div class="header_wrap">
  4. <div class="left_progress">
  5. <div class="left_time_tag">剩余时间</div>
  6. <p class="time">
  7. {{
  8. operatorStore.estimatedRemainingTimeS == 0
  9. ? '已结束'
  10. : `${time_To_hhmmss(operatorStore.estimatedRemainingTimeS)}`
  11. }}
  12. </p>
  13. <p class="pre_time">预热时间约5分钟</p>
  14. <!-- <div class="progress_bg">
  15. <div
  16. class="pro"
  17. :style="{
  18. '--width': '325px',
  19. }"
  20. ></div>
  21. </div> -->
  22. </div>
  23. <div class="right_btns">
  24. <div
  25. :class="
  26. [1, 2].includes(operatorStore.disinfectStatus)
  27. ? 'btn active'
  28. : 'btn'
  29. "
  30. v-if="[1, 2].includes(operatorStore.disinfectStatus)"
  31. @click="stopDisinfect"
  32. >
  33. 停止消毒
  34. </div>
  35. <div
  36. :class="
  37. [0].includes(operatorStore.disinfectStatus) ? 'btn active' : 'btn'
  38. "
  39. v-if="operatorStore.disinfectStatus == 0"
  40. @click="showDetail"
  41. >
  42. 返回
  43. </div>
  44. <!-- <div
  45. :class="
  46. operatorStore.disinfectStatus == 1 ? 'btn active ml' : 'btn ml'
  47. "
  48. @click="pauseDisinfect"
  49. >
  50. 暂停消毒
  51. </div>
  52. <div
  53. :class="operatorStore.disinfectStatus == 2 ? 'btn active' : 'btn'"
  54. @click="continueDisinfect"
  55. >
  56. 继续消毒
  57. </div> -->
  58. </div>
  59. </div>
  60. <div class="echarts_wrap">
  61. <div class="single_wrap">
  62. <p class="title">设备温度/湿度/过氧化氢浓度</p>
  63. <div
  64. class="echarts_box"
  65. id="bin"
  66. v-if="operatorStore.disinfectStatus != 0 || binLocal"
  67. ></div>
  68. </div>
  69. <div class="single_wrap">
  70. <p class="title">环境1/湿度/过氧化氢浓度</p>
  71. <div
  72. class="echarts_box"
  73. id="envir1"
  74. v-if="operatorStore.disinfectStatus != 0 || envir1Local"
  75. ></div>
  76. </div>
  77. <div class="single_wrap">
  78. <p class="title">环境2/湿度/过氧化氢浓度</p>
  79. <div
  80. class="echarts_box"
  81. id="envir2"
  82. v-if="operatorStore.disinfectStatus != 0 || envir2Local"
  83. ></div>
  84. </div>
  85. </div>
  86. <div class="detail_wrap">
  87. <div class="detail" @click="showDetail">详情</div>
  88. </div>
  89. </div>
  90. </template>
  91. <script setup>
  92. import { useOperatorStore, useWebSocketStore, useEchartsStore } from '@/store'
  93. import { time_To_hhmmss } from '@/utils'
  94. import {
  95. stopDisinfectionJSON,
  96. getStateJSON,
  97. continueDisinfectionJSON,
  98. pauseDisinfectionJSON,
  99. } from '@/mock/command'
  100. import { onMounted, onUnmounted, ref, computed, watch } from 'vue'
  101. import * as echarts from 'echarts'
  102. import { storeToRefs } from 'pinia'
  103. const echartsStore = useEchartsStore()
  104. const binLocal = computed(() => {
  105. return echartsStore?.binCharts || localStorage.getItem('bin')
  106. })
  107. const envir1Local = computed(() => {
  108. return echartsStore?.envir1Charts || localStorage.getItem('envir1')
  109. })
  110. const envir2Local = computed(() => {
  111. return echartsStore?.envir2Charts || localStorage.getItem('envir2')
  112. })
  113. const binOption = ref({
  114. tooltip: {
  115. trigger: 'axis',
  116. },
  117. legend: {
  118. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  119. },
  120. grid: {
  121. left: '3%',
  122. right: '4%',
  123. bottom: '3%',
  124. containLabel: true,
  125. },
  126. xAxis: {
  127. type: 'category',
  128. boundaryGap: false,
  129. data: Array.from(
  130. Array(Object.keys(echartsStore.binCharts).length),
  131. (v, k) => k,
  132. ),
  133. },
  134. yAxis: {
  135. type: 'value',
  136. },
  137. series: [
  138. {
  139. name: '温度',
  140. type: 'line',
  141. stack: 'binTemp',
  142. data: echartsStore.binTemp,
  143. },
  144. {
  145. name: '湿度',
  146. type: 'line',
  147. stack: 'binHumidity',
  148. data: echartsStore.binHumidity,
  149. },
  150. {
  151. name: 'H2O2浓度',
  152. type: 'line',
  153. stack: 'binHP',
  154. data: echartsStore.binHP,
  155. },
  156. {
  157. name: 'H2O2饱和度',
  158. type: 'line',
  159. stack: 'binSaturation',
  160. data: echartsStore.binSaturation,
  161. },
  162. ],
  163. })
  164. const envir1Option = ref({
  165. tooltip: {
  166. trigger: 'axis',
  167. },
  168. legend: {
  169. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  170. },
  171. grid: {
  172. left: '3%',
  173. right: '4%',
  174. bottom: '3%',
  175. containLabel: true,
  176. },
  177. xAxis: {
  178. type: 'category',
  179. boundaryGap: false,
  180. data: Object.keys(echartsStore.envir1Charts),
  181. },
  182. yAxis: {
  183. type: 'value',
  184. },
  185. series: [
  186. {
  187. name: '温度',
  188. type: 'line',
  189. stack: '1',
  190. data: [],
  191. },
  192. {
  193. name: '湿度',
  194. type: 'line',
  195. stack: '2',
  196. data: [],
  197. },
  198. {
  199. name: 'H2O2浓度',
  200. type: 'line',
  201. stack: '3',
  202. data: [],
  203. },
  204. {
  205. name: 'H2O2饱和度',
  206. type: 'line',
  207. stack: '4',
  208. data: [],
  209. },
  210. ],
  211. })
  212. const envir2Option = ref({
  213. tooltip: {
  214. trigger: 'axis',
  215. },
  216. legend: {
  217. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  218. },
  219. grid: {
  220. left: '3%',
  221. right: '4%',
  222. bottom: '3%',
  223. containLabel: true,
  224. },
  225. xAxis: {
  226. type: 'category',
  227. boundaryGap: false,
  228. data: Object.keys(echartsStore.envir2Charts),
  229. },
  230. yAxis: {
  231. type: 'value',
  232. },
  233. series: [
  234. {
  235. name: '温度',
  236. type: 'line',
  237. stack: '1',
  238. data: [],
  239. },
  240. {
  241. name: '湿度',
  242. type: 'line',
  243. stack: '2',
  244. data: [],
  245. },
  246. {
  247. name: 'H2O2浓度',
  248. type: 'line',
  249. stack: '3',
  250. data: [],
  251. },
  252. {
  253. name: 'H2O2饱和度',
  254. type: 'line',
  255. stack: '4',
  256. data: [],
  257. },
  258. ],
  259. })
  260. const operatorStore = useOperatorStore()
  261. const webSocketStore = useWebSocketStore()
  262. const props = defineProps({
  263. changeShowOperator: {
  264. type: Function,
  265. },
  266. })
  267. const showDetail = () => {
  268. props.changeShowOperator(true)
  269. }
  270. const timer = ref(null)
  271. const binCharts = ref(null)
  272. const envir1Charts = ref(null)
  273. const envir2Charts = ref(null)
  274. const time1 = ref(null)
  275. const time2 = ref(null)
  276. onMounted(() => {
  277. timer.value = setInterval(() => {
  278. webSocketStore.sendCommandMsg(getStateJSON)
  279. }, 1000)
  280. let a = echarts.getInstanceByDom(document.getElementById('bin'))
  281. if (a == undefined) {
  282. binCharts.value = echarts.init(document.getElementById('bin'))
  283. binCharts.value.setOption(binOption.value)
  284. }
  285. let b = echarts.getInstanceByDom(document.getElementById('envir1'))
  286. if (b == undefined) {
  287. envir1Charts.value = echarts.init(document.getElementById('envir1'))
  288. envir1Charts.value.setOption(envir1Option.value)
  289. }
  290. let c = echarts.getInstanceByDom(document.getElementById('envir2'))
  291. if (c == undefined) {
  292. envir2Charts.value = echarts.init(document.getElementById('envir2'))
  293. envir2Charts.value.setOption(envir2Option.value)
  294. }
  295. time1.value = setInterval(() => {
  296. binCharts.value?.setOption({
  297. tooltip: {
  298. trigger: 'axis',
  299. },
  300. legend: {
  301. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  302. },
  303. grid: {
  304. left: '3%',
  305. right: '4%',
  306. bottom: '3%',
  307. containLabel: true,
  308. },
  309. xAxis: {
  310. type: 'category',
  311. boundaryGap: false,
  312. data: Array.from(
  313. Array(Object.keys(echartsStore.binCharts).length),
  314. (v, k) => k,
  315. ),
  316. },
  317. yAxis: {
  318. type: 'value',
  319. },
  320. series: [
  321. {
  322. name: '温度',
  323. type: 'line',
  324. stack: 'binTemp',
  325. data: echartsStore.binTemp,
  326. },
  327. {
  328. name: '湿度',
  329. type: 'line',
  330. stack: 'binHumidity',
  331. data: echartsStore.binHumidity,
  332. },
  333. {
  334. name: 'H2O2浓度',
  335. type: 'line',
  336. stack: 'binHP',
  337. data: echartsStore.binHP,
  338. },
  339. {
  340. name: 'H2O2饱和度',
  341. type: 'line',
  342. stack: 'binSaturation',
  343. data: echartsStore.binSaturation,
  344. },
  345. ],
  346. })
  347. envir1Charts.value?.setOption({
  348. tooltip: {
  349. trigger: 'axis',
  350. },
  351. legend: {
  352. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  353. },
  354. grid: {
  355. left: '3%',
  356. right: '4%',
  357. bottom: '3%',
  358. containLabel: true,
  359. },
  360. xAxis: {
  361. type: 'category',
  362. boundaryGap: false,
  363. data: Object.keys(echartsStore.envir1Charts),
  364. },
  365. yAxis: {
  366. type: 'value',
  367. },
  368. series: [
  369. {
  370. name: '温度',
  371. type: 'line',
  372. stack: '1',
  373. data: [],
  374. },
  375. {
  376. name: '湿度',
  377. type: 'line',
  378. stack: '2',
  379. data: [],
  380. },
  381. {
  382. name: 'H2O2浓度',
  383. type: 'line',
  384. stack: '3',
  385. data: [],
  386. },
  387. {
  388. name: 'H2O2饱和度',
  389. type: 'line',
  390. stack: '4',
  391. data: [],
  392. },
  393. ],
  394. })
  395. envir2Charts.value?.setOption({
  396. tooltip: {
  397. trigger: 'axis',
  398. },
  399. legend: {
  400. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  401. },
  402. grid: {
  403. left: '3%',
  404. right: '4%',
  405. bottom: '3%',
  406. containLabel: true,
  407. },
  408. xAxis: {
  409. type: 'category',
  410. boundaryGap: false,
  411. data: Object.keys(echartsStore.envir2Charts),
  412. },
  413. yAxis: {
  414. type: 'value',
  415. },
  416. series: [
  417. {
  418. name: '温度',
  419. type: 'line',
  420. stack: '1',
  421. data: [],
  422. },
  423. {
  424. name: '湿度',
  425. type: 'line',
  426. stack: '2',
  427. data: [],
  428. },
  429. {
  430. name: 'H2O2浓度',
  431. type: 'line',
  432. stack: '3',
  433. data: [],
  434. },
  435. {
  436. name: 'H2O2饱和度',
  437. type: 'line',
  438. stack: '4',
  439. data: [],
  440. },
  441. ],
  442. })
  443. }, 1000 * 20)
  444. time1.value = setInterval(() => {
  445. binCharts.value?.setOption({
  446. tooltip: {
  447. trigger: 'axis',
  448. },
  449. legend: {
  450. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  451. },
  452. grid: {
  453. left: '3%',
  454. right: '4%',
  455. bottom: '3%',
  456. containLabel: true,
  457. },
  458. xAxis: {
  459. type: 'category',
  460. boundaryGap: false,
  461. data: Array.from(
  462. Array(Object.keys(echartsStore.binCharts).length),
  463. (v, k) => k,
  464. ),
  465. },
  466. yAxis: {
  467. type: 'value',
  468. },
  469. series: [
  470. {
  471. name: '温度',
  472. type: 'line',
  473. stack: 'binTemp',
  474. data: echartsStore.binTemp,
  475. },
  476. {
  477. name: '湿度',
  478. type: 'line',
  479. stack: 'binHumidity',
  480. data: echartsStore.binHumidity,
  481. },
  482. {
  483. name: 'H2O2浓度',
  484. type: 'line',
  485. stack: 'binHP',
  486. data: echartsStore.binHP,
  487. },
  488. {
  489. name: 'H2O2饱和度',
  490. type: 'line',
  491. stack: 'binSaturation',
  492. data: echartsStore.binSaturation,
  493. },
  494. ],
  495. })
  496. envir1Charts.value?.setOption({
  497. tooltip: {
  498. trigger: 'axis',
  499. },
  500. legend: {
  501. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  502. },
  503. grid: {
  504. left: '3%',
  505. right: '4%',
  506. bottom: '3%',
  507. containLabel: true,
  508. },
  509. xAxis: {
  510. type: 'category',
  511. boundaryGap: false,
  512. data: Object.keys(echartsStore.envir1Charts),
  513. },
  514. yAxis: {
  515. type: 'value',
  516. },
  517. series: [
  518. {
  519. name: '温度',
  520. type: 'line',
  521. stack: '1',
  522. data: [],
  523. },
  524. {
  525. name: '湿度',
  526. type: 'line',
  527. stack: '2',
  528. data: [],
  529. },
  530. {
  531. name: 'H2O2浓度',
  532. type: 'line',
  533. stack: '3',
  534. data: [],
  535. },
  536. {
  537. name: 'H2O2饱和度',
  538. type: 'line',
  539. stack: '4',
  540. data: [],
  541. },
  542. ],
  543. })
  544. envir2Charts.value?.setOption({
  545. tooltip: {
  546. trigger: 'axis',
  547. },
  548. legend: {
  549. data: ['温度', '湿度', 'H2O2浓度', 'H2O2饱和度'],
  550. },
  551. grid: {
  552. left: '3%',
  553. right: '4%',
  554. bottom: '3%',
  555. containLabel: true,
  556. },
  557. xAxis: {
  558. type: 'category',
  559. boundaryGap: false,
  560. data: Object.keys(echartsStore.envir2Charts),
  561. },
  562. yAxis: {
  563. type: 'value',
  564. },
  565. series: [
  566. {
  567. name: '温度',
  568. type: 'line',
  569. stack: '1',
  570. data: [],
  571. },
  572. {
  573. name: '湿度',
  574. type: 'line',
  575. stack: '2',
  576. data: [],
  577. },
  578. {
  579. name: 'H2O2浓度',
  580. type: 'line',
  581. stack: '3',
  582. data: [],
  583. },
  584. {
  585. name: 'H2O2饱和度',
  586. type: 'line',
  587. stack: '4',
  588. data: [],
  589. },
  590. ],
  591. })
  592. }, 1000)
  593. })
  594. // 监听到store中的数据变化动态更改options
  595. onUnmounted(() => {
  596. timer.value = null
  597. time1.value = null
  598. time2.value = null
  599. })
  600. const pauseDisinfect = () => {
  601. if (operatorStore.disinfectStatus == 1) {
  602. webSocketStore.sendCommandMsg(pauseDisinfectionJSON)
  603. }
  604. }
  605. const stopDisinfect = () => {
  606. if ([1, 2].includes(operatorStore.disinfectStatus)) {
  607. webSocketStore.sendCommandMsg(stopDisinfectionJSON)
  608. }
  609. }
  610. const continueDisinfect = () => {
  611. if (operatorStore.disinfectStatus == 2) {
  612. webSocketStore.sendCommandMsg(continueDisinfectionJSON)
  613. }
  614. }
  615. </script>
  616. <style lang="scss" scoped>
  617. .progress_container {
  618. margin-bottom: 30px;
  619. height: 580px;
  620. box-sizing: border-box;
  621. background: #ffffff;
  622. border-radius: 16px;
  623. padding: 20px;
  624. padding-bottom: 30px;
  625. .header_wrap {
  626. display: flex;
  627. align-items: center;
  628. margin-bottom: 49px;
  629. .left_progress {
  630. // width: 860px;
  631. flex: 1;
  632. height: 80px;
  633. border-radius: 14px;
  634. background: #f6f6f6;
  635. box-sizing: border-box;
  636. padding: 0 23px;
  637. display: flex;
  638. align-items: center;
  639. position: relative;
  640. .left_time_tag {
  641. width: 158.66px;
  642. height: 45px;
  643. border-radius: 23px;
  644. opacity: 1;
  645. background: #06518b;
  646. display: flex;
  647. align-items: center;
  648. justify-content: center;
  649. font-family: Source Han Sans CN;
  650. font-size: 14px;
  651. font-weight: normal;
  652. letter-spacing: 0.1em;
  653. color: #ffffff;
  654. }
  655. .time {
  656. // width: 90px;
  657. flex: 1;
  658. height: 20px;
  659. font-family: Source Han Sans CN;
  660. font-size: 14px;
  661. font-weight: 500;
  662. letter-spacing: 0.1em;
  663. color: #000000;
  664. display: flex;
  665. align-items: center;
  666. justify-content: center;
  667. }
  668. .pre_time {
  669. position: absolute;
  670. font-family: Source Han Sans CN;
  671. font-size: 14px;
  672. font-weight: 500;
  673. letter-spacing: 0.1em;
  674. color: red;
  675. left: 214px;
  676. }
  677. .progress_bg {
  678. width: 396px;
  679. height: 14px;
  680. border-radius: 7px;
  681. background: #ffffff;
  682. position: relative;
  683. overflow: hidden;
  684. .pro {
  685. position: absolute;
  686. left: 0;
  687. top: 0;
  688. height: 14px;
  689. border-radius: 7px;
  690. background: #06518b;
  691. width: var(--width);
  692. }
  693. }
  694. }
  695. .right_btns {
  696. display: flex;
  697. align-items: center;
  698. box-sizing: border-box;
  699. margin-left: 20px;
  700. .btn {
  701. width: 140px;
  702. height: 45px;
  703. border-radius: 23px;
  704. background: #f6f6f6;
  705. display: flex;
  706. align-items: center;
  707. justify-content: center;
  708. font-family: Source Han Sans CN;
  709. font-size: 14px;
  710. font-weight: normal;
  711. letter-spacing: 0.1em;
  712. color: #d8d8d8;
  713. }
  714. .active {
  715. color: #ffffff;
  716. background: #06518b;
  717. }
  718. .ml {
  719. margin: 0 20px;
  720. }
  721. }
  722. }
  723. .echarts_wrap {
  724. height: 351px;
  725. display: flex;
  726. align-items: center;
  727. margin-bottom: 19px;
  728. .single_wrap {
  729. flex: 1;
  730. height: 351px;
  731. .title {
  732. font-family: Source Han Sans CN;
  733. font-size: 14px;
  734. font-weight: 500;
  735. letter-spacing: 0.1em;
  736. color: #000000;
  737. margin-bottom: 24px;
  738. padding-left: 11px;
  739. }
  740. .echarts_box {
  741. width: 380px;
  742. height: 308px;
  743. }
  744. }
  745. }
  746. .detail_wrap {
  747. display: flex;
  748. align-items: center;
  749. justify-content: flex-end;
  750. padding-right: 16px;
  751. .detail {
  752. width: 105px;
  753. height: 40px;
  754. border-radius: 20px;
  755. background: #06518b;
  756. display: flex;
  757. align-items: center;
  758. justify-content: center;
  759. font-family: Source Han Sans CN;
  760. font-size: 18px;
  761. font-weight: normal;
  762. letter-spacing: 0.1em;
  763. color: #ffffff;
  764. }
  765. }
  766. }
  767. </style>