<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 @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="出库/入库" />
|
<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>
|
</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'
|
|
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)
|
}
|
}
|
}
|
</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>
|