From 68473cefa689a71b22ee4b13e7a2298f2826d46d Mon Sep 17 00:00:00 2001
From: 董国庆 <364620639@qq.com>
Date: 星期四, 11 十二月 2025 10:11:25 +0800
Subject: [PATCH] 12.07 菌种库 除了谱系图内容
---
culture/src/views/strain-library/production-cell-library/index.vue | 4
culture/vue.config.js | 98 +-
culture/src/router/index.js | 52 +
culture/src/views/strain-library/production-cell-grandson/index.vue | 521 ++++++++++++++++++
culture/src/views/strain-library/production-cell-grandson/service.js | 56 ++
culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue | 2
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue | 2
culture/src/utils/baseurl.js | 9
culture/src/views/strain-library/validation/primitive-cell/index.vue | 4
culture/src/views/pedigree-chart/index.vue | 2
culture/src/views/strain-library/production-cell-grandson/add.vue | 439 +++++++++++++++
culture/src/views/strain-library/production-cell-grandson/record.vue | 437 +++++++++++++++
culture/src/views/strain-library/validation/chief-cell/index.vue | 6
culture/src/views/strain-library/breeding-record/index.vue | 9
culture/src/views/strain-library/validation/chief-cell/add.vue | 2
15 files changed, 1,567 insertions(+), 76 deletions(-)
diff --git a/culture/src/router/index.js b/culture/src/router/index.js
index 4e858a4..2114ac0 100644
--- a/culture/src/router/index.js
+++ b/culture/src/router/index.js
@@ -177,7 +177,7 @@
path: "strain-library-manage",
name: "StrainLibraryManage",
meta: {
- title: "原始细胞库",
+ title: "原始细胞库(原种登记)",
privilege:'strain_library_strain_library_manage'
},
component: () =>
@@ -219,7 +219,7 @@
path: "main-cell-library",
name: "MainCellLibrary",
meta: {
- title: "主细胞库",
+ title: "主细胞库(祖传母)",
privilege:'strain_library_main_cell_library'
},
component: () =>
@@ -249,7 +249,7 @@
path: "production-cell-library",
name: "ProductionCellLibrary",
meta: {
- title: "生产细胞库",
+ title: "子细胞库(母传子)",
privilege:'strain_library_production_cell_library'
},
component: () =>
@@ -264,6 +264,36 @@
},
component: () =>
import("../views/strain-library/production-cell-library/add.vue"),
+ },
+ {
+ path: "production-cell-grandson",
+ name: "ProductionCellGrandson",
+ meta: {
+ title: "孙细胞库(子传孙)",
+ privilege:'strain_library_production_cell_library'
+ },
+ component: () =>
+ import("../views/strain-library/production-cell-grandson"),
+ },
+ {
+ path: "production-cell-grandson/add",
+ name: "ProductionCellGrandsonAdd",
+ meta: {
+ title: "新增生产细胞",
+ hide: true,
+ },
+ component: () =>
+ import("../views/strain-library/production-cell-grandson/add.vue"),
+ },
+ {
+ path: "production-cell-grandson/edit",
+ name: "ProductionCellGrandsonAdd",
+ meta: {
+ title: "编辑生产细胞",
+ hide: true,
+ },
+ component: () =>
+ import("../views/strain-library/production-cell-grandson/add.vue"),
},
{
path: "production-cell-library/edit",
@@ -379,7 +409,7 @@
path: "primitive-cell",
name: "PrimitiveCell",
meta: {
- title: "原始细胞库资料",
+ title: "祖代菌种库验证资料",
privilege:'strain_validation_primitive_cell'
},
component: () =>
@@ -391,7 +421,7 @@
path: "add-primitive-cell",
name: "AddPrimitiveCell",
meta: {
- title: "新增原始细胞库资料",
+ title: "新增祖代菌种库验证资料",
hide: true,
},
component: () =>
@@ -403,7 +433,7 @@
path: "edit-primitive-cell",
name: "AddPrimitiveCell",
meta: {
- title: "编辑原始细胞库资料",
+ title: "编辑祖代菌种库验证资料",
hide: true,
},
component: () =>
@@ -415,7 +445,7 @@
path: "confirm-detail",
name: "ConfirmDetail",
meta: {
- title: "确认原始细胞库资料",
+ title: "确认祖代菌种库验证资料",
hide: true,
},
component: () =>
@@ -427,7 +457,7 @@
path: "chief-cell",
name: "ChiefCell",
meta: {
- title: "主细胞库资料",
+ title: "母代菌种库验证资料",
privilege:'strain_validation_chief_cell'
},
component: () =>
@@ -437,7 +467,7 @@
path: "add-chief-cell",
name: "AddChiefCell",
meta: {
- title: "新增主细胞库资料",
+ title: "新增母代菌种库验证资料",
hide: true,
},
component: () =>
@@ -447,7 +477,7 @@
path: "edit-chief-cell",
name: "EditChiefCell",
meta: {
- title: "编辑主细胞库资料",
+ title: "编辑母代菌种库验证资料",
hide: true,
},
component: () =>
@@ -457,7 +487,7 @@
path: "confirm-detail-chief",
name: "ConfirmDetailChief",
meta: {
- title: "确认主细胞库资料",
+ title: "确认母代菌种库验证资料",
hide: true,
},
component: () =>
diff --git a/culture/src/utils/baseurl.js b/culture/src/utils/baseurl.js
index 7b64940..fa72e83 100644
--- a/culture/src/utils/baseurl.js
+++ b/culture/src/utils/baseurl.js
@@ -2,13 +2,14 @@
// 开发环境
development: {
baseURL: "http://221.182.45.100:8081",
- imgUrl: "http://221.182.45.100:8081/open/file/upload",
- showImgUrl:'http://221.182.45.100:9998/'
+ imgUrl: "http://192.168.110.64:8081/open/file/upload",
+ showImgUrl:'http://192.168.110.64:9998/'
},
// 生产环境
production: {
- baseURL: "",
- imgUrl: "",
+ baseURL: "http://221.182.45.100:8081",
+ imgUrl: "http://221.182.45.100:8081/open/file/upload",
+ showImgUrl:'http://221.182.45.100:9998/'
},
};
diff --git a/culture/src/views/pedigree-chart/index.vue b/culture/src/views/pedigree-chart/index.vue
index 15d3c0e..8ed7a74 100644
--- a/culture/src/views/pedigree-chart/index.vue
+++ b/culture/src/views/pedigree-chart/index.vue
@@ -32,7 +32,7 @@
草稿箱
</div> -->
</div>
- <div class="flex a-center" v-if="roleType == 4">
+ <div class="flex a-center" v-if="roleType == 3">
<el-button @click="handleNewStrain" class="el-icon-plus" type="primary"
style="margin-right: 12px">新增祖代起传</el-button>
<el-button @click="handleBatchAdd" class="el-icon-plus" type="primary">新增母代起传</el-button>
diff --git a/culture/src/views/strain-library/breeding-record/index.vue b/culture/src/views/strain-library/breeding-record/index.vue
index 75e5ee4..56cb853 100644
--- a/culture/src/views/strain-library/breeding-record/index.vue
+++ b/culture/src/views/strain-library/breeding-record/index.vue
@@ -49,10 +49,13 @@
<span>{{ scope.row.preserveSource === 1 ? '来源菌株' : '来源物资' }}</span>
</template>
</el-table-column>
- <el-table-column prop="strainName" label="菌株名称">
+ <el-table-column prop="strainName" label="来源信息">
+ <template slot-scope="scope">
+ <span>{{ scope.row.preserveSource === 1 ? scope.row.strainName : scope.row.sourceMaterialTimeBatchNumber }}</span>
+ </template>
</el-table-column>
- <el-table-column prop="sourceMaterialTimeBatchNumber" label="来源物资、时间及批号">
- </el-table-column>
+ <!-- <el-table-column prop="sourceMaterialTimeBatchNumber" label="来源物资、时间及批号">
+ </el-table-column> -->
<el-table-column prop="cultureMedium" label="培养基"></el-table-column>
<el-table-column prop="temperature" label="培养温度"></el-table-column>
<el-table-column prop="aerobicType" label="需氧类型">
diff --git a/culture/src/views/strain-library/production-cell-grandson/add.vue b/culture/src/views/strain-library/production-cell-grandson/add.vue
new file mode 100644
index 0000000..bf1349f
--- /dev/null
+++ b/culture/src/views/strain-library/production-cell-grandson/add.vue
@@ -0,0 +1,439 @@
+<template>
+ <Card>
+ <el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form">
+ <div class="form-row three-columns">
+ <el-form-item label="菌种编号" prop="strainCode">
+ <el-input v-model="form.strainCode" placeholder="请输入"></el-input>
+ </el-form-item>
+ <el-form-item label="菌种名称" prop="strainName">
+ <el-input v-model="form.strainName" placeholder="请输入"></el-input>
+ </el-form-item>
+ <el-form-item label="菌种来源" prop="strainSource">
+ <el-input v-model="form.strainSource" placeholder="请输入"></el-input>
+ </el-form-item>
+ </div>
+
+ <div class="form-row">
+ <el-form-item label="鉴定方法" prop="appraisalMethod" class="full-width">
+ <el-input type="textarea" :rows="4" v-model="form.appraisalMethod" placeholder="请输入"></el-input>
+ </el-form-item>
+ </div>
+
+ <div class="form-row">
+ <el-form-item label="特征描述" prop="features" class="full-width">
+ <el-input type="textarea" v-model="form.features" :rows="4" placeholder="请输入"></el-input>
+ </el-form-item>
+ </div>
+
+ <div class="form-row three-columns">
+ <el-form-item label="保藏位置" prop="saveLocation">
+ <el-input v-model="form.saveLocation" placeholder="请输入"></el-input>
+ </el-form-item>
+ <el-form-item label="菌种保存方法" prop="saveMethod">
+ <el-input v-model="form.saveMethod" placeholder="请输入"></el-input>
+ </el-form-item>
+ <div class="form-item-placeholder"></div>
+ </div>
+
+ <div class="form-row">
+ <el-form-item label="备注" prop="remarks" class="full-width">
+ <el-input type="textarea" v-model="form.remark" :rows="4" placeholder="请输入"></el-input>
+ </el-form-item>
+ </div>
+
+ <div class="end-btn" style="margin-top: 38px">
+ <el-button type="primary" @click="handleSubmit(0)">提交</el-button>
+ <el-button v-if="!$route.query.id" type="primary" @click="handleBatchAdd">批量新增</el-button>
+ <el-button @click="handleSubmit(1)">存草稿</el-button>
+ </div>
+ </el-form>
+
+ <!-- 批量新增弹窗 -->
+ <el-dialog title="批量新增" :visible.sync="batchAddDialogVisible" width="520px" :close-on-click-modal="false"
+ :close-on-press-escape="false" custom-class="batch-add-dialog">
+ <div class="dialog-content">
+ <el-form :model="batchForm" ref="batchFormRef" label-position="top" class="batch-form">
+ <el-form-item label="批量新增数量" prop="count"
+ :rules="[{ required: true, message: '请输入批量新增数量', trigger: 'blur' }]">
+ <el-input v-model.number="batchForm.count" placeholder="请输入" />
+ </el-form-item>
+ </el-form>
+ <div class="dialog-notice">
+ <p>注意:操作批量新增后,系统会自动生成对应数量的菌种数据,</p>
+ <p>这些菌种的基础信息内容都是一致的,唯独菌种编号内容系统</p>
+ <p>不会自动生成,需要操作员自行编辑</p>
+ </div>
+ </div>
+ <template #footer>
+ <div class="end-btn">
+ <el-button type="primary" @click="handleConfirmBatchAdd">确认新增</el-button>
+ </div>
+ </template>
+ </el-dialog>
+
+ <!-- 签字确认组件 -->
+ <SignatureCanvas :visible.sync="signatureVisible" @confirm="handleSignatureConfirm" />
+ </Card>
+</template>
+
+<script>
+import SignatureCanvas from '@/components/SignatureCanvas.vue'
+import { add, edit, getDetail, addBatch } from './service'
+
+export default {
+ name: 'StrainLibraryManageAdd',
+ components: {
+ SignatureCanvas
+ },
+ data() {
+ return {
+ batchAddDialogVisible: false,
+ signatureVisible: false,
+ currentAction: '', // 'submit' or 'batchAdd'
+ batchForm: {
+ count: ''
+ },
+ form: {
+ strainCode: '',
+ strainName: '',
+ source: '',
+ appraisalMethod: '',
+ characteristics: '',
+ storageLocation: '',
+ preservationMethod: '',
+ remark: ''
+ },
+ rules: {
+ strainCode: [{
+ validator: (rule, value, callback) => {
+ if (this.currentAction === 'submit' && !value) {
+ callback(new Error('请输入菌种编号'));
+ } else {
+ callback();
+ }
+ },
+ trigger: 'change'
+ }],
+ strainName: [{ required: true, message: '请输入菌种名称', trigger: 'blur' }],
+ strainSource: [{ required: true, message: '请输入菌种来源', trigger: 'blur' }],
+ appraisalMethod: [{ required: true, message: '请输入鉴定方法', trigger: 'blur' }],
+ features: [{ required: true, message: '请输入特征描述', trigger: 'blur' }],
+ saveLocation: [{ required: true, message: '请输入保存位置', trigger: 'blur' }],
+ saveMethod: [{ required: true, message: '请输入菌种保存方法', trigger: 'blur' }]
+ }
+ }
+ },
+ mounted() {
+ this.form = {
+ strainCode: '',
+ strainName: '',
+ source: '',
+ appraisalMethod: '',
+ characteristics: '',
+ storageLocation: '',
+ preservationMethod: '',
+ remark: ''
+ }
+ if (this.$route.query.id) {
+ getDetail({ id: this.$route.query.id }).then(res => {
+ this.form = res
+ })
+ }
+ },
+ watch: {
+ '$route.query.id'() {
+ this.form = {
+ strainCode: '',
+ strainName: '',
+ source: '',
+ appraisalMethod: '',
+ characteristics: '',
+ storageLocation: '',
+ preservationMethod: '',
+ remark: ''
+ }
+ }
+ },
+ methods: {
+ handleSubmit(isDraft) {
+ this.currentAction = 'submit'
+ this.$refs.strainForm.validate((valid) => {
+ if (valid) {
+ this.form.isDraft = isDraft
+ if (isDraft == 1) {
+ //存草稿
+ this.handleSignatureConfirm('')
+ } else {
+ this.signatureVisible = true
+ }
+ }
+ })
+ },
+ handleBatchAdd() {
+ this.currentAction = 'batchAdd'
+ this.$refs.strainForm.validate((valid) => {
+ if (valid) {
+ this.batchAddDialogVisible = true
+ }
+ })
+ },
+ handleConfirmBatchAdd() {
+ this.$refs.batchFormRef.validate((valid) => {
+ if (valid) {
+ this.batchAddDialogVisible = false
+ this.signatureVisible = true
+ }
+ })
+ },
+ async handleSignatureConfirm(signatureImage) {
+ let requestData = {
+ strainCode: this.form.strainCode,
+ strainName: this.form.strainName,
+ strainSource: this.form.strainSource,
+ appraisalMethod: this.form.appraisalMethod,
+ features: this.form.features,
+ saveLocation: this.form.saveLocation,
+ saveMethod: this.form.saveMethod,
+ remark: this.form.remark,
+ signature: signatureImage,
+ type: 4,
+ };
+ if (this.currentAction === 'batchAdd') {
+ requestData.batchCount = this.batchForm.count;
+ } else {
+ requestData.isDraft = this.form.isDraft
+ }
+ try {
+ if (this.$route.query.id) {
+ requestData.id = this.$route.query.id;
+ await edit(requestData);
+ } else if (this.currentAction === 'batchAdd') {
+ await addBatch(requestData);
+ } else {
+ await add(requestData);
+ }
+ this.signatureVisible = false;
+ this.$router.push({ path: '/strain-library/production-cell-grandson' });
+ this.$message.success('操作成功');
+ } catch (error) {
+ this.$message.error('操作失败');
+ }
+ }
+ }
+}
+</script>
+
+<style scoped lang="less">
+.add-strain {
+ height: 100%;
+ background: #F5F7FA;
+
+ .form-card {
+ background: #fff;
+ border-radius: 8px;
+ }
+}
+
+.header-title {
+ margin-bottom: 24px;
+
+ &-left {
+ display: flex;
+ align-items: center;
+
+ img {
+ width: 20px;
+ height: 20px;
+ margin-right: 8px;
+ }
+
+ div {
+ font-size: 18px;
+ font-weight: bold;
+ color: #303133;
+ }
+ }
+}
+
+.end-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+
+ button {
+ width: 180px;
+ height: 36px;
+ // background: #409EFF;
+ }
+}
+
+.strain-form {
+ padding: 0 40px;
+
+ .form-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 24px;
+ margin-bottom: 24px;
+
+ &.three-columns {
+
+ .el-form-item,
+ .form-item-placeholder {
+ flex: 1;
+ min-width: 280px;
+
+ @media screen and (max-width: 1200px) {
+ min-width: calc(50% - 12px);
+ }
+
+ @media screen and (max-width: 768px) {
+ min-width: 100%;
+ }
+ }
+
+ .form-item-placeholder {
+ @media screen and (max-width: 1200px) {
+ display: none;
+ }
+ }
+ }
+
+ .el-form-item {
+ margin-bottom: 0;
+
+ &.full-width {
+ width: 100%;
+ }
+ }
+ }
+
+ :deep(.el-form-item__label) {
+ font-weight: normal;
+ color: #606266;
+ padding-bottom: 8px;
+ line-height: 20px;
+ }
+
+ :deep(.el-form-item__content) {
+ line-height: unset;
+ }
+
+ :deep(.el-input__inner) {
+ border-radius: 4px;
+ height: 36px;
+ line-height: 36px;
+ }
+
+ :deep(.el-textarea__inner) {
+ border-radius: 4px;
+ padding: 8px 12px;
+ min-height: 120px;
+ }
+}
+
+.batch-add-dialog {
+ :deep(.el-dialog__header) {
+ margin: 0;
+ padding: 20px;
+ text-align: center;
+ border-bottom: 1px solid #EBEEF5;
+
+ .el-dialog__title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ :deep(.el-dialog__body) {
+ padding: 20px;
+ }
+
+ .dialog-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .batch-form {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ :deep(.el-form-item) {
+ width: 320px;
+ margin-bottom: 0;
+ }
+
+ :deep(.el-form-item__label) {
+ width: 100%;
+ color: #606266;
+ font-weight: normal;
+ padding-bottom: 8px;
+
+ &::before {
+ color: #F56C6C;
+ }
+ }
+
+ :deep(.el-input) {
+ width: 100%;
+
+ input {
+ width: 100%;
+ }
+ }
+ }
+
+ .dialog-notice {
+ margin-top: 16px;
+ text-align: center;
+
+ p {
+ margin: 0;
+ line-height: 22px;
+ color: #606266;
+ font-size: 14px;
+ }
+ }
+
+ :deep(.el-dialog__footer) {
+ padding: 0 20px 20px;
+ text-align: center;
+
+ .el-button {
+ width: 180px;
+ height: 36px;
+ padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 14px;
+ border-radius: 4px;
+ margin: 0;
+ }
+ }
+}
+
+.end-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+
+ :deep(.el-button) {
+ width: 180px;
+ height: 36px;
+ padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 14px;
+ border-radius: 4px;
+ margin: 0;
+ }
+}
+</style>
\ No newline at end of file
diff --git a/culture/src/views/strain-library/production-cell-grandson/index.vue b/culture/src/views/strain-library/production-cell-grandson/index.vue
new file mode 100644
index 0000000..191b75b
--- /dev/null
+++ b/culture/src/views/strain-library/production-cell-grandson/index.vue
@@ -0,0 +1,521 @@
+<template>
+ <div class="list">
+ <el-card class="header-box">
+ <div class="box-title">
+ <img src="@/assets/public/notice.png" class="header-icon" />
+ <span>菌种源保藏出/入细胞库登记表说明</span>
+ <el-button type="text" class="view-more" @click="handleViewMore"
+ >查看全部 >></el-button
+ >
+ </div>
+ <div class="header-content" :class="{ collapsed: true }">
+ <p> 1. 菌种全部集中登记在【菌种源保藏出/入细胞库登记表】,菌种来源有 3条路径。</p>
+ <p> 1.1 是沙土管或甘油管的源头菌种;入原始细胞库(祖代-O)。</p>
+ <p> 1.2 是斜面的源头菌种;接种入主细胞库(祖代-O)。经过育种、验证后,菌种保藏为甘油管或沙土管的,入原始细胞库(祖代-0)</p>
+ <p> 1.3 是含菌物质自己分离后获得的斜面源头菌种,接种入主细胞库;经生产验证后,保藏为沙土管或甘油管,入原始细胞库(祖代-O)。</p>
+ <p> 2.菌种细胞库,分类入三库,进行传代运行管理。三类库存空间进行区分,保藏菌种。</p>
+ <p> 2.1 原始细胞库(祖代-O)、2.2 主细胞库(母代-M)、 </p>
+ <p> 2.3 生产细胞库(子代-S)、(孙代-G)</p>
+ <p> 3. 细胞库编码规则 </p>
+ <p>3.1
+ 细胞库编码规则:DD-M-240919-01-(O-0109-01)DD:代表项目组。M:“O”代表祖代原始细胞库,”M“代表母代主细胞库,”S“代表子代生产细胞库,“G”代表孙代生产细胞库。240919:代表在24 年
+ 9 月 19
+ 接种批次的菌种;或收到外来菌种时间的入库批次。01:代表两位序列号。(O-0109-01):代表传代菌种的编号</p>
+ <p>3.1.1
+ 传代编码方式演例:祖代:DD-O-240919-01传母代:DD-M-241017-01-(O-091901)DD-M-241017-02-(O-091901)DD-M-241017-03-(O-091901)子代:DD-S-241019-01-(M-1017-02)版权归奥利元生物所有,禁止外传。DD-S-241019-02-(M-1017-03)孙代:DD-G-241109-01-(S-1019-02)3.1.2编码规则实现了编码唯一,编码可溯源,编码直观、方便。</p>
+ <p> 3.2 细胞库说明:</p>
+ <p> 3.2.1 直接购买、自行从(土壤、相关物料、商品)等分离出来菌株进入原始细胞库。</p>
+ <p> 3.2.2 从原始细胞库中选取出来再次纯化、改造、提高性能的菌株进入主细胞库。</p>
+ <p> 3.2.3 主细胞库中选取出稳定,生产性能良好的菌株扩培后保种进入生产细胞库。</p>
+ <p> 4.菌种选育-保藏过程编号说明4.1 菌种选育时,培养皿的编号可使用 a-01、a-02等用于清晰形态观察记录;菌落编号使用序号 1/2/3等。</p>
+ <p> 4.2 接种斜面菌种编码(-O)使用原始细胞库编码;斜面转菌种保藏使用与斜面一致的编码(-O);斜面传代入主细胞库的传代菌种,按编码器规则编码(-M)。</p>
+ </div>
+
+ <!-- 查看全部弹窗 -->
+ <el-dialog
+ title="菌种源保藏出/入细胞库登记表说明"
+ :visible.sync="dialogVisible"
+ width="50%"
+ class="view-all-dialog"
+ >
+ <div class="dialog-content">
+ <p> 1. 菌种全部集中登记在【菌种源保藏出/入细胞库登记表】,菌种来源有 3条路径。</p>
+ <p> 1.1 是沙土管或甘油管的源头菌种;入原始细胞库(祖代-O)。</p>
+ <p> 1.2 是斜面的源头菌种;接种入主细胞库(祖代-O)。经过育种、验证后,菌种保藏为甘油管或沙土管的,入原始细胞库(祖代-0)</p>
+ <p> 1.3 是含菌物质自己分离后获得的斜面源头菌种,接种入主细胞库;经生产验证后,保藏为沙土管或甘油管,入原始细胞库(祖代-O)。</p>
+ <p> 2.菌种细胞库,分类入三库,进行传代运行管理。三类库存空间进行区分,保藏菌种。</p>
+ <p> 2.1 原始细胞库(祖代-O)、2.2 主细胞库(母代-M)、 </p>
+ <p> 2.3 生产细胞库(子代-S)、(孙代-G)</p>
+ <p> 3. 细胞库编码规则 </p>
+ <p>3.1
+ 细胞库编码规则:DD-M-240919-01-(O-0109-01)DD:代表项目组。M:“O”代表祖代原始细胞库,”M“代表母代主细胞库,”S“代表子代生产细胞库,“G”代表孙代生产细胞库。240919:代表在24 年
+ 9 月 19
+ 接种批次的菌种;或收到外来菌种时间的入库批次。01:代表两位序列号。(O-0109-01):代表传代菌种的编号</p>
+ <p>3.1.1
+ 传代编码方式演例:祖代:DD-O-240919-01传母代:DD-M-241017-01-(O-091901)DD-M-241017-02-(O-091901)DD-M-241017-03-(O-091901)子代:DD-S-241019-01-(M-1017-02)版权归奥利元生物所有,禁止外传。DD-S-241019-02-(M-1017-03)孙代:DD-G-241109-01-(S-1019-02)3.1.2编码规则实现了编码唯一,编码可溯源,编码直观、方便。</p>
+ <p> 3.2 细胞库说明:</p>
+ <p> 3.2.1 直接购买、自行从(土壤、相关物料、商品)等分离出来菌株进入原始细胞库。</p>
+ <p> 3.2.2 从原始细胞库中选取出来再次纯化、改造、提高性能的菌株进入主细胞库。</p>
+ <p> 3.2.3 主细胞库中选取出稳定,生产性能良好的菌株扩培后保种进入生产细胞库。</p>
+ <p> 4.菌种选育-保藏过程编号说明4.1 菌种选育时,培养皿的编号可使用 a-01、a-02等用于清晰形态观察记录;菌落编号使用序号 1/2/3等。</p>
+ <p> 4.2 接种斜面菌种编码(-O)使用原始细胞库编码;斜面转菌种保藏使用与斜面一致的编码(-O);斜面传代入主细胞库的传代菌种,按编码器规则编码(-M)。</p>
+ </div>
+ </el-dialog>
+ </el-card>
+
+ <!-- Table -->
+ <TableCustom
+ :queryForm="queryForm"
+ :tableData="tableData"
+ :total="total"
+ @handleCurrentChange="handleCurrentChange"
+ @handleSizeChange="handleSizeChange"
+ >
+ <template #search>
+ <el-form :model="form" label-width="auto" inline>
+ <el-form-item label="菌种编号:">
+ <el-input v-model="form.strainNo" placeholder="请输入"></el-input>
+ </el-form-item>
+ <el-form-item label="菌种名称:">
+ <el-input v-model="form.strainName" placeholder="请输入"></el-input>
+ </el-form-item>
+ <el-form-item v-if="roleType == 4" label="状态:">
+ <el-select v-model="form.status" placeholder="请选择">
+ <el-option label="全部" value=""></el-option>
+ <el-option label="已出库" value="1"></el-option>
+ <el-option label="出库待确认" value="2"></el-option>
+ <el-option label="已入库" value="3"></el-option>
+ <el-option label="入库待确认" value="4"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item class="search-btn-box">
+ <el-button type="default" @click="resetForm">重置</el-button>
+ <el-button type="primary" @click="searchData">查询</el-button>
+ </el-form-item>
+ </el-form>
+ </template>
+
+ <template #setting>
+ <div class="tableTitle">
+ <div class="flex a-center">
+ <div
+ class="title"
+ :class="{ active: currentType === 'list' }"
+ @click="handleTypeChange('list')"
+ >
+ 孙细胞列表
+ </div>
+ <div
+ class="drafts"
+ :class="{ active: currentType === 'draft' }"
+ @click="handleTypeChange('draft')"
+ >
+ 草稿箱
+ </div>
+ </div>
+ <div v-if="roleType == 4" class="flex a-center">
+ <el-button
+ @click="handleNewStrain"
+ class="el-icon-plus"
+ type="primary"
+ style="margin-right: 12px"
+ >新增孙细胞</el-button
+ >
+ <el-button
+ @click="handleNewStrain"
+ class="el-icon-plus"
+ type="primary"
+ >批量新增</el-button
+ >
+ </div>
+ </div>
+ </template>
+
+ <template #table>
+ <el-table-column prop="strainCode" label="菌种编号" />
+ <el-table-column prop="strainName" label="菌种名称" />
+ <el-table-column prop="strainSource" label="菌种来源" />
+ <el-table-column prop="appraisalMethod" label="鉴定方法" />
+ <el-table-column prop="features" label="特征描述" >
+ <template #default="{ row }">
+ <el-tooltip :content="row.features" placement="top" effect="dark">
+ <div class="ellipsis-text">{{ row.features }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="saveMethod" label="菌种保存方法" />
+ <el-table-column prop="saveLocation" label="保藏位置" />
+ <el-table-column prop="stock" label="库存余量" />
+ <el-table-column prop="remark" label="备注" >
+ <template #default="{ row }">
+ <el-tooltip popper-class="custom-tooltip" :content="row.remark" style="width: 200px;" placement="top" effect="dark">
+ <div class="ellipsis-text">{{ row.remark }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-if="currentType === 'list'"
+ prop="status"
+ label="当前状态"
+ >
+ <template #default="{ row }">
+ <el-tag :type="getStatusType(row.status)">{{
+ getStatusText(row.status)
+ }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" width="200">
+ <template #default="{ row }">
+ <el-button style="margin-right: 10px;" type="text" @click="handleDetail(row)">详情</el-button>
+ <el-button style="margin-right: 10px;" v-if="row.status == 2 || row.status == 4" type="text" @click="handleEdit(row)">编辑</el-button>
+ <el-button
+ style="margin-right: 10px;"
+ v-if="currentType === 'list'"
+ type="text"
+ @click="handleRecord(row)"
+ >出入库记录</el-button
+ >
+ <el-button v-if="roleType == 1" type="text" @click="handleDelete(row)">删除</el-button>
+ </template>
+ </el-table-column>
+ </template>
+ </TableCustom>
+ <StrainDetail title="生产细胞库" :visible.sync="detailVisible" :detail="currentDetail" />
+ </div>
+</template>
+
+<script>
+import StrainDetail from "../strain-library-manage/components/StrainDetail.vue";
+import { getList, deleteStrainLibrary } from "../strain-library-manage/service";
+
+export default {
+ name: "StrainLibraryManage",
+ components: {
+ StrainDetail,
+ },
+ data() {
+ return {
+ dialogVisible: false,
+ currentType: "list",
+ detailVisible: false,
+ currentDetail: {},
+ form: {
+ strainNo: "",
+ strainName: "",
+ status: "",
+ },
+ queryForm: {
+ pageSize: 10,
+ pageNum: 1,
+ },
+ total: 800,
+ tableData: [],
+ roleType: "",
+ };
+ },
+ created() {
+ this.searchData();
+ // 角色类型 1=超级管理员 2=审批人 3=工程师 4=实验员
+ this.roleType = JSON.parse(sessionStorage.getItem("userInfo")).roleType;
+ },
+ activated() {
+ this.searchData();
+ // 角色类型 1=超级管理员 2=审批人 3=工程师 4=实验员
+ this.roleType = JSON.parse(sessionStorage.getItem("userInfo")).roleType;
+ },
+ methods: {
+ handleDelete(row) {
+ this.$confirm("确定删除该数据吗?", "提示", {
+ confirmButtonText: "确定",
+ cancelButtonText: "取消",
+ type: "warning",
+ }).then(() => {
+ deleteStrainLibrary({ id: row.id }).then((res) => {
+ this.$message.success("删除成功");
+ this.searchData();
+ });
+ });
+ },
+ handleRecord(row) {
+ this.$router.push({
+ path: `/strain-library/strain-library-manage/record?id=${row.id}&type=4`,
+ });
+ },
+ handleNewStrain() {
+ this.$router.push({ path: "/strain-library/production-cell-grandson/add" });
+ },
+ handleEdit(row) {
+ this.$router.push({
+ path: `/strain-library/production-cell-grandson/edit?id=${row.id}`,
+ });
+ },
+ handleDetail(row) {
+ this.currentDetail = row;
+ this.detailVisible = true;
+ },
+ handleViewMore() {
+ this.dialogVisible = true;
+ },
+ resetForm() {
+ this.form = {
+ strainNo: "",
+ strainName: "",
+ status: "",
+ };
+ this.searchData();
+ },
+ searchData() {
+ const params = {
+ pageNum: this.queryForm.pageNum,
+ pageSize: this.queryForm.pageSize,
+ strainCode: this.form.strainNo,
+ strainName: this.form.strainName,
+ isDraft: this.currentType === "draft" ? 1 : 0,
+ status: this.form.status,
+ type: 4,
+ };
+ getList(params)
+ .then((res) => {
+ if (res.code === 200) {
+ this.tableData = res.data.records;
+ this.total = res.data.total;
+ }
+ })
+ .catch((err) => {
+ this.$message.error("数据加载失败");
+ });
+ },
+ handleCurrentChange(page) {
+ this.queryForm.pageNum = page;
+ this.searchData();
+ },
+ handleSizeChange(size) {
+ this.queryForm.pageSize = size;
+ this.searchData();
+ },
+ handleTypeChange(type) {
+ this.currentType = type;
+ this.searchData();
+ },
+ getStatusType(status) {
+ const types = {
+ 1: "info",
+ 2: "success",
+ 3: "info",
+ 4: "warning",
+ };
+ return types[status] || "info";
+ },
+ getStatusText(status) {
+ const texts = {
+ 1: "已出库",
+ 2: "出库待确认",
+ 3: "已入库",
+ 4: "入库待确认",
+ };
+ return texts[status] || "未知状态";
+ },
+ },
+};
+</script>
+
+<style scoped lang="less">
+.list {
+ padding: 20px;
+}
+
+.header-box {
+ margin-bottom: 20px;
+ border-radius: 16px;
+ background: rgba(255, 255, 255, 0.8);
+
+ .box-title {
+ display: flex;
+ align-items: center;
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 15px;
+ position: relative;
+
+ .header-icon {
+ width: 20px;
+ height: 20px;
+ margin-right: 10px;
+ }
+
+ .view-more {
+ position: absolute;
+ right: 0;
+ color: #049c9a;
+ }
+ }
+
+ .header-content {
+ color: rgba(0, 0, 0, 0.88);
+ font-size: 14px;
+ line-height: 1.8;
+ margin-left: 30px;
+ transition: max-height 0.3s ease-in-out;
+ overflow: hidden;
+
+ &.collapsed {
+ max-height: 130px;
+ overflow: hidden;
+ }
+
+ p {
+ margin: 5px 0;
+ }
+ }
+}
+
+.search-form {
+ margin-bottom: 20px;
+ background: #f5f7fa;
+ padding: 24px;
+ border-radius: 8px;
+
+ .el-form-item {
+ margin-right: 20px;
+ margin-bottom: 0;
+ }
+
+ .el-button {
+ margin-left: 10px;
+ }
+}
+
+.action-buttons {
+ margin-bottom: 20px;
+
+ .el-button {
+ margin-right: 10px;
+ }
+}
+
+.tab-container {
+ display: flex;
+ margin-bottom: 20px;
+
+ .tab {
+ padding: 10px 30px;
+ border: 1px solid #dcdfe6;
+ border-bottom: none;
+ border-radius: 8px 8px 0 0;
+ cursor: pointer;
+ margin-right: 10px;
+ background: #f5f7fa;
+
+ &.active {
+ background: #fff;
+ border-color: #049c9a;
+ color: #049c9a;
+ font-weight: bold;
+ }
+ }
+}
+
+.flex {
+ display: flex;
+ align-items: center;
+}
+
+.tableTitle {
+ display: flex;
+ padding-bottom: 20px;
+ justify-content: space-between;
+ align-items: center;
+
+ .title {
+ background: #fafafc;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #dcdfe6;
+ font-weight: bold;
+ font-size: 18px;
+ color: #606266;
+ width: unset;
+ cursor: pointer;
+ height: 50px;
+ line-height: 50px;
+ width: 166px;
+ text-align: center;
+ }
+
+ .drafts {
+ background: #fafafc;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #dcdfe6;
+ font-weight: 400;
+ font-size: 18px;
+ color: #606266;
+ margin-left: 16px;
+ cursor: pointer;
+ height: 50px;
+ line-height: 50px;
+ width: 166px;
+ text-align: center;
+ }
+
+ .active {
+ color: #049c9a;
+ background: #ffffff;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #049c9a;
+ }
+}
+
+.view-all-dialog {
+ :deep(.el-dialog__header) {
+ padding: 20px;
+ border-bottom: 1px solid #ebeef5;
+ margin-right: 0;
+
+ .el-dialog__title {
+ font-size: 18px;
+ font-weight: bold;
+ color: #303133;
+ }
+ }
+
+ :deep(.el-dialog__body) {
+ padding: 20px;
+
+ .dialog-content {
+ font-size: 14px;
+ line-height: 1.8;
+ color: #606266;
+
+ p {
+ margin: 12px 0;
+
+ &:first-child {
+ margin-top: 0;
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+ }
+}
+
+
+.ellipsis-text {
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-all;
+}
+</style>
+
+<style lang="less">
+.custom-tooltip {
+ width: 200px !important;
+ max-width: 200px !important;
+ white-space: normal;
+ word-break: break-all;
+}
+</style>
diff --git a/culture/src/views/strain-library/production-cell-grandson/record.vue b/culture/src/views/strain-library/production-cell-grandson/record.vue
new file mode 100644
index 0000000..4405c4e
--- /dev/null
+++ b/culture/src/views/strain-library/production-cell-grandson/record.vue
@@ -0,0 +1,437 @@
+<template>
+ <div class="record-page">
+ <!-- 基本信息展示区域 -->
+ <el-card class="header-box">
+ <div class="header-content">
+ <!-- 第一行 -->
+ <div class="info-row">
+ <div class="info-item left-column">
+ <span class="label">菌种编号:</span>
+ <span class="value">{{ detail.strainCode }}</span>
+ </div>
+ <div class="info-item flex-column">
+ <span class="label">鉴定方法:</span>
+ <span class="value">{{ detail.appraisalMethod }}</span>
+ </div>
+ <div class="info-item flex-column">
+ <span class="label">保藏位置:</span>
+ <span class="value">{{ detail.saveLocation }}</span>
+ </div>
+ </div>
+
+ <!-- 第二行 -->
+ <div class="info-row">
+ <div class="info-item left-column">
+ <span class="label">菌种名称:</span>
+ <span class="value">{{ detail.strainName }}</span>
+ </div>
+ <div class="info-item flex-column full-width">
+ <span class="label">特性描述:</span>
+ <span class="value">{{ detail.features }}</span>
+ </div>
+ </div>
+
+ <!-- 第三行 -->
+ <div class="info-row">
+ <div class="info-item left-column">
+ <span class="label">菌种来源:</span>
+ <span class="value">{{ detail.strainSource }}</span>
+ </div>
+ <div class="info-item flex-column">
+ <span class="label">菌种保存方法:</span>
+ <span class="value">{{ detail.saveMethod }}</span>
+ </div>
+ </div>
+ </div>
+ </el-card>
+
+ <!-- 出入库记录表格 -->
+ <TableCustom
+ :queryForm="queryForm"
+ :tableData="recordList"
+ :total="total"
+ @currentChange="handlePageChange"
+ >
+ <template #setting>
+ <div class="tableTitle">
+ <div class="flex a-center">
+ <div
+ class="title"
+ :class="{ active: currentType === 'table' }"
+ @click="handleTypeChange('table')"
+ >
+ 原始细胞保藏出/入库登记表
+ </div>
+ <div
+ class="drafts"
+ :class="{ active: currentType === 'timeline' }"
+ @click="handleTypeChange('timeline')"
+ >
+ 原始细胞保藏出/入库时间轴
+ </div>
+ </div>
+ <div class="flex a-center">
+ <el-button
+ v-if="roleType == 4"
+ @click="handleAddRecord"
+ class="el-icon-plus"
+ type="primary"
+ >新增出入库记录</el-button
+ >
+ </div>
+ </div>
+ </template>
+
+ <template #table v-if="currentType === 'table'">
+ <el-table-column prop="type" label="出库/入库">
+ <template #default="{ row }">
+ <span>
+ {{ row.type === 1 ? "出库" : "入库" }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="boundTime" label="操作时间" />
+ <el-table-column prop="handleSignature" label="操作人签字">
+ <template #default="{ row }">
+ <el-image
+ v-if="row.handleSignature"
+ style="width: 100px; height: 100px"
+ :src="row.handleSignature"
+ :preview-src-list="[row.handleSignature]"
+ >
+ </el-image>
+ </template>
+ </el-table-column>
+ <el-table-column prop="preserveSignature" label="菌种保藏人签字">
+ <template #default="{ row }">
+ <el-image
+ v-if="row.preserveSignature"
+ style="width: 100px; height: 100px"
+ :src="row.preserveSignature"
+ :preview-src-list="[row.preserveSignature]"
+ >
+ </el-image>
+ </template>
+ </el-table-column>
+ <el-table-column prop="status" label="状态">
+ <template #default="{ row }">
+ <el-tag :type="row.preserveSignature ? 'success' : 'warning'">
+ {{ row.preserveSignature ? "已确认" : "待确认" }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" width="180">
+ <template #default="{ row }">
+ <el-button
+ v-if="!row.preserveSignature && roleType == 3"
+ type="text"
+ class="operation-btn"
+ @click="handleConfirm(row)"
+ >确认</el-button
+ >
+ <el-button
+ type="text"
+ class="operation-btn"
+ @click="handleView(row)"
+ >详情</el-button
+ >
+ <el-button v-if="roleType == 1" type="text" @click="handleDelete(row)">删除</el-button>
+ </template>
+ </el-table-column>
+ </template>
+ <template #tableCustom v-if="currentType === 'timeline'">
+ <record-timeline :list="timelineList" />
+ </template>
+ </TableCustom>
+
+ <!-- 详情弹窗 -->
+ <record-detail-dialog
+ :visible.sync="dialogVisible"
+ :record-data="currentRecord"
+ @close="handleDialogClose"
+ @confirm="handleOutbound"
+ :type="dialogType"
+ />
+ <!-- 新增出入库记录弹窗 -->
+ <add-record-dialog
+ :visible.sync="addDialogVisible"
+ @confirm="handleAddRecordConfirm"
+ />
+ </div>
+</template>
+
+<script>
+import RecordDetailDialog from "../strain-library-manage/components/RecordDetailDialog.vue";
+import AddRecordDialog from "../strain-library-manage/components/AddRecordDialog.vue";
+import RecordTimeline from "../strain-library-manage/components/RecordTimeline.vue";
+import {
+ timeList,
+ getDetail,
+ addWarehousing,
+ getDetailById,
+ confirmWarehousing,
+} from "./service";
+
+export default {
+ name: "StrainRecord",
+ components: {
+ RecordDetailDialog,
+ AddRecordDialog,
+ RecordTimeline,
+ },
+ data() {
+ return {
+ currentType: "table",
+ detail: {},
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
+ queryForm: {
+ pageSize: 10,
+ pageNum: 1,
+ },
+ recordList: [],
+ timelineList: [],
+ dialogVisible: false,
+ currentRecord: {},
+ addDialogVisible: false,
+ dialogType: "detail",
+ roleType: "",
+ };
+ },
+ activated() {
+ this.roleType = JSON.parse(sessionStorage.getItem("userInfo")).roleType;
+
+ // 获取路由参数中的菌种信息
+ const strainId = this.$route.query.id;
+ this.queryForm.id = strainId;
+ if (strainId) {
+ this.getStrainDetail(strainId);
+ this.getRecordList();
+ }
+ },
+ methods: {
+ handleDelete(row) {
+ this.$confirm("确定删除该数据吗?", "提示", {
+ confirmButtonText: "确定",
+ cancelButtonText: "取消",
+ type: "warning",
+ }).then(() => {
+ deleteWarehousing({ id: row.id }).then((res) => {
+ this.$message.success("删除成功");
+ this.getRecordList();
+ });
+ });
+ },
+ getStrainDetail(id) {
+ // 这里应该调用接口获取菌种详情
+ getDetail({ id }).then((res) => {
+ this.detail = res;
+ });
+ },
+ getRecordList() {
+ // 这里应该调用接口获取出入库记录
+ timeList(this.queryForm).then((res) => {
+ this.timelineList = res.data;
+ });
+ getDetailById({ id: this.$route.query.id }).then((res) => {
+ this.recordList = res.warehousingList.records;
+ this.total = res.warehousingList.total;
+ });
+ },
+ handleView(row) {
+ this.dialogType = "detail";
+ this.currentRecord = row;
+ this.dialogVisible = true;
+ },
+ handleConfirm(row) {
+ this.dialogType = "confirm";
+ this.currentRecord = row;
+ this.dialogVisible = true;
+ },
+ handlePageChange(page) {
+ this.queryForm.pageNum = page;
+ // 这里应该调用接口获取对应页码的数据
+ },
+ handleTypeChange(type) {
+ this.currentType = type;
+ },
+ handleAddRecord() {
+ this.addDialogVisible = true;
+ },
+ handleDialogClose() {
+ this.currentRecord = {};
+ this.dialogVisible = false;
+ },
+ handleOutbound(data) {
+ // 这里调用出库API
+ confirmWarehousing({
+ id: this.currentRecord.id,
+ preserveSignature: data.preserveSignature,
+ }).then((res) => {
+ if (res.code == 200) {
+ this.$message.success("操作成功");
+ this.dialogVisible = false;
+ // 刷新列表
+ this.getRecordList();
+ } else {
+ this.$message.error(res.msg);
+ }
+ });
+ },
+ handleAddRecordConfirm(record) {
+ addWarehousing({ ...record, trainLibraryId: this.$route.query.id }).then(
+ (res) => {
+ this.$message.success("操作成功");
+ this.getRecordList();
+ }
+ );
+ },
+ goBack() {
+ this.$router.go(-1);
+ },
+ },
+};
+</script>
+
+<style lang="less" scoped>
+.record-page {
+ min-height: 100vh;
+
+ .header-box {
+ margin-bottom: 20px;
+ border-radius: 16px;
+ background: rgba(255, 255, 255, 0.8);
+ height: 130px;
+ overflow: hidden;
+
+ .header-content {
+ color: rgba(0, 0, 0, 0.88);
+ font-size: 14px;
+ line-height: 1.5;
+
+ .info-row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-bottom: 8px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ .info-item {
+ display: flex;
+ align-items: flex-start;
+ margin-right: 24px;
+ margin-bottom: 6px;
+
+ &.left-column {
+ width: 33%;
+ min-width: 200px;
+ }
+
+ &.flex-column {
+ flex: 1;
+ min-width: 150px;
+ }
+
+ &.full-width {
+ flex: 1;
+ min-width: 300px;
+ }
+
+ .label {
+ color: #606266;
+ margin-right: 8px;
+ white-space: nowrap;
+ }
+
+ .value {
+ flex: 1;
+ color: #303133;
+ word-break: break-all;
+ display: -webkit-box;
+ -webkit-line-clamp: 1;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
+ }
+ }
+
+ .flex {
+ display: flex;
+ align-items: center;
+ }
+
+ .tableTitle {
+ display: flex;
+ padding-bottom: 20px;
+ justify-content: space-between;
+ align-items: center;
+
+ .title {
+ background: #fafafc;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #dcdfe6;
+ font-weight: bold;
+ font-size: 18px;
+ color: #606266;
+ cursor: pointer;
+ height: 50px;
+ line-height: 50px;
+ width: 280px;
+ text-align: center;
+ }
+
+ .drafts {
+ background: #fafafc;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #dcdfe6;
+ font-weight: 400;
+ font-size: 18px;
+ color: #606266;
+ margin-left: 16px;
+ cursor: pointer;
+ height: 50px;
+ line-height: 50px;
+ width: 280px;
+ text-align: center;
+ }
+
+ .active {
+ color: #049c9a;
+ background: #ffffff;
+ border-radius: 8px 8px 0px 0px;
+ border: 1px solid #049c9a;
+ }
+ }
+
+ .timeline-container {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.8);
+
+ .timeline-card {
+ margin-bottom: 10px;
+ background: rgba(255, 255, 255, 0.8);
+
+ h4 {
+ margin: 0 0 10px;
+ font-size: 16px;
+ font-weight: bold;
+ }
+
+ p {
+ margin: 5px 0;
+ font-size: 14px;
+ }
+ }
+ }
+
+ .operation-btn {
+ margin-right: 12px;
+ }
+}
+</style>
diff --git a/culture/src/views/strain-library/production-cell-grandson/service.js b/culture/src/views/strain-library/production-cell-grandson/service.js
new file mode 100644
index 0000000..08f789d
--- /dev/null
+++ b/culture/src/views/strain-library/production-cell-grandson/service.js
@@ -0,0 +1,56 @@
+import axios from '@/utils/request';
+
+// 列表
+export const getList = (data) => {
+ return axios.post('/api/t-train-library/pageList', { ...data })
+}
+
+// 新增
+export const add = (data) => {
+ return axios.post('/api/t-train-library/add', { ...data })
+}
+
+// 编辑
+export const edit = (data) => {
+ return axios.post('/api/t-train-library/update', { ...data })
+}
+
+// 查看详情
+export const getDetail = (params) => {
+ return axios.get('/open/t-train-library/getDetailEditById', { params })
+}
+
+// 批量新增
+export const addBatch = (data) => {
+ return axios.post('/api/t-train-library/addBatch', data)
+}
+
+// 查看菌种库详情
+export const getDetailById = (data) => {
+ return axios.post('/open/t-train-library/getDetailById', { ...data })
+}
+
+// 获取菌种库出入库时间轴列表
+export const timeList = (data) => {
+ return axios.post('/api/t-train-library/timeList?id='+data.id, { ...data })
+}
+
+// 新增菌种库出入记录
+export const addWarehousing = (data) => {
+ return axios.post('/open/t-train-library/addWarehousing', { ...data })
+}
+
+// 确认出入库
+export const confirmWarehousing = (data) => {
+ return axios.post('/api/t-train-library/confirm', { ...data })
+}
+
+// 删除菌种库
+export const deleteStrainLibrary = (params) => {
+ return axios.delete('/open/t-train-library/deleteById', { params })
+}
+
+// 删除菌种库出入库记录
+export const deleteWarehousing = (params) => {
+ return axios.delete('/open/t-train-library/deleteWarehousingById', { params })
+}
diff --git a/culture/src/views/strain-library/production-cell-library/index.vue b/culture/src/views/strain-library/production-cell-library/index.vue
index 7fcc328..34cc9f3 100644
--- a/culture/src/views/strain-library/production-cell-library/index.vue
+++ b/culture/src/views/strain-library/production-cell-library/index.vue
@@ -103,7 +103,7 @@
:class="{ active: currentType === 'list' }"
@click="handleTypeChange('list')"
>
- 生产细胞列表
+ 子细胞列表
</div>
<div
class="drafts"
@@ -119,7 +119,7 @@
class="el-icon-plus"
type="primary"
style="margin-right: 12px"
- >新增生产细胞</el-button
+ >新增子细胞</el-button
>
<el-button
@click="handleNewStrain"
diff --git a/culture/src/views/strain-library/validation/chief-cell/add.vue b/culture/src/views/strain-library/validation/chief-cell/add.vue
index 2a20f16..c4401d7 100644
--- a/culture/src/views/strain-library/validation/chief-cell/add.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/add.vue
@@ -3,7 +3,7 @@
<!-- <div class="header-title">
<div class="header-title-left">
<img src="@/assets/public/headercard.png" />
- <div>新增原始细胞</div>
+ <div>新增母代菌种库验证资料</div>
</div>
</div> -->
<el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form">
diff --git a/culture/src/views/strain-library/validation/chief-cell/index.vue b/culture/src/views/strain-library/validation/chief-cell/index.vue
index d0a83f2..c160070 100644
--- a/culture/src/views/strain-library/validation/chief-cell/index.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/index.vue
@@ -26,7 +26,7 @@
<div class="tableTitle">
<div class="flex a-center">
<div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">
- 主细胞库验证资料
+ 母代菌种库验证资料列表
</div>
<div class="drafts" v-if="roleType == 4|| roleType==3" :class="{ active: currentType === 'draft' }"
@click="handleTypeChange('draft')">
@@ -35,7 +35,7 @@
</div>
<div class="flex a-center" v-if="roleType == 4">
<el-button @click="handleNewStrain" class="el-icon-plus" type="primary"
- style="margin-right: 12px">新增主细胞</el-button>
+ style="margin-right: 12px">新增母代菌种库验证资料</el-button>
</div>
</div>
</template>
@@ -335,7 +335,7 @@
cursor: pointer;
height: 50px;
line-height: 50px;
- width: 166px;
+ min-width: 166px;
text-align: center;
}
diff --git a/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue b/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
index 8227ad2..244385b 100644
--- a/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
@@ -1,7 +1,7 @@
<template>
<el-dialog
:visible.sync="visible"
- title="主细胞库资料详情"
+ title="母代菌种库验证资料详情"
width="650px"
:close-on-click-modal="false"
@close="handleClose"
diff --git a/culture/src/views/strain-library/validation/primitive-cell/index.vue b/culture/src/views/strain-library/validation/primitive-cell/index.vue
index 7e26411..c210af4 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/index.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/index.vue
@@ -26,7 +26,7 @@
<div class="tableTitle">
<div class="flex a-center">
<div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">
- 原始细胞库验证资料
+ 祖代菌种库验证资料
</div>
<div class="drafts" v-if="roleType == 4 || roleType == 3" :class="{ active: currentType === 'draft' }"
@click="handleTypeChange('draft')">
@@ -35,7 +35,7 @@
</div>
<div class="flex a-center" v-if="roleType == 4">
<el-button @click="handleNewStrain" class="el-icon-plus" type="primary"
- style="margin-right: 12px">新增原始细胞库资料</el-button>
+ style="margin-right: 12px">新增祖代菌种库验证资料</el-button>
</div>
</div>
</template>
diff --git a/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue b/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
index aeb7507..92b79bd 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
@@ -1,7 +1,7 @@
<template>
<el-dialog
:visible.sync="visible"
- title="原始细胞库资料详情"
+ title="祖代菌种库验证资料详情"
width="650px"
:close-on-click-modal="false"
@close="handleClose"
diff --git a/culture/vue.config.js b/culture/vue.config.js
index d811999..1209754 100644
--- a/culture/vue.config.js
+++ b/culture/vue.config.js
@@ -1,53 +1,57 @@
-const path = require('path')
+const path = require("path");
function resolve(dir) {
- return path.join(__dirname, dir)
+ return path.join(__dirname, dir);
}
module.exports = {
- outputDir: 'culture', // 配置打包后的文件夹名称
- lintOnSave: false,
- publicPath: '/',
- devServer: {
- disableHostCheck: true, //禁用主机检查
- proxy: {
- "/api": { // 设置以什么前缀开头的请求用来代理
- target: "http://221.182.45.100:8081", //要访问的跨域的域名
- secure: false, // 使用的是http协议则设置为false,https协议则设置为true
- changOrigin: true, //开启代理
- pathRewrite: {
- "^/api": "/api",
- },
- },
- "/": { // 设置以什么前缀开头的请求用来代理
- target: "http://221.182.45.100:8081", //要访问的跨域的域名
- secure: false, // 使用的是http协议则设置为false,https协议则设置为true
- changOrigin: true, //开启代理
- pathRewrite: {
- "^/": "/",
- },
- },
+ outputDir: "culture", // 配置打包后的文件夹名称
+ lintOnSave: false,
+ publicPath: "/",
+ devServer: {
+ disableHostCheck: true, //禁用主机检查
+ proxy: {
+ "/api": {
+ // 设置以什么前缀开头的请求用来代理
+ // target: "http://221.182.45.100:8081", //要访问的跨域的域名
+ target: "http://192.168.110.64:8081",
+ secure: false, // 使用的是http协议则设置为false,https协议则设置为true
+ changOrigin: true, //开启代理
+ pathRewrite: {
+ "^/api": "/api",
},
+ },
+ "/": {
+ // 设置以什么前缀开头的请求用来代理
+ // target: "http://221.182.45.100:8081", //要访问的跨域的域名
+ target: "http://192.168.110.64:8081",
+ secure: false, // 使用的是http协议则设置为false,https协议则设置为true
+ changOrigin: true, //开启代理
+ pathRewrite: {
+ "^/": "/",
+ },
+ },
},
- configureWebpack: {
- resolve: {
- alias: {
- '@': resolve('src'),
- }
+ },
+ configureWebpack: {
+ resolve: {
+ alias: {
+ "@": resolve("src"),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.m?js$/,
+ include: /node_modules/,
+ type: "javascript/auto",
+ use: {
+ loader: "babel-loader",
+ options: {
+ presets: ["@babel/preset-env"],
+ plugins: ["@babel/plugin-proposal-nullish-coalescing-operator"],
+ },
+ },
},
- module: {
- rules: [
- {
- test: /\.m?js$/,
- include: /node_modules/,
- type: "javascript/auto",
- use: {
- loader: 'babel-loader',
- options: {
- presets: ['@babel/preset-env'],
- plugins: ['@babel/plugin-proposal-nullish-coalescing-operator']
- }
- }
- }
- ]
- }
- }
-};
\ No newline at end of file
+ ],
+ },
+ },
+};
--
Gitblit v1.7.1