21 changed files with 691 additions and 81 deletions
-
4.env.test
-
3src/apis/home.ts
-
1src/apis/system.ts
-
12src/app.vue
-
1src/assets/images/empty.svg
-
1src/assets/images/error.svg
-
1src/assets/images/ing.svg
-
1src/assets/images/success.svg
-
1src/assets/images/wait.svg
-
2src/components/common/FTDialog/index.vue
-
176src/components/home/AddLiquid/index.vue
-
9src/components/home/SelectCraft/index.vue
-
15src/components/home/SetTemperature/index.vue
-
65src/components/home/Tube/index.vue
-
2src/layouts/default.vue
-
4src/router/routes.ts
-
26src/stores/homeStore.ts
-
127src/stores/systemStore.ts
-
5src/types/home.d.ts
-
46src/types/system.d.ts
-
270src/views/home/index.vue
@ -0,0 +1,3 @@ |
|||
import http from 'libs/http' |
|||
|
|||
export const setTargetTemperature = (params: Home.SetTargetTemperatureParams): Promise<null> => http.post('/heat/target-temperature', params) |
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="160" height="217" viewBox="0 0 160 217"><defs><clipPath id="master_svg0_701_8873"><rect x="0" y="0" width="160" height="217" rx="0"/></clipPath><linearGradient x1="0.8473145961761475" y1="-0.13048571348190308" x2="-0.21846741185260635" y2="0.45531219158762304" id="master_svg1_701_9703"><stop offset="0%" stop-color="#9CA0FF" stop-opacity="1"/><stop offset="100%" stop-color="#9CCFFF" stop-opacity="1"/></linearGradient><linearGradient x1="1.0152618885040283" y1="0.07957261055707932" x2="0.19026522035783114" y2="1.0885049011631125" id="master_svg2_701_9704"><stop offset="0%" stop-color="#F2F3FF" stop-opacity="1"/><stop offset="100%" stop-color="#F2F9FF" stop-opacity="1"/></linearGradient></defs><g clip-path="url(#master_svg0_701_8873)"><g><rect x="41.62646484375" y="0" width="76.74667358398438" height="42.228694915771484" rx="5" fill="url(#master_svg1_701_9703)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><rect x="0" y="21.1171875" width="160" height="195.88375854492188" rx="5" fill="url(#master_svg2_701_9704)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,94.94093875L51.01304390625,94.94093875C48.43994390625,94.94098875,46.35400390625,92.85729875,46.35400390625,90.28692875C46.35605003625,87.71803875,48.44143390625,85.6366722972,51.01304390625,85.63671875L108.87590390625,85.63671875C111.44750390625,85.6366722972,113.53290390625,87.71803875,113.53490390625,90.28692875C113.53500390625,92.85724875,111.44910390625,94.94098875,108.87600390624999,94.94093875Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,123.71047L51.01304390625,123.71047C48.43994390625,123.71052,46.35400390625,121.62683,46.35400390625,119.05646C46.35605003625,116.48757,48.44143390625,114.4062035472,51.01304390625,114.40625L108.87590390625,114.40625C111.44750390625,114.4062035472,113.53290390625,116.48757,113.53490390625,119.05646C113.53500390625,121.62678,111.44910390625,123.71052,108.87600390624999,123.71047Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,152.48000125L51.01304390625,152.48000125C48.43994390625,152.48000125,46.35400390625,150.39631125,46.35400390625,147.82599125C46.35614304625,145.25715125,48.44143390625,143.17578125,51.01304390625,143.17578125L108.87590390625,143.17578125C111.44750390625,143.17578125,113.53280390625,145.25715125,113.53490390625,147.82599125C113.53500390625,150.39631125,111.44910390625,152.48000125,108.87600390624999,152.48000125Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_685_8859"><rect x="0" y="0" width="80" height="80" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8859)"><g><path d="M39.9853890625,4.94140625C20.7118890625,4.94140625,4.9462890625,20.70700625,4.9462890625,39.98050625C4.9462890625,59.25390625,20.7118890625,75.01950625,39.9853890625,75.01950625C59.2587890625,75.01950625,75.0243890625,59.25390625,75.0243890625,39.98050625C75.0243890625,20.70700625,59.2587890625,4.94140625,39.9853890625,4.94140625ZM56.7274890625,52.05080625C57.8993890625,53.22260625,57.8993890625,55.36330625,56.7274890625,56.52730625C56.1415890625,57.11330625,55.3681890625,57.50390625,54.3915890625,57.50390625C53.6103890625,57.50390625,52.6415890625,57.11330625,52.0556890625,56.52730625L40.7665890625,45.23830625L29.4774890625,56.52730625C28.3056890625,57.69920625,26.1650890625,57.69920625,25.0009890625,56.52730625C23.8368890625,55.35550625,23.8290890625,53.21480625,25.0009890625,52.05080625L36.2900890625,40.76170625L25.0009890625,29.47260625C24.4150890625,28.88670625,24.0243890625,28.11330625,24.0243890625,27.13670625C24.0243890625,26.35550625,24.4150890625,25.38670625,25.0009890625,24.80080625C26.1728890625,23.62890625,28.3134890625,23.62890625,29.4774890625,24.80080625L40.7665890625,36.089806249999995L52.0556890625,24.80080625C52.6415890625,24.21480625,53.4150890625,23.82420625,54.3915890625,23.82420625C55.1728890625,23.82420625,56.1415890625,24.21480625,56.7275890625,24.80080625C57.3134890625,25.38670625,57.7040890625,26.16020625,57.7040890625,27.13670625C57.7040890625,27.91800625,57.3134890625,28.88670625,56.7275890625,29.47260625L45.4384890625,40.76170625L56.7274890625,52.05080625Z" fill="#DF1515" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
1
src/assets/images/ing.svg
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="70" height="70" viewBox="0 0 70 70"><defs><clipPath id="master_svg0_685_8843"><rect x="0" y="0" width="70" height="70" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8843)"><g><path d="M35,70C15.6712,70,0,54.3288,0,35C0,15.6712,15.6712,0,35,0C54.3288,0,70,15.6712,70,35C70,54.3288,54.3288,70,35,70ZM27.195,48.7433C28.6189,50.1676,30.9278,50.1676,32.3517,48.7433L54.4542,26.6408C55.8781,25.2169,55.8781,22.9081,54.4542,21.4842C53.0302,20.0602,50.7215,20.0602,49.2975,21.4842L29.6158,40.8508L20.8075,32.0425C19.3838,30.6166,17.0736,30.6158,15.6488,32.0405C14.2241,33.4653,14.225,35.7755,15.6508,37.1992L27.195,48.7433Z" fill="#14A656" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_685_8855"><rect x="0" y="0" width="80" height="80" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8855)"><g><path d="M40.00636015625,5.01953125C20.68606015625,5.01953125,5.01416254044,20.69143125,5.01416254044,40.01173125C5.01416254044,59.33203125,20.68606015625,74.99613125,40.00636015625,74.99613125C59.32666015625,74.99613125,74.99856015625,59.32423125,74.99856015625,40.00393125C74.99856015625,20.683631249999998,59.32666015625,5.01953125,40.00636015625,5.01953125ZM21.97506015625,45.97263125C18.678260156249998,45.97263125,16.00636015625,43.30073125,16.00636015625,40.00393125C16.00636015625,36.70703125,18.678260156249998,34.03513125,21.97506015625,34.03513125C25.27196015625,34.03513125,27.94386015625,36.70703125,27.94386015625,40.00393125C27.94386015625,43.30073125,25.27196015625,45.97263125,21.97506015625,45.97263125ZM39.92046015625,45.97263125C36.62356015625,45.97263125,33.95166015625,43.30073125,33.95166015625,40.00393125C33.95166015625,36.70703125,36.62356015625,34.03513125,39.92046015625,34.03513125C43.21726015625,34.03513125,45.88916015625,36.70703125,45.88916015625,40.00393125C45.88916015625,43.30073125,43.21726015625,45.97263125,39.92046015625,45.97263125ZM57.86576015625,45.97263125C54.56886015625,45.97263125,51.89696015625,43.30073125,51.89696015625,40.00393125C51.89696015625,36.70703125,54.56886015625,34.03513125,57.86576015625,34.03513125C61.16256015625,34.03513125,63.83446015625,36.70703125,63.83446015625,40.00393125C63.83446015625,43.30073125,61.16256015625,45.97263125,57.86576015625,45.97263125Z" fill="#EE8223" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
@ -0,0 +1,176 @@ |
|||
<script setup lang="ts"> |
|||
import { getSolsList } from 'apis/solution' |
|||
import emptyIcon from 'assets/images/empty.svg' |
|||
import { FtMessage } from 'libs/message' |
|||
import { useHomeStore } from 'stores/homeStore' |
|||
import { onMounted, ref } from 'vue' |
|||
|
|||
const emits = defineEmits(['ok', 'cancel']) |
|||
|
|||
const homeStore = useHomeStore() |
|||
|
|||
onMounted(() => { |
|||
getSols() |
|||
}) |
|||
|
|||
const form = ref<{ |
|||
tubeNum: number |
|||
solutionId: number |
|||
volume: number |
|||
}>({}) |
|||
const formRef = ref() |
|||
|
|||
const rules = { |
|||
tubeNum: [ |
|||
{ required: true, message: '请选择试管', trigger: 'change' }, |
|||
], |
|||
solutionId: [ |
|||
{ required: true, message: '请选择溶液', trigger: 'change' }, |
|||
], |
|||
volume: [ |
|||
{ required: true, message: '请输入容量', trigger: 'blur' }, |
|||
], |
|||
} |
|||
|
|||
const addList = ref<{ tubeNum: number, solutionList: { solutionId: number, volume: number }[] }[]>([]) |
|||
|
|||
const mergeAddList = () => { |
|||
const map = new Map<number, { solutionId: number, volume: number }[]>() |
|||
|
|||
addList.value.forEach((item) => { |
|||
if (!map.has(item.tubeNum)) { |
|||
map.set(item.tubeNum, [...item.solutionList]) |
|||
} |
|||
else { |
|||
map.get(item.tubeNum)!.push(...item.solutionList) |
|||
} |
|||
}) |
|||
|
|||
return Array.from(map.entries()).map(([tubeNum, solutionList]) => ({ |
|||
tubeNum, |
|||
solutionList, |
|||
})) |
|||
} |
|||
|
|||
const addHandle = async () => { |
|||
try { |
|||
const valid = await formRef.value.validate() |
|||
if (!valid) { |
|||
return |
|||
} |
|||
addList.value!.push({ |
|||
tubeNum: form.value.tubeNum, |
|||
solutionList: [{ |
|||
solutionId: form.value.solutionId, |
|||
volume: form.value.volume, |
|||
}], |
|||
}) |
|||
} |
|||
catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
const okHandle = async () => { |
|||
if (!addList.value.length) { |
|||
FtMessage.error('请为试管添加溶液') |
|||
return |
|||
} |
|||
console.log(mergeAddList()) |
|||
|
|||
const params = { |
|||
commandId: Date.now().toString(), |
|||
command: 'solution_add', |
|||
params: { |
|||
dataList: mergeAddList(), |
|||
}, |
|||
} |
|||
await homeStore.sendControl(params) |
|||
// await debugStore.sendControl(params) |
|||
emits('ok') |
|||
} |
|||
const cancel = () => { |
|||
emits('cancel') |
|||
} |
|||
|
|||
const solsList = ref<Solution.SolutionItem[]>([]) |
|||
|
|||
const getSols = async () => { |
|||
const res = await getSolsList() |
|||
solsList.value = res.list |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<FtDialog visible title="添加溶液" width="60%" :ok-handle="okHandle" @cancel="cancel"> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto"> |
|||
<el-form-item label="选择试管" prop="tubeNum"> |
|||
<el-select v-model="form.tubeNum" placeholder="请选择试管"> |
|||
<el-option v-for="item in 16" :key="item" :label="`试管${item}`" :value="item" /> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="选择溶液" prop="solutionId"> |
|||
<el-select v-model="form.solutionId" placeholder="请选择溶液"> |
|||
<el-option v-for="item in solsList" :key="item.id" :label="item.name" :value="item.id" /> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="容量" prop="volume"> |
|||
<el-input v-model="form.volume" placeholder="请输入容量"> |
|||
<template #append> |
|||
ml |
|||
</template> |
|||
</el-input> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<div style="width: 100%;display: flex;justify-content: center"> |
|||
<ft-button type="primary" @click="addHandle"> |
|||
添加 |
|||
</ft-button> |
|||
</div> |
|||
</el-form-item> |
|||
</el-form> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<template v-if="addList.length"> |
|||
<el-tag v-for="(item, key) in addList" :key> |
|||
<div> |
|||
<span>试管{{ item.tubeNum }}</span> |
|||
<span>-</span> |
|||
<span>{{ solsList.find(i => i.id === item.solutionList[0].solutionId)!.name }}</span> |
|||
<span>添加{{ item.solutionList[0].volume }}ml</span> |
|||
</div> |
|||
<el-icon><Close /></el-icon> |
|||
</el-tag> |
|||
</template> |
|||
<div v-else style="width: 100%;height: 100%;display: flex; flex-direction: column;justify-content: center;align-items: center;color: #C6C6C6"> |
|||
<img :src="emptyIcon" alt="" style="width: 80px;margin-bottom: 10px"> |
|||
暂无添加 |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
</FtDialog> |
|||
</template> |
|||
|
|||
<style scoped lang="scss"> |
|||
.el-tag { |
|||
margin-right: 5px; |
|||
} |
|||
.el-row { |
|||
height: 200px; |
|||
.el-col { |
|||
height: 100%; |
|||
overflow: auto; |
|||
:deep(.el-tag) { |
|||
width: 100%; |
|||
margin-bottom: 5px; |
|||
.el-tag__content { |
|||
display: flex; |
|||
width: 100%; |
|||
justify-content: space-between; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue