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

355 lines
8.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
  1. <template>
  2. <div class="operator_main_content">
  3. <div class="left_contaienr">
  4. <div class="info_cards">
  5. <div class="card">
  6. <DisinfectantLiquidInfo />
  7. </div>
  8. <div class="card">
  9. <EnvironmentInfo :cardType="1" />
  10. </div>
  11. <div class="card">
  12. <EnvironmentInfo :cardType="2" />
  13. </div>
  14. <div class="card">
  15. <EnvironmentInfo :cardType="3" />
  16. </div>
  17. </div>
  18. <div class="warn_wrap">
  19. <p class="warn_text">警报信息</p>
  20. <div
  21. class="detail_btn"
  22. v-if="operatorStore.disinfectStatus"
  23. @click="toDetail"
  24. >
  25. 详情
  26. </div>
  27. </div>
  28. </div>
  29. <div class="right_container">
  30. <div class="setting_title">
  31. <p>消毒设置</p>
  32. <p>SET</p>
  33. </div>
  34. <div class="set_form">
  35. <input
  36. type="number"
  37. :disabled="operatorStore.disinfectStatus"
  38. v-model="roomSize"
  39. class="room_size"
  40. id="room_size"
  41. @focus="handleShowKeyBoard"
  42. />
  43. <div class="log" @click="showLogPicker">{{ logVal }}</div>
  44. </div>
  45. <div
  46. :class="operatorStore.disinfectStatus ? 'start cant' : 'start'"
  47. @click="startDisinfect"
  48. >
  49. 开始消毒
  50. </div>
  51. <div class="progress">
  52. <p class="title">剩余时间</p>
  53. <!-- <div class="tube">
  54. <div
  55. class="pro"
  56. :style="{
  57. '--width': '50px',
  58. }"
  59. ></div>
  60. </div>
  61. <div class="num">000/100</div> -->
  62. <div class="time">
  63. {{
  64. operatorStore.estimatedRemainingTimeS == 0
  65. ? `${operatorStore.estimatedRemainingTimeS} S`
  66. : '已结束'
  67. }}
  68. </div>
  69. </div>
  70. </div>
  71. <!-- <WarnModal /> -->
  72. <LogPicker
  73. v-if="logVisible"
  74. :changeLogVal="changeLogVal"
  75. :logVal="logVal"
  76. />
  77. </div>
  78. </template>
  79. <script setup>
  80. import LogPicker from 'cpns/dialogs/LogPicker'
  81. import WarnModal from 'cpns/dialogs/WarnModal'
  82. import DisinfectantLiquidInfo from 'cpns/info/DisinfectantLiquidInfo'
  83. import EnvironmentInfo from 'cpns/info/EnvironmentInfo'
  84. import { ref, watch, onMounted, onUnmounted } from 'vue'
  85. import { useOperatorStore, useWebSocketStore } from '@/store'
  86. import { startDisinfectionJSON, getStateJSON } from '@/mock/command'
  87. import { showSuccessToast, showFailToast } from 'vant'
  88. const operatorStore = useOperatorStore()
  89. const webSocketStore = useWebSocketStore()
  90. const props = defineProps({
  91. changeShowOperator: {
  92. type: Function,
  93. },
  94. handleShowKeyBoard: {
  95. type: Function,
  96. },
  97. hideKeyBoard: {
  98. type: Function,
  99. },
  100. input: {
  101. type: String,
  102. },
  103. })
  104. const toDetail = () => {
  105. // 判断当前消毒任务是否开始,如果开始时才生效 否则点击不生效
  106. if (operatorStore.disinfectStatus) {
  107. props.changeShowOperator(false)
  108. }
  109. }
  110. const logVisible = ref(false)
  111. const logVal = ref(1)
  112. const roomSize = ref(0)
  113. watch(() => {
  114. roomSize.value = props.input.match(/\d+/g)[0]
  115. })
  116. const changeLogVal = val => {
  117. logVal.value = val
  118. logVisible.value = false
  119. }
  120. const startDisinfect = () => {
  121. // 改变开始消毒状态 如果已经开始则不可点击
  122. if (!operatorStore.disinfectStatus) {
  123. if (roomSize.value == 0) {
  124. showFailToast('请调整房间大小设置,不能为0')
  125. } else {
  126. localStorage.clear()
  127. webSocketStore.sendCommandMsg(
  128. startDisinfectionJSON(logVal.value, roomSize.value),
  129. )
  130. operatorStore.updateDisinfectStatus(true)
  131. props.changeShowOperator(false)
  132. }
  133. }
  134. }
  135. const showLogPicker = () => {
  136. if (!operatorStore.disinfectStatus) {
  137. logVisible.value = true
  138. }
  139. }
  140. const timer = ref(null)
  141. onMounted(() => {
  142. timer.value = setInterval(() => {
  143. webSocketStore.sendCommandMsg(getStateJSON)
  144. }, 1000)
  145. })
  146. onUnmounted(() => {
  147. timer.value = null
  148. })
  149. </script>
  150. <style lang="scss" scoped>
  151. .operator_main_content {
  152. margin-bottom: 30px;
  153. height: 580px;
  154. box-sizing: border-box;
  155. display: flex;
  156. align-items: center;
  157. .left_contaienr {
  158. margin-right: 30px;
  159. width: 766px;
  160. height: 580px;
  161. box-sizing: border-box;
  162. border-radius: 16px;
  163. background: #ffffff;
  164. padding: 20px;
  165. .info_cards {
  166. width: 726px;
  167. height: 470px;
  168. box-sizing: border-box;
  169. display: grid;
  170. grid-template-columns: repeat(2, 1fr);
  171. grid-template-rows: repeat(2, 1fr);
  172. column-gap: 20px;
  173. row-gap: 20px;
  174. margin-bottom: 20px;
  175. .card {
  176. width: 353px;
  177. height: 225px;
  178. border-radius: 17.5px;
  179. background: #06518b;
  180. }
  181. }
  182. .warn_wrap {
  183. display: flex;
  184. align-items: center;
  185. justify-content: space-between;
  186. box-sizing: border-box;
  187. padding: 0 20px;
  188. width: 726px;
  189. height: 50px;
  190. border-radius: 6px;
  191. background: #f6f6f6;
  192. .warn_text {
  193. font-family: Source Han Sans CN;
  194. font-size: 12px;
  195. font-weight: 500;
  196. letter-spacing: 0.1em;
  197. color: #fa1c1c;
  198. }
  199. .detail_btn {
  200. width: 105px;
  201. height: 31px;
  202. border-radius: 16px;
  203. background: #06518b;
  204. display: flex;
  205. align-items: center;
  206. justify-content: center;
  207. font-family: Source Han Sans CN;
  208. font-size: 12px;
  209. font-weight: normal;
  210. letter-spacing: 0.1em;
  211. color: #ffffff;
  212. }
  213. }
  214. }
  215. .right_container {
  216. height: 580px;
  217. box-sizing: border-box;
  218. border-radius: 16px;
  219. background: #ffffff;
  220. flex: 1;
  221. padding: 42px;
  222. padding-top: 32px;
  223. .setting_title {
  224. width: 340px;
  225. height: 45px;
  226. border-radius: 23px;
  227. background: #06518b;
  228. padding: 0 24px;
  229. box-sizing: border-box;
  230. display: flex;
  231. align-items: center;
  232. justify-content: space-between;
  233. font-family: Source Han Sans CN;
  234. font-size: 14px;
  235. font-weight: normal;
  236. letter-spacing: 0.1em;
  237. color: #ffffff;
  238. margin-bottom: 41px;
  239. }
  240. .set_form {
  241. width: 340px;
  242. height: 190px;
  243. box-sizing: border-box;
  244. margin-bottom: 41px;
  245. overflow: hidden;
  246. background: url(../assets/img/operator/form.png) no-repeat;
  247. background-size: 100% 100%;
  248. position: relative;
  249. .room_size {
  250. position: absolute;
  251. top: 45px;
  252. left: 23px;
  253. width: 189px;
  254. height: 20px;
  255. text-align: center;
  256. border: none;
  257. outline: none;
  258. }
  259. .log {
  260. position: absolute;
  261. top: 145px;
  262. left: 0px;
  263. width: 240px;
  264. height: 42px;
  265. text-align: center;
  266. display: flex;
  267. align-items: center;
  268. justify-content: center;
  269. font-family: Source Han Sans CN;
  270. font-size: 14px;
  271. font-weight: 500;
  272. letter-spacing: 0.06em;
  273. color: #0e0e0e;
  274. }
  275. }
  276. .start {
  277. margin-bottom: 30px;
  278. width: 340px;
  279. height: 45px;
  280. border-radius: 23px;
  281. background: #06518b;
  282. display: flex;
  283. align-items: center;
  284. justify-content: center;
  285. font-family: Source Han Sans CN;
  286. font-size: 14px;
  287. font-weight: normal;
  288. letter-spacing: 0.1em;
  289. color: #ffffff;
  290. }
  291. .cant {
  292. background: #f4f4f4;
  293. }
  294. .progress {
  295. width: 340px;
  296. height: 114px;
  297. border-radius: 16px;
  298. opacity: 1;
  299. background: #f6f6f6;
  300. box-sizing: border-box;
  301. padding: 27px 24px 18px 27px;
  302. .title {
  303. font-family: Source Han Sans CN;
  304. font-size: 12px;
  305. font-weight: 350;
  306. letter-spacing: 0.06em;
  307. color: #9e9e9e;
  308. margin-bottom: 13px;
  309. }
  310. .time {
  311. text-align: center;
  312. padding: 10px;
  313. }
  314. .tube {
  315. width: 292px;
  316. height: 14px;
  317. border-radius: 7px;
  318. background: #ffffff;
  319. margin-bottom: 11px;
  320. position: relative;
  321. overflow: hidden;
  322. .pro {
  323. position: absolute;
  324. left: 0;
  325. top: 0;
  326. height: 14px;
  327. width: var(--width);
  328. border-radius: 7px;
  329. background: #06518b;
  330. }
  331. }
  332. .num {
  333. display: flex;
  334. justify-content: flex-end;
  335. font-family: Source Han Sans CN;
  336. font-size: 10px;
  337. font-weight: normal;
  338. letter-spacing: 0.06em;
  339. color: #9e9e9e;
  340. }
  341. }
  342. }
  343. }
  344. </style>