董国庆
2025-05-29 c94535b792e9df0d3bbeffa10f427624c7c10ee4
Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/leshan-laboratory
6个文件已添加
14个文件已修改
2252 ■■■■ 已修改文件
culture/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/confirm-storage-dialog/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/router/index.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/EditConditionDialog.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/add.vue 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/index.vue 707 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/service.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue 131 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/EditConditionDialog.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/add.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/index.vue 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/primitive-cell/service.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/package.json
@@ -2,7 +2,7 @@
  "name": "appointment",
  "version": "0.1.0",
  "private": true,
  "scripts": {
  "scripts": {
    "serve:dev": "cross-env VUE_APP_ENV=development vue-cli-service serve --port 8087",
    "serve:prod": "cross-env VUE_APP_ENV=production vue-cli-service serve",
    "build:dev": "cross-env VUE_APP_ENV=development vue-cli-service build",
culture/src/components/confirm-storage-dialog/index.vue
@@ -3,6 +3,7 @@
    :visible.sync="visible"
    title="签字确认"
    width="520px"
    @open="handleOpen"
    :close-on-click-modal="false"
    custom-class="record-detail-dialog"
    @close="handleClose"
@@ -65,6 +66,10 @@
      type: String,
      default: "",
    },
    handleSignature: {
      type: String,
      default:"",
    }
  },
  data() {
    return {
@@ -78,6 +83,9 @@
    };
  },
  methods: {
    handleOpen() {
       this.form.signature = this.handleSignature;
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
culture/src/router/index.js
@@ -334,6 +334,18 @@
              ),
          },
          {
            path: "edit-primitive-cell",
            name: "AddPrimitiveCell",
            meta: {
              title: "编辑原始细胞库资料",
              hide: true,
            },
            component: () =>
              import(
                "../views/strain-library/validation/primitive-cell/add.vue"
              ),
          },
          {
            path: "confirm-detail",
            name: "ConfirmDetail",
            meta: {
@@ -354,6 +366,38 @@
            component: () =>
              import("../views/strain-library/validation/chief-cell"),
          },
          {
            path: "add-chief-cell",
            name: "AddChiefCell",
            meta: {
              title: "新增主细胞库资料",
              hide: true,
            },
            component: () =>
              import("../views/strain-library/validation/chief-cell/add.vue"),
          },
          {
            path: "edit-chief-cell",
            name: "EditChiefCell",
            meta: {
              title: "编辑主细胞库资料",
              hide: true,
            },
            component: () =>
              import("../views/strain-library/validation/chief-cell/add.vue"),
          },
          {
            path: "confirm-detail-chief",
            name: "ConfirmDetailChief",
            meta: {
              title: "确认主细胞库资料",
              hide: true,
            },
            component: () =>
              import(
                "../views/strain-library/validation/chief-cell/confirm-detail.vue"
              ),
          },
        ],
      },
    ],
culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue
New file
@@ -0,0 +1,271 @@
<template>
  <el-dialog :visible.sync="visible" width="80%" @open="handleOpen" @close="handleClose">
    <el-card class="top-card">
      <el-row :gutter="24" class="top-info-row">
        <el-col :span="8" class="info-col">
          <div class="info-item">
            <span class="label">菌种来源:</span>{{ detail.strainSource }}
          </div>
          <div class="info-item">
            <span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}
          </div>
          <div class="info-item">
            <span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}
          </div>
        </el-col>
        <el-col :span="8" class="info-col">
          <div class="info-item">
            <span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}
          </div>
          <div class="info-item">
            <span class="label">实验时间:</span>{{ detail.experimentTime }}
          </div>
          <div class="info-item"></div>
        </el-col>
        <el-col :span="8" class="info-col">
          <div class="info-item sign-label">
            <span class="label">菌种实验员签字</span>
          </div>
          <div class="info-item signature-item">
            <div class="signature-area">
              <img v-if="detail.handleSignature" :src="detail.handleSignature" alt="签字" />
              <span v-else class="waiting-text">暂无签名</span>
            </div>
          </div>
        </el-col>
      </el-row>
    </el-card>
    <div class="section-card" style="margin-top: 24px">
      <el-form ref="form" label-width="100px" :model="detail" label-position="top">
        <el-form-item label="实验结论" prop="result">
          <el-input type="textarea" :disabled="true" v-model="detail.result" :rows="3" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="批准菌株用途" prop="purpose">
          <el-checkbox-group :disabled="true" v-model="detail.purpose">
            <el-checkbox label="1">传代</el-checkbox>
            <el-checkbox label="2">菌种保藏</el-checkbox>
            <el-checkbox label="3">废弃</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </div>
    <div class="section-card" style="margin-top: 12px">
      <el-table :data="tableData" border style="width: 100%" :row-class-name="getRowClassName">
        <el-table-column prop="conditions" label="菌种培养工艺条件" />
        <el-table-column prop="record" label="菌种培养工艺实况记录" />
        <el-table-column prop="workmanship" label="菌种培养标准工艺" />
        <el-table-column label="操作" width="120">
          <template #default="{ row }">
            <el-button type="text" @click="handleEdit(row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </el-dialog>
