Browse Source

feat: 执行工艺

master
guoapeng 1 week ago
parent
commit
0c385c8031
  1. 2
      src/apis/home.ts
  2. 5
      src/app.vue
  3. 5
      src/components/home/CleanSolution/index.vue
  4. 9
      src/components/home/DrainSolution/index.vue
  5. 5
      src/components/home/DrainWasteSolution/index.vue
  6. 5
      src/components/home/FillSolution/index.vue
  7. 138
      src/components/home/selectCraft/index.vue
  8. 2
      src/main.ts
  9. 239
      src/stores/systemStore.ts
  10. 8
      src/types/home.d.ts
  11. 65
      src/types/system.d.ts
  12. 176
      src/views/home/index.vue

2
src/apis/home.ts

@ -2,7 +2,7 @@ import http from 'libs/http'
const baseUrl = '/tasks/'
export const setTargetTemperature = (params: Home.SetTargetTemperatureParams): Promise<null> => http.post('/heat/target-temperature', params)
export const trayTube = (params: Home.TrayTubeParams): Promise<null> => http.post('/tray/tube', params)
export const trayTube = (params: Home.TrayTubeParams[]): Promise<null> => http.put('/tube/set-tube-exist', params)
export const addTask = (params: Task.TaskAdd): Promise<null> => http.post(baseUrl, params)
export const stopTask = (): Promise<null> => http.post(`${baseUrl}stop`)
export const getTask = (id: number): Promise<Task.Task> => http.get(`${baseUrl}${id}`)

5
src/app.vue

@ -1,4 +1,5 @@
<script setup lang="ts">
import { getStatus } from 'apis/system'
// import { getStatus } from 'apis/system'
import { socket } from 'libs/socket'
import { useSystemStore } from 'stores/systemStore'
@ -6,10 +7,10 @@ import { onBeforeUnmount, onMounted, ref } from 'vue'
const systemStore = useSystemStore()
onMounted(async () => {
// const res = await getStatus()
const res = await getStatus()
// console.log(res)
// console.log(systemStore.systemStatus)
// systemStore.updateSystemStatus(res)
systemStore.updateSystemStatus(res)
startProgress()
})

5
src/components/home/CleanSolution/index.vue

@ -73,7 +73,7 @@ const checked = ref<number>()
</script>
<template>
<FtDialog visible title="清洗管路" width="50%" :show-close="true" @cancel="cancel">
<FtDialog visible title="清洗管路" width="50%" @cancel="cancel">
<div class="module-box">
<el-radio v-model="titrationModuleCode" label="滴定位1" size="large" value="MODULE_1" border />
<el-radio v-model="titrationModuleCode" label="滴定位2" size="large" value="MODULE_2" border />
@ -91,6 +91,9 @@ const checked = ref<number>()
<ft-button type="default" :click-handle="clean_solution_stop">
停止清洗
</ft-button>
<ft-button type="default" :click-handle="cancel">
关闭
</ft-button>
</template>
</FtDialog>
</template>

9
src/components/home/DrainSolution/index.vue

@ -73,14 +73,16 @@ const checked = ref<number>()
</script>
<template>
<FtDialog visible title="排空管路" width="50%" :show-close="true" @cancel="cancel">
<FtDialog visible title="排空管路" width="50%" @cancel="cancel">
<div class="module-box">
<el-radio v-model="titrationModuleCode" label="滴定位1" size="large" value="MODULE_1" border />
<el-radio v-model="titrationModuleCode" label="滴定位2" size="large" value="MODULE_2" border />
</div>
<div class="item-box">
<el-radio-group v-model="checked">
<el-radio v-for="item in solutionList" :key="item.id" border :label="solutionMap[item.id]" :value="item.id" />
<div style="display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr); gap: 10px">
<el-radio v-for="item in solutionList" :key="item.id" border :label="solutionMap[item.id]" :value="item.id" />
</div>
</el-radio-group>
</div>
@ -91,6 +93,9 @@ const checked = ref<number>()
<ft-button type="default" :click-handle="filled_solution_stop">
停止排空
</ft-button>
<ft-button type="default" :click-handle="cancel">
关闭
</ft-button>
</template>
</FtDialog>
</template>

5
src/components/home/DrainWasteSolution/index.vue

