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

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