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.

326 lines
8.4 KiB

2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
  1. <script setup lang="ts">
  2. import { pauseCraft, resumeCraft, stopCraft } from 'apis/crafts'
  3. import { trayTube } from 'apis/home'
  4. import errorIcon from 'assets/images/error.svg'
  5. import ingIcon from 'assets/images/ing.svg'
  6. import successIcon from 'assets/images/success.svg'
  7. import waitIcon from 'assets/images/wait.svg'
  8. import { useHomeStore } from 'stores/homeStore'
  9. import { useSystemStore } from 'stores/systemStore'
  10. import { computed, ref } from 'vue'
  11. const props = withDefaults(defineProps<{ data?: System.HeatArea }>(), {
  12. data: () => ({
  13. moduleCode: 'heat_module_01',
  14. enable: true,
  15. trayStatus: true,
  16. heatingType: 'stop',
  17. fanOpen: true,
  18. dryTemperature: 0,
  19. annealTemperature: 0,
  20. heatTemperature: 0,
  21. targetTemperature: 0,
  22. temperature: 0,
  23. }),
  24. })
  25. const emits = defineEmits(['selectChange', 'setTemperature'])
  26. const homeStore = useHomeStore()
  27. const systemStore = useSystemStore()
  28. const mousedownHandle = async (index: number) => {
  29. await trayTube({
  30. trayUuid: tray.value?.uuid,
  31. tubes: [
  32. {
  33. columnNum: index,
  34. exists: !tray.value?.tubes.find(t => t.columnNum === index)?.exists,
  35. },
  36. ],
  37. })
  38. }
  39. const activeTubeBox = ref(false)
  40. const tubeSelect = () => {
  41. emits('selectChange')
  42. }
  43. const hearInfo = computed(() => {
  44. return homeStore.heatAreaList.find(item => item.value === props.data.moduleCode)
  45. })
  46. console.log(hearInfo.value)
  47. const craft = computed(() => {
  48. return systemStore.systemStatus.tray?.find(item => item.heatModuleId === props.data.moduleCode)?.crafts
  49. })
  50. const tray = computed(() => {
  51. return systemStore.systemStatus.trays?.find(item => item.heatModuleCode === props.data.moduleCode)
  52. })
  53. const setTemperature = () => {
  54. emits('setTemperature', props.data.moduleCode)
  55. }
  56. const pauseCraftHandle = async () => {
  57. await pauseCraft({
  58. heatId: props.data.moduleCode,
  59. })
  60. }
  61. const resumeCraftHandle = async () => {
  62. await resumeCraft({
  63. heatId: props.data.moduleCode,
  64. })
  65. }
  66. const stopCraftHandle = async () => {
  67. await stopCraft({
  68. heatId: props.data.moduleCode,
  69. })
  70. }
  71. defineExpose({
  72. activeTubeBox,
  73. })
  74. </script>
  75. <template>
  76. <div class="tube" :class="{ 'tube-active': hearInfo?.selected, 'tube-shadow': data.trayStatus }">
  77. <div class="header">
  78. <span>{{ hearInfo?.label }}</span>
  79. <el-tag v-show="!data.trayStatus" type="info">
  80. 空置
  81. </el-tag>
  82. <el-tag v-show="data.trayStatus" type="success">
  83. 已放置
  84. </el-tag>
  85. </div>
  86. <div class="tube-item">
  87. <div v-if="!data.trayStatus" class="tube-disable" />
  88. <div
  89. v-if="data.trayStatus && craft?.state"
  90. class="status" :class="{
  91. 'status-success': false,
  92. 'status-wait': craft?.state === 'READY',
  93. 'status-PAUSED': craft?.state === 'PAUSED',
  94. 'status-error': craft?.state === 'ERROR',
  95. 'status-ing': craft?.state === 'RUNNING',
  96. }"
  97. >
  98. <img v-if="craft?.state === 'FINISHED'" :src="successIcon" alt="">
  99. <img v-if="craft?.state === 'RUNNING'" :src="ingIcon" alt="">
  100. <img v-if="craft?.state === 'READY'" :src="waitIcon" alt="">
  101. <img v-if="craft?.state === 'PAUSED'" :src="waitIcon" alt="">
  102. <img v-if="craft?.state === 'ERROR'" :src="errorIcon" alt="">
  103. <span class="status-name">{{ craft?.craft?.name || ' ' }}</span>
  104. <span v-if="craft?.state === 'RUNNING'" class="status-text">预设执行中</span>
  105. <span v-if="craft?.state === 'READY'" class="status-text">预设等待执行</span>
  106. <span v-if="craft?.state === 'PAUSED'" class="status-text">预设已暂停</span>
  107. <span v-if="craft?.state === 'ERROR'" class="status-text">预设执行错误</span>
  108. <span v-if="craft?.state === 'FINISHED'" class="status-text">预设执行成功</span>
  109. <div class="status-operation">
  110. <ft-button v-if="craft?.state === 'RUNNING'" type="primary" size="small" :click-handle="pauseCraftHandle">
  111. 暂停
  112. </ft-button>
  113. <ft-button v-if="craft?.state === 'PAUSED'" type="primary" size="small" :click-handle="resumeCraftHandle">
  114. 继续
  115. </ft-button>
  116. <ft-button v-if="craft?.state !== 'READY'" size="small" :click-handle="stopCraftHandle">
  117. 停止
  118. </ft-button>
  119. </div>
  120. </div>
  121. <div
  122. v-for="item in 5"
  123. :key="item"
  124. class="tube-line"
  125. :class="{ 'tube-line-active': tray?.tubes.find(tu => tu.columnNum === item)?.exists }"
  126. @click.prevent="() => mousedownHandle(item)"
  127. @touch.prevent="() => mousedownHandle(item)"
  128. >
  129. <span v-for="i in 8" :key="i" class="tube-line-inner" />
  130. </div>
  131. </div>
  132. <div class="temperature-box">
  133. <span>
  134. <span>当前温度: </span>
  135. <span>{{ data.temperature || '--' }}</span>
  136. <span></span>
  137. </span>
  138. <span v-show="data.fanOpen" style="color: #FE0A0A ">降温中</span>
  139. <span v-show="data.heatingType === 'heating'" style="color: #1677FF ">加热中</span>
  140. <span v-show="data.heatingType === 'drying'" style="color: #F2652D ">烘干中</span>
  141. <span v-show="data.heatingType === 'annealing'" style="color: #14A656 ">退火中</span>
  142. </div>
  143. <div class="footer">
  144. <div class="tem-box" @click="setTemperature">
  145. <span :class="{ 'active-footer': hearInfo?.selected }"> {{ data.targetTemperature || '--' }}</span>
  146. <el-icon><Setting /></el-icon>
  147. </div>
  148. <ft-button size="small" :type="hearInfo?.selected ? 'primary' : 'default'" @click="tubeSelect">
  149. 选择
  150. </ft-button>
  151. </div>
  152. </div>
  153. </template>
  154. <style scoped lang="scss">
  155. .tube-active {
  156. border-color: #275EFB !important;
  157. }
  158. .tube-shadow {
  159. box-shadow: 0 0 10px rgba(0,0,0,0.9);
  160. }
  161. .tube {
  162. box-sizing: border-box;
  163. width: 100%;
  164. height: 95%;
  165. background: #E9F3FF;
  166. border-radius: 10px;
  167. padding: 10px;
  168. font-size: 14px;
  169. display: flex;
  170. flex-direction: column;
  171. justify-content: space-between;
  172. border: 2px solid #E9F3FF;
  173. transition: all 0.3s;
  174. position: relative;
  175. overflow: hidden;
  176. .header {
  177. display: flex;
  178. justify-content: space-between;
  179. align-items: center;
  180. color: #4D6882;
  181. }
  182. .tube-item {
  183. padding: 5px;
  184. background: #384D5D;
  185. border-radius: 10px;
  186. display: grid;
  187. grid-template-columns: repeat(5, 1fr);
  188. grid-template-rows: repeat(1, 1fr);
  189. grid-gap: 5px;
  190. position: relative;
  191. .tube-disable {
  192. position: absolute;
  193. width: 100%;
  194. height: 100%;
  195. top: 0;
  196. left: 0;
  197. background: rgba(255,255,255,0.9);
  198. border-radius: 9px;
  199. }
  200. .tube-line {
  201. display: flex;
  202. flex-direction: column;
  203. .tube-line-inner {
  204. display: inline-block;
  205. width: 25px;
  206. height: 25px;
  207. border-radius: 50%;
  208. background: #fff;
  209. margin: 2px;
  210. transition: background 0.5s;
  211. }
  212. }
  213. .tube-line-active {
  214. .tube-line-inner {
  215. background: #26D574;
  216. }
  217. }
  218. }
  219. .temperature-box {
  220. display: flex;
  221. justify-content: space-between;
  222. background: #fff;
  223. padding: 5px;
  224. border-radius: 5px;
  225. font-size: 12px;
  226. }
  227. .footer {
  228. display: flex;
  229. justify-content: space-between;
  230. align-items: center;
  231. font-weight: bold;
  232. color: #4D6882;
  233. .active-footer {
  234. color: #1562B7;
  235. }
  236. .ft-button {
  237. margin-right: 0;
  238. }
  239. }
  240. }
  241. .status {
  242. position: absolute;
  243. top: 0;
  244. left: 0;
  245. width: 100%;
  246. height: 100%;
  247. background: rgba(255,255,255,0.9);
  248. z-index: 1;
  249. display: flex;
  250. flex-direction: column;
  251. justify-content: flex-start;
  252. align-items: center;
  253. border-radius: 10px;
  254. img {
  255. width: 30px;
  256. margin: 10px 0;
  257. }
  258. .status-name {
  259. font-size: 14px;
  260. }
  261. .status-text {
  262. font-size: 16px;
  263. font-weight: 700;
  264. }
  265. .status-operation {
  266. width: 100%;
  267. margin-top: auto;
  268. margin-bottom: 10px;
  269. display: flex;
  270. justify-content: center;
  271. .ft-button {
  272. margin-right: 5px;
  273. }
  274. }
  275. }
  276. .status-wait {
  277. background: rgba(242,235,231, 0.9);
  278. border: 1px solid #EE8223;
  279. color: #EE8223;
  280. }
  281. .status-PAUSED {
  282. background: rgba(242,235,231, 0.9);
  283. border: 1px solid #EE8223;
  284. color: #EE8223;
  285. }
  286. .status-error {
  287. background: rgba(232,212,222, 0.9);
  288. border: 1px solid #DF1515;
  289. color: #DF1515;
  290. }
  291. .status-ing {
  292. background: rgba(205,223,255, 0.9);
  293. border: 1px solid #0256FF;
  294. color: #0256FF;
  295. }
  296. .tem-box {
  297. display: flex;
  298. align-items: center;
  299. .el-icon {
  300. margin-left: 5px;
  301. }
  302. }
  303. </style>