</template>
<script>
import DetailConditionDialog from "./DetailConditionDialog.vue";
import { detail } from "./service.js";
export default {
  name: "DetailConditionDialog",
  components: { DetailConditionDialog },
  props: {
    visible: Boolean,
    value: {
      type: Object,
      default: () => ({ condition: "", record: "", process: "" }),
    },
    value: {
      type: Object,
      default: () => ({})
    },
  },
  data() {
    return {
      detail: {
        strainSource: '',
        identifyingStrainCode: '',
        identifyingStrainName: '',
        validationExperimentCode: '',
        experimentTime: '',
        handleSignature: '', // 签名图片url
        result: '',
        purpose: []
      },
      activeTab: "conditions",
      initialTableData: [
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      tableData: [
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      dialogVisible: false,
      dialogIsEdit: false,
      dialogIsFixed: false,
      dialogValue: {},
      dialogIndex: null,
    };
  },
  methods: {
    handleOpen() {
      if (this.value.id) {
        detail({ id: this.value.id }).then(res => {
          this.detail = {
            ...res,
            handleSignature: res.handleSignature || '', // 处理签名为空的情况
            purpose: res.purpose.split(',') || [] // 处理 purpose 为空的情况
          }
          this.tableData = res.list || []
        })
      }
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
    handleEdit(row) {
       this.$emit("viewDetail", row);
    },
    handleSave() {
      this.dialogVisible = true;
      this.dialogIsEdit = false;
      this.dialogIsFixed = false;
      this.dialogValue = { condition: "", record: "", process: "" };
      this.dialogIndex = null;
    },
    handleDraft() {
      // 存稿逻辑
    },
    handleDialogOk(val) {
      if (this.dialogIsEdit && this.dialogIndex !== null) {
        this.$set(this.tableData, this.dialogIndex, val);
      } else {
        this.tableData.push(val);
      }
    },
    getRowClassName({ rowIndex }) {
      return rowIndex < this.initialTableData.length ? "fixed-row" : "";
    },
  },
};
</script>
<style scoped lang="less">
.el-dialog__body {
  padding-bottom: 0;
}
.top-card {
  margin-bottom: 0;
  background: rgba(239, 239, 239, 1);
  border-radius: 16px;
}
.top-info-row {
  align-items: stretch;
}
.info-col {
  display: flex;
  flex-direction: column;
}
.info-item {
  display: flex;
  font-size: 15px;
  height: 45px;
  line-height: 45px;
}
.label {
  color: #666;
  font-weight: 500;
}
.sign-col {
  align-items: center;
  text-align: center;
}
.sign-label {
  justify-content: center;
}
.signature-item {
  justify-content: center;
}
.signature-area {
  min-height: 80px;
  min-width: 120px;
  background: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 8px;
}
.signature-area img {
  max-width: 100%;
  max-height: 100%;
  display: block;
}
.waiting-text {
  color: #909399;
  font-size: 14px;
}
.sign-time {
  justify-content: center;
  text-align: center;
  color: #666;
  font-size: 14px;
}
.section-card {
  margin-bottom: 0;
}
.footer-btns {
  display: flex;
  justify-content: center;
  padding: 24px;
  padding-bottom: 0;
  gap: 24px;
  .el-button {
    width: 150px;
  }
}
::v-deep(.fixed-row) {
  background-color: rgb(228, 248, 250) !important;
}
@media (max-width: 900px) {
  .info-col {
    height: auto;
  }
}
</style>
culture/src/views/strain-library/validation/chief-cell/EditConditionDialog.vue
New file
@@ -0,0 +1,67 @@
<template>
  <el-dialog :visible.sync="visible"  width="800px" @close="handleClose">
    <el-form label-width="120px" label-position="top">
      <el-form-item label="菌种培养工艺条件">
        <el-input v-model="form.conditions" :disabled="isFixed || value.isDetail" placeholder="请输入" />
      </el-form-item>
      <el-form-item label="菌种培养工艺实况记录">
        <el-input type="textarea" :disabled="value.isDetail" v-model="form.record" :rows="7" placeholder="请输入文本内容" />
      </el-form-item>
      <el-form-item label="菌种培养标准工艺">
        <el-input type="textarea" :disabled="value.isDetail" v-model="form.workmanship" :rows="7" placeholder="请输入文本内容" />
      </el-form-item>
    </el-form>
    <div style="text-align: center; margin-top: 24px;">
      <el-button v-if="value.isDetail" @click="handleClose">关闭</el-button>
      <el-button type="primary" v-if="!value.isDetail" @click="handleOk">保存</el-button>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: 'EditConditionDialog',
  props: {
    visible: Boolean,
    isEdit: Boolean,
    isFixed: Boolean, // true: 固定的8个条件,false: 新增条件
    value: {
      type: Object,
      default: () => ({ conditions: '', record: '', workmanship: '' })
    }
  },
  data() {
    return {
      form: { conditions: '', record: '', workmanship: '' }
    }
  },
  watch: {
    value: {
      immediate: true,
      handler(val) {
        this.form = { ...val }
      }
    },
    visible(val) {
      if (!val) {
        this.form = { conditions: '', record: '', workmanship: '' }
      }
    }
  },
  methods: {
    handleOk() {
      this.$emit('ok', { ...this.form })
      this.handleClose()
    },
    handleClose() {
      this.$emit('update:visible', false)
    }
  }
}
</script>
<style scoped>
.el-dialog__body {
  padding-bottom: 0;
}
</style>
culture/src/views/strain-library/validation/chief-cell/add.vue
New file
@@ -0,0 +1,356 @@
<template>
    <Card>
        <!-- <div class="header-title">
            <div class="header-title-left">
                <img src="@/assets/public/headercard.png" />
                <div>新增原始细胞</div>
            </div>
        </div> -->
        <el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form">
            <div class="form-row">
                <el-form-item label="菌种来源" prop="strainSource">
                    <el-input v-model="form.strainSource" placeholder="请输入"></el-input>
                </el-form-item>
            </div>
            <div class="form-row three-columns">
                <el-form-item label="鉴别菌株编号" prop="identifyingStrainCode">
                    <el-input v-model="form.identifyingStrainCode" placeholder="请输入"></el-input>
                </el-form-item>
                <el-form-item label="鉴别菌株名称" prop="identifyingStrainName">
                    <el-input v-model="form.identifyingStrainName" placeholder="请输入"></el-input>
                </el-form-item>
                <div class="form-item-placeholder"></div>
            </div>
            <div class="form-row three-columns">
                <el-form-item label="验证实验编号" prop="validationExperimentCode">
                    <el-input v-model="form.validationExperimentCode" placeholder="请输入"></el-input>
                </el-form-item>
                <el-form-item label="实验时间" prop="experimentTime">
                    <el-date-picker :prefix-icon="' '" style="width: 290px;" v-model="form.experimentTime" type="date"
                        placeholder="请选择实验时间"></el-date-picker>
                </el-form-item>
                <div class="form-item-placeholder"></div>
            </div>
            <div class="end-btn" style="margin-top: 400px">
                <el-button type="primary" @click="handleSubmit">提交</el-button>
                <el-button @click="handleDraft">存草稿</el-button>
            </div>
        </el-form>
        <!-- 签字确认组件 -->
        <ConfirmStorageDialog :visible.sync="signatureVisible" :handleSignature="form.handleSignature"
            @confirm="handleSignatureConfirm" name="操作人签字" text="是否确认提交该项原始细胞库资料信息?" />
    </Card>
</template>
<script>
import ConfirmStorageDialog from '@/components/confirm-storage-dialog/index.vue'
import { add, edit, detail } from './service'
import moment from 'moment'
export default {
    name: 'AddprimitiveCell',
    components: {
        ConfirmStorageDialog
    },
    data() {
        return {
            signatureVisible: false,
            currentAction: '', // 'submit' or 'batchAdd'
            batchForm: {
                count: ''
            },
            form: {
                strainSource: '',         // 菌种来源
                identifyingStrainCode: '',      // 鉴别菌株编号
                identifyingStrainName: '',    // 鉴别菌株名称
                validationExperimentCode: '',      // 验证实验编号
                experimentTime: '', // 实验时间
                handleSignature: '', // 签名图片url
            },
            rules: {
                strainSource: [{ required: true, message: '请输入菌种来源', trigger: 'blur' }],
                identifyingStrainCode: [{ required: true, message: '请输入鉴别菌株编号', trigger: 'blur' }],
                identifyingStrainName: [{ required: true, message: '请输入鉴别菌株名称', trigger: 'blur' }],
                validationExperimentCode: [{ required: true, message: '请输入验证实验编号', trigger: 'blur' }],
                experimentTime: [{ required: true, message: '请输入实验时间', trigger: 'blur' }]
            }
        }
    },
    mounted() {
        if (this.$route.query.id) {
            detail({ id: this.$route.query.id }).then(res => {
                if (res) {
                    // 这里根据实际接口返回字段做适配
                    this.form = res
                }
            })
        }
    },
    methods: {
        handleSubmit() {
            this.$refs.strainForm.validate((valid) => {
                if (valid) {
                    this.currentAction = 'submit'
                    this.signatureVisible = true
                }
            })
        },
        handleDraft() {
            // 实现存草稿逻辑
            this.signatureVisible = true
            this.currentAction = 'draft'
        },
        handleSignatureConfirm(signatureImage) {
            this.signatureVisible = false;
            const id = this.$route.query.id || this.$route.params.id;
            const submitData = { ...this.form, strainType: 2, isDraft: this.currentAction == 'submit' ? 0 : 1, handleSignature: signatureImage.signature, experimentTime: moment(this.form.experimentTime).format('YYYY-MM-DD') };
            if (this.currentAction === 'submit') {
                if (id) {
                    // 编辑
                    edit({ ...submitData, id }).then(() => {
                        this.$router.back();
                    });
                } else {
                    // 新增
                    add(submitData).then(() => {
                        this.$router.back();
                    });
                }
            } else {
                // 存草稿
                add(submitData).then(() => {
                    this.$router.back();
                });
            }
        },
        mounted() {
            const id = this.$route.query.id || this.$route.params.id;
            if (id) {
                // 编辑或详情回显
                detail({ id }).then(res => {
                    if (res && res.data) {
                        // 这里根据实际接口返回字段做适配
                        Object.assign(this.form, res.data);
                    }
                });
            }
        }
    }
}
</script>
<style scoped lang="less">
.add-strain {
    height: 100%;
    background: #F5F7FA;
    .form-card {
        background: #fff;
        border-radius: 8px;
    }
}
.header-title {
    margin-bottom: 24px;
    &-left {
        display: flex;
        align-items: center;
        img {
            width: 20px;
            height: 20px;
            margin-right: 8px;
        }
        div {
            font-size: 18px;
            font-weight: bold;
            color: #303133;
        }
    }
}
.end-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    button {
        width: 180px;
        height: 36px;
        // background: #409EFF;
    }
}
.strain-form {
    padding: 0 40px;
    .form-row {
        display: flex;
        flex-wrap: wrap;
        gap: 24px;
        margin-bottom: 24px;
        &.three-columns {
            .el-form-item,
            .form-item-placeholder {
                flex: 1;
                min-width: 280px;
                @media screen and (max-width: 1200px) {
                    min-width: calc(50% - 12px);
                }
                @media screen and (max-width: 768px) {
                    min-width: 100%;
                }
            }
            .form-item-placeholder {
                @media screen and (max-width: 1200px) {
                    display: none;
                }
            }
        }
        .el-form-item {
            margin-bottom: 0;
            &.full-width {
                width: 100%;
            }
        }
    }
    :deep(.el-form-item__label) {
        font-weight: normal;
        color: #606266;
        padding-bottom: 8px;
        line-height: 20px;
    }
    :deep(.el-form-item__content) {
        line-height: unset;
    }
    :deep(.el-input__inner) {
        border-radius: 4px;
        height: 36px;
        line-height: 36px;
    }
    :deep(.el-textarea__inner) {
        border-radius: 4px;
        padding: 8px 12px;
        min-height: 120px;
    }
}
.batch-add-dialog {
    :deep(.el-dialog__header) {
        margin: 0;
        padding: 20px;
        text-align: center;
        border-bottom: 1px solid #EBEEF5;
        .el-dialog__title {
            font-size: 16px;
            font-weight: 600;
            color: #303133;
        }
    }
    :deep(.el-dialog__body) {
        padding: 20px;
    }
    .dialog-content {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .batch-form {
        width: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        :deep(.el-form-item) {
            width: 320px;
            margin-bottom: 0;
        }
        :deep(.el-form-item__label) {
            width: 100%;
            color: #606266;
            font-weight: normal;
            padding-bottom: 8px;
            &::before {
                color: #F56C6C;
            }
        }
        :deep(.el-input) {
            width: 100%;
            input {
                width: 100%;
            }
        }
    }
    .dialog-notice {
        margin-top: 16px;
        text-align: center;
        p {
            margin: 0;
            line-height: 22px;
            color: #606266;
            font-size: 14px;
        }
    }
    :deep(.el-dialog__footer) {
        padding: 0 20px 20px;
        text-align: center;
        .el-button {
            width: 180px;
            height: 36px;
            padding: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            border-radius: 4px;
            margin: 0;
        }
    }
}
.end-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    :deep(.el-button) {
        width: 180px;
        height: 36px;
        padding: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 14px;
        border-radius: 4px;
        margin: 0;
    }
}
</style>
culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue
New file
@@ -0,0 +1,287 @@
<template>
  <Card class="confirm-detail-page">
    <el-card class="top-card">
      <el-row :gutter="24" class="top-info-row">
        <el-col :span="8" class="info-col">
          <div class="info-item"><span class="label">菌种来源:</span>{{ detail.strainSource }}</div>
          <div class="info-item"><span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}</div>
          <div class="info-item"><span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}</div>
        </el-col>
        <el-col :span="8" class="info-col">
          <div class="info-item"><span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}</div>
          <div class="info-item"><span class="label">实验时间:</span>{{ detail.experimentTime }}</div>
          <div class="info-item"></div>
        </el-col>
        <el-col :span="8" class="info-col ">
          <div class="info-item sign-label"><span class="label">菌种实验员签字</span></div>
          <div class="info-item signature-item">
            <div class="signature-area">
              <img v-if="detail.handleSignature" :src="detail.handleSignature" alt="签字" />
              <span v-else class="waiting-text">暂无签名</span>
            </div>
          </div>
        </el-col>
      </el-row>
    </el-card>
    <div class="section-card" style="margin-top: 24px;">
      <el-form ref="form" label-width="100px" :model="detail" :rules="rules" label-position="top">
        <el-form-item label="实验结论" prop="result">
          <el-input type="textarea" v-model="detail.result" :rows="3" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="批准菌株用途" prop="purpose">
          <el-checkbox-group v-model="detail.purpose">
            <el-checkbox :label="1">传代</el-checkbox>
            <el-checkbox :label="2">菌种保藏</el-checkbox>
            <el-checkbox :label="3">废弃</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </div>
    <el-button type="primary" @click="handleSave" class="el-icon-plus"> 新增</el-button>
    <EditConditionDialog
      :visible.sync="dialogVisible"
      :isEdit="dialogIsEdit"
      :isFixed="dialogIsFixed"
      :value="dialogValue"
      @ok="handleDialogOk"
    />
    <div class="section-card" style="margin-top: 12px;">
      <el-table :data="tableData" border style="width: 100%;" :row-class-name="getRowClassName">
        <el-table-column prop="conditions" label="菌种培养工艺条件" />
        <el-table-column prop="record" label="菌种培养工艺实况记录" />
        <el-table-column prop="workmanship" label="菌种培养标准工艺" />
        <el-table-column label="操作" width="120">
          <template #default="{ row }">
            <el-button type="text" @click="handleEdit(row)">编辑</el-button>
            <el-button type="text" @click="handleEdit(row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="footer-btns">
      <el-button type="primary" @click="handleSave">保存</el-button>
      <el-button @click="handleDraft">存稿</el-button>
    </div>
    <!-- <DetailConditionDialog
      :visible.sync="detailDialogVisible"
      :value="detailDialogValue"
    /> -->
  </Card>
