Browse Source

实验操作界面

master
王梦远 1 week ago
parent
commit
aa7019a06c
  1. 2
      src/apis/point.ts
  2. 128
      src/components/home/AddLiquid/index.vue
  3. 120
      src/components/home/CleanSolution/index.vue
  4. 120
      src/components/home/DrainSolution/index.vue
  5. 54
      src/components/home/DrainWasteSolution/index.vue
  6. 63
      src/components/home/FillSolution/index.vue
  7. 106
      src/components/home/SetTemperature/index.vue
  8. 99
      src/views/home/index.vue

2
src/apis/point.ts

@ -1,4 +1,4 @@
import http from 'libs/http'
export const getPointList = (): Promise<Point.Point[]> => http.get('/device-point/list')
export const getPointList = (): Promise<Point.Point[]> => http.post('/position/list')
export const updatePoint = (params: Point.UpdateParams): Promise<null> => http.put('/device-point', params)

128
src/components/home/AddLiquid/index.vue

@ -1,4 +1,9 @@
<script setup lang="ts">
import { getSolsList } from 'apis/solution'
import { useHomeStore } from 'stores/homeStore'
import { useSolutionStore } from 'stores/useSolutionStore'
import { onMounted, ref } from 'vue'
defineProps({
visible: {
type: Boolean,
@ -6,12 +11,108 @@ defineProps({
},
})
const emits = defineEmits(['close'])
const homeStore = useHomeStore()
const activeTab = ref(1)
const close = () => {
emits('close')
}
let currentCommandId = ''
const moveHeat = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'titration_move_to_heat_area',
params: {
heatModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
},
}
await homeStore.sendControl(params)
}
const moveTray = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'titration_move_tray_area',
params: {
tubeNum: 1, // todo
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
},
}
await homeStore.sendControl(params)
}
const addMagnet = async () => { // todo
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_drain_start',
params: {
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
},
}
await homeStore.sendControl(params)
}
const addSolution = async () => { // todo
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_add_start',
params: {
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
solutionId: solutionId.value,
volume: solutionVolume.value,
},
}
await homeStore.sendControl(params)
}
const shakeStart = async () => { // todo
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'shake_start',
params: {
speed: shakeSpeed.value,
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
time: shakeTime.value,
},
}
await homeStore.sendControl(params)
}
const shakeStop = async () => { // todo
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'shake_stop',
params: {
titrationModuleCode: activeTab.value === 1 ? 'MODULE_1' : 'MODULE_2',
},
}
await homeStore.sendControl(params)
}
const shakeSpeed = ref(30)
const shakeTime = ref(10)
const solutionList = ref<Solution.SolutionItem[]>([])
const solutionMap = ref<Record<string | number, string>>({})
const solutionStore = useSolutionStore()
const solutionId = ref()
const solutionVolume = ref()
const querySolutionList = async () => {
const res = await getSolsList()
if (res && res.list) {
solutionList.value = res.list
solutionList.value.forEach((item) => {
if (item.id) {
solutionMap.value[item.id] = item.name
}
})
solutionStore.updateSolution(res.list)
}
}
onMounted(() => {
querySolutionList()
})
</script>
<template lang="pug">
@ -25,31 +126,36 @@ const close = () => {
Close
div.body
div.button-box
ft-button
ft-button(@click="moveHeat")
| 移至加热
ft-button
ft-button(@click="moveTray")
| 移至托盘
ft-button
ft-button(@click="addMagnet")
| 加入磁子
div.form-box
span
| 选择溶液
el-select
el-input
el-select(v-model="solutionId")
el-option( v-for="item in solutionList" :key="item.id" :label="solutionMap[item.id]" :value="item.id")
el-input(placeholder="加液量" v-model="solutionVolume")
template(#append)
el-select
ft-button
el-select(v-model="solutionVolume")
el-option(value="1" label="1ml")
el-option(value="2" label="2ml")
el-option(value="5" label="5ml")
el-option(value="0.2" label="1滴")
ft-button(@click="addSolution")
| 添加
div.form-box
span
| 搅拌设置
el-input(placeholder="搅拌速度" )
el-input(placeholder="搅拌速度" v-model="shakeSpeed" )
template(#append)
| ms
el-input(placeholder="搅拌时间" )
el-input(placeholder="搅拌时间" v-model="shakeTime")
template(#append)
| s
ft-button
ft-button(@click="shakeStart")
| 开始
</template>

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

@ -0,0 +1,120 @@
<script setup lang="ts">
import { getSolsList } from 'apis/solution'
import { FtMessage } from 'libs/message'
import { useHomeStore } from 'stores/homeStore'
import { useSolutionStore } from 'stores/useSolutionStore'
import { onMounted, ref } from 'vue'
const emits = defineEmits(['ok', 'close'])
const homeStore = useHomeStore()
let currentCommandId = ''
onMounted(() => {
querySolutionList()
})
const cancel = async () => {
currentCommandId = Date.now().toString()
// const params = {
// commandId: currentCommandId,
// command: 'liquid_motor_origin',
// params: {},
// }
// await homeStore.sendControl(params)
emits('close')
}
const solutionList = ref<Solution.SolutionItem[]>([])
const solutionMap = ref<Record<string | number, string>>({})
const solutionStore = useSolutionStore()
const querySolutionList = async () => {
const res = await getSolsList()
if (res && res.list) {
solutionList.value = res.list
solutionList.value.forEach((item) => {
if (item.id) {
solutionMap.value[item.id] = item.name
}
})
solutionStore.updateSolution(res.list)
}
}
const clean_solution_start = async () => {
if (!checked.value) {
FtMessage.warning('请选择清洗的管道')
return
}
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_clean_start',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
}
const clean_solution_stop = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_clean_stop',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
}
const titrationModuleCode = ref<string>('')
const checked = ref<number>()
</script>
<template>
<FtDialog visible title="清洗管路" width="50%" :show-close="true" @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" />
</el-radio-group>
</div>
<template #footer>
<ft-button type="primary" :click-handle="clean_solution_start">
开始清洗
</ft-button>
<ft-button type="default" :click-handle="clean_solution_stop">
停止清洗
</ft-button>
</template>
</FtDialog>
</template>
<style scoped lang="scss">
.module-box {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px;
}
.item-box {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px;
}
.el-checkbox {
margin: 10px 5px;
min-width: 100px;
}
.button-box {
margin-top: 10px;
display: flex;
justify-content: center;
}
</style>

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

@ -0,0 +1,120 @@
<script setup lang="ts">
import { getSolsList } from 'apis/solution'
import { FtMessage } from 'libs/message'
import { useHomeStore } from 'stores/homeStore'
import { useSolutionStore } from 'stores/useSolutionStore'
import { onMounted, ref } from 'vue'
const emits = defineEmits(['ok', 'close'])
const homeStore = useHomeStore()
let currentCommandId = ''
onMounted(() => {
querySolutionList()
})
const cancel = async () => {
currentCommandId = Date.now().toString()
// const params = {
// commandId: currentCommandId,
// command: 'liquid_motor_origin',
// params: {},
// }
// await homeStore.sendControl(params)
emits('close')
}
const solutionList = ref<Solution.SolutionItem[]>([])
const solutionMap = ref<Record<string | number, string>>({})
const solutionStore = useSolutionStore()
const querySolutionList = async () => {
const res = await getSolsList()
if (res && res.list) {
solutionList.value = res.list
solutionList.value.forEach((item) => {
if (item.id) {
solutionMap.value[item.id] = item.name
}
})
solutionStore.updateSolution(res.list)
}
}
const filled_solution_start = async () => {
if (!checked.value) {
FtMessage.warning('请选择要排空的管道')
return
}
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_drain_start',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
}
const filled_solution_stop = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_drain_stop',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
}
const titrationModuleCode = ref<string>('')
const checked = ref<number>()
</script>
<template>
<FtDialog visible title="排空管路" width="50%" :show-close="true" @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" />
</el-radio-group>
</div>
<template #footer>
<ft-button type="primary" :click-handle="filled_solution_start">
开始排空
</ft-button>
<ft-button type="default" :click-handle="filled_solution_stop">
停止排空
</ft-button>
</template>
</FtDialog>
</template>
<style scoped lang="scss">
.module-box {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px;
}
.item-box {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px;
}
.el-checkbox {
margin: 10px 5px;
min-width: 100px;
}
.button-box {
margin-top: 10px;
display: flex;
justify-content: center;
}
</style>

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

@ -0,0 +1,54 @@
<script setup lang="ts">
import { getSolsList } from 'apis/solution'
import { FtMessage } from 'libs/message'
import { useHomeStore } from 'stores/homeStore'
import { useSolutionStore } from 'stores/useSolutionStore'
import { onMounted, ref } from 'vue'
const emits = defineEmits(['ok', 'close'])
const homeStore = useHomeStore()
let currentCommandId = ''
onMounted(() => {
})
const cancel = async () => {
emits('close')
}
const drain_waste_solution_start = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_waste_drain_start',
params: {
},
}
await homeStore.sendControl(params)
}
const drain_waste_solution_stop = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'solution_waste_drain_stop',
params: {
},
}
await homeStore.sendControl(params)
}
</script>
<template>
<FtDialog visible title="抽取废液" width="50%" :show-close="true" @cancel="cancel">
<template #footer>
<ft-button type="primary" :click-handle="drain_waste_solution_start">
开始抽液
</ft-button>
<ft-button type="default" :click-handle="drain_waste_solution_stop">
停止抽液
</ft-button>
</template>
</FtDialog>
</template>
<style scoped lang="scss">
</style>

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

