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

797 lines
19 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
  1. <template>
  2. <div class="device_container">
  3. <div class="row_wrap">
  4. <p class="title">注射蠕动泵速率(g/min)</p>
  5. <p class="num">
  6. <van-field
  7. type="number"
  8. v-model="sprayLiquidConfigVal"
  9. :clickable="true"
  10. :formatter="formatter7"
  11. readonly
  12. @click.stop="hideClickKey(2)"
  13. />
  14. </p>
  15. </div>
  16. <div class="row_wrap">
  17. <p class="title">消毒停止过氧化氢浓度(ppm)</p>
  18. <p class="num">
  19. <van-field
  20. type="number"
  21. v-model="stoped_gs"
  22. :clickable="true"
  23. :formatter="formatter1"
  24. readonly
  25. @click.stop="hideClickKey(3)"
  26. />
  27. </p>
  28. </div>
  29. <div class="row_wrap">
  30. <p class="title">消毒继续过氧化氢浓度(ppm)</p>
  31. <p class="num">
  32. <van-field
  33. type="number"
  34. v-model="continued_gs"
  35. :clickable="true"
  36. :formatter="formatter2"
  37. readonly
  38. @click.stop="hideClickKey(4)"
  39. />
  40. </p>
  41. </div>
  42. <div class="row_wrap">
  43. <p class="title">消毒停止相对湿度(%RH)</p>
  44. <p class="num">
  45. <van-field
  46. type="number"
  47. v-model="stoped_humi"
  48. :clickable="true"
  49. :formatter="formatter9"
  50. readonly
  51. @click.stop="hideClickKey(9)"
  52. />
  53. </p>
  54. </div>
  55. <div class="row_wrap">
  56. <p class="title">消毒继续相对湿度(%RH)</p>
  57. <p class="num">
  58. <van-field
  59. type="number"
  60. v-model="continued_humi"
  61. :clickable="true"
  62. :formatter="formatter10"
  63. readonly
  64. @click.stop="hideClickKey(10)"
  65. />
  66. </p>
  67. </div>
  68. <div class="row_wrap">
  69. <p class="title">消毒停止过氧化氢相对饱和度(%RS)</p>
  70. <p class="num">
  71. <van-field
  72. type="number"
  73. :formatter="formatter3"
  74. v-model="stoped_satur"
  75. :clickable="true"
  76. readonly
  77. @click.stop="hideClickKey(5)"
  78. />
  79. </p>
  80. </div>
  81. <div class="row_wrap">
  82. <p class="title">消毒继续过氧化氢相对饱和度(%RS)</p>
  83. <p class="num">
  84. <van-field
  85. type="number"
  86. :formatter="formatter4"
  87. v-model="continued_satur"
  88. :clickable="true"
  89. readonly
  90. @click.stop="hideClickKey(6)"
  91. />
  92. </p>
  93. </div>
  94. <div class="row_wrap" @click="showLogPicker">
  95. <p class="title">Log等级</p>
  96. <div class="num">
  97. <p class="log">{{ logVal }}</p>
  98. </div>
  99. </div>
  100. <div class="row_wrap">
  101. <p class="title">配方名称</p>
  102. <div>
  103. <input
  104. id="id_formula"
  105. type="text"
  106. v-model="formula_id"
  107. class="formula_input"
  108. placeholder="请输入配方名称"
  109. @focus="handleShowKeyBoard"
  110. />
  111. </div>
  112. </div>
  113. <van-number-keyboard
  114. v-model="addLiquidConfigVal"
  115. :title="addLiquidConfigVal"
  116. :show="addLiquidConfigValShow"
  117. @input="val => handleInput(val, 1)"
  118. theme="custom"
  119. close-button-text="配置"
  120. @close="setAddliquidVal"
  121. @blur="addLiquidConfigValShow = false"
  122. />
  123. <van-number-keyboard
  124. v-model="sprayLiquidConfigVal"
  125. @input="val => handleInput(val, 2)"
  126. :title="sprayLiquidConfigVal"
  127. :show="sprayLiquidConfigValShow"
  128. theme="custom"
  129. @close="setSprayLiquidVal"
  130. close-button-text="配置"
  131. @blur="sprayLiquidConfigValShow = false"
  132. />
  133. <van-number-keyboard
  134. v-model="stoped_gs"
  135. @input="val => handleInput(val, 3)"
  136. :title="stoped_gs"
  137. :show="stoped_gsShow"
  138. theme="custom"
  139. @close="setStopedGsVal"
  140. close-button-text="配置"
  141. @blur="stoped_gsShow = false"
  142. />
  143. <van-number-keyboard
  144. v-model="continued_gs"
  145. @input="val => handleInput(val, 4)"
  146. :title="continued_gs"
  147. @close="setcontinuedGsVal"
  148. :show="continued_gsShow"
  149. theme="custom"
  150. close-button-text="配置"
  151. @blur="continued_gsShow = false"
  152. />
  153. <van-number-keyboard
  154. v-model="stoped_satur"
  155. @input="val => handleInput(val, 5)"
  156. :title="stoped_satur"
  157. @close="setstopedSaturVal"
  158. :show="stoped_saturShow"
  159. theme="custom"
  160. close-button-text="配置"
  161. @blur="stoped_saturShow = false"
  162. />
  163. <van-number-keyboard
  164. v-model="continued_satur"
  165. @input="val => handleInput(val, 6)"
  166. :title="continued_satur"
  167. @close="setContinuedSaturVal"
  168. :show="continued_saturShow"
  169. theme="custom"
  170. close-button-text="配置"
  171. @blur="continued_saturShow = false"
  172. />
  173. <van-number-keyboard
  174. v-model="max_humidity"
  175. @input="val => handleInput(val, 7)"
  176. :title="max_humidity"
  177. @close="setMaxHumidityVal"
  178. :show="max_humidityShow"
  179. theme="custom"
  180. close-button-text="配置"
  181. @blur="max_humidityShow = false"
  182. />
  183. <van-number-keyboard
  184. theme="custom"
  185. close-button-text="配置"
  186. @input="val => handleInput(val, 8)"
  187. @close="setHeat_timeVal"
  188. v-model="pre_heat_time_s"
  189. :title="pre_heat_time_s"
  190. :show="pre_heat_time_sShow"
  191. @blur="pre_heat_time_sShow = false"
  192. />
  193. <van-number-keyboard
  194. @input="val => handleInput(val, 9)"
  195. theme="custom"
  196. close-button-text="配置"
  197. @close="setstoped_humiVal"
  198. v-model="stoped_humi"
  199. :title="stoped_humi"
  200. :show="stoped_humiShow"
  201. @blur="stoped_humiShow = false"
  202. />
  203. <van-number-keyboard
  204. theme="custom"
  205. @input="val => handleInput(val, 10)"
  206. close-button-text="配置"
  207. @close="setcontinued_humiVal"
  208. v-model="continued_humi"
  209. :title="continued_humi"
  210. :show="continued_humiShow"
  211. @blur="continued_humiShow = false"
  212. />
  213. <LogPicker
  214. v-if="logVisible"
  215. :hiddenLogVisible="hiddenLogVisible"
  216. :changeLogVal="changeLogVal"
  217. :logVal="logVal"
  218. />
  219. <div class="btns">
  220. <div class="btn" @click="save">保存</div>
  221. <div class="btn ml" @click="hiddleSettingModal">返回</div>
  222. </div>
  223. <div class="key_wrap" v-if="showkeyboard" id="keyboard_formula">
  224. <SimpleKeyboard @onChange="onChange" :input="formula_id" />
  225. </div>
  226. </div>
  227. </template>
  228. <script setup>
  229. import { ref, onMounted } from 'vue'
  230. import SimpleKeyboard from 'cpns/SimpleKeyboard'
  231. import { showSuccessToast, showFailToast } from 'vant'
  232. import { useSettingStore, useWebSocketStore, useOperatorStore } from '@/store'
  233. import { storeToRefs } from 'pinia'
  234. import {
  235. setSettingValJSON,
  236. addFormulaJSON,
  237. getAllFormulaJSON,
  238. } from '@/mock/command'
  239. import LogPicker from 'cpns/dialogs/LogPicker'
  240. const settingStore = useSettingStore()
  241. const webSocketStore = useWebSocketStore()
  242. const operatorStore = useOperatorStore()
  243. const max_humidity = ref('0')
  244. const continued_satur = ref('0')
  245. const stoped_satur = ref('0')
  246. const continued_gs = ref('0')
  247. const stoped_gs = ref('0')
  248. const addLiquidConfigVal = ref('0')
  249. const sprayLiquidConfigVal = ref('0')
  250. const stoped_humi = ref('0')
  251. const continued_humi = ref('0')
  252. const pre_heat_time_s = ref('0')
  253. const pre_heat_time_sShow = ref(false)
  254. const addLiquidConfigValShow = ref(false)
  255. const sprayLiquidConfigValShow = ref(false)
  256. const stoped_gsShow = ref(false)
  257. const continued_gsShow = ref(false)
  258. const stoped_saturShow = ref(false)
  259. const continued_saturShow = ref(false)
  260. const max_humidityShow = ref(false)
  261. const stoped_humiShow = ref(false)
  262. const continued_humiShow = ref(false)
  263. const logVisible = ref(false)
  264. const logVal = ref('6')
  265. const formula_id = ref('')
  266. const save = () => {
  267. if (formula_id.value == '') {
  268. showFailToast('配方名称不能为空')
  269. return
  270. }
  271. const data = {
  272. formula_id: formula_id.value,
  273. loglevel: logVal.value,
  274. injection_pump_speed: sprayLiquidConfigVal.value,
  275. stoped_gs: stoped_gs.value,
  276. continued_gs: continued_gs.value,
  277. stoped_satur: stoped_satur.value,
  278. continued_satur: continued_satur.value,
  279. stoped_humi: stoped_humi.value,
  280. continued_humi: continued_humi.value,
  281. }
  282. console.log(data)
  283. webSocketStore.sendCommandMsg(addFormulaJSON(data))
  284. webSocketStore.sendCommandMsg(getAllFormulaJSON)
  285. props.hideSettingModal()
  286. }
  287. const changeLogVal = val => {
  288. logVal.value = val
  289. logVisible.value = false
  290. }
  291. const hiddenLogVisible = () => {
  292. logVisible.value = false
  293. }
  294. const showLogPicker = () => {
  295. logVisible.value = true
  296. }
  297. const isFirstClick = ref(true)
  298. const props = defineProps({
  299. hideSettingModal: {
  300. type: Function,
  301. },
  302. })
  303. const hiddleSettingModal = () => {
  304. props.hideSettingModal()
  305. }
  306. const hideClickKey = flag => {
  307. isFirstClick.value = true
  308. stoped_humiShow.value = false
  309. continued_humiShow.value = false
  310. pre_heat_time_sShow.value = false
  311. addLiquidConfigValShow.value = false
  312. sprayLiquidConfigValShow.value = false
  313. stoped_gsShow.value = false
  314. continued_gsShow.value = false
  315. stoped_saturShow.value = false
  316. continued_saturShow.value = false
  317. max_humidityShow.value = false
  318. if (flag == 1) {
  319. addLiquidConfigValShow.value = true
  320. }
  321. if (flag == 2) {
  322. sprayLiquidConfigValShow.value = true
  323. }
  324. if (flag == 3) {
  325. stoped_gsShow.value = true
  326. }
  327. if (flag == 4) {
  328. continued_gsShow.value = true
  329. }
  330. if (flag == 5) {
  331. stoped_saturShow.value = true
  332. }
  333. if (flag == 6) {
  334. continued_saturShow.value = true
  335. }
  336. if (flag == 7) {
  337. max_humidityShow.value = true
  338. }
  339. if (flag == 8) {
  340. pre_heat_time_sShow.value = true
  341. }
  342. if (flag == 9) {
  343. stoped_humiShow.value = true
  344. }
  345. if (flag == 10) {
  346. continued_humiShow.value = true
  347. }
  348. }
  349. const handleInput = (value, index) => {
  350. if (isFirstClick.value) {
  351. if (index == 1) {
  352. setTimeout(() => {
  353. addLiquidConfigVal.value = value + ''
  354. })
  355. }
  356. if (index == 2) {
  357. setTimeout(() => {
  358. sprayLiquidConfigVal.value = value + ''
  359. })
  360. }
  361. if (index == 3) {
  362. setTimeout(() => {
  363. stoped_gs.value = value + ''
  364. })
  365. }
  366. if (index == 4) {
  367. setTimeout(() => {
  368. continued_gs.value = value + ''
  369. })
  370. }
  371. if (index == 5) {
  372. setTimeout(() => {
  373. stoped_satur.value = value + ''
  374. })
  375. }
  376. if (index == 6) {
  377. setTimeout(() => {
  378. continued_satur.value = value + ''
  379. })
  380. }
  381. if (index == 7) {
  382. setTimeout(() => {
  383. max_humidity.value = value + ''
  384. })
  385. }
  386. if (index == 8) {
  387. setTimeout(() => {
  388. pre_heat_time_s.value = value + ''
  389. })
  390. }
  391. if (index == 9) {
  392. setTimeout(() => {
  393. stoped_humi.value = value + ''
  394. })
  395. }
  396. if (index == 10) {
  397. setTimeout(() => {
  398. continued_humi.value = value + ''
  399. })
  400. }
  401. isFirstClick.value = false
  402. }
  403. }
  404. const formatter1 = value => {
  405. if (parseInt(value) == 0) {
  406. return '0'
  407. }
  408. let arr = settingStore.allSettingList.filter(item => item.name == 'stoped_gs')
  409. if (arr && arr.length > 0) {
  410. if (parseInt(value) > arr[0].val_upper_limit) {
  411. return arr[0].val_upper_limit + ''
  412. }
  413. if (parseInt(value) < arr[0].val_lower_limit) {
  414. return arr[0].val_lower_limit + ''
  415. }
  416. }
  417. return value.replace(/^0+/gi, '')
  418. }
  419. const formatter2 = value => {
  420. if (parseInt(value) == 0) {
  421. return '0'
  422. }
  423. let arr = settingStore.allSettingList.filter(
  424. item => item.name == 'continued_gs',
  425. )
  426. if (arr && arr.length > 0) {
  427. if (parseInt(value) > arr[0].val_upper_limit) {
  428. return arr[0].val_upper_limit + ''
  429. }
  430. if (parseInt(value) < arr[0].val_lower_limit) {
  431. return arr[0].val_lower_limit + ''
  432. }
  433. }
  434. return value.replace(/^0+/gi, '')
  435. }
  436. const formatter3 = value => {
  437. if (parseInt(value) == 0) {
  438. return '0'
  439. }
  440. let arr = settingStore.allSettingList.filter(
  441. item => item.name == 'stoped_satur',
  442. )
  443. if (arr && arr.length > 0) {
  444. if (parseInt(value) > arr[0].val_upper_limit) {
  445. return arr[0].val_upper_limit + ''
  446. }
  447. if (parseInt(value) < arr[0].val_lower_limit) {
  448. return arr[0].val_lower_limit + ''
  449. }
  450. }
  451. return value.replace(/^0+/gi, '')
  452. }
  453. const formatter4 = value => {
  454. if (parseInt(value) == 0) {
  455. return '0'
  456. }
  457. let arr = settingStore.allSettingList.filter(
  458. item => item.name == 'continued_satur',
  459. )
  460. if (arr && arr.length > 0) {
  461. if (parseInt(value) > arr[0].val_upper_limit) {
  462. return arr[0].val_upper_limit + ''
  463. }
  464. if (parseInt(value) < arr[0].val_lower_limit) {
  465. return arr[0].val_lower_limit + ''
  466. }
  467. }
  468. return value.replace(/^0+/gi, '')
  469. }
  470. const formatter5 = value => {
  471. if (parseInt(value) == 0) {
  472. return '0'
  473. }
  474. let arr = settingStore.allSettingList.filter(
  475. item => item.name == 'max_humidity',
  476. )
  477. if (arr && arr.length > 0) {
  478. if (parseInt(value) > arr[0].val_upper_limit) {
  479. return arr[0].val_upper_limit + ''
  480. }
  481. if (parseInt(value) < arr[0].val_lower_limit) {
  482. return arr[0].val_lower_limit + ''
  483. }
  484. }
  485. return value.replace(/^0+/gi, '')
  486. }
  487. const formatter6 = value => {
  488. if (parseInt(value) == 0) {
  489. return '0'
  490. }
  491. let arr = settingStore.allSettingList.filter(
  492. item => item.name == 'drainage_pump_speed',
  493. )
  494. if (arr && arr.length > 0) {
  495. if (parseInt(value) > arr[0].val_upper_limit) {
  496. return arr[0].val_upper_limit + ''
  497. }
  498. if (parseInt(value) < arr[0].val_lower_limit) {
  499. return arr[0].val_lower_limit + ''
  500. }
  501. }
  502. return value.replace(/^0+/gi, '')
  503. }
  504. const formatter7 = value => {
  505. if (parseInt(value) == 0) {
  506. return '0'
  507. }
  508. let arr = settingStore.allSettingList.filter(
  509. item => item.name == 'injection_pump_speed',
  510. )
  511. if (arr && arr.length > 0) {
  512. if (parseInt(value) > arr[0].val_upper_limit) {
  513. return arr[0].val_upper_limit + ''
  514. }
  515. if (parseInt(value) < arr[0].val_lower_limit) {
  516. return arr[0].val_lower_limit + ''
  517. }
  518. }
  519. return value.replace(/^0+/gi, '')
  520. }
  521. const formatter8 = value => {
  522. if (parseInt(value) == 0) {
  523. return '0'
  524. }
  525. let arr = settingStore.allSettingList.filter(
  526. item => item.name == 'pre_heat_time_s',
  527. )
  528. if (arr && arr.length > 0) {
  529. if (parseInt(value) > arr[0].val_upper_limit) {
  530. return arr[0].val_upper_limit + ''
  531. }
  532. if (parseInt(value) < arr[0].val_lower_limit) {
  533. return arr[0].val_lower_limit + ''
  534. }
  535. }
  536. return value.replace(/^0+/gi, '')
  537. }
  538. const formatter9 = value => {
  539. if (parseInt(value) == 0) {
  540. return '0'
  541. }
  542. let arr = settingStore.allSettingList.filter(
  543. item => item.name == 'stoped_humi',
  544. )
  545. if (arr && arr.length > 0) {
  546. if (parseInt(value) > arr[0].val_upper_limit) {
  547. return arr[0].val_upper_limit + ''
  548. }
  549. if (parseInt(value) < arr[0].val_lower_limit) {
  550. return arr[0].val_lower_limit + ''
  551. }
  552. }
  553. return value.replace(/^0+/gi, '')
  554. }
  555. const formatter10 = value => {
  556. if (parseInt(value) == 0) {
  557. return '0'
  558. }
  559. let arr = settingStore.allSettingList.filter(
  560. item => item.name == 'continued_humi',
  561. )
  562. if (arr && arr.length > 0) {
  563. if (parseInt(value) > arr[0].val_upper_limit) {
  564. return arr[0].val_upper_limit + ''
  565. }
  566. if (parseInt(value) < arr[0].val_lower_limit) {
  567. return arr[0].val_lower_limit + ''
  568. }
  569. }
  570. return value.replace(/^0+/gi, '')
  571. }
  572. const setAddliquidVal = () => {
  573. const val = parseInt(addLiquidConfigVal.value)
  574. if (isNaN(val)) {
  575. showFailToast('设置失败,请填写正确参数')
  576. return
  577. }
  578. }
  579. const setStopedGsVal = () => {
  580. const val = parseInt(stoped_gs.value)
  581. if (isNaN(val)) {
  582. showFailToast('设置失败,请填写正确参数')
  583. return
  584. }
  585. }
  586. const setcontinuedGsVal = () => {
  587. const val = parseInt(continued_gs.value)
  588. if (isNaN(val)) {
  589. showFailToast('设置失败,请填写正确参数')
  590. return
  591. }
  592. }
  593. const setstopedSaturVal = () => {
  594. const val = parseInt(stoped_satur.value)
  595. if (isNaN(val)) {
  596. showFailToast('设置失败,请填写正确参数')
  597. return
  598. }
  599. }
  600. const setContinuedSaturVal = () => {
  601. const val = parseInt(continued_satur.value)
  602. if (isNaN(val)) {
  603. showFailToast('设置失败,请填写正确参数')
  604. return
  605. }
  606. }
  607. const setMaxHumidityVal = () => {
  608. const val = parseInt(max_humidity.value)
  609. if (isNaN(val)) {
  610. showFailToast('设置失败,请填写正确参数')
  611. return
  612. }
  613. }
  614. const setHeat_timeVal = () => {
  615. const val = parseInt(pre_heat_time_s.value)
  616. if (isNaN(val)) {
  617. showFailToast('设置失败,请填写正确参数')
  618. return
  619. }
  620. }
  621. const setstoped_humiVal = () => {
  622. const val = parseInt(stoped_humi.value)
  623. if (isNaN(val)) {
  624. showFailToast('设置失败,请填写正确参数')
  625. return
  626. }
  627. }
  628. const setcontinued_humiVal = () => {
  629. const val = parseInt(continued_humi.value)
  630. if (isNaN(val)) {
  631. showFailToast('设置失败,请填写正确参数')
  632. return
  633. }
  634. }
  635. const setSprayLiquidVal = () => {
  636. const val = parseInt(sprayLiquidConfigVal.value)
  637. if (isNaN(val)) {
  638. showFailToast('设置失败,请填写正确参数')
  639. return
  640. }
  641. }
  642. const showkeyboard = ref(false)
  643. const onChange = a => {
  644. formula_id.value = a
  645. }
  646. const handleShowKeyBoard = () => {
  647. showkeyboard.value = true
  648. }
  649. onMounted(() => {
  650. document.addEventListener('click', e => {
  651. let box = document.getElementById('keyboard_formula')
  652. let room = document.getElementById('id_formula')
  653. if (!box?.contains(e.target) && e.target != room) {
  654. showkeyboard.value = false
  655. }
  656. })
  657. })
  658. </script>
  659. <style lang="scss" scoped>
  660. .device_container {
  661. box-sizing: border-box;
  662. width: 100%;
  663. height: 580px;
  664. display: grid;
  665. overflow: hidden;
  666. grid-template-columns: repeat(2, 1fr);
  667. row-gap: 20px;
  668. column-gap: 20px;
  669. padding: 20px;
  670. padding-bottom: 180px;
  671. position: relative;
  672. .btns {
  673. position: absolute;
  674. right: 20px;
  675. bottom: 20px;
  676. width: 300px;
  677. height: 68px;
  678. display: flex;
  679. align-items: center;
  680. justify-content: flex-end;
  681. .btn {
  682. width: 111px;
  683. height: 38px;
  684. border-radius: 19px;
  685. background: #06518b;
  686. display: flex;
  687. align-items: center;
  688. justify-content: center;
  689. font-family: Source Han Sans CN;
  690. font-size: 14px;
  691. font-weight: normal;
  692. line-height: normal;
  693. letter-spacing: 0.1em;
  694. color: #ffffff;
  695. }
  696. .ml {
  697. margin-left: 20px;
  698. }
  699. }
  700. .row_wrap {
  701. // width: 726px;
  702. height: 80px;
  703. border-radius: 14px;
  704. background: #f6f6f6;
  705. box-sizing: border-box;
  706. padding: 0 18px 0 40px;
  707. display: flex;
  708. align-items: center;
  709. justify-content: space-between;
  710. .title {
  711. font-family: Zona Pro;
  712. white-space: nowrap;
  713. font-size: 20px;
  714. font-weight: normal;
  715. letter-spacing: 0.06em;
  716. color: #000000;
  717. }
  718. .num {
  719. font-family: Source Han Sans CN;
  720. font-size: 14px;
  721. font-weight: 500;
  722. letter-spacing: 0.1em;
  723. color: #000000;
  724. display: flex;
  725. align-items: center;
  726. .log {
  727. width: 182px;
  728. display: flex;
  729. align-items: center;
  730. justify-content: center;
  731. }
  732. }
  733. .formula_input {
  734. border: none;
  735. height: 38px;
  736. padding: 0 12px;
  737. width: 220px;
  738. }
  739. .btn {
  740. width: 87px;
  741. height: 45px;
  742. border-radius: 23px;
  743. background: #06518b;
  744. font-family: Source Han Sans CN;
  745. font-size: 14px;
  746. font-weight: normal;
  747. letter-spacing: 0.1em;
  748. color: #ffffff;
  749. display: flex;
  750. align-items: center;
  751. justify-content: center;
  752. }
  753. }
  754. .key_wrap {
  755. position: absolute;
  756. left: 0;
  757. right: 0;
  758. bottom: 0;
  759. height: 230px;
  760. }
  761. }
  762. </style>