<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
|
条路径。1.1 是沙土管或甘油管的源头菌种;入原始细胞库(祖代-O)。1.2
|
是斜面的源头菌种;接种入主细胞库(祖代-O)。经过育种、验证后,菌种保藏为甘油管或沙土管的,入原始细胞库(祖代-0)1.3
|
是含菌物质自己分离后获得的斜面源头菌种,接种入主细胞库;经生产验证后,保藏为沙土管或甘油管,入原始细胞库(祖代-O)。
|
2.
|
菌种细胞库,分类入三库,进行传代运行管理。三类库存空间进行区分,保藏菌种。2.1
|
原始细胞库(祖代-O)、2.2 主细胞库(母代-M)、2.3
|
生产细胞库(子代-S)、(孙代-G)3. 细胞库编码规则3.1
|
细胞库编码规则:DD-M-240919-01-(O-0109-01)DD:代表项目组。M:“O”代表祖代原始细胞库,”M“代表母代主细胞库,”S“代表子代生产细胞库,“G”代表孙代生产细胞库。240919:代表在
|
24 年 9 月 19
|
接种批次的菌种;或收到外来菌种时间的入库批次。01:代表两位序列号。(O-0109-01):代表传代菌种的编号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
|
编码规则实现了编码唯一,编码可溯源,编码直观、方便。3.2
|
细胞库说明:3.2.1
|
直接购买、自行从(土壤、相关物料、商品)等分离出来菌株进入原始细胞库。3.2.2
|
从原始细胞库中选取出来再次纯化、改造、提高性能的菌株进入主细胞库。3.2.3
|
主细胞库中选取出稳定,生产性能良好的菌株扩培后保种进入生产细胞库。4.
|
菌种选育-保藏过程编号说明4.1 菌种选育时,培养皿的编号可使用 a-01、a-02
|
等用于清晰形态观察记录;菌落编号使用序号 1/2/3等。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
|
条路径。1.1 是沙土管或甘油管的源头菌种;入原始细胞库(祖代-O)。1.2
|
是斜面的源头菌种;接种入主细胞库(祖代-O)。经过育种、验证后,菌种保藏为甘油管或沙土管的,入原始细胞库(祖代-0)1.3
|
是含菌物质自己分离后获得的斜面源头菌种,接种入主细胞库;经生产验证后,保藏为沙土管或甘油管,入原始细胞库(祖代-O)。2.
|
菌种细胞库,分类入三库,进行传代运行管理。三类库存空间进行区分,保藏菌种。2.1
|
原始细胞库(祖代-O)、2.2 主细胞库(母代-M)、2.3
|
生产细胞库(子代-S)、(孙代-G)3. 细胞库编码规则3.1
|
细胞库编码规则:DD-M-240919-01-(O-0109-01)DD:代表项目组。M:“O”代表祖代原始细胞库,”M“代表母代主细胞库,”S“代表子代生产细胞库,“G”代表孙代生产细胞库。240919:代表在
|
24 年 9 月 19
|
接种批次的菌种;或收到外来菌种时间的入库批次。01:代表两位序列号。(O-0109-01):代表传代菌种的编号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
|
编码规则实现了编码唯一,编码可溯源,编码直观、方便。3.2
|
细胞库说明:3.2.1
|
直接购买、自行从(土壤、相关物料、商品)等分离出来菌株进入原始细胞库。3.2.2
|
从原始细胞库中选取出来再次纯化、改造、提高性能的菌株进入主细胞库。3.2.3
|
主细胞库中选取出稳定,生产性能良好的菌株扩培后保种进入生产细胞库。4.
|
菌种选育-保藏过程编号说明4.1 菌种选育时,培养皿的编号可使用
|
a-01、a-02 等用于清晰形态观察记录;菌落编号使用序号 1/2/3等。4.2
|
接种斜面菌种编码(-O)使用原始细胞库编码;斜面转菌种保藏使用与斜面一致的编码(-O);斜面传代入主细胞库的传代菌种,按编码器规则编码(-M)。
|
</p>
|
</div>
|
</el-dialog>
|
</el-card>
|
|
<!-- Table -->
|
<TableCustom
|
:queryForm="queryForm"
|
:tableData="tableData"
|
:total="total"
|
@currentChange="handleCurrentChange"
|
@sizeChange="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="特征描述" />
|
<el-table-column prop="saveMethod" label="菌种保存方法" />
|
<el-table-column prop="saveLocation" label="保藏位置" />
|
<el-table-column prop="stock" label="库存余量" />
|
<el-table-column prop="remark" label="备注" />
|
<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 type="text" @click="handleDetail(row)">详情</el-button>
|
<el-button v-if="row.status == 2 || row.status == 4" type="text" @click="handleEdit(row)">编辑</el-button>
|
<el-button
|
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 :visible.sync="detailVisible" :detail="currentDetail" />
|
</div>
|
</template>
|
|
<script>
|
import StrainDetail from "./components/StrainDetail.vue";
|
import { getList, deleteStrainLibrary } from "./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: "",
|
};
|
},
|
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}`,
|
});
|
},
|
handleNewStrain() {
|
this.$router.push({ path: "/strain-library/strain-library-manage/add" });
|
},
|
handleEdit(row) {
|
this.$router.push({
|
path: `/strain-library/strain-library-manage/add?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: 1,
|
};
|
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: "warning",
|
2: "warning",
|
3: "success",
|
4: "success",
|
};
|
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: 48px;
|
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;
|
}
|
}
|
}
|
}
|
}
|
</style>
|