@ -1,36 +1,26 @@
<script setup lang="ts">
import { getContainerList } from 'apis/container'
import { getSolsList } from 'apis/solution'
import { FtMessage } from 'libs/message'
import { useHomeStore } from 'stores/homeStore'
import { useSolutionStore } from 'stores/useSolutionStore'
import { onMounted, ref } from 'vue'
const emits = defineEmits(['ok', 'cancel'])
const emits = defineEmits(['ok', 'close'])
const homeStore = useHomeStore()
let currentCommandId = ''
onMounted(() => {
queryContainerList()
querySolutionList()
})
const containerList = ref<Container.ContainerItem[]>([])
const queryContainerList = async () => {
const res = await getContainerList()
containerList.value = res.filter(item => item.type === 0)
}
const cancel = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'liquid_motor_origin',
params: {},
}
await homeStore.sendControl(params)
emits('cancel')
// const params = {
// commandId: currentCommandId,
// command: 'liquid_motor_origin',
// params: {},
// }
// await homeStore.sendControl(params)
emits('close')
}
const solutionList = ref<Solution.SolutionItem[]>([])
@ -57,9 +47,10 @@ const filled_solution_start = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'liquid_pre_fill_start',
command: 'solution_pre_fill_start',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
@ -69,36 +60,48 @@ const filled_solution_stop = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'liquid_pre_fill_stop',
params: {},
command: 'solution_pre_fill_stop',
params: {
solutionId: checked.value,
titrationModuleCode: titrationModuleCode.value,
},
}
await homeStore.sendControl(params)
}
const titrationModuleCode = ref<string>('')
const checked = ref<number>()
</script>
<template>
<FtDialog visible title="预充管路" width="50%">
<el-radio-group v-model="checked">
<el-radio v-for="item in containerList" :key="item.id" border :label="solutionMap[item.solutionId]" :value="item.id" />
</el-radio-group>
<FtDialog visible title="预充管路" width="50%" :show-close="true" @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" />
</el-radio-group>
</div>
<template #footer>
<ft-button type="primary" :click-handle="filled_solution_start">
开始预充
</ft-button>
<ft-button type="primary" :click-handle="filled_solution_stop">
<ft-button type="default" :click-handle="filled_solution_stop">
停止预充
</ft-button>
<ft-button :click-handle="cancel">
完成预充
</ft-button>
</template>
</FtDialog>
</template>
<style scoped lang="scss">
.module-box {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px;
}
.item-box {
display: flex;
align-items: center;

106
src/components/home/SetTemperature/index.vue

@ -0,0 +1,106 @@
<script setup lang="ts">
import { configList } from 'apis/system'
import { FtMessage } from 'libs/message'
import { useHomeStore } from 'stores/homeStore'
import { useSystemStore } from 'stores/systemStore'
import { computed, onMounted, ref } from 'vue'
const props = defineProps({
heatModuleCode: {
type: String,
required: true,
},
})
const emits = defineEmits(['ok', 'cancel'])
const homeStore = useHomeStore()
const configData = ref<any[]>([])
onMounted(async () => {
configData.value = await configList()
})
const heatMax = computed(() => {
return configData.value.find(item => item.code === 'heat_temperature')?.value || 100
})
const heatModule = computed(() => {
return useSystemStore().systemStatus.heatModule.find(item => item.moduleCode === props.heatModuleCode)
})
const form = ref({
heatTemperature: heatModule.value?.heatTemperature,
})
const formRef = ref()
const validateHandle = (rule: any, value: any, callback: any) => {
if (value && (value < 0 || +value > +heatMax.value)) {
callback(new Error(`加热温度设置范围0℃-${heatMax.value}`))
}
else {
callback()
}
}
const rules = {
heatTemperature: [
{ required: false, trigger: 'blur', validator: validateHandle },
],
}
let currentCommandId = ''
const heatStart = async () => {
const valid = await formRef.value.validate()
if (!valid) {
return
}
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'heater_start',
params: {
heatModuleCode: props.heatModuleCode,
temperature: form.value.heatTemperature,
},
}
await homeStore.sendControl(params)
}
const heatStop = async () => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'heater_stop',
params: {
heatModuleCode: props.heatModuleCode,
},
}
await homeStore.sendControl(params)
}
const cancel = () => {
emits('cancel')
}
</script>
<template>
<FtDialog visible :title="`${props.heatModuleCode === 'MODULE_1' ? '加热区1' : '加热区2'}设置目标温度`" width="40%" :show-close="true" @cancel="cancel">
<el-form ref="formRef" label-width="auto" :model="form" :rules="rules">
<el-form-item label="加热温度" prop="heatTemperature">
<el-input v-model="form.heatTemperature" type="number" placeholder="请输入加热温度">
<template #append>
</template>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button type="primary" @click="heatStart">
开始加热
</el-button>
<el-button @click="heatStop">
停止加热
</el-button>
</template>
</FtDialog>
</template>
<style scoped lang="scss">
.el-tag {
margin-right: 5px;
}
</style>

