add 培养方案页面
This commit is contained in:
parent
f42b22dc0a
commit
acd9fcf076
93
src/api/admin/CultureProtocolApi.ts
Normal file
93
src/api/admin/CultureProtocolApi.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { RequestParams } from './http-client'
|
||||||
|
import { ContentType, HttpClient } from './http-client'
|
||||||
|
import type {
|
||||||
|
CultureProtocolDto,
|
||||||
|
CultureProtocolPageInput,
|
||||||
|
CultureProtocolPageResponse,
|
||||||
|
CultureProtocolOutput,
|
||||||
|
CultureProtocolAddInput,
|
||||||
|
CultureProtocolUpdateInput
|
||||||
|
} from '/@/api/types/cultureprotocol'
|
||||||
|
|
||||||
|
export class CultureProtocolApi extends HttpClient {
|
||||||
|
/**
|
||||||
|
* 获取分页列表
|
||||||
|
*/
|
||||||
|
getPage = (data: CultureProtocolPageInput, params: RequestParams = {}) =>
|
||||||
|
this.request<CultureProtocolPageResponse>({
|
||||||
|
path: `/api/admin/culture-protocol/get-page`,
|
||||||
|
method: 'POST',
|
||||||
|
body: data,
|
||||||
|
type: ContentType.Json,
|
||||||
|
...params,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单条数据
|
||||||
|
*/
|
||||||
|
get = (params: { id: number }, requestParams: RequestParams = {}) =>
|
||||||
|
this.request<CultureProtocolOutput>({
|
||||||
|
path: `/api/admin/culture-protocol/get`,
|
||||||
|
method: 'GET',
|
||||||
|
query: params,
|
||||||
|
...requestParams,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
*/
|
||||||
|
add = (data: CultureProtocolAddInput, params: RequestParams = {}) =>
|
||||||
|
this.request<any>({
|
||||||
|
path: `/api/admin/culture-protocol/add`,
|
||||||
|
method: 'POST',
|
||||||
|
body: data,
|
||||||
|
type: ContentType.Json,
|
||||||
|
...params,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新
|
||||||
|
*/
|
||||||
|
update = (data: CultureProtocolUpdateInput, params: RequestParams = {}) =>
|
||||||
|
this.request<any>({
|
||||||
|
path: `/api/admin/culture-protocol/update`,
|
||||||
|
method: 'PUT',
|
||||||
|
body: data,
|
||||||
|
type: ContentType.Json,
|
||||||
|
...params,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 软删除
|
||||||
|
*/
|
||||||
|
softDelete = (params: { id: number }, requestParams: RequestParams = {}) =>
|
||||||
|
this.request<any>({
|
||||||
|
path: `/api/admin/culture-protocol/soft-delete`,
|
||||||
|
method: 'DELETE',
|
||||||
|
query: params,
|
||||||
|
...requestParams,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制培养方案
|
||||||
|
*/
|
||||||
|
copy = (params: { id: number; reactorId: number }, requestParams: RequestParams = {}) =>
|
||||||
|
this.request<any>({
|
||||||
|
path: `/api/admin/culture-protocol/copy`,
|
||||||
|
method: 'POST',
|
||||||
|
body: params,
|
||||||
|
type: ContentType.Json,
|
||||||
|
...requestParams,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换培养方案状态
|
||||||
|
*/
|
||||||
|
toggleStatus = (params: { id: number; isEnabled: boolean }, requestParams: RequestParams = {}) =>
|
||||||
|
this.request<any>({
|
||||||
|
path: `/api/admin/culture-protocol/toggle-status`,
|
||||||
|
method: 'POST',
|
||||||
|
query: params,
|
||||||
|
...requestParams,
|
||||||
|
})
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { ReactorPageInput, ReactorPageResponse, ReactorOutput, ReactorAddInput, ReactorUpdateInput, ReactorTypeEnumListOutput } from '/@/api/types/ReactorType'
|
import { ReactorPageInput, ReactorPageResponse, ReactorOutput, ReactorAddInput, ReactorUpdateInput, ReactorTypeEnumListOutput } 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'
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ export interface ReactorDto {
|
|||||||
modifiedTime?: string | null
|
modifiedTime?: string | null
|
||||||
/** 压力单位 */
|
/** 压力单位 */
|
||||||
pressureUnit?: string | null
|
pressureUnit?: string | null
|
||||||
|
/** 是否外置泵 */
|
||||||
|
isExternalPump?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 反应器添加和更新输入接口 */
|
/** 反应器添加和更新输入接口 */
|
||||||
|
146
src/api/types/cultureprotocol.ts
Normal file
146
src/api/types/cultureprotocol.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import { ServiceResponse } from './response'
|
||||||
|
import { ServiceRequestPage } from './pageInput'
|
||||||
|
import { PageResponse } from './pageResponse'
|
||||||
|
|
||||||
|
// 过滤条件
|
||||||
|
export interface CultureProtocolFilter {
|
||||||
|
/** 设备编号 */
|
||||||
|
keyWord?: string | null
|
||||||
|
/** 开始时间 */
|
||||||
|
stDate?: string | null
|
||||||
|
/** 结束时间 */
|
||||||
|
edDate?: string | null
|
||||||
|
/** 反应器Id */
|
||||||
|
equReactorId?: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培养方案实体接口
|
||||||
|
*/
|
||||||
|
export interface CultureProtocolPageDto {
|
||||||
|
/** 主键ID */
|
||||||
|
id: number
|
||||||
|
/** 培养方案名称 */
|
||||||
|
cultureProtocolName: string
|
||||||
|
/** 反应器ID */
|
||||||
|
equReactorId: number
|
||||||
|
/** 补料秤ID */
|
||||||
|
equFeedingScaleId: number
|
||||||
|
/** 培养天数 */
|
||||||
|
days: number
|
||||||
|
/** 初始工作体积 */
|
||||||
|
initialWorkingVolume: number
|
||||||
|
/** 初始工作培养基ID */
|
||||||
|
initialWorkingMediumId: number
|
||||||
|
/** 转种细胞体积 */
|
||||||
|
transferCellVolume: number
|
||||||
|
/** 转种细胞类型ID */
|
||||||
|
transferCellTypeId: number
|
||||||
|
/** 实验组ID */
|
||||||
|
experimentalGroupId: number
|
||||||
|
/** 葡萄糖补料验证 */
|
||||||
|
glucoseFeedingVerification: boolean
|
||||||
|
/** 备注 */
|
||||||
|
remark: string
|
||||||
|
/** 是否启用 */
|
||||||
|
enabled: boolean
|
||||||
|
/** 创建时间 */
|
||||||
|
createdTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CultureProtocolDto {
|
||||||
|
/** 主键ID */
|
||||||
|
id: number
|
||||||
|
/** 培养方案名称 */
|
||||||
|
cultureProtocolName: string
|
||||||
|
/** 反应器ID */
|
||||||
|
equReactorId?: number
|
||||||
|
/** 补料秤ID */
|
||||||
|
equFeedingScaleId?: number
|
||||||
|
/** 培养天数 */
|
||||||
|
days: number
|
||||||
|
/** 初始工作体积 */
|
||||||
|
initialWorkingVolume: number
|
||||||
|
/** 初始工作培养基ID */
|
||||||
|
initialWorkingMediumId: number
|
||||||
|
/** 转种细胞体积 */
|
||||||
|
transferCellVolume: number
|
||||||
|
/** 转种细胞类型ID */
|
||||||
|
transferCellTypeId: number
|
||||||
|
/** 葡萄糖补料验证 */
|
||||||
|
glucoseFeedingVerification: boolean
|
||||||
|
/** 备注 */
|
||||||
|
remark: string
|
||||||
|
/** 自动葡萄糖补料规则 */
|
||||||
|
autoGlucoseFeedingRules: AutoGlucoseFeedingRule[]
|
||||||
|
/** 补料任务 */
|
||||||
|
feedingTasks: FeedingTask[]
|
||||||
|
/** 固定补料泵配置 */
|
||||||
|
fixedFeedingPumps: FixedFeedingPump[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 自动葡萄糖补料规则 */
|
||||||
|
export interface AutoGlucoseFeedingRule {
|
||||||
|
/** 主键ID */
|
||||||
|
id: number
|
||||||
|
/** 培养方案ID */
|
||||||
|
cultureProtocolId: number
|
||||||
|
/** 培养开始天数 */
|
||||||
|
cultureDayStarting: number
|
||||||
|
/** 培养结束天数 */
|
||||||
|
cultureDayEnding: number
|
||||||
|
/** 下限值 */
|
||||||
|
lowerLimit: number
|
||||||
|
/** 补料目标值 */
|
||||||
|
feedingTo: number
|
||||||
|
/** 下限操作符 */
|
||||||
|
lowerLimitOperator: string
|
||||||
|
/** 计算模式 */
|
||||||
|
calculationMode: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 补料任务 */
|
||||||
|
export interface FeedingTask {
|
||||||
|
/** 主键ID */
|
||||||
|
id: number
|
||||||
|
/** 培养方案ID */
|
||||||
|
cultureProtocolId: number
|
||||||
|
/** 补料泵编号 */
|
||||||
|
feedingPumpNo: number
|
||||||
|
/** 培养天数 */
|
||||||
|
day: number
|
||||||
|
/** 补料时间 */
|
||||||
|
feedingTime: string
|
||||||
|
/** 补料类型 */
|
||||||
|
feedingType: number
|
||||||
|
/** 补料体积百分比 */
|
||||||
|
feedingVolumePercent: number
|
||||||
|
/** 补料体积 */
|
||||||
|
feedingVolume: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 固定补料泵配置 */
|
||||||
|
export interface FixedFeedingPump {
|
||||||
|
/** 主键ID */
|
||||||
|
id: number
|
||||||
|
/** 培养方案ID */
|
||||||
|
cultureProtocolId?: number
|
||||||
|
/** 配置ID */
|
||||||
|
configId?: number
|
||||||
|
/** 补料泵编号 */
|
||||||
|
feedingPumpNo: number
|
||||||
|
/** 物料定义袋ID */
|
||||||
|
itemDefBagID?: number
|
||||||
|
/** 物料定义培养基ID */
|
||||||
|
itemDefFeedingMediumID?: number
|
||||||
|
/** 设备泵ID */
|
||||||
|
equPumpId?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CultureProtocolPageInput = ServiceRequestPage<CultureProtocolFilter>
|
||||||
|
export type CultureProtocolPageResponse = ServiceResponse<PageResponse<CultureProtocolPageDto>>;
|
||||||
|
|
||||||
|
export type CultureProtocolOutput = ServiceResponse<CultureProtocolDto>;
|
||||||
|
export type CultureProtocolAddInput = CultureProtocolDto;
|
||||||
|
export type CultureProtocolUpdateInput = CultureProtocolDto;
|
@ -1,5 +1,5 @@
|
|||||||
import { ServiceResponse } from './response';
|
import { ServiceResponse } from './response';
|
||||||
import { ServiceRequstPage } from './pageInput'
|
import { ServiceRequestPage } from './pageInput'
|
||||||
import { PageResponse } from './pageResponse'
|
import { PageResponse } from './pageResponse'
|
||||||
|
|
||||||
// 过滤
|
// 过滤
|
||||||
@ -93,7 +93,7 @@ export interface RevokeTypeEnumItem {
|
|||||||
label: string
|
label: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RevokeReasonPageInput = ServiceRequstPage<RevokeReasonFilter>;
|
export type RevokeReasonPageInput = ServiceRequestPage<RevokeReasonFilter>;
|
||||||
export type RevokeReasonPageResponse = ServiceResponse<PageResponse<RevokeReasonPageDto>>;
|
export type RevokeReasonPageResponse = ServiceResponse<PageResponse<RevokeReasonPageDto>>;
|
||||||
|
|
||||||
export type RevokeReasonOutput = ServiceResponse<RevokeReasonDto[]>;
|
export type RevokeReasonOutput = ServiceResponse<RevokeReasonDto[]>;
|
||||||
|
515
src/views/admin/template/components/culture-protocol-form.vue
Normal file
515
src/views/admin/template/components/culture-protocol-form.vue
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<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>
|
||||||
|
<el-form :model="form" ref="formRef" size="default" label-width="120px">
|
||||||
|
<el-tabs v-model="state.activeTab">
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<el-tab-pane label="基本信息" name="basic">
|
||||||
|
<div class="form-section">
|
||||||
|
<el-row :gutter="25">
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
|
<el-form-item label="方案名称" prop="cultureProtocolName"
|
||||||
|
:rules="[{ required: true, message: '请输入方案名称', trigger: ['blur', 'change'] }]">
|
||||||
|
<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="days"
|
||||||
|
:rules="[{ required: true, message: '请输入培养天数', trigger: ['blur', 'change'] }]">
|
||||||
|
<el-input-number v-model="form.days" :min="1" 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="equReactorId"
|
||||||
|
: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-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24">
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 固定补料泵 -->
|
||||||
|
<el-tab-pane label="固定补料泵" name="pumps">
|
||||||
|
<div class="form-section">
|
||||||
|
<el-table :data="form.fixedFeedingPumps" border style="width: 100%">
|
||||||
|
<el-table-column label="补料泵编号" prop="feedingPumpNo" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input v-model="scope.row.feedingPumpNo" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-if="state.form.equReactorId && state.reactorOptions.find(r => r.id === state.form.equReactorId)?.needExternalPump === true"
|
||||||
|
label="外置泵"
|
||||||
|
prop="equPumpId"
|
||||||
|
min-width="200"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-select v-model="scope.row.equPumpId" placeholder="请选择外置泵" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in state.pumpOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</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"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="补料培养基" prop="itemDefFeedingMediumID" min-width="200">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-select v-model="scope.row.itemDefFeedingMediumID" placeholder="请选择补料培养基" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in state.mediumOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 补料任务 -->
|
||||||
|
<el-tab-pane label="补料任务" name="tasks">
|
||||||
|
<div class="form-section">
|
||||||
|
<div v-for="(task, index) in form.feedingTasks" :key="index" class="task-item">
|
||||||
|
<el-row :gutter="25">
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '补料泵编号' : ''"
|
||||||
|
:prop="'feedingTasks.' + index + '.feedingPumpNo'">
|
||||||
|
<el-input-number v-model="task.feedingPumpNo" :min="1" style="width: 100%" placeholder="泵编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '培养天数' : ''" :prop="'feedingTasks.' + index + '.day'">
|
||||||
|
<el-input-number v-model="task.day" :min="1" style="width: 100%" placeholder="天数" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '补料时间' : ''" :prop="'feedingTasks.' + index + '.feedingTime'">
|
||||||
|
<el-time-picker v-model="task.feedingTime" format="HH:mm" style="width: 100%"
|
||||||
|
placeholder="补料时间" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '补料体积' : ''" :prop="'feedingTasks.' + index + '.feedingVolume'">
|
||||||
|
<el-input-number v-model="task.feedingVolume" :min="0" :precision="2" style="width: 100%"
|
||||||
|
placeholder="补料体积" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-button type="danger" icon="ele-Delete" circle @click="removeTask(index)"
|
||||||
|
v-if="form.feedingTasks.length > 1" />
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" icon="ele-Plus" @click="addTask">添加任务</el-button>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 自动葡萄糖补料规则 -->
|
||||||
|
<el-tab-pane label="自动葡萄糖补料规则" name="glucose">
|
||||||
|
<div class="form-section">
|
||||||
|
<div v-for="(rule, index) in form.autoGlucoseFeedingRules" :key="index" class="rule-item">
|
||||||
|
<el-row :gutter="25">
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '培养开始天数' : ''"
|
||||||
|
:prop="'autoGlucoseFeedingRules.' + index + '.cultureDayStarting'">
|
||||||
|
<el-input-number v-model="rule.cultureDayStarting" :min="0" style="width: 100%"
|
||||||
|
placeholder="开始天数" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '培养结束天数' : ''"
|
||||||
|
:prop="'autoGlucoseFeedingRules.' + index + '.cultureDayEnding'">
|
||||||
|
<el-input-number v-model="rule.cultureDayEnding" :min="0" style="width: 100%"
|
||||||
|
placeholder="结束天数" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '下限值' : ''"
|
||||||
|
:prop="'autoGlucoseFeedingRules.' + index + '.lowerLimit'">
|
||||||
|
<el-input-number v-model="rule.lowerLimit" :min="0" :precision="2" style="width: 100%"
|
||||||
|
placeholder="下限值" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6">
|
||||||
|
<el-form-item :label="index === 0 ? '补料目标值' : ''"
|
||||||
|
:prop="'autoGlucoseFeedingRules.' + index + '.feedingTo'">
|
||||||
|
<el-input-number v-model="rule.feedingTo" :min="0" :precision="2" style="width: 100%"
|
||||||
|
placeholder="目标值" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-button type="danger" icon="ele-Delete" circle @click="removeRule(index)"
|
||||||
|
v-if="form.autoGlucoseFeedingRules.length > 1" />
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" icon="ele-Plus" @click="addRule">添加规则</el-button>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSure" size="default" :loading="state.sureLoading">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="admin/culture-protocol/form">
|
||||||
|
import { reactive, toRefs, ref, getCurrentInstance, onMounted } from 'vue'
|
||||||
|
import { CultureProtocolApi } from '/@/api/admin/CultureProtocolApi'
|
||||||
|
import { ReactorApi } from '/@/api/admin/ReactorApi'
|
||||||
|
import { UspscaleApi } from '/@/api/admin/UspscaleApi'
|
||||||
|
import { ItemDefFeedingMediumApi } from '/@/api/admin/item-def-feeding-medium'
|
||||||
|
import { ItemDefBagApi } from '/@/api/admin/item-def-bag'
|
||||||
|
import type { CultureProtocolDto } from '/@/api/types/cultureprotocol'
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as any
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'ok'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const formRef = ref()
|
||||||
|
const state = reactive({
|
||||||
|
showDialog: false,
|
||||||
|
sureLoading: false,
|
||||||
|
activeTab: 'basic',
|
||||||
|
form: {
|
||||||
|
id: 0,
|
||||||
|
cultureProtocolName: '',
|
||||||
|
equReactorId: undefined,
|
||||||
|
equFeedingScaleId: undefined,
|
||||||
|
days: 0,
|
||||||
|
initialWorkingVolume: 0,
|
||||||
|
initialWorkingMediumId: 0,
|
||||||
|
transferCellVolume: 0,
|
||||||
|
transferCellTypeId: 0,
|
||||||
|
glucoseFeedingVerification: true,
|
||||||
|
enabled: true,
|
||||||
|
remark: '',
|
||||||
|
autoGlucoseFeedingRules: [],
|
||||||
|
feedingTasks: [],
|
||||||
|
fixedFeedingPumps: []
|
||||||
|
} as CultureProtocolDto,
|
||||||
|
reactorOptions: [] as Array<{ id: number; name: string; needExternalPump: boolean }>,
|
||||||
|
scaleOptions: [] as Array<{ id: number; name: string }>,
|
||||||
|
mediumOptions: [] as Array<{ id: number; name: string }>,
|
||||||
|
cellTypeOptions: [],
|
||||||
|
bagOptions: [] as Array<{ id: number; name: string }>,
|
||||||
|
pumpOptions: [] as Array<{ id: number; name: string }>,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { form } = toRefs(state)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getReactorOptions()
|
||||||
|
getScaleOptions()
|
||||||
|
getMediumOptions()
|
||||||
|
getBagOptions()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 打开对话框
|
||||||
|
const open = async (row: any = {}, isCopy = false) => {
|
||||||
|
proxy.$modal.loading()
|
||||||
|
|
||||||
|
if (row.id > 0) {
|
||||||
|
const res = await new CultureProtocolApi().get({ id: row.id }, { loading: true })
|
||||||
|
if (res?.success) {
|
||||||
|
let formData = res.data as CultureProtocolDto
|
||||||
|
if (isCopy) {
|
||||||
|
formData.id = 0
|
||||||
|
formData.cultureProtocolName = formData.cultureProtocolName + ' - 副本'
|
||||||
|
}
|
||||||
|
state.form = formData
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.form = {
|
||||||
|
id: 0,
|
||||||
|
cultureProtocolName: '',
|
||||||
|
equReactorId: undefined,
|
||||||
|
equFeedingScaleId: undefined,
|
||||||
|
days: 0,
|
||||||
|
initialWorkingVolume: 0,
|
||||||
|
initialWorkingMediumId: 0,
|
||||||
|
transferCellVolume: 0,
|
||||||
|
transferCellTypeId: 0,
|
||||||
|
glucoseFeedingVerification: true,
|
||||||
|
remark: '',
|
||||||
|
autoGlucoseFeedingRules: [],
|
||||||
|
feedingTasks: [],
|
||||||
|
fixedFeedingPumps: defaultPumps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.showDialog = true
|
||||||
|
proxy.$modal.closeLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加规则
|
||||||
|
const addRule = () => {
|
||||||
|
state.form.autoGlucoseFeedingRules.push({
|
||||||
|
id: 0,
|
||||||
|
cultureProtocolId: 0,
|
||||||
|
cultureDayStarting: 0,
|
||||||
|
cultureDayEnding: 0,
|
||||||
|
lowerLimit: 0,
|
||||||
|
feedingTo: 0,
|
||||||
|
lowerLimitOperator: '',
|
||||||
|
calculationMode: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除规则
|
||||||
|
const removeRule = (index: number) => {
|
||||||
|
state.form.autoGlucoseFeedingRules.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加任务
|
||||||
|
const addTask = () => {
|
||||||
|
state.form.feedingTasks.push({
|
||||||
|
id: 0,
|
||||||
|
cultureProtocolId: 0,
|
||||||
|
feedingPumpNo: 0,
|
||||||
|
day: 0,
|
||||||
|
feedingTime: '',
|
||||||
|
feedingType: 0,
|
||||||
|
feedingVolumePercent: 0,
|
||||||
|
feedingVolume: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除任务
|
||||||
|
const removeTask = (index: number) => {
|
||||||
|
state.form.feedingTasks.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSure = async () => {
|
||||||
|
if (!formRef.value) return
|
||||||
|
await formRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
state.sureLoading = true
|
||||||
|
try {
|
||||||
|
const api = new CultureProtocolApi()
|
||||||
|
const res = state.form.id
|
||||||
|
? await api.update(state.form)
|
||||||
|
: await api.add(state.form)
|
||||||
|
if (res.success) {
|
||||||
|
proxy.$modal.msgSuccess(state.form.id ? '修改成功' : '新增成功')
|
||||||
|
state.showDialog = false
|
||||||
|
emit('ok')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(state.form.id ? '修改失败:' : '新增失败:', error)
|
||||||
|
} finally {
|
||||||
|
state.sureLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消按钮
|
||||||
|
const onCancel = () => {
|
||||||
|
state.showDialog = false
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const reset = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields()
|
||||||
|
}
|
||||||
|
state.form = {
|
||||||
|
id: 0,
|
||||||
|
cultureProtocolName: '',
|
||||||
|
equReactorId: undefined,
|
||||||
|
equFeedingScaleId: undefined,
|
||||||
|
days: 0,
|
||||||
|
initialWorkingVolume: 0,
|
||||||
|
initialWorkingMediumId: 0,
|
||||||
|
transferCellVolume: 0,
|
||||||
|
transferCellTypeId: 0,
|
||||||
|
glucoseFeedingVerification: true,
|
||||||
|
remark: '',
|
||||||
|
autoGlucoseFeedingRules: [],
|
||||||
|
feedingTasks: [],
|
||||||
|
fixedFeedingPumps: defaultPumps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getReactorOptions = async () => {
|
||||||
|
try {
|
||||||
|
const res = await new ReactorApi().getPage({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.success) {
|
||||||
|
state.reactorOptions = res.data?.list?.map(item => ({
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: item.productID ?? '',
|
||||||
|
needExternalPump: item.isExternalPump === true
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取反应器列表失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getScaleOptions = async () => {
|
||||||
|
const res = await new UspscaleApi().getPage({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.success) {
|
||||||
|
state.scaleOptions = res.data?.list?.filter(item => item.isFeedingScale === true).map(item => ({
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: item.deviceNo ?? ''
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取补料培养基列表
|
||||||
|
const getMediumOptions = async () => {
|
||||||
|
const res = await new ItemDefFeedingMediumApi().getPage({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.success) {
|
||||||
|
state.mediumOptions = res.data?.list?.map(item => ({
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: item.mediumName ?? ''
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取物料定义袋列表
|
||||||
|
const getBagOptions = async () => {
|
||||||
|
const res = await new ItemDefBagApi().getPage({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.success) {
|
||||||
|
state.bagOptions = res.data?.list?.map(item => ({
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: item.itemDescription ?? ''
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultPumps = [
|
||||||
|
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 1, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined },
|
||||||
|
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 2, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined },
|
||||||
|
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 3, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined },
|
||||||
|
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 4, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined },
|
||||||
|
{ id: 0, cultureProtocolId: undefined, configId: undefined, feedingPumpNo: 5, itemDefBagID: undefined, itemDefFeedingMediumID: undefined, equPumpId: undefined },
|
||||||
|
{ 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 }
|
||||||
|
]
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.form-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule-item,
|
||||||
|
.task-item,
|
||||||
|
.pump-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
285
src/views/admin/template/index.vue
Normal file
285
src/views/admin/template/index.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<MyLayout>
|
||||||
|
<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-item label="方案名称">
|
||||||
|
<el-input v-model="state.filter.keyWord" placeholder="请输入方案名称" @keyup.enter="onQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="反应器">
|
||||||
|
<el-select v-model="state.filter.equReactorId" placeholder="请选择反应器" clearable style="width: 150px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in state.reactorOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开始时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="state.filter.stDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="开始日期"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结束时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="state.filter.edDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="结束日期"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="ele-Search" @click="onQuery">查询</el-button>
|
||||||
|
<el-button v-auth="'api:admin:culture-protocol:add'" type="primary" icon="ele-Plus" @click="onAdd">新增</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card class="my-fill mt8" shadow="never">
|
||||||
|
<div class="my-tools-box mb8 my-flex my-flex-between">
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-if="state.showProtocolList"
|
||||||
|
:data="state.protocolListData"
|
||||||
|
style="width: 100%"
|
||||||
|
v-loading="state.loading"
|
||||||
|
row-key="id"
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<el-table-column prop="cultureProtocolName" label="方案名称" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="days" label="培养天数" min-width="100" 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 }">
|
||||||
|
<el-tag type="success" v-if="row.glucoseFeedingVerification">是</el-tag>
|
||||||
|
<el-tag type="info" v-else>否</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态" width="100" align="center" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||||
|
<el-tag type="danger" v-else>禁用</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="createdUserName" label="创建者" min-width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="createdTime" label="创建时间" min-width="160" show-overflow-tooltip />
|
||||||
|
<el-table-column label="操作" width="240" fixed="right" header-align="center" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button
|
||||||
|
v-if="auth('api:admin:culture-protocol:update')"
|
||||||
|
icon="ele-EditPen"
|
||||||
|
size="small"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="onEdit(row)"
|
||||||
|
>编辑</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="auth('api:admin:culture-protocol:copy')"
|
||||||
|
icon="ele-CopyDocument"
|
||||||
|
size="small"
|
||||||
|
text
|
||||||
|
type="success"
|
||||||
|
@click="onCopy(row)"
|
||||||
|
>复制</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="auth('api:admin:culture-protocol:soft-delete')"
|
||||||
|
icon="ele-Delete"
|
||||||
|
size="small"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="onDelete(row)"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||||
|
<el-pagination
|
||||||
|
v-model:currentPage="state.pageInput.currentPage"
|
||||||
|
v-model:page-size="state.pageInput.pageSize"
|
||||||
|
:total="state.total"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
size="small"
|
||||||
|
background
|
||||||
|
@size-change="onSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<culture-protocol-form ref="protocolFormRef" :title="state.protocolFormTitle" @ok="Query" />
|
||||||
|
</MyLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="admin/culture-protocol">
|
||||||
|
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||||
|
import { CultureProtocolApi } from '/@/api/admin/CultureProtocolApi'
|
||||||
|
import type { CultureProtocolDto, CultureProtocolPageInput, CultureProtocolPageDto } from '/@/api/types/cultureprotocol'
|
||||||
|
import eventBus from '/@/utils/mitt'
|
||||||
|
import { auth } from '/@/utils/authFunction'
|
||||||
|
import { ReactorApi } from '/@/api/admin/ReactorApi'
|
||||||
|
|
||||||
|
// 引入组件
|
||||||
|
const CultureProtocolForm = defineAsyncComponent(() => import('./components/culture-protocol-form.vue'))
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as any
|
||||||
|
|
||||||
|
const protocolFormRef = ref()
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
protocolFormTitle: '',
|
||||||
|
filter: {
|
||||||
|
keyWord: '',
|
||||||
|
stDate: '',
|
||||||
|
edDate: '',
|
||||||
|
equReactorId: null as number | null
|
||||||
|
},
|
||||||
|
total: 0,
|
||||||
|
pageInput: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
} as CultureProtocolPageInput,
|
||||||
|
protocolListData: [] as Array<CultureProtocolPageDto>,
|
||||||
|
showQuery: true,
|
||||||
|
showProtocolList: true,
|
||||||
|
reactorOptions: [] as Array<{ id: number; name: string }>,
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
Query()
|
||||||
|
getReactorOptions()
|
||||||
|
})
|
||||||
|
|
||||||
|
const onQuery = () => {
|
||||||
|
Query()
|
||||||
|
}
|
||||||
|
|
||||||
|
const Query = async () => {
|
||||||
|
state.loading = true
|
||||||
|
state.pageInput.filter = state.filter
|
||||||
|
const res = await new CultureProtocolApi().getPage(state.pageInput).catch(() => {
|
||||||
|
state.loading = false
|
||||||
|
})
|
||||||
|
|
||||||
|
state.protocolListData = res?.data?.list ?? []
|
||||||
|
state.total = res?.data?.total ?? 0
|
||||||
|
state.loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAdd = () => {
|
||||||
|
state.protocolFormTitle = '新增培养方案'
|
||||||
|
protocolFormRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit = (row: CultureProtocolDto) => {
|
||||||
|
state.protocolFormTitle = '编辑培养方案'
|
||||||
|
protocolFormRef.value?.open(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCopy = (row: CultureProtocolDto) => {
|
||||||
|
state.protocolFormTitle = '复制培养方案'
|
||||||
|
protocolFormRef.value?.open(row, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete = (row: CultureProtocolDto) => {
|
||||||
|
proxy.$modal.confirm('确认要删除该记录吗?').then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await new CultureProtocolApi().softDelete({ id: row.id! })
|
||||||
|
if (res.success) {
|
||||||
|
proxy.$modal.msgSuccess('删除成功')
|
||||||
|
Query()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSizeChange = (val: number) => {
|
||||||
|
state.pageInput.pageSize = val
|
||||||
|
Query()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCurrentChange = (val: number) => {
|
||||||
|
state.pageInput.currentPage = val
|
||||||
|
Query()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getReactorOptions = async () => {
|
||||||
|
try {
|
||||||
|
const res = await new ReactorApi().getPage({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.success) {
|
||||||
|
state.reactorOptions = res.data?.list?.map(item => ({
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: item.productID ?? ''
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取反应器列表失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getReactorDescription = async (reactorId: number) => {
|
||||||
|
return state.reactorOptions.find(item => item.id === reactorId)?.name ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const onReset = () => {
|
||||||
|
state.filter = {
|
||||||
|
keyWord: '',
|
||||||
|
stDate: '',
|
||||||
|
edDate: '',
|
||||||
|
equReactorId: null
|
||||||
|
}
|
||||||
|
onQuery()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.my-query-box {
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-fill {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-flex-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-flex-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt8 {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb8 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,137 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog v-model="visible" :title="title" width="500px" append-to-body destroy-on-close>
|
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
|
||||||
<el-form-item label="反应器名称" prop="reactorName">
|
|
||||||
<el-input v-model="form.reactorName" placeholder="请输入反应器名称" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="反应器类型" prop="reactorType">
|
|
||||||
<el-select v-model="form.reactorType" placeholder="请选择反应器类型" style="width: 100%">
|
|
||||||
<el-option v-for="item in reactorTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-radio-group v-model="form.status">
|
|
||||||
<el-radio :label="true">启用</el-radio>
|
|
||||||
<el-radio :label="false">禁用</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|
||||||
<el-button @click="cancel">取 消</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { ReactorApi } from '../../../../api/admin/ReactorApi'
|
|
||||||
import type { ReactorDto, ReactorTypeEnumItem } from '../../../../api/types/reactorType'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
title: string
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'ok'): void
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const visible = ref(false)
|
|
||||||
const formRef = ref()
|
|
||||||
const reactorTypeOptions = ref<ReactorTypeEnumItem[]>([])
|
|
||||||
|
|
||||||
const form = reactive<ReactorDto>({
|
|
||||||
reactorName: '',
|
|
||||||
reactorType: '',
|
|
||||||
status: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const rules = {
|
|
||||||
reactorName: [
|
|
||||||
{ required: true, message: '请输入反应器名称', trigger: 'blur' },
|
|
||||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
|
||||||
],
|
|
||||||
reactorType: [
|
|
||||||
{ required: true, message: '请选择反应器类型', trigger: 'change' }
|
|
||||||
],
|
|
||||||
status: [
|
|
||||||
{ required: true, message: '请选择状态', trigger: 'change' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取反应器类型枚举列表 */
|
|
||||||
const getReactorTypeOptions = async () => {
|
|
||||||
try {
|
|
||||||
const res = await new ReactorApi().getReactorTypeEnumList()
|
|
||||||
reactorTypeOptions.value = res.data ?? []
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取反应器类型枚举列表失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
|
||||||
const open = (row?: ReactorDto) => {
|
|
||||||
visible.value = true
|
|
||||||
if (row) {
|
|
||||||
Object.assign(form, row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 提交表单 */
|
|
||||||
const submitForm = async () => {
|
|
||||||
if (!formRef.value) return
|
|
||||||
await formRef.value.validate(async (valid: boolean) => {
|
|
||||||
if (valid) {
|
|
||||||
try {
|
|
||||||
const api = new ReactorApi()
|
|
||||||
const res = form.id
|
|
||||||
? await api.update(form)
|
|
||||||
: await api.add(form)
|
|
||||||
if (res.success) {
|
|
||||||
ElMessage.success(form.id ? '修改成功' : '新增成功')
|
|
||||||
visible.value = false
|
|
||||||
emit('ok')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(form.id ? '修改失败:' : '新增失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 取消按钮 */
|
|
||||||
const cancel = () => {
|
|
||||||
visible.value = false
|
|
||||||
reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置表单 */
|
|
||||||
const reset = () => {
|
|
||||||
if (formRef.value) {
|
|
||||||
formRef.value.resetFields()
|
|
||||||
}
|
|
||||||
Object.assign(form, {
|
|
||||||
id: undefined,
|
|
||||||
reactorName: '',
|
|
||||||
reactorType: '',
|
|
||||||
status: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getReactorTypeOptions()
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.dialog-footer {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,224 +0,0 @@
|
|||||||
<template>
|
|
||||||
<my-layout>
|
|
||||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
|
||||||
<el-form :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
|
||||||
<el-form-item label="反应器名称" prop="reactorName">
|
|
||||||
<el-input v-model="state.filter.keyWord" placeholder="请输入反应器名称" clearable @keyup.enter="handleQuery" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="反应器类型" prop="reactorType">
|
|
||||||
<el-select v-model="state.filter.reactorType" placeholder="请选择反应器类型" clearable style="width: 200px">
|
|
||||||
<el-option v-for="item in state.reactorTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-select v-model="state.filter.status" placeholder="请选择状态" clearable style="width: 200px">
|
|
||||||
<el-option label="启用" :value="true" />
|
|
||||||
<el-option label="禁用" :value="false" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开始时间">
|
|
||||||
<el-date-picker v-model="state.filter.startTime" type="datetime" placeholder="选择开始时间"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" style="width: 180px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="结束时间">
|
|
||||||
<el-date-picker v-model="state.filter.endTime" type="datetime" placeholder="选择结束时间"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" style="width: 180px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="ele-Search" @click="handleQuery">查询</el-button>
|
|
||||||
<el-button v-auth="'api:admin:reactor:add'" type="primary" icon="ele-Plus" @click="handleAdd">新增</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card class="my-fill mt8" shadow="never">
|
|
||||||
<el-table v-loading="loading" :data="state.reactorList" row-key="id" style="width: 100%" border>
|
|
||||||
<el-table-column prop="reactorName" label="反应器名称" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="反应器类型" min-width="120" show-overflow-tooltip>
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ getReactorTypeName(row.reactorType) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" width="100" align="center">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-tag :type="row.status ? 'success' : 'danger'">
|
|
||||||
{{ row.status ? '启用' : '禁用' }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="createdUserName" label="创建者" min-width="100" show-overflow-tooltip />
|
|
||||||
<el-table-column prop="createdTime" label="创建时间" min-width="160" show-overflow-tooltip />
|
|
||||||
<el-table-column label="操作" width="180" fixed="right" header-align="center" align="center">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-button v-auth="'api:admin:reactor:update'" icon="ele-EditPen" size="small" text type="primary"
|
|
||||||
@click="handleEdit(row)">编辑</el-button>
|
|
||||||
<el-button v-auth="'api:admin:reactor:soft-delete'" icon="ele-Delete" size="small" text type="danger"
|
|
||||||
@click="handleDelete(row)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
|
||||||
<el-pagination v-model:current-page="state.pageInput.currentPage" v-model:page-size="state.pageInput.pageSize"
|
|
||||||
:total="state.total" :page-sizes="[10, 20, 50, 100]" size="small" background @size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange" layout="total, sizes, prev, pager, next, jumper" />
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<reactor-form ref="formRef" :title="state.formTitle" @ok="getList" />
|
|
||||||
</my-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, onMounted, onBeforeMount } from 'vue'
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
||||||
import { ReactorApi } from '../../../api/admin/ReactorApi'
|
|
||||||
import eventBus from '/@/utils/mitt'
|
|
||||||
import type {
|
|
||||||
ReactorPageInput,
|
|
||||||
ReactorDto,
|
|
||||||
ReactorTypeEnumItem
|
|
||||||
} from '../../../api/types/reactorType'
|
|
||||||
|
|
||||||
import ReactorForm from './components/reactor-form.vue'
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const formRef = ref()
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
loading: false,
|
|
||||||
formTitle: '',
|
|
||||||
total: 0,
|
|
||||||
filter: {
|
|
||||||
keyWord: "",
|
|
||||||
reactorType: "",
|
|
||||||
status: null,
|
|
||||||
startTime: "",
|
|
||||||
endTime: ""
|
|
||||||
},
|
|
||||||
pageInput: {
|
|
||||||
currentPage: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
} as ReactorPageInput,
|
|
||||||
reactorList: [] as Array<ReactorDto>,
|
|
||||||
reactorTypeOptions: [] as ReactorTypeEnumItem[]
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 查询列表 */
|
|
||||||
const getList = async () => {
|
|
||||||
loading.value = true
|
|
||||||
state.pageInput.filter = state.filter
|
|
||||||
try {
|
|
||||||
const res = await new ReactorApi().getPage(state.pageInput)
|
|
||||||
state.reactorList = res.data?.list || []
|
|
||||||
state.total = res.data?.total || 0
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取列表失败:', error)
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取反应器类型枚举列表 */
|
|
||||||
const getReactorTypeOptions = async () => {
|
|
||||||
try {
|
|
||||||
const res = await new ReactorApi().getReactorTypeEnumList()
|
|
||||||
state.reactorTypeOptions = res.data ?? []
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取反应器类型枚举列表失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getReactorTypeName = (reactorType: string) => {
|
|
||||||
const item = state.reactorTypeOptions.find(item => item.value === Number(reactorType))
|
|
||||||
return item?.label || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
|
||||||
const handleQuery = () => {
|
|
||||||
state.pageInput.currentPage = 1
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
|
||||||
const handleAdd = () => {
|
|
||||||
state.formTitle = '新增反应器'
|
|
||||||
formRef.value?.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
|
||||||
const handleEdit = (row: ReactorDto) => {
|
|
||||||
state.formTitle = '编辑反应器'
|
|
||||||
formRef.value?.open(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
|
||||||
const handleDelete = (row: ReactorDto) => {
|
|
||||||
ElMessageBox.confirm('确认要删除该记录吗?', '警告', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(async () => {
|
|
||||||
try {
|
|
||||||
const res = await new ReactorApi().softDelete({ id: row.id! })
|
|
||||||
if (res.success) {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('删除失败:', error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 每页条数改变 */
|
|
||||||
const handleSizeChange = (val: number) => {
|
|
||||||
state.pageInput.pageSize = val
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 当前页改变 */
|
|
||||||
const handleCurrentChange = (val: number) => {
|
|
||||||
state.pageInput.currentPage = val
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getReactorTypeOptions()
|
|
||||||
getList()
|
|
||||||
eventBus.on('refreshReactor', getList)
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
eventBus.off('refreshReactor')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.my-query-box {
|
|
||||||
:deep(.el-form-item) {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-fill {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-flex-end {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mt8 {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb8 {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
x
Reference in New Issue
Block a user