From e950c38ba82e5e6bc8b0c50c35e5dbb6a180165a Mon Sep 17 00:00:00 2001 From: 13404089107 <puwei@sinata.cn> Date: 星期二, 20 五月 2025 16:43:06 +0800 Subject: [PATCH] Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/leshan-laboratory --- culture/src/views/strain-library/main-cell-library/record.vue | 684 ++++++++++++++++++++++++++++++++------------------------ 1 files changed, 385 insertions(+), 299 deletions(-) diff --git a/culture/src/views/strain-library/main-cell-library/record.vue b/culture/src/views/strain-library/main-cell-library/record.vue index e434d70..aef2643 100644 --- a/culture/src/views/strain-library/main-cell-library/record.vue +++ b/culture/src/views/strain-library/main-cell-library/record.vue @@ -1,352 +1,438 @@ <template> <div class="record-page"> - <div class="page-header"> - <div class="header-left"> - <el-page-header @back="goBack" content="主细胞出入库记录"></el-page-header> - </div> - <div class="header-right"> - <el-button type="primary" icon="el-icon-plus" @click="handleAddRecord">新增记录</el-button> - </div> - </div> - - <el-card class="record-card"> - <div class="strain-info"> + <!-- 基本信息展示区域 --> + <el-card class="header-box"> + <div class="header-content"> + <!-- 第一行 --> <div class="info-row"> - <div class="info-item"> + <div class="info-item left-column"> <span class="label">菌种编号:</span> - <span class="value">{{ strainInfo.strainNo }}</span> + <span class="value">{{ detail.strainCode }}</span> </div> - <div class="info-item"> - <span class="label">菌种名称:</span> - <span class="value">{{ strainInfo.strainName }}</span> - </div> - <div class="info-item"> - <span class="label">菌种来源:</span> - <span class="value">{{ strainInfo.source }}</span> - </div> - </div> - <div class="info-row"> - <div class="info-item"> + <div class="info-item flex-column"> <span class="label">鉴定方法:</span> - <span class="value">{{ strainInfo.method }}</span> + <span class="value">{{ detail.appraisalMethod }}</span> </div> - <div class="info-item full"> - <span class="label">特征描述:</span> - <span class="value">{{ strainInfo.certificate }}</span> + <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"> - <span class="label">菌种保存方法:</span> - <span class="value">{{ strainInfo.storage }}</span> + <div class="info-item left-column"> + <span class="label">菌种名称:</span> + <span class="value">{{ detail.strainName }}</span> </div> - <div class="info-item"> - <span class="label">保存位置:</span> - <span class="value">{{ strainInfo.amount }}</span> - </div> - <div class="info-item"> - <span class="label">出入库状态:</span> - <span class="value status">{{ strainInfo.statusText }}</span> + <div class="info-item flex-column full-width"> + <span class="label">特性描述:</span> + <span class="value">{{ detail.features }}</span> </div> </div> - </div> - - <div class="record-timeline-container"> - <h3 class="section-title">出入库记录</h3> - <RecordTimeline :list="recordList" /> + + <!-- 第三行 --> + <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> - - <!-- 新增记录弹窗 --> - <el-dialog - title="新增出入库记录" - :visible.sync="dialogVisible" - width="500px" + + <!-- 出入库记录表格 --> + <TableCustom + :queryForm="queryForm" + :tableData="recordList" + :total="total" + @currentChange="handlePageChange" > - <el-form ref="recordForm" :model="recordForm" :rules="recordRules" label-width="100px"> - <el-form-item label="操作类型" prop="type"> - <el-radio-group v-model="recordForm.type"> - <el-radio label="入库">入库</el-radio> - <el-radio label="出库">出库</el-radio> - </el-radio-group> - </el-form-item> - - <el-form-item label="操作人" prop="operator"> - <el-input v-model="recordForm.operator" placeholder="请输入操作人"></el-input> - </el-form-item> - - <el-form-item label="操作时间" prop="operateTime"> - <el-date-picker - v-model="recordForm.operateTime" - type="datetime" - placeholder="选择日期时间" - value-format="yyyy-MM-dd HH:mm:ss" - ></el-date-picker> - </el-form-item> - - <el-form-item label="保藏人" prop="reviewer"> - <el-input v-model="recordForm.reviewer" placeholder="请输入保藏人"></el-input> - </el-form-item> - - <el-form-item label="操作数量" prop="amount"> - <el-input-number v-model="recordForm.amount" :min="1" :max="100"></el-input-number> - </el-form-item> - - <el-form-item label="备注" prop="remarks"> - <el-input - type="textarea" - v-model="recordForm.remarks" - :rows="3" - placeholder="请输入备注" - ></el-input> - </el-form-item> - </el-form> - - <span slot="footer" class="dialog-footer"> - <el-button @click="dialogVisible = false">取 消</el-button> - <el-button type="primary" @click="submitRecord">确 定</el-button> - </span> - </el-dialog> + <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 RecordTimeline from '../strain-library-manage/components/RecordTimeline.vue' +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: 'MainCellRecord', + name: "StrainRecord", components: { - RecordTimeline + RecordDetailDialog, + AddRecordDialog, + RecordTimeline, }, data() { return { - strainId: '', - strainInfo: { - strainNo: 'M-2024001', - strainName: '大肠杆菌BL21', - source: '原始细胞库', - method: '分子生物学鉴定', - certificate: '常用表达宿主菌,含有DE3溶源体,适合蛋白表达', - storage: '甘油冷冻', - amount: 'M区-01-001', - inventory: '100', - status: '1', - statusText: '已入库' + currentType: "table", + detail: {}, + currentPage: 1, + pageSize: 10, + total: 0, + queryForm: { + pageSize: 10, + pageNum: 1, }, - recordList: [ - { - type: '入库', - operator: '张三', - operateTime: '2024-05-01 10:30:00', - reviewer: '李四', - confirmTime: '2024-05-01 14:20:00' - }, - { - type: '出库', - operator: '王五', - operateTime: '2024-05-15 09:45:00', - reviewer: '赵六', - confirmTime: '2024-05-15 11:30:00' - }, - { - type: '入库', - operator: '钱七', - operateTime: '2024-05-20 14:00:00', - reviewer: '孙八', - confirmTime: '2024-05-20 16:15:00' - } - ], + recordList: [], + timelineList: [], dialogVisible: false, - recordForm: { - type: '入库', - operator: '', - operateTime: '', - reviewer: '', - amount: 1, - remarks: '' - }, - recordRules: { - type: [ - { required: true, message: '请选择操作类型', trigger: 'change' } - ], - operator: [ - { required: true, message: '请输入操作人', trigger: 'blur' } - ], - operateTime: [ - { required: true, message: '请选择操作时间', trigger: 'change' } - ], - reviewer: [ - { required: true, message: '请输入保藏人', trigger: 'blur' } - ], - amount: [ - { required: true, message: '请输入操作数量', trigger: 'blur' } - ] - } - } + currentRecord: {}, + addDialogVisible: false, + dialogType: "detail", + roleType: "", + }; }, - created() { - // 获取路由参数中的菌种ID - this.strainId = this.$route.query.id - // 实际项目中这里应该根据ID加载菌种信息和记录列表 - console.log('加载菌种ID:', this.strainId) + 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: { - goBack() { - this.$router.push('/strain-library/main-cell-library') + 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.dialogVisible = true - this.resetRecordForm() + this.addDialogVisible = true; }, - submitRecord() { - this.$refs.recordForm.validate(valid => { - if (valid) { - // 表单验证通过,提交数据 - console.log('提交的记录数据:', this.recordForm) - - // 模拟添加记录到列表 - const newRecord = { - type: this.recordForm.type, - operator: this.recordForm.operator, - operateTime: this.recordForm.operateTime, - reviewer: this.recordForm.reviewer, - confirmTime: new Date().toLocaleString() - } - - // 添加到记录列表的开头 - this.recordList.unshift(newRecord) - - // 关闭弹窗 - this.dialogVisible = false - - // 显示成功消息 - this.$message.success('记录添加成功') + handleDialogClose() { + this.currentRecord = {}; + this.dialogVisible = false; + }, + handleOutbound(data) { + // 这里调用出库API + confirmWarehousing({ + id: this.currentRecord.id, + preserveSignature: data.preserveSignature, + }).then((res) => { + console.log(res); + if (res.code == 200) { + this.$message.success("操作成功"); + this.dialogVisible = false; + // 刷新列表 + this.getRecordList(); } else { - this.$message.error('请正确填写表单') - return false + this.$message.error(res.msg); } - }) + }); }, - resetRecordForm() { - this.recordForm = { - type: '入库', - operator: '', - operateTime: '', - reviewer: '', - amount: 1, - remarks: '' - } - } - } -} + handleAddRecordConfirm(record) { + addWarehousing({ ...record, trainLibraryId: this.$route.query.id }).then( + (res) => { + this.$message.success("操作成功"); + this.getRecordList(); + } + ); + }, + goBack() { + this.$router.go(-1); + }, + }, +}; </script> -<style scoped lang="less"> +<style lang="less" scoped> .record-page { - padding: 20px; -} + min-height: 100vh; -.page-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - - .header-left { - :deep(.el-page-header__content) { - font-size: 18px; - font-weight: bold; - color: #333; - } - } -} - -.record-card { - background: #fff; - border-radius: 16px; - margin-bottom: 20px; -} - -.strain-info { - padding: 10px 0; - - .info-row { - display: flex; - flex-wrap: wrap; - margin-bottom: 16px; - - &:last-child { - margin-bottom: 0; - } - } - - .info-item { - flex: 1; - min-width: 200px; - margin-right: 20px; - - &:last-child { - margin-right: 0; - } - - &.full { - flex: 2; - } - - .label { - color: #606266; - margin-right: 8px; - } - - .value { - color: #333; - font-weight: 500; - - &.status { - color: #67C23A; - } - } - } -} - -.record-timeline-container { - margin-top: 30px; - - .section-title { - font-size: 16px; - color: #333; + .header-box { margin-bottom: 20px; - font-weight: 500; - } -} + border-radius: 16px; + background: rgba(255, 255, 255, 0.8); + height: 130px; + overflow: hidden; -:deep(.el-dialog__body) { - padding: 20px 30px; -} + .header-content { + color: rgba(0, 0, 0, 0.88); + font-size: 14px; + line-height: 1.5; -@media screen and (max-width: 768px) { - .strain-info { - .info-row { - flex-direction: column; - - .info-item { - margin-right: 0; - margin-bottom: 10px; - + .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; + } + } } } } - - .page-header { - flex-direction: column; - align-items: flex-start; - - .header-right { - margin-top: 16px; + + .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> \ No newline at end of file +</style> -- Gitblit v1.7.1