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/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