</template>
<script>
import EditConditionDialog from './EditConditionDialog.vue'
import DetailConditionDialog from './DetailConditionDialog.vue'
import { detail,confirm } from './service'
export default {
  name: 'ConfirmDetail',
  components: { EditConditionDialog, DetailConditionDialog },
  data() {
    return {
      detail: {
        strainSource: '',
        identifyingStrainCode: '',
        identifyingStrainName: '',
        validationExperimentCode: '',
        experimentTime: '',
        handleSignature: '', // 签名图片url
        result:'',
        purpose: []
      },
      activeTab: 'conditions',
      rules: {
        result: [
          { required: true, message: '请输入实验结论', trigger: 'blur' }
        ],
        purpose: [
          { required: true, message: '请选择菌种用途', trigger: 'change' }
        ]
      },
      initialTableData: [
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      tableData: [
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      dialogVisible: false,
      dialogIsEdit: false,
      dialogIsFixed: false,
      dialogValue: {},
      dialogIndex: null,
      detailDialogVisible: false,
      detailDialogValue: {}
    }
  },
  mounted() {
    this.getDetail()
  },
  methods: {
    getDetail() {
      detail({id: this.$route.query.id}).then(res => {
        this.detail = {
          ...res,
          handleSignature: res.handleSignature || '', // 处理签名为空的情况
          purpose: res.purpose || [] // 处理 purpose 为空的情况
        }
      })
    },
    handleEdit(row) {
      const idx = this.tableData.indexOf(row)
      this.dialogVisible = true
      this.dialogIsEdit = true
      this.dialogIsFixed = idx < this.initialTableData?.length
      this.dialogValue = { ...row }
      this.dialogIndex = idx
    },
    handleDetail(row) {
      this.detailDialogVisible = true
      this.detailDialogValue = { ...row }
    },
    handleSave() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.detail.list = this.tableData || []
          this.detail.purpose = this.detail.purpose.join(',')
          confirm({...this.detail}).then(res => {
            if (res.code == 200) {
              this.$message.success('保存成功');
              this.$router.back()
            } else {
              this.$message.error(res.msg);
            }
          })
        } else {
          this.$message.error('请填写必填项');
          return false;
        }
      });
    },
    handleDraft() {
      // 存稿逻辑
    },
    handleDialogOk(val) {
      if (this.dialogIsEdit && this.dialogIndex !== null) {
        this.$set(this.tableData, this.dialogIndex, val)
      } else {
        this.tableData.push(val)
      }
    },
    getRowClassName({ rowIndex }) {
      return rowIndex < this.initialTableData?.length ? 'fixed-row' : '';
    }
  }
}
</script>
<style scoped lang="less">
.top-card {
  margin-bottom: 0;
  background: rgba(239, 239, 239, 1);
  border-radius: 16px;
}
.top-info-row {
  align-items: stretch;
}
.info-col {
  display: flex;
  flex-direction: column;
}
.info-item {
  display: flex;
  font-size: 15px;
  height: 45px;
  line-height: 45px;
}
.label {
  color: #666;
  font-weight: 500;
}
.sign-col {
  align-items: center;
  text-align: center;
}
.sign-label {
  justify-content: center;
}
.signature-item {
  justify-content: center;
}
.signature-area {
  min-height: 80px;
  min-width: 120px;
  background: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 8px;
}
.signature-area img {
  max-width: 100%;
  max-height: 100%;
  display: block;
}
.waiting-text {
  color: #909399;
  font-size: 14px;
}
.sign-time {
  justify-content: center;
  text-align: center;
  color: #666;
  font-size: 14px;
}
.section-card {
  margin-bottom: 0;
}
.footer-btns {
  display: flex;
  justify-content: center;
  padding: 24px;
  padding-bottom: 0;
  gap: 24px;
  .el-button {
    width: 150px;
  }
}
::v-deep(.fixed-row) {
  background-color: rgb(228, 248, 250) !important;
}
@media (max-width: 900px) {
  .info-col {
    height: auto;
  }
}
</style>
culture/src/views/strain-library/validation/chief-cell/index.vue
@@ -1,435 +1,392 @@
<template>
    <div class="list">
  <div class="list">
    <!-- Table -->
    <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @handleCurrentChange="handleCurrentChange"
      @handleSizeChange="handleSizeChange">
      <template #search>
        <el-form :model="form" label-width="auto" inline>
          <el-form-item label="鉴别菌株编号:">
            <el-input v-model="form.identifyingStrainCode" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="鉴别菌株名称:">
            <el-input v-model="form.identifyingStrainName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="验证实验编号:" v-if="roleType != 4">
            <el-input v-model="form.validationExperimentCode" placeholder="请输入"></el-input>
          </el-form-item>
        <!-- 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 label="验证实验编号:">
                        <el-input v-model="form.strainName" 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 label="菌种名称:">
                        <el-input v-model="form.strainName" placeholder="请输入"></el-input>
                    </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>
          <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 class="flex a-center">
                        <el-button @click="handleNewStrain" class="el-icon-plus" type="primary" style="margin-right: 12px;">新增主细胞</el-button>
                    </div>
                </div>
            </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" v-if="roleType==4" :class="{ active: currentType === 'draft' }" @click="handleTypeChange('draft')">
              草稿箱
            </div>
          </div>
          <div class="flex a-center" v-if="roleType == 4">
            <el-button @click="handleNewStrain" class="el-icon-plus" type="primary"
              style="margin-right: 12px">新增原始细胞库资料</el-button>
          </div>
        </div>
      </template>
            <template #table>
                <el-table-column prop="strainNo" label="菌种来源" />
                <el-table-column prop="strainNo" label="鉴别菌株编号" />
                <el-table-column prop="strainName" label="鉴别菌株名称" />
                <el-table-column prop="source" label="验证实验编号" />
                <el-table-column prop="method" label="创建人" />
                <el-table-column prop="certificate" label="创建时间" />
                <el-table-column 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 type="text" @click="handleEdit(row)">编辑</el-button>
                        <el-button type="text" @click="handleRecord(row)">删除</el-button>
                        <el-button type="text" @click="handleRecord(row)">确认</el-button>
                    </template>
                </el-table-column>
            </template>
        </TableCustom>
    </div>
      <template #table>
        <el-table-column prop="strainSource" label="菌种来源" />
        <el-table-column prop="identifyingStrainCode" label="鉴别菌株编号" />
        <el-table-column prop="identifyingStrainName" label="鉴别菌株名称" />
        <el-table-column prop="validationExperimentCode" label="验证实验编号" />
        <el-table-column prop="createBy" label="创建人" />
        <el-table-column prop="createTime" label="创建时间" />
        <el-table-column prop="status" label="状态" v-if="currentType == 'list'">
          <template #default="{ row }">
            <el-tag v-if="row.status == 1" type="info">待确认</el-tag>
            <el-tag v-if="row.status == 2" type="success">已提交</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template #default="{ row }">
            <el-button type="text"
             v-if="row.status == 1 && roleType == 3"
              @click="$router.push('/strain/validation/confirm-detail?id=' + row.id)">确认</el-button>
            <el-button type="text" @click="handleDetail(row)">详情</el-button>
            <el-button type="text" @click="handleDetail2(row)">详情</el-button>
            <el-button type="text" @click="handleEdit(row)">编辑</el-button>
            <el-button type="text" @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </template>
    </TableCustom>
    <PrimitiveCellDetailDialog :visible.sync="detailVisible" :detail="currentDetail" />
    <DetailConditionDialog @viewDetail="viewDetail" :visible.sync="detailDialogVisible" :value="detailDialogValue" />
    <EditConditionDialog :visible.sync="editDialogVisible" :value="editDialogValue" />
    <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
  </div>
