feat 方案模板 基本信息及补料泵修改

This commit is contained in:
Asoka.Wang 2025-06-18 15:02:33 +08:00
parent acd9fcf076
commit c3f7f719b7
7 changed files with 354 additions and 109 deletions

View File

@ -1,4 +1,4 @@
import { ReactorPageInput, ReactorPageResponse, ReactorOutput, ReactorAddInput, ReactorUpdateInput, ReactorTypeEnumListOutput } from '/@/api/types/reactorType' import { ReactorPageInput, ReactorPageResponse, ReactorOutput, ReactorAddInput, ReactorUpdateInput, ReactorTypeEnumListOutput, ReactorListResponse } from '/@/api/types/reactorType'
import { RequestParams } from './http-client' import { RequestParams } from './http-client'
import { ContentType, HttpClient } from './http-client' import { ContentType, HttpClient } from './http-client'
@ -15,6 +15,13 @@ export class ReactorApi extends HttpClient {
...params, ...params,
}) })
getList = (params: RequestParams = {}) =>
this.request<ReactorListResponse>({
path: `/api/admin/equ-reactor/get-list`,
method: 'GET',
...params,
})
/** /**
* *
*/ */

View File

@ -81,6 +81,25 @@ export interface ReactorDto {
isExternalPump?: boolean isExternalPump?: boolean
} }
export interface ReactorDtoWithList extends ReactorDto {
pump1Speed?: number
pump2Speed?: number
pump3Speed?: number
pump4Speed?: number
pump5Speed?: number
pump6Speed?: number
pump7Speed?: number
pump8Speed?: number
pump1ConfigId?: number
pump2ConfigId?: number
pump3ConfigId?: number
pump4ConfigId?: number
pump5ConfigId?: number
pump6ConfigId?: number
pump7ConfigId?: number
pump8ConfigId?: number
}
/** 反应器添加和更新输入接口 */ /** 反应器添加和更新输入接口 */
export interface ReactorAddInputAndUpdateInput { export interface ReactorAddInputAndUpdateInput {
/** 设备编号 */ /** 设备编号 */
@ -191,6 +210,7 @@ export const defaultPumpConfig: PumpConfig = {
// API 类型定义 // API 类型定义
export type ReactorPageInput = ServiceRequestPage<ReactorFilter>; export type ReactorPageInput = ServiceRequestPage<ReactorFilter>;
export type ReactorPageResponse = ServiceResponse<PageResponse<ReactorDto>>; export type ReactorPageResponse = ServiceResponse<PageResponse<ReactorDto>>;
export type ReactorListResponse = ServiceResponse<ReactorDtoWithList[]>;
export type ReactorOutput = ServiceResponse<ReactorDto[]>; export type ReactorOutput = ServiceResponse<ReactorDto[]>;
export type ReactorAddInput = ReactorDto; export type ReactorAddInput = ReactorDto;
export type ReactorUpdateInput = ReactorDto; export type ReactorUpdateInput = ReactorDto;

View File

@ -46,7 +46,9 @@ export interface CultureProtocolPageDto {
/** 是否启用 */ /** 是否启用 */
enabled: boolean enabled: boolean
/** 创建时间 */ /** 创建时间 */
createdTime: string createdTime: string,
/** 补料任务数量 */
feedingTaskCount: number
} }
export interface CultureProtocolDto { export interface CultureProtocolDto {
@ -136,6 +138,12 @@ export interface FixedFeedingPump {
itemDefFeedingMediumID?: number itemDefFeedingMediumID?: number
/** 设备泵ID */ /** 设备泵ID */
equPumpId?: number equPumpId?: number
/** 补料泵名称 */
feedingPumpName?: string
/** 量程(g/min) */
pumpSpeed?: number
/** 是否是糖补料 */
isGlucose?: boolean
} }
export type CultureProtocolPageInput = ServiceRequestPage<CultureProtocolFilter> export type CultureProtocolPageInput = ServiceRequestPage<CultureProtocolFilter>

View File

@ -68,7 +68,7 @@ import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { ReactorEPSettingApi } from '/@/api/admin/ReactorEPSettingApi' import { ReactorEPSettingApi } from '/@/api/admin/ReactorEPSettingApi'
import { ReactorEPSetting } from '/@/api/types/reactorEPSetting' import { ReactorEPSetting } from '/@/api/types/reactorEPSetting'
import { ReactorDto } from '/@/api/types/ReactorType' import { ReactorDto } from '/@/api/types/reactorType'
defineOptions({ name: 'AlarmSettingForm' }) defineOptions({ name: 'AlarmSettingForm' })

View File

@ -90,7 +90,7 @@ import type {
ReactorPageInput, ReactorPageInput,
ReactorDto, ReactorDto,
ReactorTypeEnumItem ReactorTypeEnumItem
} from '/@/api/types/ReactorType' } from '/@/api/types/reactorType'
const AlarmSettingForm = defineAsyncComponent(() => import('./components/alarm-setting-form.vue')) const AlarmSettingForm = defineAsyncComponent(() => import('./components/alarm-setting-form.vue'))
const ReactorForm = defineAsyncComponent(() => import('./components/reactor-form.vue')) const ReactorForm = defineAsyncComponent(() => import('./components/reactor-form.vue'))

View File

@ -1,17 +1,26 @@
<template> <template>
<div> <div>
<el-dialog v-model="state.showDialog" destroy-on-close :title="title" draggable :close-on-click-modal="false" <el-dialog v-model="state.showDialog" destroy-on-close :title="title" draggable :close-on-click-modal="false"
:close-on-press-escape="false" width="65%" append-to-body> :close-on-press-escape="false" width="75%" append-to-body>
<el-form :model="form" ref="formRef" size="default" label-width="120px"> <el-form :model="form" ref="formRef" size="default" label-width="130px">
<el-tabs v-model="state.activeTab"> <el-tabs @tab-click="handleTabClick" v-model="activeTab">
<!-- 基本信息 --> <!-- 基本信息 -->
<el-tab-pane label="基本信息" name="basic"> <el-tab-pane label="基本信息" name="basic">
<div class="form-section"> <div class="form-section">
<el-row :gutter="25"> <el-row :gutter="25">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="方案名称" prop="cultureProtocolName" <el-form-item label="模板名称" prop="cultureProtocolName"
:rules="[{ required: true, message: '请输入方案名称', trigger: ['blur', 'change'] }]"> :rules="[{ required: true, message: '请输入模板名称', trigger: ['blur', 'change'] }]">
<el-input v-model="form.cultureProtocolName" clearable placeholder="请输入方案名称" /> <el-input v-model="form.cultureProtocolName" clearable placeholder="请输入模板名称" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="反应器" prop="equReactorId"
:rules="[{ required: true, message: '请选择反应器', trigger: ['blur', 'change'] }]">
<el-select v-model="form.equReactorId" filterable placeholder="请选择反应器" style="width: 100%">
<el-option v-for="item in state.reactorOptions" :key="item.id"
:label="item.name + ' (' + item.spec + ')'" :value="item.id" />
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
@ -21,39 +30,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="反应器" prop="equReactorId" <el-form-item label="补糖时计算补料引起的糖浓度变化">
:rules="[{ required: true, message: '请选择反应器', trigger: ['blur', 'change'] }]">
<el-select v-model="form.equReactorId" placeholder="请选择反应器" style="width: 100%">
<el-option v-for="item in state.reactorOptions" :key="item.id" :label="item.name"
:value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="补料秤" prop="equFeedingScaleId"
:rules="[{ required: true, message: '请选择补料秤', trigger: ['blur', 'change'] }]">
<el-select v-model="form.equFeedingScaleId" placeholder="请选择补料秤" style="width: 100%">
<el-option v-for="item in state.scaleOptions" :key="item.id" :label="item.name"
:value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="初始工作体积" prop="initialWorkingVolume"
:rules="[{ required: true, message: '请输入初始工作体积', trigger: ['blur', 'change'] }]">
<el-input-number v-model="form.initialWorkingVolume" :min="0" :precision="2" style="width: 100%"
placeholder="请输入初始工作体积" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="转种细胞体积" prop="transferCellVolume"
:rules="[{ required: true, message: '请输入转种细胞体积', trigger: ['blur', 'change'] }]">
<el-input-number v-model="form.transferCellVolume" :min="0" :precision="2" style="width: 100%"
placeholder="请输入转种细胞体积" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="葡萄糖补料验证">
<el-switch v-model="form.glucoseFeedingVerification" active-text="是" inactive-text="否" /> <el-switch v-model="form.glucoseFeedingVerification" active-text="是" inactive-text="否" />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -70,52 +47,62 @@
<el-tab-pane label="固定补料泵" name="pumps"> <el-tab-pane label="固定补料泵" name="pumps">
<div class="form-section"> <div class="form-section">
<el-table :data="form.fixedFeedingPumps" border style="width: 100%"> <el-table :data="form.fixedFeedingPumps" border style="width: 100%">
<el-table-column label="补料泵编号" prop="feedingPumpNo" width="120"> <el-table-column label="序号" prop="feedingPumpNo" width="70">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.feedingPumpNo" disabled /> <el-input v-model="scope.row.feedingPumpNo" disabled />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
<el-table-column label="泵名称" prop="feedingPumpName" width="150">
<template #default="scope">
<el-input v-model="scope.row.feedingPumpName" disabled />
</template>
</el-table-column>
<el-table-column
v-if="state.form.equReactorId && state.reactorOptions.find(r => r.id === state.form.equReactorId)?.needExternalPump === true" v-if="state.form.equReactorId && state.reactorOptions.find(r => r.id === state.form.equReactorId)?.needExternalPump === true"
label="外置泵" label="外置泵" prop="equPumpId" min-width="100">
prop="equPumpId"
min-width="200"
>
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.equPumpId" placeholder="请选择外置泵" style="width: 100%"> <el-select v-model="scope.row.equPumpId" placeholder="请选择外置泵" style="width: 100%" filterable
<el-option @change="() => handlePumpChange(scope.$index)">
v-for="item in state.pumpOptions" <el-option v-for="item in state.pumpOptions" :key="item.id" :label="item.name" :value="item.id" />
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="物料定义袋" prop="itemDefBagID" min-width="200"> <el-table-column label="量程(g/min)" prop="pumpSpeed" width="120">
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.itemDefBagID" placeholder="请选择物料定义袋" style="width: 100%"> <el-input v-model="scope.row.pumpSpeed" disabled />
<el-option
v-for="item in state.bagOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="补料培养基" prop="itemDefFeedingMediumID" min-width="200"> <el-table-column label="补料培养基" prop="itemDefFeedingMediumID" min-width="200">
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.itemDefFeedingMediumID" placeholder="请选择补料培养基" style="width: 100%"> <el-select v-model="scope.row.itemDefFeedingMediumID" placeholder="请选择补料培养基" filterable
<el-option @change="() => handleMediumChange(scope.$index)" style="width: 100%">
v-for="item in state.mediumOptions" <el-option v-for="item in state.mediumOptions" :key="item.id"
:key="item.id" :label="item.name + ' (' + item.glucoseConc + 'g/L)' + (item.isGlucose ? ' (糖补料)' : '')"
:label="item.name" :value="item.id" />
:value="item.id"
/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="耗材" prop="itemDefBagID" min-width="200">
<template #default="scope">
<el-select v-model="scope.row.itemDefBagID" placeholder="请选择耗材" style="width: 100%">
<el-option v-for="item in state.bagOptions" :key="item.id"
:label="item.name + ' (下限体积: ' + item.lowerLimitVolume + 'g)'" :value="item.id" />
</el-select>
</template>
</el-table-column>
<el-table-column label="泵速策略" prop="configId" min-width="200">
<template #default="scope">
<el-select v-model="scope.row.configId" placeholder="请选择泵速策略" style="width: 100%">
<el-option v-for="item in state.configOptions" :key="item.id"
:label="item.name + (item.isTwo === 1 ? ' (二段式)' : ' (三段式)')" :value="item.id" />
</el-select>
</template>
</el-table-column>
</el-table> </el-table>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -209,14 +196,16 @@
</template> </template>
<script lang="ts" setup name="admin/culture-protocol/form"> <script lang="ts" setup name="admin/culture-protocol/form">
import { reactive, toRefs, ref, getCurrentInstance, onMounted } from 'vue' import { reactive, toRefs, ref, getCurrentInstance, onMounted, watch, computed, nextTick } from 'vue'
import { CultureProtocolApi } from '/@/api/admin/CultureProtocolApi' import { CultureProtocolApi } from '/@/api/admin/CultureProtocolApi'
import { ReactorApi } from '/@/api/admin/ReactorApi' import { ReactorApi } from '/@/api/admin/ReactorApi'
import { UspscaleApi } from '/@/api/admin/UspscaleApi' import { UspscaleApi } from '/@/api/admin/UspscaleApi'
import { ItemDefFeedingMediumApi } from '/@/api/admin/item-def-feeding-medium' import { ItemDefFeedingMediumApi } from '/@/api/admin/item-def-feeding-medium'
import { ItemDefBagApi } from '/@/api/admin/item-def-bag' import { ItemDefBagApi } from '/@/api/admin/item-def-bag'
import { PumpApi } from '/@/api/admin/PumpApi'
import { UspFeedingConfigApi } from '/@/api/admin/UspFeedingConfigApi'
import type { CultureProtocolDto } from '/@/api/types/cultureprotocol' import type { CultureProtocolDto } from '/@/api/types/cultureprotocol'
import { ElMessageBox, ElMessage } from 'element-plus'
const { proxy } = getCurrentInstance() as any const { proxy } = getCurrentInstance() as any
defineProps({ defineProps({
@ -234,7 +223,6 @@ const formRef = ref()
const state = reactive({ const state = reactive({
showDialog: false, showDialog: false,
sureLoading: false, sureLoading: false,
activeTab: 'basic',
form: { form: {
id: 0, id: 0,
cultureProtocolName: '', cultureProtocolName: '',
@ -252,21 +240,76 @@ const state = reactive({
feedingTasks: [], feedingTasks: [],
fixedFeedingPumps: [] fixedFeedingPumps: []
} as CultureProtocolDto, } as CultureProtocolDto,
reactorOptions: [] as Array<{ id: number; name: string; needExternalPump: boolean }>, reactorOptions: [] as Array<{ id: number; name: string; needExternalPump: boolean; spec: string; pumpSpeed1: number; pumpSpeed2: number; pumpSpeed3: number; pumpSpeed4: number; pumpSpeed5: number; pumpSpeed6: number; pumpSpeed7: number; pumpSpeed8: number; pump1ConfigId: number; pump2ConfigId: number; pump3ConfigId: number; pump4ConfigId: number; pump5ConfigId: number; pump6ConfigId: number; pump7ConfigId: number; pump8ConfigId: number }>,
scaleOptions: [] as Array<{ id: number; name: string }>, scaleOptions: [] as Array<{ id: number; name: string }>,
mediumOptions: [] as Array<{ id: number; name: string }>, mediumOptions: [] as Array<{ id: number; name: string; glucoseConc: number; isGlucose: boolean; }>,
cellTypeOptions: [], bagOptions: [] as Array<{ id: number; name: string; lowerLimitVolume: number; }>,
bagOptions: [] as Array<{ id: number; name: string }>,
pumpOptions: [] as Array<{ id: number; name: string }>, pumpOptions: [] as Array<{ id: number; name: string }>,
cellTypeOptions: [],
configOptions: [] as Array<{ id: number; name: string; isTwo: number; }>,
selectedReactor: null as any,
}) })
const { form } = toRefs(state) const { form } = toRefs(state)
const activeTab = ref('basic')
const lastActiveTab = ref('basic')
//
watch(() => state.form.equReactorId, (newVal, oldVal) => {
if (newVal !== oldVal) {
//
state.selectedReactor = state.reactorOptions.find(r => r.id === newVal)
if (state.selectedReactor) {
state.form.fixedFeedingPumps.forEach(pump => {
pump.feedingPumpName = state.selectedReactor.name + ' - PUMP' + pump.feedingPumpNo
// ID
if (pump.feedingPumpNo == 1) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed1
pump.configId = state.selectedReactor.pump1ConfigId
} else if (pump.feedingPumpNo == 2) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed2
pump.configId = state.selectedReactor.pump2ConfigId
} else if (pump.feedingPumpNo == 3) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed3
pump.configId = state.selectedReactor.pump3ConfigId
} else if (pump.feedingPumpNo == 4) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed4
pump.configId = state.selectedReactor.pump4ConfigId
} else if (pump.feedingPumpNo == 5) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed5
pump.configId = state.selectedReactor.pump5ConfigId
} else if (pump.feedingPumpNo == 6) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed6
pump.configId = state.selectedReactor.pump6ConfigId
} else if (pump.feedingPumpNo == 7) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed7
pump.configId = state.selectedReactor.pump7ConfigId
} else if (pump.feedingPumpNo == 8) {
pump.pumpSpeed = state.selectedReactor.pumpSpeed8
pump.configId = state.selectedReactor.pump8ConfigId
}
// ID
if (!state.selectedReactor.needExternalPump) {
pump.equPumpId = undefined
}
})
//
if (state.selectedReactor.needExternalPump) {
getPumpOptions()
}
}
}
}, { immediate: true })
onMounted(() => { onMounted(() => {
getReactorOptions() getReactorOptions()
getScaleOptions() getScaleOptions()
getMediumOptions() getMediumOptions()
getBagOptions() getBagOptions()
getConfigOptions()
}) })
// //
@ -306,6 +349,17 @@ const open = async (row: any = {}, isCopy = false) => {
proxy.$modal.closeLoading() proxy.$modal.closeLoading()
} }
const defaultPumps = [
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 1, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 2, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 3, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 4, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 5, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 6, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 7, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false },
{ id: 0, feedingPumpName: '', cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 8, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined, isGlucose: false }
]
// //
const addRule = () => { const addRule = () => {
state.form.autoGlucoseFeedingRules.push({ state.form.autoGlucoseFeedingRules.push({
@ -344,6 +398,55 @@ const removeTask = (index: number) => {
state.form.feedingTasks.splice(index, 1) state.form.feedingTasks.splice(index, 1)
} }
const handleTabClick = async (tab: any, event: any) => {
if (lastActiveTab.value == 'pumps') {
//
if (!checkPumps()) {
await nextTick()
activeTab.value = lastActiveTab.value
return
}
//
lastActiveTab.value = tab.paneName
}
else {
lastActiveTab.value = tab.paneName
}
}
const checkPumps = () => {
let valid = true
state.form.fixedFeedingPumps.forEach(pump => {
if (pump.equPumpId != undefined || pump.itemDefBagID != undefined || pump.itemDefFeedingMediumID != undefined) {
let msg = ''
if (pump.equPumpId == undefined && state.selectedReactor?.needExternalPump) {
msg += '外置泵 '
}
if (pump.itemDefBagID == undefined) {
msg += '耗材 '
}
if (pump.itemDefFeedingMediumID == undefined) {
msg += '补料培养基 '
}
if (pump.configId == undefined) {
msg += '泵速策略 '
}
if (msg != '') {
msg = pump.feedingPumpName + ': 请选择' + msg
valid = false
proxy.$modal.msgError(msg)
}
}
})
return valid
}
// //
const onSure = async () => { const onSure = async () => {
if (!formRef.value) return if (!formRef.value) return
@ -400,16 +503,30 @@ const reset = () => {
const getReactorOptions = async () => { const getReactorOptions = async () => {
try { try {
const res = await new ReactorApi().getPage({ const res = await new ReactorApi().getList()
currentPage: 1,
pageSize: 10000
})
if (res?.success) { if (res?.success) {
state.reactorOptions = res.data?.list?.map(item => ({ state.reactorOptions = res.data?.map(item => ({
id: item.id ?? 0, id: item.id ?? 0,
name: item.productID ?? '', name: item.productID ?? '',
needExternalPump: item.isExternalPump === true needExternalPump: item.isExternalPump === true,
spec: item.specification ?? '',
pumpSpeed1: item.pump1Speed ?? 0,
pumpSpeed2: item.pump2Speed ?? 0,
pumpSpeed3: item.pump3Speed ?? 0,
pumpSpeed4: item.pump4Speed ?? 0,
pumpSpeed5: item.pump5Speed ?? 0,
pumpSpeed6: item.pump6Speed ?? 0,
pumpSpeed7: item.pump7Speed ?? 0,
pumpSpeed8: item.pump8Speed ?? 0,
pump1ConfigId: item.pump1ConfigId ?? 0,
pump2ConfigId: item.pump2ConfigId ?? 0,
pump3ConfigId: item.pump3ConfigId ?? 0,
pump4ConfigId: item.pump4ConfigId ?? 0,
pump5ConfigId: item.pump5ConfigId ?? 0,
pump6ConfigId: item.pump6ConfigId ?? 0,
pump7ConfigId: item.pump7ConfigId ?? 0,
pump8ConfigId: item.pump8ConfigId ?? 0
})) ?? [] })) ?? []
} }
} catch (error) { } catch (error) {
@ -441,7 +558,9 @@ const getMediumOptions = async () => {
if (res?.success) { if (res?.success) {
state.mediumOptions = res.data?.list?.map(item => ({ state.mediumOptions = res.data?.list?.map(item => ({
id: item.id ?? 0, id: item.id ?? 0,
name: item.mediumName ?? '' name: item.mediumName ?? '',
glucoseConc: item.glucoseConc ?? 0,
isGlucose: item.isGlucose ?? false
})) ?? [] })) ?? []
} }
} }
@ -456,21 +575,101 @@ const getBagOptions = async () => {
if (res?.success) { if (res?.success) {
state.bagOptions = res.data?.list?.map(item => ({ state.bagOptions = res.data?.list?.map(item => ({
id: item.id ?? 0, id: item.id ?? 0,
name: item.itemDescription ?? '' name: item.itemDescription ?? '',
lowerLimitVolume: item.lowerLimitVolume ?? 0,
})) ?? [] })) ?? []
} }
} }
const defaultPumps = [ const getPumpOptions = async () => {
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 1, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, const res = await new PumpApi().getPage({
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 2, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, currentPage: 1,
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 3, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, pageSize: 10000,
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 4, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, filter: {
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 5, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, isAirPump: false
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 6, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, }
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 7, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined }, })
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 8, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined } if (res?.success) {
] state.pumpOptions = res.data?.list?.map((item: { id: number; deviceNo: string }) => ({
id: item.id ?? 0,
name: item.deviceNo ?? ''
})) ?? []
}
}
const getConfigOptions = async () => {
const res = await new UspFeedingConfigApi().getPage({
currentPage: 1,
pageSize: 10000
})
if (res?.success) {
state.configOptions = res.data?.list?.map((item) => ({
id: item.id ?? 0,
name: item.configName ?? '',
isTwo: item.isTwoStep ?? 0
})) ?? []
}
}
//
const handlePumpChange = async (index: number) => {
const row = state.form.fixedFeedingPumps[index]
if (!row) return
const pumpId = row.equPumpId
if (!pumpId) {
//
row.pumpSpeed = 0
row.configId = undefined
return
}
try {
//
const res = await new PumpApi().get({ id: pumpId })
if (res?.success && res.data) {
//
row.pumpSpeed = res.data.pumpSpeed || 0
//
row.configId = res.data.configId
}
} catch (error) {
console.error('获取泵信息失败:', error)
proxy.$modal.msgError('获取泵信息失败')
}
}
const handleMediumChange = (index: number) => {
const row = state.form.fixedFeedingPumps[index]
if (!row) return
row.isGlucose = state.mediumOptions.find(item => item.id == row.itemDefFeedingMediumID)?.isGlucose ?? false
//
if (row.isGlucose) {
const glucose = state.form.fixedFeedingPumps.find(item => item.isGlucose == true && item.feedingPumpNo != row.feedingPumpNo)
if (glucose) {
ElMessageBox.confirm('糖补料不能重复,请检查', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'warning'
}).then(() => {
row.itemDefFeedingMediumID = undefined
row.isGlucose = false
return
}).catch(() => {
return
})
}
}
//
const medium = state.form.fixedFeedingPumps.find(item => item.itemDefFeedingMediumID == row.itemDefFeedingMediumID && item.feedingPumpNo != row.feedingPumpNo)
if (medium) {
proxy.$modal.msgWarning('补料培养基存在重复')
}
}
defineExpose({ defineExpose({
open open

View File

@ -2,8 +2,8 @@
<MyLayout> <MyLayout>
<el-card v-show="state.showQuery" class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }"> <el-card v-show="state.showQuery" class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
<el-form :inline="true" label-width="auto" @submit.stop.prevent> <el-form :inline="true" label-width="auto" @submit.stop.prevent>
<el-form-item label="方案名称"> <el-form-item label="模板名称">
<el-input v-model="state.filter.keyWord" placeholder="请输入方案名称" @keyup.enter="onQuery" /> <el-input v-model="state.filter.keyWord" placeholder="请输入模板名称" @keyup.enter="onQuery" />
</el-form-item> </el-form-item>
<el-form-item label="反应器"> <el-form-item label="反应器">
<el-select v-model="state.filter.equReactorId" placeholder="请选择反应器" clearable style="width: 150px"> <el-select v-model="state.filter.equReactorId" placeholder="请选择反应器" clearable style="width: 150px">
@ -53,15 +53,19 @@
row-key="id" row-key="id"
border border
> >
<el-table-column prop="cultureProtocolName" label="方案名称" min-width="120" show-overflow-tooltip /> <el-table-column prop="cultureProtocolName" label="模板名称" min-width="150" show-overflow-tooltip />
<el-table-column prop="days" label="培养天数" min-width="100" show-overflow-tooltip /> <el-table-column prop="equReactorId" label="反应器" width="120" align="center" show-overflow-tooltip>
<el-table-column prop="initialWorkingVolume" label="初始工作体积" min-width="120" show-overflow-tooltip />
<el-table-column label="葡萄糖补料验证" width="150" align="center" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-tag type="success" v-if="row.glucoseFeedingVerification"></el-tag> {{ getReactorDescription(row.equReactorId) }}
<el-tag type="info" v-else></el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="equReactorId" label="规格" width="120" align="center" show-overflow-tooltip>
<template #default="{ row }">
{{ getReactorSpec(row.equReactorId) }}
</template>
</el-table-column>
<el-table-column prop="days" label="培养天数" min-width="100" show-overflow-tooltip />
<el-table-column prop="feedingTaskCount" label="补料任务" min-width="100" show-overflow-tooltip />
<el-table-column label="状态" width="100" align="center" show-overflow-tooltip> <el-table-column label="状态" width="100" align="center" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-tag type="success" v-if="row.enabled">启用</el-tag> <el-tag type="success" v-if="row.enabled">启用</el-tag>
@ -154,7 +158,7 @@ const state = reactive({
protocolListData: [] as Array<CultureProtocolPageDto>, protocolListData: [] as Array<CultureProtocolPageDto>,
showQuery: true, showQuery: true,
showProtocolList: true, showProtocolList: true,
reactorOptions: [] as Array<{ id: number; name: string }>, reactorOptions: [] as Array<{ id: number; name: string; spec: string }>,
}) })
onMounted(() => { onMounted(() => {
@ -227,7 +231,8 @@ const getReactorOptions = async () => {
if (res?.success) { if (res?.success) {
state.reactorOptions = res.data?.list?.map(item => ({ state.reactorOptions = res.data?.list?.map(item => ({
id: item.id ?? 0, id: item.id ?? 0,
name: item.productID ?? '' name: item.productID ?? '',
spec: item.specification ?? ''
})) ?? [] })) ?? []
} }
} catch (error) { } catch (error) {
@ -235,8 +240,14 @@ const getReactorOptions = async () => {
} }
} }
const getReactorDescription = async (reactorId: number) => { const getReactorDescription = (reactorId: number) => {
return state.reactorOptions.find(item => item.id === reactorId)?.name ?? '' const reactor = state.reactorOptions.find(item => item.id == reactorId)
return reactor?.name ?? ''
}
const getReactorSpec = (reactorId: number) => {
const reactor = state.reactorOptions.find(item => item.id == reactorId)
return reactor?.spec ?? ''
} }
const onReset = () => { const onReset = () => {