消毒机前端代码
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.

415 lines
9.3 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
  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. : `${operatorStore.estimatedRemainingTimeS} S`
  11. }}
  12. </p>
  13. <!-- <div class="progress_bg">
  14. <div
  15. class="pro"
  16. :style="{
  17. '--width': '325px',
  18. }"
  19. ></div>
  20. </div> -->
  21. </div>
  22. <div class="right_btns">
  23. <div
  24. :class="operatorStore.disinfectStatus ? 'btn active' : 'btn'"
  25. @click="stopDisinfect"
  26. >
  27. 停止消毒
  28. </div>
  29. <div
  30. :class="operatorStore.disinfectStatus ? 'btn active ml' : 'btn ml'"
  31. @click="pauseDisinfect"
  32. >
  33. 暂停消毒
  34. </div>
  35. <div
  36. :class="operatorStore.disinfectStatus ? 'btn' : 'btn active'"
  37. @click="continueDisinfect"
  38. >
  39. 继续消毒
  40. </div>
  41. </div>
  42. </div>
  43. <div class="echarts_wrap">
  44. <div class="single_wrap">
  45. <p class="title">设备温度/湿度/过氧化氢浓度</p>
  46. <div
  47. class="echarts_box"
  48. id="bin"
  49. v-if="operatorStore.disinfectStatus || localStorage.getItem('bin')"
  50. ></div>
  51. </div>
  52. <div class="single_wrap">
  53. <p class="title">环境1/湿度/过氧化氢浓度</p>
  54. <div
  55. class="echarts_box"
  56. id="envir1"
  57. v-if="operatorStore.disinfectStatus || localStorage.getItem('envir1')"
  58. ></div>
  59. </div>
  60. <div class="single_wrap">
  61. <p class="title">环境2/湿度/过氧化氢浓度</p>
  62. <div
  63. class="echarts_box"
  64. id="envir2"
  65. v-if="operatorStore.disinfectStatus || localStorage.getItem('envir2')"
  66. ></div>
  67. </div>
  68. </div>
  69. <div class="detail_wrap">
  70. <div class="detail" @click="showDetail">详情</div>
  71. </div>
  72. </div>
  73. </template>
  74. <script setup>
  75. import { useOperatorStore, useWebSocketStore, useEchartsStore } from '@/store'
  76. import {
  77. stopDisinfectionJSON,
  78. getStateJSON,
  79. continueDisinfectionJSON,
  80. pauseDisinfectionJSON,
  81. } from '@/mock/command'
  82. import { onMounted, onUnmounted, ref } from 'vue'
  83. import * as echarts from 'echarts'
  84. import { storeToRefs } from 'pinia'
  85. const echartsStore = useEchartsStore()
  86. const binOption = ref({
  87. tooltip: {
  88. trigger: 'axis',
  89. },
  90. legend: {
  91. data: ['温度', '湿度', '过氧化氢浓度'],
  92. },
  93. grid: {
  94. left: '3%',
  95. right: '4%',
  96. bottom: '3%',
  97. containLabel: true,
  98. },
  99. xAxis: {
  100. type: 'category',
  101. boundaryGap: false,
  102. data: Object.keys(echartsStore.binCharts),
  103. },
  104. yAxis: {
  105. type: 'value',
  106. },
  107. series: [
  108. {
  109. name: '温度',
  110. type: 'line',
  111. stack: 'Total',
  112. data: echartsStore.binTemp,
  113. },
  114. {
  115. name: '湿度',
  116. type: 'line',
  117. stack: 'Total',
  118. data: echartsStore.binHumidity,
  119. },
  120. {
  121. name: '过氧化氢浓度',
  122. type: 'line',
  123. stack: 'Total',
  124. data: echartsStore.binHP,
  125. },
  126. ],
  127. })
  128. const envir1Option = ref({
  129. tooltip: {
  130. trigger: 'axis',
  131. },
  132. legend: {
  133. data: ['温度', '湿度', '过氧化氢浓度'],
  134. },
  135. grid: {
  136. left: '3%',
  137. right: '4%',
  138. bottom: '3%',
  139. containLabel: true,
  140. },
  141. xAxis: {
  142. type: 'category',
  143. boundaryGap: false,
  144. data: Object.keys(echartsStore.envir1Charts),
  145. },
  146. yAxis: {
  147. type: 'value',
  148. },
  149. series: [
  150. {
  151. name: '温度',
  152. type: 'line',
  153. stack: 'Total',
  154. data: echartsStore.envir1Temp,
  155. },
  156. {
  157. name: '湿度',
  158. type: 'line',
  159. stack: 'Total',
  160. data: echartsStore.envir1Humidity,
  161. },
  162. {
  163. name: '过氧化氢浓度',
  164. type: 'line',
  165. stack: 'Total',
  166. data: echartsStore.envir1HP,
  167. },
  168. ],
  169. })
  170. const envir2Option = ref({
  171. tooltip: {
  172. trigger: 'axis',
  173. },
  174. legend: {
  175. data: ['温度', '湿度', '过氧化氢浓度'],
  176. },
  177. grid: {
  178. left: '3%',
  179. right: '4%',
  180. bottom: '3%',
  181. containLabel: true,
  182. },
  183. xAxis: {
  184. type: 'category',
  185. boundaryGap: false,
  186. data: Object.keys(echartsStore.envir2Charts),
  187. },
  188. yAxis: {
  189. type: 'value',
  190. },
  191. series: [
  192. {
  193. name: '温度',
  194. type: 'line',
  195. stack: 'Total',
  196. data: echartsStore.envir2Temp,
  197. },
  198. {
  199. name: '湿度',
  200. type: 'line',
  201. stack: 'Total',
  202. data: echartsStore.envir2Humidity,
  203. },
  204. {
  205. name: '过氧化氢浓度',
  206. type: 'line',
  207. stack: 'Total',
  208. data: echartsStore.envir2HP,
  209. },
  210. ],
  211. })
  212. const operatorStore = useOperatorStore()
  213. const webSocketStore = useWebSocketStore()
  214. const props = defineProps({
  215. changeShowOperator: {
  216. type: Function,
  217. },
  218. })
  219. const showDetail = () => {
  220. props.changeShowOperator(true)
  221. }
  222. const timer = ref(null)
  223. onMounted(() => {
  224. timer.value = setInterval(() => {
  225. webSocketStore.sendCommandMsg(getStateJSON)
  226. }, 1000)
  227. let a = echarts.getInstanceByDom(document.getElementById('bin'))
  228. if (a == undefined) {
  229. var binCharts = echarts.init(document.getElementById('bin'))
  230. binCharts.setOption(binOption.value)
  231. }
  232. let b = echarts.getInstanceByDom(document.getElementById('envir1'))
  233. if (b == undefined) {
  234. var envir1Charts = echarts.init(document.getElementById('envir1'))
  235. envir1Charts.setOption(envir1Option.value)
  236. }
  237. let c = echarts.getInstanceByDom(document.getElementById('envir2'))
  238. if (c == undefined) {
  239. var envir2Charts = echarts.init(document.getElementById('envir2'))
  240. envir2Charts.setOption(envir2Option.value)
  241. }
  242. })
  243. onUnmounted(() => {
  244. timer.value = null
  245. })
  246. const pauseDisinfect = () => {
  247. if (operatorStore.disinfectStatus) {
  248. webSocketStore.sendCommandMsg(pauseDisinfectionJSON)
  249. operatorStore.updateDisinfectStatus(false)
  250. }
  251. }
  252. const stopDisinfect = () => {
  253. if (operatorStore.disinfectStatus) {
  254. webSocketStore.sendCommandMsg(stopDisinfectionJSON)
  255. operatorStore.updateDisinfectStatus(false)
  256. }
  257. }
  258. const continueDisinfect = () => {
  259. if (!operatorStore.disinfectStatus) {
  260. webSocketStore.sendCommandMsg(continueDisinfectionJSON)
  261. operatorStore.updateDisinfectStatus(true)
  262. }
  263. }
  264. </script>
  265. <style lang="scss" scoped>
  266. .progress_container {
  267. margin-bottom: 30px;
  268. height: 580px;
  269. box-sizing: border-box;
  270. background: #ffffff;
  271. border-radius: 16px;
  272. padding: 20px;
  273. padding-bottom: 30px;
  274. .header_wrap {
  275. display: flex;
  276. align-items: center;
  277. margin-bottom: 49px;
  278. .left_progress {
  279. // width: 860px;
  280. flex: 1;
  281. height: 80px;
  282. border-radius: 14px;
  283. background: #f6f6f6;
  284. box-sizing: border-box;
  285. padding: 0 23px;
  286. display: flex;
  287. align-items: center;
  288. .left_time_tag {
  289. width: 158.66px;
  290. height: 45px;
  291. border-radius: 23px;
  292. opacity: 1;
  293. background: #06518b;
  294. display: flex;
  295. align-items: center;
  296. justify-content: center;
  297. font-family: Source Han Sans CN;
  298. font-size: 14px;
  299. font-weight: normal;
  300. letter-spacing: 0.1em;
  301. color: #ffffff;
  302. }
  303. .time {
  304. // width: 90px;
  305. flex: 1;
  306. height: 20px;
  307. font-family: Source Han Sans CN;
  308. font-size: 14px;
  309. font-weight: 500;
  310. letter-spacing: 0.1em;
  311. color: #000000;
  312. display: flex;
  313. align-items: center;
  314. justify-content: center;
  315. }
  316. .progress_bg {
  317. width: 396px;
  318. height: 14px;
  319. border-radius: 7px;
  320. background: #ffffff;
  321. position: relative;
  322. overflow: hidden;
  323. .pro {
  324. position: absolute;
  325. left: 0;
  326. top: 0;
  327. height: 14px;
  328. border-radius: 7px;
  329. background: #06518b;
  330. width: var(--width);
  331. }
  332. }
  333. }
  334. .right_btns {
  335. display: flex;
  336. align-items: center;
  337. box-sizing: border-box;
  338. margin-left: 20px;
  339. .btn {
  340. width: 140px;
  341. height: 45px;
  342. border-radius: 23px;
  343. background: #f6f6f6;
  344. display: flex;
  345. align-items: center;
  346. justify-content: center;
  347. font-family: Source Han Sans CN;
  348. font-size: 14px;
  349. font-weight: normal;
  350. letter-spacing: 0.1em;
  351. color: #d8d8d8;
  352. }
  353. .active {
  354. color: #ffffff;
  355. background: #06518b;
  356. }
  357. .ml {
  358. margin: 0 20px;
  359. }
  360. }
  361. }
  362. .echarts_wrap {
  363. height: 351px;
  364. display: flex;
  365. align-items: center;
  366. margin-bottom: 19px;
  367. .single_wrap {
  368. flex: 1;
  369. height: 351px;
  370. .title {
  371. font-family: Source Han Sans CN;
  372. font-size: 14px;
  373. font-weight: 500;
  374. letter-spacing: 0.1em;
  375. color: #000000;
  376. margin-bottom: 24px;
  377. padding-left: 11px;
  378. }
  379. .echarts_box {
  380. width: 380px;
  381. height: 308px;
  382. }
  383. }
  384. }
  385. .detail_wrap {
  386. display: flex;
  387. align-items: center;
  388. justify-content: flex-end;
  389. padding-right: 16px;
  390. .detail {
  391. width: 105px;
  392. height: 31px;
  393. border-radius: 16px;
  394. background: #06518b;
  395. display: flex;
  396. align-items: center;
  397. justify-content: center;
  398. font-family: Source Han Sans CN;
  399. font-size: 12px;
  400. font-weight: normal;
  401. letter-spacing: 0.1em;
  402. color: #ffffff;
  403. }
  404. }
  405. }
  406. </style>