</template>
<script>
import PrimitiveCellDetailDialog from "./primitive-cell-detail-dialog.vue";
import DetailConditionDialog from "./DetailConditionDialog.vue";
import EditConditionDialog from "./EditConditionDialog.vue";
import { getList, delOne } from "./service";
export default {
    name: 'ChiefCell',
    components: {
  name: "PrimitiveCell",
  components: {
    PrimitiveCellDetailDialog,
    DetailConditionDialog,
    EditConditionDialog,
  },
  data() {
    return {
      detailDialogVisible: false,
      detailDialogValue: {},
      dialogVisible: false,
      currentType: "list",
      detailVisible: false,
      editDialogVisible: false,
      showDelConfirm: false,
      editDialogValue: {},
      currentDetail: {},
      roleType: JSON.parse(sessionStorage.getItem("userInfo")).roleType,
      form: {
        identifyingStrainCode: "",
        identifyingStrainName: "",
        validationExperimentCode: "",
        startTime: "",
        endTime: "",
        isDraft: 0,
        strainType: 2,
      },
      queryForm: {
        pageSize: 10,
        pageNum: 1,
      },
      total: 0,
      tableData: [],
    };
  },
  methods: {
    handleDetail(row) {
      this.currentDetail = row;
      this.detailVisible = true;
    },
    data() {
        return {
            dialogVisible: false,
            currentType: 'list',
            detailVisible: false,
            currentDetail: {},
            form: {
                strainNo: '',
                strainName: '',
                status: ''
            },
            queryForm: {
                pageSize: 10,
                pageNum: 1
            },
            total: 800,
            tableData: [
                {
                    strainNo: 'YX-2024001',
                    strainName: '大肠杆菌',
                    source: '实验室分离',
                    method: '形态学鉴定、生理生化试验',
                    certificate: '革兰氏阴性杆菌,可发酵葡萄糖产酸产气,IMViC试验++--',
                    storage: '斜面培养',
                    amount: 'A区-01-001',
                    inventory: '50',
                    notes: '用于质粒转化',
                    status: '1'
                },
                {
                    strainNo: 'YX-2024002',
                    strainName: '枯草芽孢杆菌',
                    source: '菌种保藏中心',
                    method: '16S rDNA测序',
                    certificate: '革兰氏阳性芽孢杆菌,可水解淀粉,产生溶菌素',
                    storage: '冷冻保存',
                    amount: 'B区-02-005',
                    inventory: '30',
                    notes: '工业发酵菌种',
                    status: '1'
                },
                {
                    strainNo: 'YX-2024003',
                    strainName: '酿酒酵母',
                    source: '发酵工厂',
                    method: '显微镜观察、生理特性',
                    certificate: '椭圆形单细胞真菌,可发酵葡萄糖产生乙醇',
                    storage: '甘油管保存',
                    amount: 'A区-03-002',
                    inventory: '40',
                    notes: '发酵工艺优化',
                    status: '2'
                },
                {
                    strainNo: 'YX-2024004',
                    strainName: '乳酸菌',
                    source: '乳制品分离',
                    method: '生化鉴定、API条',
                    certificate: '革兰氏阳性球菌,产生乳酸,耐酸性强',
                    storage: '冷冻干燥',
                    amount: 'C区-01-003',
                    inventory: '25',
                    notes: '益生菌研究',
                    status: '3'
                },
                {
                    strainNo: 'YX-2024005',
                    strainName: '青霉菌',
                    source: '环境样本',
                    method: '形态学特征、ITS测序',
                    certificate: '丝状真菌,产生蓝绿色分生孢子,可产青霉素',
                    storage: '斜面培养',
                    amount: 'B区-04-001',
                    inventory: '35',
                    notes: '次级代谢产物研究',
                    status: '1'
                }
            ]
        }
    handleDetail2(row) {
      this.detailDialogValue = row;
      this.detailDialogVisible = true;
    },
    methods: {
        handleViewMore() {
            this.dialogVisible = true;
    handleViewMore() {
      this.dialogVisible = true;
    },
    viewDetail(row) {
      row.isDetail = true;
      this.editDialogValue = row;
      this.editDialogVisible = true;
    },
    resetForm() {
      this.form = {
        identifyingStrainCode: "",
        identifyingStrainName: "",
        startTime: "",
        endTime: "",
        validationExperimentCode: "",
        isDraft: this.currentType === 'draft' ? 1 : 0,
        strainType: 2,
      };
      this.searchData();
    },
    async searchData() {
      const params = {
        ...this.form,
        pageNum: this.queryForm.pageNum,
        pageSize: this.queryForm.pageSize,
      };
      try {
        const res = await getList(params);
        this.tableData = res.data?.records || [];
        this.total = res.data?.total || 0;
      } catch (e) {
        this.tableData = [];
        this.total = 0;
      }
    },
    handleNewStrain() {
      this.$router.push("/strain/validation/add-primitive-cell");
      // Implement new strain logic
    },
    handleBatchAdd() {
      // Implement batch add logic
    },
    handleEdit(row) {
      this.$router.push({
        path: "/strain/validation/edit-primitive-cell",
        query: {
          id: row.id,
        },
        resetForm() {
            this.form = {
                strainNo: '',
                strainName: '',
                status: ''
            }
            this.searchData()
        },
        searchData() {
            // 模拟搜索逻辑
            const { strainNo, strainName, status } = this.form
            let filteredData = [...this.tableData]
            if (strainNo) {
                filteredData = filteredData.filter(item =>
                    item.strainNo.toLowerCase().includes(strainNo.toLowerCase())
                )
            }
            if (strainName) {
                filteredData = filteredData.filter(item =>
                    item.strainName.toLowerCase().includes(strainName.toLowerCase())
                )
            }
            if (status) {
                filteredData = filteredData.filter(item =>
                    item.status === status
                )
            }
            this.total = filteredData.length
            // 实际项目中这里应该调用API
            console.log('搜索条件:', this.form)
            console.log('分页信息:', this.queryForm)
        },
        handleNewStrain() {
            this.$router.push('/strain-library/strain-library-manage/add')
            // Implement new strain logic
        },
        handleBatchAdd() {
            // Implement batch add logic
        },
        handleDetail(row) {
            this.currentDetail = row;
            this.detailVisible = true;
        },
        handleEdit(row) {
            // Implement edit logic
        },
        handleRecord(row) {
            this.$router.push({
                path: '/strain-library/strain-library-manage/record',
                query: {
                    id: row.strainNo
                }
            })
        },
        handleCurrentChange(page) {
            this.queryForm.pageNum = page
            // Implement page change logic
        },
        handleSizeChange(size) {
            this.queryForm.pageSize = size
            // Implement size change logic
        },
        handleTypeChange(type) {
            this.currentType = type;
            // Implement type change logic
        },
        getStatusType(status) {
            const types = {
                1: 'success',
                2: 'info',
                3: 'warning'
            }
            return types[status] || 'info'
        },
        getStatusText(status) {
            const texts = {
                1: '已入库',
                2: '已出库',
                3: '入库待确认'
            }
            return texts[status] || '未知状态'
      });
      // Implement edit logic
    },
    handleDelete(row) {
      this.currentDetail = row;
      this.showDelConfirm = true;
    },
    handleDelConfirm() {
      delOne({ id: this.currentDetail.id }).then(res => {
        this.$message.success('删除成功')
        this.showDelConfirm = false
        if (this.tableData.length == 1 && this.queryForm.pageNum > 1) {
          this.queryForm.pageNum -= 1;
        }
    }
}
        this.searchData()
      })
    },
    handleCurrentChange(page) {
      this.queryForm.pageNum = page;
      this.searchData();
    },
    handleSizeChange(size) {
      this.queryForm.pageSize = size;
      this.searchData();
    },
    handleTypeChange(type) {
      this.currentType = type;
      this.form.isDraft = type === "draft" ? 1 : 0;
      this.form.strainType = 2; // 1: 原始细胞库
      this.searchData();
    },
  },
  mounted() {
    this.searchData();
  },
};
</script>
<style scoped lang="less">
.list {
    padding: 20px;
  padding: 20px;
}
.header-box {
    margin-bottom: 20px;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.8);
  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;
  .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-icon {
      width: 20px;
      height: 20px;
      margin-right: 10px;
    }
    .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;
        }
    .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;
  margin-bottom: 20px;
  background: #f5f7fa;
  padding: 24px;
  border-radius: 8px;
    .el-form-item {
        margin-right: 20px;
        margin-bottom: 0;
    }
  .el-form-item {
    margin-right: 20px;
    margin-bottom: 0;
  }
    .el-button {
        margin-left: 10px;
    }
  .el-button {
    margin-left: 10px;
  }
}
.action-buttons {
    margin-bottom: 20px;
  margin-bottom: 20px;
    .el-button {
        margin-right: 10px;
    }
  .el-button {
    margin-right: 10px;
  }
}
.tab-container {
    display: flex;
    margin-bottom: 20px;
  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;
  .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;
        }
    &.active {
      background: #fff;
      border-color: #049c9a;
      color: #049c9a;
      font-weight: bold;
    }
  }
}
.flex {
    display: flex;
    align-items: center;
  display: flex;
  align-items: center;
}
.tableTitle {
    display: flex;
    padding-bottom: 20px;
    justify-content: space-between;
    align-items: center;
  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;
  .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;
  }
    .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;
    }
  .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__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;
  :deep(.el-dialog__body) {
    padding: 20px;
        .dialog-content {
            font-size: 14px;
            line-height: 1.8;
            color: #606266;
    .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;
                }
            }
      p {
        margin: 12px 0;
        &:first-child {
          margin-top: 0;
        }
        &:last-child {
          margin-bottom: 0;
        }
      }
    }
  }
}
</style>
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
New file
@@ -0,0 +1,107 @@
<template>
  <el-dialog
    :visible.sync="visible"
    title="原始细胞库资料详情"
    width="650px"
    @close="handleClose"
  >
    <el-form label-width="120px" label-position="top" class="detail-form">
        <el-row :gutter="24">
            <el-col :span="12">
            <el-form-item label="菌种源">
                <el-input v-model="detail.strainSource" disabled placeholder="请输入" />
            </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="菌种编号">
            <el-input v-model="detail.identifyingStrainCode" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="菌种名称">
            <el-input v-model="detail.identifyingStrainName" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="验证实验编号">
            <el-input v-model="detail.validationExperimentCode" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="实验时间">
            <el-input v-model="detail.experimentTime" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="菌种实验员签字">
            <div class="signature-area">
              <img v-if="detail.handleSignature" :src="detail.handleSignature" alt="签字" />
              <span v-else class="waiting-text">暂无签名</span>
            </div>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="签字时间">
            <el-input v-model="detail.handleTime" disabled />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </el-dialog>
