|
|
<script setup lang="ts"> import { pauseCraft, resumeCraft, stopCraft } from 'apis/crafts' import { trayTube } from 'apis/home' import errorIcon from 'assets/images/error.svg' import ingIcon from 'assets/images/ing.svg' import successIcon from 'assets/images/success.svg' import waitIcon from 'assets/images/wait.svg' import { useHomeStore } from 'stores/homeStore' import { useSystemStore } from 'stores/systemStore' import { computed, ref } from 'vue'
const props = withDefaults(defineProps<{ data?: System.HeatArea }>(), { data: () => ({ moduleCode: 'heat_module_01', enable: true, trayStatus: true, heatingType: 'stop', fanOpen: true, dryTemperature: 0, annealTemperature: 0, heatTemperature: 0, targetTemperature: 0, temperature: 0, }), })
const emits = defineEmits(['selectChange', 'setTemperature'])
const homeStore = useHomeStore() const systemStore = useSystemStore() const mousedownHandle = async (index: number) => { await trayTube({ trayUuid: tray.value?.uuid, tubes: [ { columnNum: index, exists: !tray.value?.tubes.find(t => t.columnNum === index)?.exists, }, ], }) }
const activeTubeBox = ref(false)
const tubeSelect = () => { emits('selectChange') }
const hearInfo = computed(() => { return homeStore.heatAreaList.find(item => item.value === props.data.moduleCode) }) console.log(hearInfo.value)
const craft = computed(() => { return systemStore.systemStatus.tray?.find(item => item.heatModuleId === props.data.moduleCode)?.crafts })
const tray = computed(() => { return systemStore.systemStatus.trays?.find(item => item.heatModuleCode === props.data.moduleCode) })
const setTemperature = () => { emits('setTemperature', props.data.moduleCode) }
const pauseCraftHandle = async () => { await pauseCraft({ heatId: props.data.moduleCode, }) }
const resumeCraftHandle = async () => { await resumeCraft({ heatId: props.data.moduleCode, }) }
const stopCraftHandle = async () => { await stopCraft({ heatId: props.data.moduleCode, }) }
defineExpose({ activeTubeBox, }) </script>
<template> <div class="tube" :class="{ 'tube-active': hearInfo?.selected, 'tube-shadow': data.trayStatus }"> <div class="header"> <span>{{ hearInfo?.label }}</span> <el-tag v-show="!data.trayStatus" type="info"> 空置 </el-tag> <el-tag v-show="data.trayStatus" type="success"> 已放置 </el-tag> </div> <div class="tube-item"> <div v-if="!data.trayStatus" class="tube-disable" /> <div v-if="data.trayStatus && craft?.state" class="status" :class="{ 'status-success': false, 'status-wait': craft?.state === 'READY', 'status-PAUSED': craft?.state === 'PAUSED', 'status-error': craft?.state === 'ERROR', 'status-ing': craft?.state === 'RUNNING', }" > <img v-if="craft?.state === 'FINISHED'" :src="successIcon" alt=""> <img v-if="craft?.state === 'RUNNING'" :src="ingIcon" alt=""> <img v-if="craft?.state === 'READY'" :src="waitIcon" alt=""> <img v-if="craft?.state === 'PAUSED'" :src="waitIcon" alt=""> <img v-if="craft?.state === 'ERROR'" :src="errorIcon" alt="">
<span class="status-name">{{ craft?.craft?.name || ' ' }}</span> <span v-if="craft?.state === 'RUNNING'" class="status-text">预设执行中</span> <span v-if="craft?.state === 'READY'" class="status-text">预设等待执行</span> <span v-if="craft?.state === 'PAUSED'" class="status-text">预设已暂停</span> <span v-if="craft?.state === 'ERROR'" class="status-text">预设执行错误</span> <span v-if="craft?.state === 'FINISHED'" class="status-text">预设执行成功</span> <div class="status-operation"> <ft-button v-if="craft?.state === 'RUNNING'" type="primary" size="small" :click-handle="pauseCraftHandle"> 暂停 </ft-button> <ft-button v-if="craft?.state === 'PAUSED'" type="primary" size="small" :click-handle="resumeCraftHandle"> 继续 </ft-button> <ft-button v-if="craft?.state !== 'READY'" size="small" :click-handle="stopCraftHandle"> 停止 </ft-button> </div> </div> <div v-for="item in 5" :key="item" class="tube-line" :class="{ 'tube-line-active': tray?.tubes.find(tu => tu.columnNum === item)?.exists }"
@click.prevent="() => mousedownHandle(item)" @touch.prevent="() => mousedownHandle(item)" > <span v-for="i in 8" :key="i" class="tube-line-inner" /> </div> </div> <div class="temperature-box"> <span> <span>当前温度: </span> <span>{{ data.temperature || '--' }}</span> <span>℃</span> </span> <span v-show="data.fanOpen" style="color: #FE0A0A ">降温中</span> <span v-show="data.heatingType === 'heating'" style="color: #1677FF ">加热中</span> <span v-show="data.heatingType === 'drying'" style="color: #F2652D ">烘干中</span> <span v-show="data.heatingType === 'annealing'" style="color: #14A656 ">退火中</span> </div> <div class="footer"> <div class="tem-box" @click="setTemperature"> <span :class="{ 'active-footer': hearInfo?.selected }"> {{ data.targetTemperature || '--' }}℃</span> <el-icon><Setting /></el-icon> </div>
<ft-button size="small" :type="hearInfo?.selected ? 'primary' : 'default'" @click="tubeSelect"> 选择 </ft-button> </div> </div> </template>
<style scoped lang="scss"> .tube-active { border-color: #275EFB !important; } .tube-shadow { box-shadow: 0 0 10px rgba(0,0,0,0.9); } .tube { box-sizing: border-box; width: 100%; height: 95%; background: #E9F3FF; border-radius: 10px; padding: 10px; font-size: 14px; display: flex; flex-direction: column; justify-content: space-between; border: 2px solid #E9F3FF; transition: all 0.3s; position: relative; overflow: hidden;
.header { display: flex; justify-content: space-between; align-items: center; color: #4D6882; } .tube-item { padding: 5px; background: #384D5D; border-radius: 10px; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(1, 1fr); grid-gap: 5px; position: relative; .tube-disable { position: absolute; width: 100%; height: 100%; top: 0; left: 0; background: rgba(255,255,255,0.9); border-radius: 9px; } .tube-line { display: flex; flex-direction: column; .tube-line-inner { display: inline-block; width: 25px; height: 25px; border-radius: 50%; background: #fff; margin: 2px; transition: background 0.5s; } } .tube-line-active { .tube-line-inner { background: #26D574; } }
} .temperature-box { display: flex; justify-content: space-between; background: #fff; padding: 5px; border-radius: 5px; font-size: 12px; } .footer { display: flex; justify-content: space-between; align-items: center; font-weight: bold; color: #4D6882; .active-footer { color: #1562B7; } .ft-button { margin-right: 0; } }
}
.status { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.9); z-index: 1; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; border-radius: 10px; img { width: 30px; margin: 10px 0; } .status-name { font-size: 14px; } .status-text { font-size: 16px; font-weight: 700; } .status-operation { width: 100%; margin-top: auto; margin-bottom: 10px; display: flex; justify-content: center; .ft-button { margin-right: 5px; } } } .status-wait { background: rgba(242,235,231, 0.9); border: 1px solid #EE8223; color: #EE8223; } .status-PAUSED { background: rgba(242,235,231, 0.9); border: 1px solid #EE8223; color: #EE8223; } .status-error { background: rgba(232,212,222, 0.9); border: 1px solid #DF1515; color: #DF1515; } .status-ing { background: rgba(205,223,255, 0.9); border: 1px solid #0256FF; color: #0256FF; }
.tem-box { display: flex; align-items: center; .el-icon { margin-left: 5px; } } </style>
|