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

<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>