</template>
<script>
export default {
  name: 'PrimitiveCellDetailDialog',
  props: {
    visible: Boolean,
    detail: {
      type: Object,
      default: () => ({
        strainSource: '',
        identifyingStrainCode: '',
        identifyingStrainName: '',
        validationExperimentCode: '',
        experimentTime: '',
        handleSignature: '',
        handleTime: ''
      })
    }
  },
  methods: {
    handleClose() {
      this.$emit('update:visible', false)
    }
  }
}
</script>
<style scoped>
.detail-form {
  margin-top: 10px;
}
.signature-area {
  min-height: 120px;
  min-width: 240px;
  background: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.signature-area img {
  max-width: 100%;
  max-height: 100%;
  display: block;
}
.waiting-text {
  color: #909399;
  font-size: 14px;
}
</style>
culture/src/views/strain-library/validation/chief-cell/service.js
New file
@@ -0,0 +1,42 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  console.log('data', data)
  return axios.post('/api/t-strain-validation-data/pageList', { ...data })
}
//新增
export const add = (data) => {
    console.log('data', data)
    return axios.post('/api/t-strain-validation-data/add', { ...data })
}
//编辑
export const edit = (data) => {
    return axios.post('/api/t-strain-validation-data/updateOriginal', { ...data })
}
//详情
export const detail = (data) => {
    return axios.get('/open/t-strain-validation-data/getDetailById', { params: { id: data.id } })
}
//主细胞删除
export const delOne = (data) => {
    return axios.delete('/open/t-strain-validation-data/deleteMain', { params: { id: data.id }})
}
//原始细胞删除
export const delTwo = (data) => {
    return axios.delete('/open/t-strain-validation-data/deleteOriginal', { params: { id: data.id }})
}
// 确认
export const confirm = (data) => {
    console.log('data', data)
    return axios.post('/api/t-strain-validation-data/confirm', { ...data })
}
culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue
@@ -1,21 +1,21 @@
<template>
  <el-dialog :visible.sync="visible" width="80%" @close="handleClose">
  <el-dialog :visible.sync="visible" width="80%" @open="handleOpen" @close="handleClose">
    <el-card class="top-card">
      <el-row :gutter="24" class="top-info-row">
        <el-col :span="8" class="info-col">
          <div class="info-item">
            <span class="label">菌种来源:</span>{{ detail.source }}
            <span class="label">菌种来源:</span>{{ detail.strainSource }}
          </div>
          <div class="info-item">
            <span class="label">鉴别菌株编号:</span>{{ detail.strainNo }}
            <span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}
          </div>
          <div class="info-item">
            <span class="label">鉴别菌株名称:</span>{{ detail.strainName }}
            <span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}
          </div>
        </el-col>
        <el-col :span="8" class="info-col">
          <div class="info-item">
            <span class="label">验证实验编号:</span>{{ detail.verifyNo }}
            <span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}
          </div>
          <div class="info-item">
            <span class="label">实验时间:</span>{{ detail.experimentTime }}
