拉杆箱消毒机
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.

648 lines
16 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
  1. <template>
  2. <div class="seal_test_container">
  3. <div class="left_container">
  4. <div class="title_wrap">
  5. <img class="icon" :src="SealPng" alt="" />
  6. <div class="title">实时压力表</div>
  7. </div>
  8. <div class="echarts_box" id="seal_echarts"></div>
  9. <div class="oper_box">
  10. <div class="air_box">
  11. <p class="box"></p>
  12. <p class="tit">测试前气压</p>
  13. <p class="num">
  14. {{
  15. sealStore.oldAirPressure != null
  16. ? sealStore.oldAirPressure
  17. : '--'
  18. }}KPa
  19. </p>
  20. </div>
  21. <img
  22. class="air_img"
  23. v-if="!sealStore.isStartTest"
  24. @click="newStartTest(1)"
  25. :src="StartTest"
  26. alt=""
  27. />
  28. <img
  29. class="air_img"
  30. @click="newStartTest(2)"
  31. v-if="sealStore.isStartTest"
  32. :src="StopTest"
  33. alt=""
  34. />
  35. <!-- <input
  36. type="number"
  37. placeholder="第一次"
  38. v-model="sleepVal1"
  39. style="width: 100px; height: 100px"
  40. />
  41. <input
  42. type="number"
  43. placeholder="第二次"
  44. v-model="sleepVal2"
  45. style="width: 100px; height: 100px"
  46. /> -->
  47. </div>
  48. </div>
  49. <div class="right_container">
  50. <div class="header">
  51. <div class="left">
  52. <img :src="TestIcon" class="icon" alt="" />
  53. <p class="title">密封测试</p>
  54. </div>
  55. <p class="en">SEAL</p>
  56. </div>
  57. <div class="oper_box">
  58. <div class="emp_box">
  59. <div class="title">测试时间</div>
  60. <div class="num">
  61. {{ resultTime ? resultTime : '未开始' }}
  62. </div>
  63. </div>
  64. <div class="emp_box">
  65. <div class="title">气压差值</div>
  66. <div class="num">
  67. {{
  68. sealStore.differenceValue != null
  69. ? `${sealStore.differenceValue}KPa`
  70. : '未开始'
  71. }}
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. <van-overlay :show="testOverlayVisible" z-index="3">
  77. <div class="wrapper" @click.stop>
  78. <div class="block">
  79. <van-loading />
  80. <p class="shutdown_text">正在充气...</p>
  81. </div>
  82. </div>
  83. </van-overlay>
  84. </div>
  85. </template>
  86. <script setup>
  87. import * as echarts from 'echarts'
  88. import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
  89. import SealPng from '@/assets/img/seal/seal.png'
  90. import TestIcon from '@/assets/img/seal/test.png'
  91. import StartTest from '@/assets/img/seal/starttest.png'
  92. import StopTest from '@/assets/img/seal/stoptest.png'
  93. import {
  94. someAirSwitchJSON,
  95. airCompressor_setStateJSON,
  96. airCompressorGetPressureDirectIntervalJSON,
  97. airCompressor_channelCtrlJSON,
  98. AirInletProportionalValve_setStateJSON,
  99. AirOutletProportionalValve_setStateJSON,
  100. airCompressorGetPressureDirectJSON,
  101. airCompressorSetValve1JSON,
  102. airCompressorSetValve2JSON,
  103. airCompressorChannelSelectJSON,
  104. AirOutletProportionalValve_getStateJSON,
  105. airInletProportionalValve_getStateJSON,
  106. airProportionalValveIsBusyJSON,
  107. } from '@/mock/command'
  108. import { useSealStore, useTestStore, useWebSocketStore } from '@/store'
  109. import { storeToRefs } from 'pinia'
  110. const sealStore = useSealStore()
  111. const testStore = useTestStore()
  112. const websocketStore = useWebSocketStore()
  113. const testOverlayVisible = ref(false)
  114. const { airInletProportionalInitVal, airOutletProportionalInitVal } =
  115. storeToRefs(sealStore)
  116. const sealCharts = ref(null)
  117. const sealOptions = ref({
  118. series: [
  119. {
  120. type: 'gauge',
  121. min: 0,
  122. max: 10,
  123. progress: {
  124. show: true,
  125. width: 18,
  126. itemStyle: {
  127. color: '#3442aa',
  128. },
  129. },
  130. pointer: {
  131. itemStyle: {
  132. color: '#3442aa',
  133. },
  134. },
  135. axisLine: {
  136. lineStyle: {
  137. width: 18,
  138. },
  139. },
  140. axisTick: {
  141. show: false,
  142. },
  143. splitLine: {
  144. length: 15,
  145. lineStyle: {
  146. width: 2,
  147. color: '#999',
  148. },
  149. },
  150. axisLabel: {
  151. distance: 25,
  152. color: '#999',
  153. fontSize: 20,
  154. },
  155. anchor: {
  156. show: true,
  157. showAbove: true,
  158. size: 25,
  159. itemStyle: {
  160. borderWidth: 10,
  161. borderColor: '#3442aa',
  162. },
  163. },
  164. title: {
  165. show: false,
  166. },
  167. detail: {
  168. valueAnimation: true,
  169. fontSize: 40,
  170. color: '#3442aa',
  171. formatter: '{value} KPa',
  172. offsetCenter: [0, '70%'],
  173. },
  174. data: [
  175. {
  176. value: sealStore.currentAirPressure,
  177. },
  178. ],
  179. },
  180. ],
  181. })
  182. const n_sec = ref(0) // 秒
  183. const n_min = ref(0) // 分
  184. const n_hour = ref(0) // 时
  185. const resultTime = ref('')
  186. const timerStart = ref(null)
  187. const timerReal = () => {
  188. var str_sec = n_sec.value
  189. var str_min = n_min.value
  190. var str_hour = n_hour.value
  191. if (n_sec.value < 10) {
  192. str_sec = '0' + n_sec.value
  193. }
  194. if (n_min.value < 10) {
  195. str_min = '0' + n_min.value
  196. }
  197. if (n_hour.value < 10) {
  198. str_hour = '0' + n_hour.value
  199. }
  200. resultTime.value = str_hour + ':' + str_min + ':' + str_sec
  201. n_sec.value = n_sec.value + 1
  202. if (n_sec.value > 59) {
  203. n_sec.value = 0
  204. n_min.value = n_min.value + 1
  205. }
  206. if (n_min.value > 59) {
  207. n_min.value = 0
  208. n_hour.value = n_hour.value + 1
  209. }
  210. }
  211. watch(
  212. () => sealStore.isStartTest,
  213. (newValue, oldValue) => {
  214. if (!newValue) {
  215. stopTimer()
  216. }
  217. },
  218. )
  219. const stopTimer = () => {
  220. // 改变测试前oldAirPressure为null
  221. sealStore.updateOldAirPressure(null)
  222. // 结束测试时将时间重置null
  223. clearInterval(timerStart.value)
  224. timerStart.value = null
  225. resultTime.value = null
  226. n_sec.value = 0
  227. n_min.value = 0
  228. n_hour.value = 0
  229. sealStore.updateIsStartTest(false)
  230. }
  231. const timerFunc = () => {
  232. timerReal()
  233. timerStart.value = setInterval(() => {
  234. timerReal()
  235. }, 1000)
  236. }
  237. const wait = async ms => {
  238. await new Promise(resolve => setTimeout(resolve, ms))
  239. }
  240. const waitAirFinish = async () => {
  241. await new Promise(async resolve => {
  242. let flag = true
  243. while (flag) {
  244. await wait(500)
  245. websocketStore.sendCommandMsg(airProportionalValveIsBusyJSON)
  246. if (sealStore.AirProportionalValveIsBusy == 0) {
  247. flag = false
  248. }
  249. }
  250. resolve()
  251. })
  252. }
  253. const sleepVal1 = ref(1)
  254. const sleepVal2 = ref(60)
  255. const newStartTest = async flag => {
  256. if (flag == 1) {
  257. // 开始测试
  258. // 启动计时器
  259. // 开启遮罩loading 并在1min后消失 展示数据
  260. testOverlayVisible.value = true
  261. timerFunc()
  262. sealStore.updateIsStartTest(true)
  263. // 空压机选通阀切换到通道2(空气)
  264. websocketStore.sendCommandMsg(airCompressorChannelSelectJSON([2]))
  265. // 空压机电子阀1打开 空压机电子阀2打开
  266. websocketStore.sendCommandMsg(airCompressorSetValve1JSON([1]))
  267. websocketStore.sendCommandMsg(airCompressorSetValve2JSON([1]))
  268. // 风机入口比例阀闭合 风机出口比例阀闭合
  269. websocketStore.sendCommandMsg(AirInletProportionalValve_setStateJSON([0]))
  270. websocketStore.sendCommandMsg(AirOutletProportionalValve_setStateJSON([0]))
  271. // 等待风机入口比例阀闭合 风机出口比例阀闭合完毕后再打开空压机
  272. websocketStore.sendCommandMsg(airProportionalValveIsBusyJSON)
  273. await waitAirFinish()
  274. // 空压机打开
  275. websocketStore.sendCommandMsg(airCompressor_setStateJSON([1]))
  276. await wait(sleepVal1.value * 1000)
  277. // 空压机关闭
  278. websocketStore.sendCommandMsg(airCompressor_setStateJSON([0]))
  279. // 空压机电子阀1关闭 空压机电子阀2关闭
  280. websocketStore.sendCommandMsg(airCompressorSetValve1JSON([0]))
  281. websocketStore.sendCommandMsg(airCompressorSetValve2JSON([0]))
  282. // 空压机选通阀切换到通道1 (入气口)
  283. websocketStore.sendCommandMsg(airCompressorChannelSelectJSON([1]))
  284. // 等待1min
  285. await wait(sleepVal2.value * 1000)
  286. // 记录当前压力数值作为初始压力值
  287. // 等待1min 然后展示数据
  288. testOverlayVisible.value = false
  289. websocketStore.sendCommandMsg(airCompressorGetPressureDirectJSON)
  290. }
  291. if (flag == 2) {
  292. // 停止测试
  293. /**
  294. * 空压机电子阀1打开
  295. * 空压机电子阀2打开
  296. * 空压机选通阀切换到通道1
  297. * 风机入口比例阀恢复
  298. * 风机出口比例阀恢复
  299. */
  300. sealStore.updateAirProportionalValveIsBusy(1)
  301. websocketStore.sendCommandMsg(airCompressorSetValve1JSON([1]))
  302. websocketStore.sendCommandMsg(airCompressorSetValve2JSON([1]))
  303. websocketStore.sendCommandMsg(airCompressorChannelSelectJSON([1]))
  304. // 数值为刚开始记录的数值
  305. websocketStore.sendCommandMsg(
  306. AirInletProportionalValve_setStateJSON([
  307. airInletProportionalInitVal.value[0],
  308. ]),
  309. )
  310. websocketStore.sendCommandMsg(
  311. AirOutletProportionalValve_setStateJSON([
  312. airOutletProportionalInitVal.value[0],
  313. ]),
  314. )
  315. // 停止计时器
  316. stopTimer()
  317. }
  318. }
  319. const timer = ref(null)
  320. const timerData = ref(null)
  321. onBeforeUnmount(() => {
  322. clearInterval(timerData.value)
  323. clearInterval(timer.value)
  324. clearInterval(timerStart.value)
  325. })
  326. onMounted(() => {
  327. // 需要记录当前的风机入口出口比例阀数值
  328. sealCharts.value = echarts.init(document.getElementById('seal_echarts'))
  329. sealCharts.value.setOption(sealOptions.value)
  330. timer.value = setInterval(() => {
  331. sealCharts.value.setOption({
  332. series: [
  333. {
  334. type: 'gauge',
  335. min: 0,
  336. max: 10,
  337. progress: {
  338. show: true,
  339. width: 18,
  340. itemStyle: {
  341. color: '#3442aa',
  342. },
  343. },
  344. pointer: {
  345. itemStyle: {
  346. color: '#3442aa',
  347. },
  348. },
  349. axisLine: {
  350. lineStyle: {
  351. width: 18,
  352. },
  353. },
  354. axisTick: {
  355. show: false,
  356. },
  357. splitLine: {
  358. length: 15,
  359. lineStyle: {
  360. width: 2,
  361. color: '#999',
  362. },
  363. },
  364. axisLabel: {
  365. distance: 25,
  366. color: '#999',
  367. fontSize: 20,
  368. },
  369. anchor: {
  370. show: true,
  371. showAbove: true,
  372. size: 25,
  373. itemStyle: {
  374. borderWidth: 10,
  375. borderColor: '#3442aa',
  376. },
  377. },
  378. title: {
  379. show: false,
  380. },
  381. detail: {
  382. valueAnimation: true,
  383. fontSize: 40,
  384. color: '#3442aa',
  385. formatter: '{value} KPa',
  386. offsetCenter: [0, '70%'],
  387. },
  388. data: [
  389. {
  390. value: sealStore.currentAirPressure,
  391. },
  392. ],
  393. },
  394. ],
  395. })
  396. }, 1000)
  397. websocketStore.sendCommandMsg(airInletProportionalValve_getStateJSON)
  398. websocketStore.sendCommandMsg(AirOutletProportionalValve_getStateJSON)
  399. timerData.value = setInterval(() => {
  400. websocketStore.sendCommandMsg(airCompressorGetPressureDirectIntervalJSON)
  401. }, 100)
  402. })
  403. </script>
  404. <style lang="scss" scoped>
  405. .seal_test_container {
  406. margin-bottom: 19px;
  407. height: 580px;
  408. box-sizing: border-box;
  409. border-radius: 16px;
  410. display: flex;
  411. align-items: center;
  412. .left_container {
  413. margin-right: 30px;
  414. width: 766px;
  415. height: 580px;
  416. box-sizing: border-box;
  417. border-radius: 16px;
  418. background: #ffffff;
  419. position: relative;
  420. .title_wrap {
  421. position: absolute;
  422. left: 28px;
  423. top: 28px;
  424. width: 141px;
  425. height: 31px;
  426. box-sizing: border-box;
  427. display: flex;
  428. align-items: center;
  429. .title {
  430. font-family: 思源黑体;
  431. font-size: 20px;
  432. font-weight: bold;
  433. line-height: normal;
  434. letter-spacing: 0.02em;
  435. font-feature-settings: 'kern' on;
  436. color: #000000;
  437. margin-left: 9px;
  438. }
  439. .icon {
  440. width: 30px;
  441. height: 30px;
  442. }
  443. }
  444. .oper_box {
  445. position: absolute;
  446. left: 28px;
  447. bottom: 28px;
  448. width: 710px;
  449. height: 110px;
  450. display: flex;
  451. align-items: center;
  452. justify-content: space-between;
  453. .air_img {
  454. width: 341px;
  455. height: 110px;
  456. }
  457. .air_box {
  458. width: 341px;
  459. height: 110px;
  460. border-radius: 16px;
  461. background: #f6f6f6;
  462. display: flex;
  463. align-items: center;
  464. justify-content: center;
  465. .box {
  466. width: 16px;
  467. height: 16px;
  468. background: #4359b9;
  469. margin-right: 6px;
  470. }
  471. .tit {
  472. font-family: 思源黑体;
  473. font-size: 20px;
  474. font-weight: normal;
  475. line-height: normal;
  476. letter-spacing: 0.06em;
  477. font-feature-settings: 'kern' on;
  478. color: #3d3d3d;
  479. margin-right: 8px;
  480. }
  481. .num {
  482. font-family: Source Han Sans;
  483. font-size: 30px;
  484. font-weight: bold;
  485. line-height: normal;
  486. letter-spacing: 0.06em;
  487. font-feature-settings: 'kern' on;
  488. color: #4359b9;
  489. }
  490. }
  491. }
  492. .echarts_box {
  493. height: 580px;
  494. position: absolute;
  495. left: 0;
  496. top: -36px;
  497. width: 100%;
  498. }
  499. }
  500. .right_container {
  501. height: 580px;
  502. box-sizing: border-box;
  503. border-radius: 16px;
  504. background: #ffffff;
  505. flex: 1;
  506. padding: 32px 42px;
  507. .header {
  508. display: flex;
  509. align-items: center;
  510. justify-content: space-between;
  511. box-sizing: border-box;
  512. width: 340px;
  513. height: 45px;
  514. border-radius: 245px;
  515. background: #06518b;
  516. padding-left: 17px;
  517. padding-right: 24px;
  518. margin-bottom: 20px;
  519. .left {
  520. display: flex;
  521. align-items: center;
  522. .icon {
  523. width: 16px;
  524. height: 16px;
  525. }
  526. .title {
  527. font-family: 思源黑体;
  528. font-size: 14px;
  529. font-weight: normal;
  530. line-height: normal;
  531. letter-spacing: 0.1em;
  532. margin-left: 9px;
  533. color: #ffffff;
  534. }
  535. }
  536. .en {
  537. font-family: 思源黑体;
  538. font-size: 12px;
  539. font-weight: normal;
  540. line-height: normal;
  541. letter-spacing: 0.1em;
  542. color: #ffffff;
  543. }
  544. }
  545. .oper_box {
  546. width: 340px;
  547. height: 455px;
  548. border-radius: 16px;
  549. background: #f6f6f6;
  550. box-sizing: border-box;
  551. padding: 20px;
  552. .emp_box {
  553. width: 300px;
  554. height: 198px;
  555. border-radius: 12px;
  556. background: #fff;
  557. margin-bottom: 20px;
  558. box-sizing: border-box;
  559. padding-top: 16px;
  560. padding-left: 27px;
  561. padding-right: 27px;
  562. padding-bottom: 20px;
  563. display: flex;
  564. flex-direction: column;
  565. .title {
  566. font-family: Source Han Sans;
  567. font-size: 16px;
  568. font-weight: 500;
  569. line-height: normal;
  570. letter-spacing: 0.06em;
  571. font-feature-settings: 'kern' on;
  572. color: #06518b;
  573. }
  574. .num {
  575. flex: 1;
  576. display: flex;
  577. align-items: center;
  578. justify-content: center;
  579. font-family: 思源黑体;
  580. font-size: 30px;
  581. font-weight: bold;
  582. line-height: normal;
  583. letter-spacing: 0.1em;
  584. color: #000000;
  585. border-radius: 12px;
  586. background: #fafafa;
  587. box-sizing: border-box;
  588. }
  589. }
  590. .test_png {
  591. width: 300px;
  592. height: 50px;
  593. }
  594. }
  595. }
  596. }
  597. // input[type='number']::-webkit-inner-spin-button,
  598. // input[type='number']::-webkit-outer-spin-button,
  599. // input[type='datetime']::-webkit-inner-spin-button,
  600. // input[type='datetime']::-webkit-outer-spin-button {
  601. // /* 设置箭头按钮的宽度和高度 */
  602. // width: 50px;
  603. // height: 100px;
  604. // }
  605. .wrapper {
  606. display: flex;
  607. align-items: center;
  608. justify-content: center;
  609. height: 100%;
  610. }
  611. .block {
  612. width: 120px;
  613. height: 120px;
  614. display: flex;
  615. flex-direction: column;
  616. padding: 16px;
  617. align-items: center;
  618. justify-content: center;
  619. .shutdown_text {
  620. margin-top: 24px;
  621. font-family: Source Han Sans CN;
  622. font-size: 18px;
  623. font-weight: normal;
  624. line-height: normal;
  625. letter-spacing: 0.06em;
  626. color: #fff;
  627. white-space: nowrap;
  628. }
  629. }
  630. </style>