From 8ac7e0ca090ab5ce0f8435e8af6f78a23c0dd6e0 Mon Sep 17 00:00:00 2001 From: pyt <626651354@qq.com> Date: 星期一, 19 五月 2025 18:04:45 +0800 Subject: [PATCH] feat --- culture/src/views/strain-library/strain-library-manage/record.vue | 791 +++++++++++++++++++++++++++++--------------------------- 1 files changed, 408 insertions(+), 383 deletions(-) diff --git a/culture/src/views/strain-library/strain-library-manage/record.vue b/culture/src/views/strain-library/strain-library-manage/record.vue index 0db0f96..03eab17 100644 --- a/culture/src/views/strain-library/strain-library-manage/record.vue +++ b/culture/src/views/strain-library/strain-library-manage/record.vue @@ -1,413 +1,438 @@ <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 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> - </el-card> + <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> - <!-- 出入库记录表格 --> - <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 @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> - <template #table v-if="currentType === 'table'"> - <el-table-column prop="type" label="出库/入库" /> - <el-table-column prop="operateTime" label="操作时间" /> - <el-table-column prop="operator" label="操作人签字" /> - <el-table-column prop="reviewer" label="菌种保藏人签字" /> - <el-table-column prop="status" label="状态"> - <template #default="{ row }"> - <el-tag :type="row.status === '已确认' ? 'success' : 'warning'"> - {{ row.status }} - </el-tag> - </template> - </el-table-column> - <el-table-column label="操作" width="180"> - <template #default="{ row }"> - <el-button type="text" class="operation-btn" @click="handleView(row)">详情</el-button> - <el-button type="text" class="operation-btn" @click="handleEdit(row)">编辑</el-button> - <el-button 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" - /> - - <add-record-dialog - :visible.sync="addDialogVisible" - @confirm="handleAddRecordConfirm" - /> - </div> + <!-- 详情弹窗 --> + <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 './components/RecordDetailDialog.vue' -import AddRecordDialog from './components/AddRecordDialog.vue' -import RecordTimeline from './components/RecordTimeline.vue' -import { timeList,getDetail,addWarehousing } from './service' +import RecordDetailDialog from "./components/RecordDetailDialog.vue"; +import AddRecordDialog from "./components/AddRecordDialog.vue"; +import RecordTimeline from "./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: [ - { - type: '入库', - operateTime: '2025-1-21 15:46:50', - operator: '张三', - reviewer: '李四', - status: '已确认' - }, - { - type: '出库', - operateTime: '2025-1-21 15:46:50', - operator: '张三', - reviewer: '李四', - status: '已确认' - }, - { - type: '入库', - operateTime: '2025-1-21 15:46:50', - operator: '张三', - reviewer: '李四', - status: '已确认' - }, - { - type: '出库', - operateTime: '2025-1-21 15:46:50', - operator: '张三', - reviewer: '李四', - status: '已确认' - }, - { - type: '入库', - operateTime: '2025-1-21 15:46:50', - operator: '李四', - reviewer: '李四', - status: '已确认' - } - ], - timelineList: [], - dialogVisible: false, - currentRecord: {}, - addDialogVisible: false - } - }, - computed: { - // timelineList() { - // // 可根据需要处理数据格式,这里直接用 recordList - // return this.recordList.map(item => ({ - // ...item, - // confirmTime: item.confirmTime || item.operateTime // 若无确认时间则用操作时间 - // })) - // } - }, - created() { - // 获取路由参数中的菌种信息 - const strainId = this.$route.query.id - this.queryForm.id = strainId - if (strainId) { - this.getStrainDetail(strainId) - this.getRecordList() - } - }, - methods: { - getStrainDetail(id) { - // 这里应该调用接口获取菌种详情 - getDetail({id}).then(res => { - this.detail = res - }) - }, - getRecordList() { - // 这里应该调用接口获取出入库记录 - timeList(this.queryForm).then(res => { - this.timelineList = res.data - }) - this.total = this.recordList.length - }, - handleView(row) { - this.currentRecord = { - ...row, - operatorSignature: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', // 模拟操作人签字图片 - reviewerSignature: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', // 模拟保藏人签字图片 - operateTime: '2025-1-22 13:49:51', - confirmTime: '2025-1-22 14:30:00' - } - this.dialogVisible = true - }, - handlePageChange(page) { - this.queryForm.pageNum = page - // 这里应该调用接口获取对应页码的数据 - }, - handleTypeChange(type) { - this.currentType = type - }, - handleAddRecord() { - this.addDialogVisible = true - }, - handleEdit(row) { - console.log('编辑记录:', row) - // 实现编辑记录逻辑 - }, - handleDelete(row) { - this.$confirm('确认删除该记录吗?', '提示', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { - console.log('删除记录:', row) - // 实际项目中这里应该调用删除API - this.$message({ - type: 'success', - message: '删除成功!' - }) - }).catch(() => { - this.$message({ - type: 'info', - message: '已取消删除' - }) - }) - }, - handleDialogClose() { - this.currentRecord = {} - this.dialogVisible = false - }, - handleOutbound(data) { - // 这里调用出库API - console.log('出库操作:', data) - this.$message.success('出库成功') - this.dialogVisible = false - // 刷新列表 - this.getRecordList() - }, - handleAddRecordConfirm(record) { - addWarehousing({...record,trainLibraryId: this.$route.query.id}).then(res => { - this.$message.success('操作成功') - this.getRecordList() - }) - }, - goBack() { - this.$router.go(-1) - } + 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: "", + }; + }, + created() { + 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) => { + console.log(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; + min-height: 100vh; - .header-box { - margin-bottom: 20px; - border-radius: 16px; - background: rgba(255, 255, 255, 0.8); - height: 130px; - overflow: hidden; + .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; + .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 { + .info-row { display: flex; - align-items: center; - } + flex-wrap: wrap; + margin-bottom: 8px; - .tableTitle { - display: flex; - padding-bottom: 20px; - justify-content: space-between; - align-items: center; + &:last-child { + margin-bottom: 0; + } - .title { - background: #fafafc; - border-radius: 8px 8px 0px 0px; - border: 1px solid #dcdfe6; - font-weight: bold; - font-size: 18px; + .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; - cursor: pointer; - height: 50px; - line-height: 50px; - width: 280px; - text-align: center; - } + margin-right: 8px; + white-space: nowrap; + } - .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; + .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; + } } + } + } + } - .active { - color: #049c9a; - background: #ffffff; - border-radius: 8px 8px 0px 0px; - border: 1px solid #049c9a; - } + .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; } - .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; - } - } + .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; } - .operation-btn { - margin-right: 12px; + .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