@@ -28,7 +28,7 @@
          </div>
          <div class="info-item signature-item">
            <div class="signature-area">
              <img v-if="detail.signature" :src="detail.signature" alt="签字" />
              <img v-if="detail.handleSignature" :src="detail.handleSignature" alt="签字" />
              <span v-else class="waiting-text">暂无签名</span>
            </div>
          </div>
@@ -36,35 +36,25 @@
      </el-row>
    </el-card>
    <div class="section-card" style="margin-top: 24px">
      <el-form label-width="100px" label-position="top">
        <el-form-item label="实验结论">
          <el-input
            type="textarea"
            v-model="detail.conclusion"
            :rows="3"
            placeholder="请输入"
          />
      <el-form ref="form" label-width="100px" :model="detail" label-position="top">
        <el-form-item label="实验结论" prop="result">
          <el-input type="textarea" :disabled="true" v-model="detail.result" :rows="3" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="批准菌株用途">
          <el-checkbox-group v-model="detail.usage">
            <el-checkbox label="传代" />
            <el-checkbox label="菌种保藏" />
            <el-checkbox label="废弃" />
        <el-form-item label="批准菌株用途" prop="purpose">
          <el-checkbox-group :disabled="true" v-model="detail.purpose">
            <el-checkbox label="1">传代</el-checkbox>
            <el-checkbox label="2">菌种保藏</el-checkbox>
            <el-checkbox label="3">废弃</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </div>
    <div class="section-card" style="margin-top: 12px">
      <el-table
        :data="tableData"
        border
        style="width: 100%"
        :row-class-name="getRowClassName"
      >
        <el-table-column prop="condition" label="菌种培养工艺条件" />
      <el-table :data="tableData" border style="width: 100%" :row-class-name="getRowClassName">
        <el-table-column prop="conditions" label="菌种培养工艺条件" />
        <el-table-column prop="record" label="菌种培养工艺实况记录" />
        <el-table-column prop="process" label="菌种培养标准工艺" />
        <el-table-column prop="workmanship" label="菌种培养标准工艺" />
        <el-table-column label="操作" width="120">
          <template #default="{ row }">
            <el-button type="text" @click="handleEdit(row)">详情</el-button>