@ -38,7 +38,7 @@ const drain_waste_solution_stop = async () => {
</script>
<template>
<FtDialog visible title="抽取废液" width="50%" :show-close="true" @cancel="cancel">
<FtDialog visible title="抽取废液" width="50%" @cancel="cancel">
<template #footer>
<ft-button type="primary" :click-handle="drain_waste_solution_start">
开始抽液
@ -46,6 +46,9 @@ const drain_waste_solution_stop = async () => {
<ft-button type="default" :click-handle="drain_waste_solution_stop">
停止抽液
</ft-button>
<ft-button type="default" :click-handle="cancel">
关闭
</ft-button>
</template>
</FtDialog>
</template>

5
src/components/home/FillSolution/index.vue

@ -73,7 +73,7 @@ const checked = ref<number>()
</script>
<template>
<FtDialog visible title="预充管路" width="50%" :show-close="true" @cancel="cancel">
<FtDialog visible title="预充管路" width="50%" @cancel="cancel">
<div class="module-box">
<el-radio v-model="titrationModuleCode" label="滴定位1" size="large" value="MODULE_1" border />
<el-radio v-model="titrationModuleCode" label="滴定位2" size="large" value="MODULE_2" border />
@ -91,6 +91,9 @@ const checked = ref<number>()
<ft-button type="default" :click-handle="filled_solution_stop">
停止预充
</ft-button>
<ft-button type="default" :click-handle="cancel">
关闭
</ft-button>
</template>
</FtDialog>
</template>

138
src/components/home/selectCraft/index.vue

@ -0,0 +1,138 @@
<script setup lang="ts">
import type { CheckboxValueType } from 'element-plus'
import { getCraftList } from 'apis/crafts'
import { onMounted } from 'vue'
const emits = defineEmits(['close'])
const craftList = ref([])
onMounted(async () => {
const res = await getCraftList()
craftList.value = res.list
})
const checkAll1 = ref(false)
const isIndeterminate1 = ref(false)
const trayTubes1 = ref([])
const checkAll2 = ref(false)
const isIndeterminate2 = ref(false)
const trayTubes2 = ref([])
const handleCheckAllChange = (val: CheckboxValueType, type: number) => {
if (type === 1) {
checkAll1.value = val
trayTubes1.value = val ? Array.from({ length: 16 }, (_, index) => index + 1) : []
isIndeterminate1.value = false
}
else {
checkAll2.value = val
trayTubes2.value = val ? Array.from({ length: 16 }, (_, index) => index + 17) : []
isIndeterminate2.value = false
}
}
const tubeCrafts = ref([])
const close = () => {
emits('close')
}
</script>
<template lang="pug">
FtDialog(visible title="自动滴定" width="60%")
div.box
el-card
el-checkbox(v-model="checkAll1" :indeterminate="isIndeterminate1" @change="val => handleCheckAllChange(val, 1)") 全选
el-checkbox-group(v-model="trayTubes1" )
div.tube-content
div.tube-box(v-for="item in 16" :key="item" :class="{ 'tube-box-success': true }")
div.tube-item
span.serial-number {{item.toString().padStart(2, '0')}}
el-checkbox(:value="item")
el-card
el-checkbox(v-model="checkAll2" :indeterminate="isIndeterminate2" @change="val => handleCheckAllChange(val, 2)") 全选
el-checkbox-group(v-model="trayTubes2" )
div.tube-content
div.tube-box(v-for="item in 16" :key="item" :class="{ 'tube-box-success': true }")
div.tube-item
span.serial-number {{(item+16).toString().padStart(2, '0')}}
el-checkbox(:value="item+16")
p 加热位打发过分沙发斯蒂芬
div.select-box
p 选择工艺
el-select(style="width: 200px")
el-option(v-for="item in craftList" :key="item.id" :label="item.name" :value="item.id")
template(#footer)
ft-button(type="primary" :click-handle="start")
| 开始滴定
ft-button(type="primary" :click-handle="pause")
| 暂停滴定
ft-button(type="primary" :click-handle="stop")
| 停止滴定
ft-button(:click-handle="close")
| 关闭
</template>
<style scoped lang="stylus">
.box
height 350px
display flex
justify-content space-between
.el-card
width calc(50% - 5px)
height 100%
background #F7F7F7
border-radius 10px !important
box-shadow none
border none
:deep(.el-card__body)
background #F7F7F7
border-radius 10px!important
padding 10px
height 100%
.tube-content
width 100%
height calc(100% - 30px)
display grid
grid-template-columns repeat(4, 1fr)
grid-template-rows repeat(4, 1fr)
grid-gap 4px
.tube-box-success
background #12C290 !important
color #fff !important
.tube-box
font-size 10px
background #EBEFF4
border-radius: 10px
padding 0 5px
color #606266
border 2px solid #ffffff
transition all .5s
position relative
overflow hidden
p
position absolute
bottom 0
left 0
padding 0 10px
height 20px
width 100%
background rgba(0, 0, 0, 0.15)
text-align center
line-height 20px
.tube-item
display flex
justify-content space-between
align-items center
.serial-number
font-size 14px
font-weight 900
.select-box
display flex
align-items center
gap 20px
margin-top 10px
.el-checkbox-group
height 100%
</style>

2
src/main.ts

@ -1,7 +1,7 @@
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import FtButton from 'components/common/FTButton/index.vue'
import FtChart from 'components/common/FTChart/index.vue'
import FtDatetime from 'components/common/FTDatetime/index.vue'
import FtDatetime from 'components/common/FTDateTime/index.vue'
import FtDialog from 'components/common/FTDialog/index.vue'
import FtStream from 'components/common/FTStream/index.vue'
import FtTable from 'components/common/FTTable/index.vue'

239
src/stores/systemStore.ts

@ -6,237 +6,18 @@ import router from '@/router'
export const useSystemStore = defineStore('system', {
state: (): System.SystemStore => ({
systemStatus: {
virtual: false,
initComplete: true,
selfTest: true,
emergencyStop: false,
craftsPaused: true, // 当前设备是否暂停
trayExist1: true, // 托盘1是否存在
trayExist2: true, // 托盘2是否存在
virtual: true, // 虚拟模式
initComplete: true, // 初始化状态
selfTest: true, // 自检状态
emergencyStop: true, // 是否是急停状态
currentUser: {
},
currentTasks: null,
doorModule: {
open: false,
},
transferModule: {
idle: true,
trayStatus: false,
},
solutionModule: {
idle: true,
feedAreaTrayStatus: false,
pumping: false,
valveState: {
state: 1,
},
solutionContainer: [
{
containerCode: 1,
type: 'solution',
empty: false,
full: false,
filledSolution: false,
},
{
containerCode: 2,
type: 'solution',
empty: false,
full: false,
filledSolution: false,
},
{
containerCode: 3,
type: 'solution',
empty: false,
full: false,
filledSolution: false,
},
{
containerCode: 4,
type: 'solution',
empty: false,
full: false,
filledSolution: false,
},
],
},
heatModule: [
{
moduleCode: 'heat_module_01',
enable: true,
trayStatus: true,
heatingType: 'heating',
fanOpen: false,
targetTemperature: 0,
temperature: 0,
startHeatTime: 1749126403564,
targetTime: 1800,
},
{
moduleCode: 'heat_module_02',
enable: true,
trayStatus: true,
heatingType: 'stop',
fanOpen: true,
dryTemperature: 0,
annealTemperature: 0,
heatTemperature: 0,
targetTemperature: 0,
temperature: 0,
},
{
moduleCode: 'heat_module_03',
enable: true,
trayStatus: true,
heatingType: 'drying',
fanOpen: false,
dryTemperature: 0,
annealTemperature: 0,
heatTemperature: 0,
targetTemperature: 0,
temperature: 0,
},
{
moduleCode: 'heat_module_04',
enable: true,
trayStatus: true,
heatingType: 'annealing',
fanOpen: false,
dryTemperature: 0,
annealTemperature: 0,
heatTemperature: 0,
targetTemperature: 0,
temperature: 0,
},
],
trays: [
{
uuid: '22',
heatModuleCode: 'heat_module_01',
inFeedArea: false,
inSolutionPositon: false,
inHeatModule: true,
useArm: true,
tubes: [
{
columnNum: 1,
addSolution: true,
exists: true,
},
{
columnNum: 2,
addSolution: true,
exists: true,
},
{
columnNum: 3,
addSolution: true,
exists: false,
},
{
columnNum: 4,
addSolution: true,
exists: true,
},
{
columnNum: 5,
addSolution: true,
exists: true,
},
],
crafts: {
craft: {
id: 1,
name: '菱锌矿硫酸溶解法',
steps: '[{"name":"加液","method":"addLiquid","params":{"addLiquidList":[{"containerId":1,"volume":3},{"containerId":4,"volume":4},{"containerId":3,"volume":5}],"description":["添加硫酸-3ml; ","添加氢氟酸-4ml; ","添加硝酸-5ml; "]}},{"name":"加热","method":"startHeating","params":{"temperature":4,"second":123,"description":"加热: 4度, 保持2分3秒","minutes":2,"seconds":3}},{"name":"摇匀","method":"shaking","params":{"second":122,"seconds":2,"minutes":2,"description":"摇匀: 122秒"}},{"name":"拍照","method":"takePhoto","params":{"description":"拍照"}}]',
},
state: 'RUNNING',
currentIndex: 1,
},
},
{
uuid: '3',
heatModuleCode: 'heat_module_02',
inFeedArea: false,
inSolutionPositon: true,
inHeatModule: false,
tubes: [
{
columnNum: 1,
addSolution: true,
exists: true,
},
{
columnNum: 2,
addSolution: true,
exists: true,
},
{
columnNum: 3,
addSolution: true,
exists: false,
},
{
columnNum: 4,
addSolution: true,
exists: true,
},
{
columnNum: 5,
addSolution: true,
exists: true,
},
],
// crafts: {
// craft: {
// id: 1,
// name: '菱锌矿硫酸溶解法',
// steps: '[{"name":"加液","method":"addLiquid","params":{"addLiquidList":[{"containerId":1,"volume":3},{"containerId":4,"volume":4},{"containerId":3,"volume":5}],"description":["添加硫酸-3ml; ","添加氢氟酸-4ml; ","添加硝酸-5ml; "]}},{"name":"加热","method":"startHeating","params":{"temperature":4,"second":123,"description":"加热: 4度, 保持2分3秒","minutes":2,"seconds":3}},{"name":"摇匀","method":"shaking","params":{"second":122,"seconds":2,"minutes":2,"description":"摇匀: 122秒"}},{"name":"拍照","method":"takePhoto","params":{"description":"拍照"}}]',
// },
// state: 'RUNNING',
// currentIndex: 1,
// },
},
{
uuid: '5',
heatModuleCode: 'heat_module_03',
inFeedArea: false,
inSolutionPositon: false,
inHeatModule: true,
tubes: [
{
columnNum: 1,
addSolution: true,
exists: true,
},
],
// crafts: {
// craft: {
// id: 1,
// name: '菱锌矿硫酸溶解法',
// steps: '[{"name":"加液","method":"addLiquid","params":{"addLiquidList":[{"containerId":1,"volume":3},{"containerId":4,"volume":4},{"containerId":3,"volume":5}],"description":["添加硫酸-3ml; ","添加氢氟酸-4ml; ","添加硝酸-5ml; "]}},{"name":"加热","method":"startHeating","params":{"temperature":4,"second":123,"description":"加热: 4度, 保持2分3秒","minutes":2,"seconds":3}},{"name":"摇匀","method":"shaking","params":{"second":122,"seconds":2,"minutes":2,"description":"摇匀: 122秒"}},{"name":"拍照","method":"takePhoto","params":{"description":"拍照"}}]',
// },
// state: 'RUNNING',
// currentIndex: 1,
// },
},
{
uuid: '5',
heatModuleCode: 'heat_module_04',
inFeedArea: false,
inSolutionPositon: false,
inHeatModule: true,
tubes: [
],
// crafts: {
// craft: {
// id: 1,
// name: '菱锌矿硫酸溶解法',
// steps: '[{"name":"加液","method":"addLiquid","params":{"addLiquidList":[{"containerId":1,"volume":3},{"containerId":4,"volume":4},{"containerId":3,"volume":5}],"description":["添加硫酸-3ml; ","添加氢氟酸-4ml; ","添加硝酸-5ml; "]}},{"name":"加热","method":"startHeating","params":{"temperature":4,"second":123,"description":"加热: 4度, 保持2分3秒","minutes":2,"seconds":3}},{"name":"摇匀","method":"shaking","params":{"second":122,"seconds":2,"minutes":2,"description":"摇匀: 122秒"}},{"name":"拍照","method":"takePhoto","params":{"description":"拍照"}}]',
// },
// state: 'RUNNING',
// currentIndex: 1,
// },
},
],
titrationModule: [],
heatModuleState: [],
trayTubeState: [],
},
errCraftList: [],
loginForm: {

8
src/types/home.d.ts

@ -21,12 +21,8 @@ declare namespace Home {
heatTemperature: number | undefined
}
interface TrayTubeParams {
trayUuid?: string
tubes: {
columnNum: number
addSolution?: boolean
exists: boolean
}[]
tubeNum: number
tubeExist: boolean
}
}

65
src/types/system.d.ts

@ -18,32 +18,47 @@ declare namespace System {
time: string
}
interface SystemStatus {
virtual: boolean
initComplete: boolean
selfTest: boolean
emergencyStop: boolean
currentUser: User.User | null
currentTasks: Task.Task[] | null
doorModule: {
open: boolean
actionable?: boolean
}
transferModule: {
idle: boolean
trayStatus: boolean
}
solutionModule: {
idle: boolean
feedAreaTrayStatus: boolean
pumping: boolean
valveState: {
state: number
}
solutionContainer: SolutionContainer[]
craftsPaused: boolean // 当前设备是否暂停
trayExist1: boolean // 托盘1是否存在
trayExist2: boolean // 托盘2是否存在
virtual: boolean // 虚拟模式
initComplete: boolean // 初始化状态
selfTest: boolean // 自检状态
emergencyStop: boolean // 是否是急停状态
currentUser: User.User
titrationModule: {
moduleCode: 'MODULE_1' | 'MODULE_2' // 滴定模块code
tubeExist: boolean // 是否存在试管
}[]
heatModuleState:
{
moduleCode: 'MODULE_1' | 'MODULE_2' // 加热模块code
tubeExist: boolean // 是否存在试管
open: boolean // 是否启动加热
temperature: number // 加热器当前温度
targetTemperature: number // 加热器目标温度
targetTime: number // 加热器目标加热时间,单位秒
startHeatTime: string // 开始加热的时间
}[]
trayTubeState:
{
tubeNum: number // 试管编号
tubeExist: boolean // 是否存在试管
volume: number // 体积 double
result: number // 结果 double
craftsName: string // 配置的工艺名称
craftsId: number // 配置的工艺ID
queueNum: number // 当前试管工艺队列的编号 int
titrationModuleCodes:
{
moduleCode: 'MODULE_1' | 'MODULE_2' // 滴定模块code
tubeExist: boolean // 是否存在试管
}[]
titrationStatus: 'NOT_STARTED' | 'IN_PROGRESS' | 'COMPLETED'
}[]
}
heatModule: HeatArea[]
trays?: Tray[]
}
interface Tray {
uuid: string

176
src/views/home/index.vue

@ -1,12 +1,15 @@
<script setup lang="ts">
import { trayTube } from 'apis/home'
import ColorEdit from 'components/color/Edit/index.vue'
import AddLiquid from 'components/home/AddLiquid/index.vue'
import CleanSolution from 'components/home/CleanSolution/index.vue'
import DrainSolution from 'components/home/DrainSolution/index.vue'
import DrainWasteSolution from 'components/home/DrainWasteSolution/index.vue'
import FillSolution from 'components/home/FillSolution/index.vue'
import SetTemperature from 'components/home/SetTemperature/index.vue'
import SelectCraft from 'components/home/selectCraft/index.vue'
import StartHeat from 'components/home/StartHeat/index.vue'
import { ElMessageBox } from 'element-plus'
import { FtMessage } from 'libs/message'
import { socket } from 'libs/socket'
import { useHomeStore } from 'stores/homeStore'
import { useSystemStore } from 'stores/systemStore'
@ -40,7 +43,7 @@ const chartBox = ref(null)
const systemStore = useSystemStore()
const homeStore = useHomeStore()
watch(() => systemStore.menuExpand, () => {
chartBox.value.resize()
chartBox.value?.resize()
})
const colorVisible = ref(false)
@ -51,38 +54,81 @@ const startHeat = (moduleCode: 'MODULE_1' | 'MODULE_2') => {
currentHeatModuleCode.value = moduleCode
heatVisible.value = true
}
const visible = ref(false)
const preFillVisible = ref(false)
const cleanVisible = ref(false)
const drainVisible = ref(false)
const drainWasteVisible = ref(false)
const setTemperatureVisible = ref(false)
const heatModuleCode = ref('MODULE_1')
let currentCommandId = ''
const moveToMODULE_1 = async (item: number) => {
const stopHeat = async (moduleCode: 'MODULE_1' | 'MODULE_2') => {
await ElMessageBox.confirm('是否停止加热?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'tray_move_titration_area',
command: 'heater_stop',
params: {
tubeNum: item,
titrationModuleCode: 'MODULE_1',
heatModuleCode: moduleCode,
},
}
await homeStore.sendControl(params)
}
const heatMoveHandle = async (moduleCode: 'MODULE_1' | 'MODULE_2') => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'heat_move_to_titration_area',
params: {
heatModuleCode: moduleCode,
},
}
await homeStore.sendControl(params)
}
const moveToMODULE_2 = async (item: number) => {
const visible = ref(false)
const preFillVisible = ref(false)
const cleanVisible = ref(false)
const drainVisible = ref(false)
const drainWasteVisible = ref(false)
const selectCraftVisible = ref(false)
const tubeMoveHandle = async (item: number) => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'tray_move_titration_area',
params: {
tubeNum: item,
titrationModuleCode: 'MODULE_2',
},
}
await homeStore.sendControl(params)
}
const addTube = async (item: number) => {
await trayTube([{
tubeNum: item,
tubeExist: true,
}])
FtMessage.success('操作成功')
}
const delTube = async (item: number) => {
await trayTube([{
tubeNum: item,
tubeExist: false,
}])
FtMessage.success('操作成功')
}
const trayList = computed(() => {
return systemStore.systemStatus.trayTubeState
})
const heatList = computed(() => {
return systemStore.systemStatus.heatModuleState
})
const titrationList = computed(() => {
return systemStore.systemStatus.titrationModule
})
onMounted(() => {
socket.init(receiveMessage, 'log')
})
@ -99,21 +145,32 @@ const list = homeStore.logList
div.home-left
div.left-top
el-card
div.tube-box(v-for="item in 16" :key="item" @click="() => { console.log(item) }")
el-popover(placement="right-end" trigger="click" :width="180")
div
ft-button(type="primary" @click="()=>{moveToMODULE_1(item)}") 移动到滴定位1
div(style="text-align: center;margin: 10px;")
ft-button(type="primary" @click="()=>{moveToMODULE_2(item)}") 移动到滴定位2
template(v-slot:reference)
span.serial-number {{item.toString().padStart(2, '0')}}
span 体积: 000000
span 结果: 00.00%
div.tube-box(v-for="item in 16" :key="item" :class="{ 'tube-box-success': trayList.find(tray => tray.tubeNum === item)?.tubeExist }")
el-popover(placement="bottom" :width="100" rigger="click")
template(#default)
div.operation-box
ft-button(type="primary" :click-handle="() => addTube(item)") 放入试管
ft-button(type="primary" :click-handle="() => delTube(item)") 取出试管
//ft-button(type="primary" :click-handle="() => tubeMoveHandle(item)")
ft-button(type="primary" :click-handle="() => tubeMoveHandle(item)") 移至滴定位
template(#reference)
div.tube-item
span.serial-number {{item.toString().padStart(2, '0')}}
span 体积: {{trayList.find(tray => tray.tubeNum === item)?.volume}}
span 结果: {{trayList.find(tray => tray.tubeNum === item)?.result}}
el-card
div.tube-box(v-for="item in 16" :key="item",class="tube-box-success")
span.serial-number {{(item+16).toString().padStart(2, '0')}}
span 体积: 00000
span 结果: 00.00%
div.tube-box(v-for="item in 16" :key="item" :class="{ 'tube-box-success': trayList.find(tray => tray.tubeNum === item+16)?.tubeExist }")
el-popover(placement="bottom" :width="100" rigger="click")
template(#default)
div.operation-box
ft-button(type="primary" :click-handle="() => addTube(item + 16)") 放入试管
//ft-button(type="primary" :click-handle="() => tubeMoveHandle(item + 16)")
ft-button(type="primary" :click-handle="() => tubeMoveHandle(item + 16)") 移至滴定位
template(#reference)
div.tube-item
span.serial-number {{(item+16).toString().padStart(2, '0')}}
span 体积: {{trayList.find(tray => tray.tubeNum === item+16)?.volume}}
span 结果: {{trayList.find(tray => tray.tubeNum === item+16)?.result}}
div.left-bottom
el-card
div.home-chart
@ -136,24 +193,38 @@ const list = homeStore.logList
template(#header)
span 加热位
div.content-box
div.heat-box(:class="{'heat-box-active': true}", @click="startHeat('MODULE_1')")
p.title 加热位1
span.body 32
div.heat-box(:class="{'heat-box-active': true}", @click="startHeat('MODULE_2')")
p.title 加热位2
el-popover(placement="bottom" :width="100" rigger="click")
template(#default)
div.operation-box
ft-button(type="primary" :click-handle="() => startHeat('MODULE_1')") 开始加热
ft-button(type="primary" :click-handle="() => stopHeat('MODULE_1')") 停止加热
ft-button(type="primary" :click-handle="() => heatMoveHandle('MODULE_1')") 移至滴定位
template(#reference)
div.heat-box(:class="{'heat-box-active': heatList.find(heat => heat.moduleCode === 'MODULE_1')?.tubeExist, 'heat-box-heating': heatList.find(heat => heat.moduleCode === 'MODULE_1')?.open}")
p.title 加热位1
span.body 32
el-popover(placement="bottom" :width="100" rigger="click")
template(#default)
div.operation-box
ft-button(type="primary" :click-handle="() => startHeat('MODULE_2')") 开始加热
ft-button(type="primary" :click-handle="() => stopHeat('MODULE_2')") 停止加热
ft-button(type="primary" :click-handle="() => heatMoveHandle('MODULE_2')") 移至滴定位
template(#reference)
div.heat-box(:class="{'heat-box-active': heatList.find(heat => heat.moduleCode === 'MODULE_2')?.tubeExist, 'heat-box-heating': heatList.find(heat => heat.moduleCode === 'MODULE_2')?.open}")
p.title 加热位2
span.body 32
div.right-titration
el-card
template(#header)
span 滴定位
div.content-box
div.titration-box(:class="{'titration-box-active': true}")
div.titration-box(:class="{'titration-box-active': titrationList.find(titration => titration.moduleCode === 'MODULE_1')?.tubeExist}")
p.title 滴定位1
div.titration-box
div.titration-box(:class="{'titration-box-active': titrationList.find(titration => titration.moduleCode === 'MODULE_2')?.tubeExist}")
p.title 滴定位2
div.right-button
ft-button(@click="visible = true") 手动滴定
ft-button 自动滴定
ft-button(@click="selectCraftVisible = true") 自动滴定
ft-button(@click="preFillVisible = true") 预充管路
ft-button(@click="cleanVisible = true") 清洗管路
ft-button(@click="drainVisible = true") 排空管路
@ -163,9 +234,9 @@ const list = homeStore.logList
CleanSolution(:visible="cleanVisible" @close="cleanVisible = false")
DrainSolution(:visible="drainVisible" @close="drainVisible = false")
DrainWasteSolution(:visible="drainWasteVisible" @close="drainWasteVisible = false")
SetTemperature(:visible=" setTemperatureVisible" @close="setTemperatureVisible = false" :heat-module-code="heatModuleCode")
ColorEdit(v-if="colorVisible", @ok=" colorVisible = false", @cancel="colorVisible = false")
StartHeat(:visible="heatVisible" :heat-module-code="currentHeatModuleCode" @ok="heatVisible = false" @close="heatVisible = false")
SelectCraft(:visible="selectCraftVisible" @close="selectCraftVisible = false")
</template>
<style scoped lang="stylus">
@ -210,17 +281,19 @@ const list = homeStore.logList
color #fff !important
.tube-box
font-size 10px
display flex
flex-direction column
justify-content space-between
background #EBEFF4
border-radius: 10px
padding 5px 2px
color #606266
border 2px solid #ffffff
.serial-number
font-size 14px
font-weight 900
transition all .5s
.tube-item
display flex
flex-direction column
justify-content space-between
.serial-number
font-size 14px
font-weight 900
.left-bottom
height calc(50% - 5px)
.el-card
@ -311,6 +384,9 @@ const list = homeStore.logList
display flex
justify-content space-between
align-items center
.heat-box-heating
.body
color red
.heat-box-active, .titration-box-active
background: #12C290 !important
color: #fff !important
@ -326,6 +402,7 @@ const list = homeStore.logList
flex-direction column
justify-content flex-start
align-items center
transition all .5s
.body
margin-top 25 px
font-size 14px
@ -340,4 +417,11 @@ const list = homeStore.logList
font-size 10px
text-align center
background: rgba(0, 38, 77, 0.1)
.operation-box
display flex
flex-direction column
gap 10px
justify-content center
align-items center
</style>
Loading…
Cancel
Save