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

454 lines
11 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
  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. dataZoom: {
  91. show: true, // 为true 滚动条出现
  92. realtime: true,
  93. type: 'slider', // 有type这个属性,滚动条在最下面,也可以不行,写y:36,这表示距离顶端36px,一般就是在图上面。
  94. height: 10, // 表示滚动条的高度,也就是粗细
  95. start: 40, // 表示默认展示0%~80%这一段。
  96. end: 100,
  97. backgroundColor: 'transparent',
  98. bottom: 10,
  99. textStyle: {
  100. color: 'transparent',
  101. },
  102. },
  103. legend: {
  104. data: ['温度', '湿度', '过氧化氢浓度'],
  105. },
  106. grid: {
  107. left: '3%',
  108. right: '4%',
  109. bottom: '3%',
  110. containLabel: true,
  111. },
  112. xAxis: {
  113. type: 'category',
  114. boundaryGap: false,
  115. data: Object.keys(echartsStore.binCharts),
  116. },
  117. yAxis: {
  118. type: 'value',
  119. },
  120. series: [
  121. {
  122. name: '温度',
  123. type: 'line',
  124. stack: 'Total',
  125. data: echartsStore.binTemp,
  126. },
  127. {
  128. name: '湿度',
  129. type: 'line',
  130. stack: 'Total',
  131. data: echartsStore.binHumidity,
  132. },
  133. {
  134. name: '过氧化氢浓度',
  135. type: 'line',
  136. stack: 'Total',
  137. data: echartsStore.binHP,
  138. },
  139. ],
  140. })
  141. const envir1Option = ref({
  142. tooltip: {
  143. trigger: 'axis',
  144. },
  145. dataZoom: {
  146. show: true, // 为true 滚动条出现
  147. realtime: true,
  148. type: 'slider', // 有type这个属性,滚动条在最下面,也可以不行,写y:36,这表示距离顶端36px,一般就是在图上面。
  149. height: 10, // 表示滚动条的高度,也就是粗细
  150. start: 40, // 表示默认展示0%~80%这一段。
  151. end: 100,
  152. backgroundColor: 'transparent',
  153. bottom: 10,
  154. textStyle: {
  155. color: 'transparent',
  156. },
  157. },
  158. legend: {
  159. data: ['温度', '湿度', '过氧化氢浓度'],
  160. },
  161. grid: {
  162. left: '3%',
  163. right: '4%',
  164. bottom: '3%',
  165. containLabel: true,
  166. },
  167. xAxis: {
  168. type: 'category',
  169. boundaryGap: false,
  170. data: Object.keys(echartsStore.envir1Charts),
  171. },
  172. yAxis: {
  173. type: 'value',
  174. },
  175. series: [
  176. {
  177. name: '温度',
  178. type: 'line',
  179. stack: 'Total',
  180. data: echartsStore.envir1Temp,
  181. },
  182. {
  183. name: '湿度',
  184. type: 'line',
  185. stack: 'Total',
  186. data: echartsStore.envir1Humidity,
  187. },
  188. {
  189. name: '过氧化氢浓度',
  190. type: 'line',
  191. stack: 'Total',
  192. data: echartsStore.envir1HP,
  193. },
  194. ],
  195. })
  196. const envir2Option = ref({
  197. tooltip: {
  198. trigger: 'axis',
  199. },
  200. dataZoom: {
  201. show: true, // 为true 滚动条出现
  202. realtime: true,
  203. type: 'slider', // 有type这个属性,滚动条在最下面,也可以不行,写y:36,这表示距离顶端36px,一般就是在图上面。
  204. height: 10, // 表示滚动条的高度,也就是粗细
  205. start: 40, // 表示默认展示0%~80%这一段。
  206. end: 100,
  207. backgroundColor: 'transparent',
  208. bottom: 10,
  209. textStyle: {
  210. color: 'transparent',
  211. },
  212. },
  213. legend: {
  214. data: ['温度', '湿度', '过氧化氢浓度'],
  215. },
  216. grid: {
  217. left: '3%',
  218. right: '4%',
  219. bottom: '3%',
  220. containLabel: true,
  221. },
  222. xAxis: {
  223. type: 'category',
  224. boundaryGap: false,
  225. data: Object.keys(echartsStore.envir2Charts),
  226. },
  227. yAxis: {
  228. type: 'value',
  229. },
  230. series: [
  231. {
  232. name: '温度',
  233. type: 'line',
  234. stack: 'Total',
  235. data: echartsStore.envir2Temp,
  236. },
  237. {
  238. name: '湿度',
  239. type: 'line',
  240. stack: 'Total',
  241. data: echartsStore.envir2Humidity,
  242. },
  243. {
  244. name: '过氧化氢浓度',
  245. type: 'line',
  246. stack: 'Total',
  247. data: echartsStore.envir2HP,
  248. },
  249. ],
  250. })
  251. const operatorStore = useOperatorStore()
  252. const webSocketStore = useWebSocketStore()
  253. const props = defineProps({
  254. changeShowOperator: {
  255. type: Function,
  256. },
  257. })
  258. const showDetail = () => {
  259. props.changeShowOperator(true)
  260. }
  261. const timer = ref(null)
  262. onMounted(() => {
  263. timer.value = setInterval(() => {
  264. webSocketStore.sendCommandMsg(getStateJSON)
  265. }, 1000)
  266. let a = echarts.getInstanceByDom(document.getElementById('bin'))
  267. if (a == undefined) {
  268. var binCharts = echarts.init(document.getElementById('bin'))
  269. binCharts.setOption(binOption.value)
  270. }
  271. let b = echarts.getInstanceByDom(document.getElementById('envir1'))
  272. if (b == undefined) {
  273. var envir1Charts = echarts.init(document.getElementById('envir1'))
  274. envir1Charts.setOption(envir1Option.value)
  275. }
  276. let c = echarts.getInstanceByDom(document.getElementById('envir2'))
  277. if (c == undefined) {
  278. var envir2Charts = echarts.init(document.getElementById('envir2'))
  279. envir2Charts.setOption(envir2Option.value)
  280. }
  281. })
  282. onUnmounted(() => {
  283. timer.value = null
  284. })
  285. const pauseDisinfect = () => {
  286. if (operatorStore.disinfectStatus) {
  287. webSocketStore.sendCommandMsg(pauseDisinfectionJSON)
  288. operatorStore.updateDisinfectStatus(false)
  289. }
  290. }
  291. const stopDisinfect = () => {
  292. if (operatorStore.disinfectStatus) {
  293. webSocketStore.sendCommandMsg(stopDisinfectionJSON)
  294. operatorStore.updateDisinfectStatus(false)
  295. }
  296. }
  297. const continueDisinfect = () => {
  298. if (!operatorStore.disinfectStatus) {
  299. webSocketStore.sendCommandMsg(continueDisinfectionJSON)
  300. operatorStore.updateDisinfectStatus(true)
  301. }
  302. }
  303. </script>
  304. <style lang="scss" scoped>
  305. .progress_container {
  306. margin-bottom: 30px;
  307. height: 580px;
  308. box-sizing: border-box;
  309. background: #ffffff;
  310. border-radius: 16px;
  311. padding: 20px;
  312. padding-bottom: 30px;
  313. .header_wrap {
  314. display: flex;
  315. align-items: center;
  316. margin-bottom: 49px;
  317. .left_progress {
  318. // width: 860px;
  319. flex: 1;
  320. height: 80px;
  321. border-radius: 14px;
  322. background: #f6f6f6;
  323. box-sizing: border-box;
  324. padding: 0 23px;
  325. display: flex;
  326. align-items: center;
  327. .left_time_tag {
  328. width: 158.66px;
  329. height: 45px;
  330. border-radius: 23px;
  331. opacity: 1;
  332. background: #06518b;
  333. display: flex;
  334. align-items: center;
  335. justify-content: center;
  336. font-family: Source Han Sans CN;
  337. font-size: 14px;
  338. font-weight: normal;
  339. letter-spacing: 0.1em;
  340. color: #ffffff;
  341. }
  342. .time {
  343. // width: 90px;
  344. flex: 1;
  345. height: 20px;
  346. font-family: Source Han Sans CN;
  347. font-size: 14px;
  348. font-weight: 500;
  349. letter-spacing: 0.1em;
  350. color: #000000;
  351. display: flex;
  352. align-items: center;
  353. justify-content: center;
  354. }
  355. .progress_bg {
  356. width: 396px;
  357. height: 14px;
  358. border-radius: 7px;
  359. background: #ffffff;
  360. position: relative;
  361. overflow: hidden;
  362. .pro {
  363. position: absolute;
  364. left: 0;
  365. top: 0;
  366. height: 14px;
  367. border-radius: 7px;
  368. background: #06518b;
  369. width: var(--width);
  370. }
  371. }
  372. }
  373. .right_btns {
  374. display: flex;
  375. align-items: center;
  376. box-sizing: border-box;
  377. margin-left: 20px;
  378. .btn {
  379. width: 140px;
  380. height: 45px;
  381. border-radius: 23px;
  382. background: #f6f6f6;
  383. display: flex;
  384. align-items: center;
  385. justify-content: center;
  386. font-family: Source Han Sans CN;
  387. font-size: 14px;
  388. font-weight: normal;
  389. letter-spacing: 0.1em;
  390. color: #d8d8d8;
  391. }
  392. .active {
  393. color: #ffffff;
  394. background: #06518b;
  395. }
  396. .ml {
  397. margin: 0 20px;
  398. }
  399. }
  400. }
  401. .echarts_wrap {
  402. height: 351px;
  403. display: flex;
  404. align-items: center;
  405. margin-bottom: 19px;
  406. .single_wrap {
  407. flex: 1;
  408. height: 351px;
  409. .title {
  410. font-family: Source Han Sans CN;
  411. font-size: 14px;
  412. font-weight: 500;
  413. letter-spacing: 0.1em;
  414. color: #000000;
  415. margin-bottom: 24px;
  416. padding-left: 11px;
  417. }
  418. .echarts_box {
  419. width: 380px;
  420. height: 308px;
  421. }
  422. }
  423. }
  424. .detail_wrap {
  425. display: flex;
  426. align-items: center;
  427. justify-content: flex-end;
  428. padding-right: 16px;
  429. .detail {
  430. width: 105px;
  431. height: 31px;
  432. border-radius: 16px;
  433. background: #06518b;
  434. display: flex;
  435. align-items: center;
  436. justify-content: center;
  437. font-family: Source Han Sans CN;
  438. font-size: 12px;
  439. font-weight: normal;
  440. letter-spacing: 0.1em;
  441. color: #ffffff;
  442. }
  443. }
  444. }
  445. </style>