大空间消毒机
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.

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