@@ -77,6 +67,7 @@
<script>
import DetailConditionDialog from "./DetailConditionDialog.vue";
import { detail } from "./service.js";
export default {
  name: "DetailConditionDialog",
  components: { DetailConditionDialog },
@@ -86,47 +77,43 @@
      type: Object,
      default: () => ({ condition: "", record: "", process: "" }),
    },
    value: {
      type: Object,
      default: () => ({})
    },
  },
  data() {
    return {
      detail: {
        source: "内容的内容内容内容",
        strainNo: "3411234",
        strainName: "名称名称名称",
        verifyNo: "34133214",
        experimentTime: "2025-1-23 11:10:28",
        signature: "", // 签名图片url
        conclusion: "",
        usage: [],
        strainSource: '',
        identifyingStrainCode: '',
        identifyingStrainName: '',
        validationExperimentCode: '',
        experimentTime: '',
        handleSignature: '', // 签名图片url
        result: '',
        purpose: []
      },
      activeTab: "condition",
      activeTab: "conditions",
      initialTableData: [
        {
          condition: "平板培养基",
          record: "文字内容文字内容文字内容文字内容文字内容文字内容",
          process: "文字内容文字内容文字内容文字内容文字内容文字内容",
        },
        { condition: "培养温度", record: "", process: "" },
        { condition: "培养时间", record: "", process: "" },
        { condition: "摇瓶培养基", record: "", process: "" },
        { condition: "接种量", record: "", process: "" },
        { condition: "培养时间", record: "", process: "" },
        { condition: "发酵时间", record: "", process: "" },
        { condition: "检测数据及结果", record: "", process: "" },
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      tableData: [
        {
          condition: "平板培养基",
          record: "文字内容文字内容文字内容文字内容文字内容文字内容",
          process: "文字内容文字内容文字内容文字内容文字内容文字内容",
        },
        { condition: "培养温度", record: "", process: "" },
        { condition: "培养时间", record: "", process: "" },
        { condition: "摇瓶培养基", record: "", process: "" },
        { condition: "接种量", record: "", process: "" },
        { condition: "培养时间", record: "", process: "" },
        { condition: "发酵时间", record: "", process: "" },
        { condition: "检测数据及结果", record: "", process: "" },
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      dialogVisible: false,
      dialogIsEdit: false,
@@ -136,18 +123,26 @@
    };
  },
  methods: {
    handleOpen() {
      if (this.value.id) {
        detail({ id: this.value.id }).then(res => {
          this.detail = {
            ...res,
            handleSignature: res.handleSignature || '', // 处理签名为空的情况
            purpose: res.purpose.split(',') || [] // 处理 purpose 为空的情况
          }
          this.tableData = res.list || []
        })
      }
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
    handleEdit(row) {
      const idx = this.tableData.indexOf(row);
      this.dialogVisible = true;
      this.dialogIsEdit = true;
      this.dialogIsFixed = idx < this.initialTableData.length;
      this.dialogValue = { ...row };
      this.dialogIndex = idx;
       this.$emit("viewDetail", row);
    },
    handleSave() {
      this.dialogVisible = true;
      this.dialogIsEdit = false;
@@ -176,6 +171,7 @@
.el-dialog__body {
  padding-bottom: 0;
}
.top-card {
  margin-bottom: 0;
  background: rgba(239, 239, 239, 1);
@@ -257,6 +253,7 @@
  padding: 24px;
  padding-bottom: 0;
  gap: 24px;
  .el-button {
    width: 150px;
  }
culture/src/views/strain-library/validation/primitive-cell/EditConditionDialog.vue
@@ -2,17 +2,18 @@
  <el-dialog :visible.sync="visible"  width="800px" @close="handleClose">
    <el-form label-width="120px" label-position="top">
      <el-form-item label="菌种培养工艺条件">
        <el-input v-model="form.condition" :disabled="isFixed" placeholder="请输入" />
        <el-input v-model="form.conditions" :disabled="isFixed || value.isDetail" placeholder="请输入" />
      </el-form-item>
      <el-form-item label="菌种培养工艺实况记录">
        <el-input type="textarea" v-model="form.record" :rows="7" placeholder="请输入文本内容" />
        <el-input type="textarea" :disabled="value.isDetail" v-model="form.record" :rows="7" placeholder="请输入文本内容" />
      </el-form-item>
      <el-form-item label="菌种培养标准工艺">
        <el-input type="textarea" v-model="form.process" :rows="7" placeholder="请输入文本内容" />
        <el-input type="textarea" :disabled="value.isDetail" v-model="form.workmanship" :rows="7" placeholder="请输入文本内容" />
      </el-form-item>
    </el-form>
    <div style="text-align: center; margin-top: 24px;">
      <el-button type="primary" @click="handleOk">保存</el-button>
      <el-button v-if="value.isDetail" @click="handleClose">关闭</el-button>
      <el-button type="primary" v-if="!value.isDetail" @click="handleOk">保存</el-button>
    </div>
  </el-dialog>
</template>
@@ -26,12 +27,12 @@
    isFixed: Boolean, // true: 固定的8个条件,false: 新增条件
    value: {
      type: Object,
      default: () => ({ condition: '', record: '', process: '' })
      default: () => ({ conditions: '', record: '', workmanship: '' })
    }
  },
  data() {
    return {
      form: { condition: '', record: '', process: '' }
      form: { conditions: '', record: '', workmanship: '' }
    }
  },
  watch: {
@@ -43,7 +44,7 @@
    },
    visible(val) {
      if (!val) {
        this.form = { condition: '', record: '', process: '' }
        this.form = { conditions: '', record: '', workmanship: '' }
      }
    }
  },
culture/src/views/strain-library/validation/primitive-cell/add.vue
@@ -38,8 +38,8 @@
        </el-form>
        <!-- 签字确认组件 -->
        <ConfirmStorageDialog :visible.sync="signatureVisible" @confirm="handleSignatureConfirm" name="操作人签字"
            text="是否确认提交该项原始细胞库资料信息?" />
        <ConfirmStorageDialog :visible.sync="signatureVisible" :handleSignature="form.handleSignature"
            @confirm="handleSignatureConfirm" name="操作人签字" text="是否确认提交该项原始细胞库资料信息?" />
    </Card>
</template>
@@ -65,7 +65,8 @@
                identifyingStrainCode: '',      // 鉴别菌株编号
                identifyingStrainName: '',    // 鉴别菌株名称
                validationExperimentCode: '',      // 验证实验编号
                experimentTime: '' // 实验时间
                experimentTime: '', // 实验时间
                handleSignature: '', // 签名图片url
            },
            rules: {
                strainSource: [{ required: true, message: '请输入菌种来源', trigger: 'blur' }],
@@ -76,6 +77,16 @@
            }
        }
    },
    mounted() {
        if (this.$route.query.id) {
            detail({ id: this.$route.query.id }).then(res => {
                if (res) {
                    // 这里根据实际接口返回字段做适配
                    this.form = res
                }
            })
        }
    },
    methods: {
        handleSubmit() {
            this.$refs.strainForm.validate((valid) => {
culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue
@@ -3,12 +3,12 @@
    <el-card class="top-card">
      <el-row :gutter="24" class="top-info-row">
        <el-col :span="8" class="info-col">
          <div class="info-item"><span class="label">菌种来源:</span>{{ detail.source }}</div>
          <div class="info-item"><span class="label">鉴别菌株编号:</span>{{ detail.strainNo }}</div>
          <div class="info-item"><span class="label">鉴别菌株名称:</span>{{ detail.strainName }}</div>
          <div class="info-item"><span class="label">菌种来源:</span>{{ detail.strainSource }}</div>
          <div class="info-item"><span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}</div>
          <div class="info-item"><span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}</div>
        </el-col>
        <el-col :span="8" class="info-col">
          <div class="info-item"><span class="label">验证实验编号:</span>{{ detail.verifyNo }}</div>
          <div class="info-item"><span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}</div>
          <div class="info-item"><span class="label">实验时间:</span>{{ detail.experimentTime }}</div>
          <div class="info-item"></div>
        </el-col>
@@ -16,7 +16,7 @@
          <div class="info-item sign-label"><span class="label">菌种实验员签字</span></div>
          <div class="info-item signature-item">
            <div class="signature-area">
              <img v-if="detail.signature" :src="detail.signature" alt="签字" />
              <img v-if="detail.handleSignature" :src="detail.handleSignature" alt="签字" />
              <span v-else class="waiting-text">暂无签名</span>
            </div>
          </div>
@@ -24,15 +24,15 @@
      </el-row>
    </el-card>
    <div class="section-card" style="margin-top: 24px;">
      <el-form label-width="100px" label-position="top">
        <el-form-item label="实验结论">
          <el-input type="textarea" v-model="detail.conclusion" :rows="3" placeholder="请输入" />
      <el-form ref="form" label-width="100px" :model="detail" :rules="rules" label-position="top">
        <el-form-item label="实验结论" prop="result">
          <el-input type="textarea" v-model="detail.result" :rows="3" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="批准菌株用途">
          <el-checkbox-group v-model="detail.usage">
            <el-checkbox label="传代" />
            <el-checkbox label="菌种保藏" />
            <el-checkbox label="废弃" />
        <el-form-item label="批准菌株用途" prop="purpose">
          <el-checkbox-group v-model="detail.purpose">
            <el-checkbox :label="1">传代</el-checkbox>
            <el-checkbox :label="2">菌种保藏</el-checkbox>
            <el-checkbox :label="3">废弃</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
@@ -48,13 +48,13 @@
    <div class="section-card" style="margin-top: 12px;">
      <el-table :data="tableData" border style="width: 100%;" :row-class-name="getRowClassName">
        <el-table-column prop="condition" label="菌种培养工艺条件" />
        <el-table-column prop="conditions" label="菌种培养工艺条件" />
        <el-table-column prop="record" label="菌种培养工艺实况记录" />
        <el-table-column prop="process" label="菌种培养标准工艺" />
        <el-table-column prop="workmanship" label="菌种培养标准工艺" />
        <el-table-column label="操作" width="120">
          <template #default="{ row }">
            <el-button type="text" @click="handleEdit(row)">编辑</el-button>
            <el-button type="text" @click="handleDetail(row)">详情2</el-button>
            <el-button type="text" @click="handleEdit(row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -63,52 +63,60 @@
      <el-button type="primary" @click="handleSave">保存</el-button>
      <el-button @click="handleDraft">存稿</el-button>
    </div>
    <DetailConditionDialog
    <!-- <DetailConditionDialog
      :visible.sync="detailDialogVisible"
      :value="detailDialogValue"
    />
    /> -->
  </Card>
</template>
<script>
import EditConditionDialog from './EditConditionDialog.vue'
import DetailConditionDialog from './DetailConditionDialog.vue'
import { detail } from './service'
import { detail,confirm } from './service'
export default {
  name: 'ConfirmDetail',
  components: { EditConditionDialog, DetailConditionDialog },
  data() {
    return {
      detail: {
        source: '内容的内容内容内容',
        strainNo: '3411234',
        strainName: '名称名称名称',
        verifyNo: '34133214',
        experimentTime: '2025-1-23 11:10:28',
        signature: '', // 签名图片url
        conclusion: '',
        usage: []
        strainSource: '',
        identifyingStrainCode: '',
        identifyingStrainName: '',
        validationExperimentCode: '',
        experimentTime: '',
        handleSignature: '', // 签名图片url
        result:'',
        purpose: []
      },
      activeTab: 'condition',
      activeTab: 'conditions',
      rules: {
        result: [
          { required: true, message: '请输入实验结论', trigger: 'blur' }
        ],
        purpose: [
          { required: true, message: '请选择菌种用途', trigger: 'change' }
        ]
      },
      initialTableData: [
        { condition: '平板培养基', record: '文字内容文字内容文字内容文字内容文字内容文字内容', process: '文字内容文字内容文字内容文字内容文字内容文字内容' },
        { condition: '培养温度', record: '', process: '' },
        { condition: '培养时间', record: '', process: '' },
        { condition: '摇瓶培养基', record: '', process: '' },
        { condition: '接种量', record: '', process: '' },
        { condition: '培养时间', record: '', process: '' },
        { condition: '发酵时间', record: '', process: '' },
        { condition: '检测数据及结果', record: '', process: '' }
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      tableData: [
        { condition: '平板培养基', record: '文字内容文字内容文字内容文字内容文字内容文字内容', process: '文字内容文字内容文字内容文字内容文字内容文字内容' },
        { condition: '培养温度', record: '', process: '' },
        { condition: '培养时间', record: '', process: '' },
        { condition: '摇瓶培养基', record: '', process: '' },
        { condition: '接种量', record: '', process: '' },
        { condition: '培养时间', record: '', process: '' },
        { condition: '发酵时间', record: '', process: '' },
        { condition: '检测数据及结果', record: '', process: '' }
        { conditions: '平板培养基', record: '', workmanship: '' },
        { conditions: '培养温度', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '摇瓶培养基', record: '', workmanship: '' },
        { conditions: '接种量', record: '', workmanship: '' },
        { conditions: '培养时间', record: '', workmanship: '' },
        { conditions: '发酵时间', record: '', workmanship: '' },
        { conditions: '检测数据及结果', record: '', workmanship: '' }
      ],
      dialogVisible: false,
      dialogIsEdit: false,
@@ -125,14 +133,18 @@
  methods: {
    getDetail() {
      detail({id: this.$route.query.id}).then(res => {
        this.detail = res.data
        this.detail = {
          ...res,
          handleSignature: res.handleSignature || '', // 处理签名为空的情况
          purpose: res.purpose || [] // 处理 purpose 为空的情况
        }
      })
    },
    handleEdit(row) {
      const idx = this.tableData.indexOf(row)
      this.dialogVisible = true
      this.dialogIsEdit = true
      this.dialogIsFixed = idx < this.initialTableData.length
      this.dialogIsFixed = idx < this.initialTableData?.length
      this.dialogValue = { ...row }
      this.dialogIndex = idx
    },
@@ -141,11 +153,23 @@
      this.detailDialogValue = { ...row }
    },
    handleSave() {
      this.dialogVisible = true
      this.dialogIsEdit = false
      this.dialogIsFixed = false
      this.dialogValue = { condition: '', record: '', process: '' }
      this.dialogIndex = null
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.detail.list = this.tableData || []
          this.detail.purpose = this.detail.purpose.join(',')
          confirm({...this.detail}).then(res => {
            if (res.code == 200) {
              this.$message.success('保存成功');
              this.$router.back()
            } else {
              this.$message.error(res.msg);
            }
          })
        } else {
          this.$message.error('请填写必填项');
          return false;
        }
      });
    },
    handleDraft() {
      // 存稿逻辑
@@ -158,7 +182,7 @@
      }
    },
    getRowClassName({ rowIndex }) {
      return rowIndex < this.initialTableData.length ? 'fixed-row' : '';
      return rowIndex < this.initialTableData?.length ? 'fixed-row' : '';
    }
  }
}
culture/src/views/strain-library/validation/primitive-cell/index.vue
@@ -11,7 +11,7 @@
          <el-form-item label="鉴别菌株名称:">
            <el-input v-model="form.identifyingStrainName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="验证实验编号:">
          <el-form-item label="验证实验编号:" v-if="roleType != 4">
            <el-input v-model="form.validationExperimentCode" placeholder="请输入"></el-input>
          </el-form-item>