99
src/views/home/index.vue

@ -1,11 +1,14 @@
<script setup lang="ts">
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 StartHeat from 'components/home/StartHeat/index.vue'
import { ElMessageBox } from 'element-plus'
import { useHomeStore } from 'stores/homeStore'
import { useSystemStore } from 'stores/systemStore'
import { watch } from 'vue'
import { ref, watch } from 'vue'
const option = ref({
grid: {
@ -44,45 +47,54 @@ const list = [
]
const homeStore = useHomeStore()
let currentCommandId = ''
const chartBox = ref(null)
const systemStore = useSystemStore()
const homeStore = useHomeStore()
watch(() => systemStore.menuExpand, () => {
chartBox.value.resize()
})
const addLiquidVisible = ref(false)
const colorVisible = ref(false)
const heatVisible = ref(false)
const currentHeatModuleCode = ref('MODULE_1')
const startHeat = async (moduleCode: 'MODULE_1' | 'MODULE_2') => {
// TODO
if (false) {
await ElMessageBox.confirm('确定停止加热?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'heater_stop',
params: {
heatModuleCode: moduleCode,
},
}
await homeStore.sendControl(params)
return
}
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) => {
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'tray_move_titration_area',
params: {
tubeNum: item,
titrationModuleCode: 'MODULE_1',
},
}
await homeStore.sendControl(params)
}
const moveToMODULE_2 = 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)
}
</script>
<template lang="pug">
@ -92,10 +104,16 @@ const startHeat = async (moduleCode: 'MODULE_1' | 'MODULE_2') => {
div.home-left
div.left-top
el-card
div.tube-box(v-for="item in 16" :key="item")
span.serial-number {{item.toString().padStart(2, '0')}}
span 体积: 000000
span 结果: 00.00%
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%
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')}}
@ -138,12 +156,19 @@ const startHeat = async (moduleCode: 'MODULE_1' | 'MODULE_2') => {
div.titration-box
p.title 滴定位2
div.right-button
ft-button.full-width(@click="addLiquidVisible = true") 手动滴定
ft-button 预充管路
ft-button(@click="visible = true") 手动滴定
ft-button 自动滴定
ft-button 清洗管路
ft-button 排空管路
AddLiquid(:visible="addLiquidVisible" @close="addLiquidVisible = false")
ft-button(@click="preFillVisible = true") 预充管路
ft-button(@click="cleanVisible = true") 清洗管路
ft-button(@click="drainVisible = true") 排空管路
ft-button(@click="drainWasteVisible = true") 抽取废液
AddLiquid(:visible="visible" @close="visible = false")
FillSolution(:visible="preFillVisible" @close="preFillVisible = false")
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")
</template>

Loading…
Cancel
Save