@@ -28,11 +28,11 @@
            <div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">
              原始细胞库验证资料
            </div>
            <div class="drafts" :class="{ active: currentType === 'draft' }" @click="handleTypeChange('draft')">
            <div class="drafts" v-if="roleType==4" :class="{ active: currentType === 'draft' }" @click="handleTypeChange('draft')">
              草稿箱
            </div>
          </div>
          <div class="flex a-center">
          <div class="flex a-center" v-if="roleType == 4">
            <el-button @click="handleNewStrain" class="el-icon-plus" type="primary"
              style="margin-right: 12px">新增原始细胞库资料</el-button>
          </div>
@@ -54,18 +54,21 @@
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template #default="{ row }">
            <el-button type="text" @click="$router.push('/strain/validation/confirm-detail')">确认</el-button>
            <el-button type="text"
             v-if="row.status == 1 && roleType == 3"
              @click="$router.push('/strain/validation/confirm-detail?id=' + row.id)">确认</el-button>
            <el-button type="text" @click="handleDetail(row)">详情</el-button>
            <el-button type="text" @click="handleDetail2(row)">详情</el-button>
            <el-button type="text" @click="handleEdit(row)">编辑</el-button>
            <el-button type="text" @click="handleRecord(row)">删除</el-button>
            <el-button type="text" @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </template>
    </TableCustom>
    <PrimitiveCellDetailDialog :visible.sync="detailVisible" :detail="currentDetail" />
    <DetailConditionDialog :visible.sync="detailDialogVisible" :value="detailDialogValue" />
    <DetailConditionDialog @viewDetail="viewDetail" :visible.sync="detailDialogVisible" :value="detailDialogValue" />
    <EditConditionDialog :visible.sync="editDialogVisible" :value="editDialogValue" />
    <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
  </div>
</template>
@@ -74,7 +77,7 @@
import DetailConditionDialog from "./DetailConditionDialog.vue";
import EditConditionDialog from "./EditConditionDialog.vue";
import { getList } from "./service";
import { getList, delTwo } from "./service";
export default {
  name: "PrimitiveCell",
  components: {
@@ -89,7 +92,11 @@
      dialogVisible: false,
      currentType: "list",
      detailVisible: false,
      editDialogVisible: false,
      showDelConfirm: false,
      editDialogValue: {},
      currentDetail: {},
      roleType: JSON.parse(sessionStorage.getItem("userInfo")).roleType,
      form: {
        identifyingStrainCode: "",
        identifyingStrainName: "",
@@ -118,6 +125,11 @@
    },
    handleViewMore() {
      this.dialogVisible = true;
    },
    viewDetail(row) {
      row.isDetail = true;
      this.editDialogValue = row;
      this.editDialogVisible = true;
    },
    resetForm() {
      this.form = {
@@ -154,15 +166,27 @@
      // Implement batch add logic
    },
    handleEdit(row) {
      // Implement edit logic
    },
    handleRecord(row) {
      this.$router.push({
        path: "/strain-library/strain-library-manage/record",
        path: "/strain/validation/edit-primitive-cell",
        query: {
          id: row.strainNo,
          id: row.id,
        },
      });
      // Implement edit logic
    },
    handleDelete(row) {
      this.currentDetail = row;
      this.showDelConfirm = true;
    },
    handleDelConfirm() {
      delTwo({ id: this.currentDetail.id }).then(res => {
        this.$message.success('删除成功')
        this.showDelConfirm = false
        if (this.tableData.length == 1 && this.queryForm.pageNum > 1) {
          this.queryForm.pageNum -= 1;
        }
        this.searchData()
      })
    },
    handleCurrentChange(page) {
      this.queryForm.pageNum = page;
culture/src/views/strain-library/validation/primitive-cell/service.js
@@ -13,12 +13,12 @@
//编辑
export const edit = (data) => {
    return axios.post('/api/t-strain-validation-data/edit', { ...data })
    return axios.post('/api/t-strain-validation-data/updateOriginal', { ...data })
}
//详情
export const detail = (data) => {
    return axios.get('/api/t-strain-validation-data/detail', { params: { id: data.id } })
    return axios.get('/open/t-strain-validation-data/getDetailById', { params: { id: data.id } })
}
//主细胞删除
@@ -32,4 +32,10 @@
}
// 确认
export const confirm = (data) => {
    console.log('data', data)
    return axios.post('/api/t-strain-validation-data/confirm', { ...data })
}
culture/src/views/strainReportLibrary/reportLibraryOne/index.vue
@@ -163,6 +163,9 @@
            deleteReport({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                if (this.queryForm.pageNum > 1 && this.tableData.length === 1) {
                    this.queryForm.pageNum = this.queryForm.pageNum - 1
                }
                this.rowId = ''
                this.getLists()
            })
culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue
@@ -179,6 +179,9 @@
            deleteReport({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                if (this.queryForm.pageNum > 1 && this.tableData.length === 1) {
                    this.queryForm.pageNum = this.queryForm.pageNum - 1
                }
                this.rowId = ''
                this.getLists()
            })
culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue
@@ -178,6 +178,9 @@
            deleteReport({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                if (this.queryForm.pageNum > 1 && this.tableData.length === 1) {
                    this.queryForm.pageNum = this.queryForm.pageNum - 1
                }
                this.rowId = ''
                this.getLists()
            })
culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue
@@ -179,6 +179,9 @@
            deleteReport({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                if (this.queryForm.pageNum > 1 && this.tableData.length === 1) {
                    this.queryForm.pageNum = this.queryForm.pageNum - 1
                }
                this.rowId = ''
                this.getLists()
            })