13404089107
2025-05-27 e59a8d48ac6a46d7343f0013a333d7779c93e4fc
菌种库菌种选育保藏记录对接口
1个文件已添加
6个文件已修改
503 ■■■■■ 已修改文件
culture/src/router/index.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/add.vue 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/confirm-preserve-dialog.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/index.vue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/preserve-strain-record-dialog.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/service.js 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/router/index.js
@@ -286,6 +286,24 @@
        component: () => import("../views/strain-library/breeding-record/add"),
      },
      {
        path: "edit-breeding-record",
        name: "EditBreedingRecord",
        meta: {
          title: "编辑菌种选育保藏记录",
          hide: true,
        },
        component: () => import("../views/strain-library/breeding-record/add"),
      },
      {
        path: "detail-breeding-record",
        name: "DetailBreedingRecord",
        meta: {
          title: "菌种选育保藏记录详情",
          hide: true,
        },
        component: () => import("../views/strain-library/breeding-record/add"),
      },
      {
        path: "validation",
        meta: {
          title: "菌种验证数据资料",
culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue
@@ -4,12 +4,12 @@
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="分离菌落编号" prop="separateColonyCode">
            <el-input v-model="form.separateColonyCode" placeholder="请输入分离菌落编号" />
            <el-input :disabled="roleType!=4" v-model="form.separateColonyCode" placeholder="请输入分离菌落编号" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="形状强壮度排名" prop="strength">
            <el-input v-model="form.strength" placeholder="请输入形状强壮度排名" />
            <el-input :disabled="roleType!=4" v-model="form.strength" placeholder="请输入形状强壮度排名" />
          </el-form-item>
        </el-col>
      </el-row>
@@ -22,13 +22,13 @@
      </el-table-column>
      <el-table-column prop="desc" label="形态记录">
        <template #default="{ row }">
          <el-input class="el-input-full" style="width: 100%;" v-model="row.desc" placeholder="请输入形态记录"
          <el-input class="el-input-full" style="width: 100%;" :disabled="roleType!=4" v-model="row.desc" placeholder="请输入形态记录"
            @blur="handleDescBlur(row)" />
        </template>
      </el-table-column>
      <el-table-column prop="images" label="拍照上传" width="120">
        <template #default="{ row }">
          <el-upload :file-list="row.images" list-type="picture-card" :on-preview="file => handlePreview(row, file)"
          <el-upload :file-list="row.images" :disabled="roleType!=4" list-type="picture-card" :on-preview="file => handlePreview(row, file)"
            :on-remove="(file, fileList) => handleRemove(row, file, fileList)"
            :on-success="(res, file, fileList) => handleUpload(row, file, fileList)" :before-upload="beforeUpload"
            action="#" :limit="5" class="mini-upload">
@@ -42,7 +42,7 @@
        </template>
      </el-table-column>
    </el-table>
    <div style="text-align: center;">
    <div style="text-align: center;" v-if="roleType==4">
      <el-button type="primary" @click="handleOk">保存</el-button>
    </div>
  </el-dialog>
@@ -61,6 +61,7 @@
  },
  data() {
    return {
      roleType: JSON.parse(sessionStorage.getItem('userInfo')).roleType,
      form: {
        separateColonyCode: '',
        strength: '',
culture/src/views/strain-library/breeding-record/add.vue
@@ -21,36 +21,39 @@
        <!-- 来源菌株 -->
        <el-row v-if="activeTab === 'strain'" :gutter="10">
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
            <el-form-item label="菌株编号" prop="strainCode" >
              <el-input v-model="form.strainCode" class="w-380" placeholder="请输入菌株编号" />
            <el-form-item label="菌株编号" prop="strainCode">
              <el-input :disabled="$route.query.isDetail" v-model="form.strainCode" class="w-380"
                placeholder="请输入菌株编号" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
            <el-form-item label="菌株名称" prop="strainName" >
              <el-input v-model="form.strainName" class="w-380" placeholder="请输入菌株名称" />
            <el-form-item label="菌株名称" prop="strainName">
              <el-input :disabled="$route.query.isDetail" v-model="form.strainName" class="w-380"
                placeholder="请输入菌株名称" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
            <el-form-item label="培养基配方" prop="formula" >
              <el-input v-model="form.formula" class="w-380" placeholder="请输入培养基配方" />
            <el-form-item label="培养基配方" prop="formula">
              <el-input :disabled="$route.query.isDetail" v-model="form.formula" class="w-380" placeholder="请输入培养基配方" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 来源物资 -->
        <el-row v-if="activeTab === 'material'" :gutter="10">
          <el-col :span="24">
            <el-form-item label="来源物资、时间及批号" prop="sourceMaterialTimeBatchNumber" >
              <el-input v-model="form.sourceMaterialTimeBatchNumber" placeholder="请输入物资编号" />
            <el-form-item label="来源物资、时间及批号" prop="sourceMaterialTimeBatchNumber">
              <el-input :disabled="$route.query.isDetail" v-model="form.sourceMaterialTimeBatchNumber"
                placeholder="请输入物资编号" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="培养基配方" prop="formula" >
              <el-input v-model="form.formula" placeholder="请输入培养基配方" />
            <el-form-item label="培养基配方" prop="formula">
              <el-input :disabled="$route.query.isDetail" v-model="form.formula" placeholder="请输入培养基配方" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="分离菌落编号" prop="separateColonyNumber" >
              <el-input v-model="form.separateColonyNumber" placeholder="请输入分离菌落编号" />
            <el-form-item label="分离菌落编号" prop="separateColonyNumber">
              <el-input :disabled="$route.query.isDetail" v-model="form.separateColonyNumber" placeholder="请输入分离菌落编号" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -62,28 +65,32 @@
        </div>
        <el-row :gutter="10">
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="培养基" prop="cultureMedium" >
              <el-input v-model="form.cultureMedium" class="w-380" placeholder="请输入培养基" />
            <el-form-item label="培养基" prop="cultureMedium">
              <el-input :disabled="$route.query.isDetail" v-model="form.cultureMedium" class="w-380"
                placeholder="请输入培养基" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="培养温度" prop="temperature" >
              <el-input v-model="form.temperature" class="w-380" placeholder="请输入培养温度" />
            <el-form-item label="培养温度" prop="temperature">
              <el-input :disabled="$route.query.isDetail" v-model="form.temperature" class="w-380"
                placeholder="请输入培养温度" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="需氧类型" prop="aerobicType" >
             <el-select v-model="form.aerobicType" class="w-380" placeholder="请选择需氧类型">
               <el-option label="专性需氧" value="1"></el-option>
               <el-option label="专性厌氧" value="2"></el-option>
               <el-option label="兼性需氧" value="3"></el-option>
               <el-option label="耐氧厌氧" value="4"></el-option>
             </el-select>
            <el-form-item label="需氧类型" prop="aerobicType">
              <el-select :disabled="$route.query.isDetail" v-model="form.aerobicType" class="w-380"
                placeholder="请选择需氧类型">
                <el-option label="专性需氧" value="1"></el-option>
                <el-option label="专性厌氧" value="2"></el-option>
                <el-option label="兼性需氧" value="3"></el-option>
                <el-option label="耐氧厌氧" value="4"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="培养时间" prop="cultureTime" >
              <el-input v-model="form.cultureTime" class="w-380" placeholder="请输入培养时间" />
            <el-form-item label="培养时间" prop="cultureTime">
              <el-input :disabled="$route.query.isDetail" v-model="form.cultureTime" class="w-380"
                placeholder="请输入培养时间" />
              <!-- <el-date-picker v-model="form.cultureTime" class="w-380" placeholder="请选择培养时间" type="date" value-format="yyyy-MM-dd" /> -->
            </el-form-item>
          </el-col>
@@ -94,23 +101,27 @@
            <div>一、培养皿分离记录</div>
          </div>
          <div class="header-title-right">
            <el-button @click="handleAddSeparation" class="el-icon-circle-plus-outline" type="primary">
            <el-button @click="handleAddSeparation" v-if="!$route.query.isDetail&&[1,4].includes(roleType)" class="el-icon-circle-plus-outline"
              type="primary">
              新增培养皿分离记录</el-button>
          </div>
        </div>
        <Table :data="form.separationOfCultureDishesList" :height="null" :queryForm="queryForm" :total="0">
          <el-table-column width="100" type="index" label="培养皿序号" />
          <el-table-column prop="separateBacterialColoniesCode" label="分离菌落编号" />
          <el-table-column prop="handleSignature" label="接种操作人签字" >
          <el-table-column prop="handleSignature" label="接种操作人签字">
            <template slot-scope="scope">
              <el-image  :preview-src-list="[scope.row.handleSignature]" style="width: 40px;" :src="scope.row.handleSignature" alt="操作人签字" />
              <el-image :preview-src-list="[scope.row.handleSignature]" style="width: 40px;"
                :src="scope.row.handleSignature" alt="操作人签字" />
            </template>
          </el-table-column>
          <el-table-column prop="createTime" label="操作时间" />
          <el-table-column prop="address" label="操作">
            <template slot-scope="scope">
              <el-button type="text" @click="handleEditSeparation(scope.row, scope.$index)">编辑</el-button>
              <el-button type="text" @click="handleDeleteSeparation(scope.$index)">删除</el-button>
          <el-table-column prop="address" label="操作" v-if="!$route.query.isDetail">
            <template slot-scope="scope" v-if="[1,4].includes(roleType)">
              <el-button type="text" @click="handleEditSeparation(scope.row, scope.$index)"
                v-if="!$route.query.isDetail">编辑</el-button>
              <el-button type="text" @click="handleDeleteSeparation(scope.$index)"
                v-if="!$route.query.isDetail">删除</el-button>
            </template>
          </el-table-column>
        </Table>
@@ -120,7 +131,7 @@
            <div>二、培养皿生物学形态观察记录</div>
          </div>
          <div class="header-title-right">
            <el-button @click="handleAddObservation" class="el-icon-circle-plus-outline" type="primary">
            <el-button @click="handleAddObservation" v-if="!$route.query.isDetail&&[1,4].includes(roleType)" class="el-icon-circle-plus-outline" type="primary">
              新增观察记录</el-button>
          </div>
        </div>
@@ -129,8 +140,10 @@
          <el-table-column prop="strength" label="形状强壮度排名" />
          <el-table-column prop="address" label="操作">
            <template slot-scope="scope">
              <el-button type="text" @click="handleEditObservation(scope.row)">编辑</el-button>
              <el-button type="text" @click="handleDeleteObservation(scope.$index)">删除</el-button>
              <!-- <el-button type="text" @click="handleEditObservation(scope.row)" v-if="!$route.query.isDetail">编辑</el-button> -->
              <el-button type="text" @click="handleEditObservation(scope.row)">形态记录</el-button>
              <el-button type="text" @click="handleDeleteObservation(scope.$index)"
                v-if="!$route.query.isDetail&&[1,4].includes(roleType)">删除</el-button>
            </template>
          </el-table-column>
        </Table>
@@ -140,17 +153,19 @@
            <div>三、接种斜面记录</div>
          </div>
          <div class="header-title-right">
            <el-button @click="handleAddInoculation" class="el-icon-circle-plus-outline" type="primary">
            <el-button @click="handleAddInoculation" v-if="!$route.query.isDetail&&[1,4].includes(roleType)" class="el-icon-circle-plus-outline" type="primary">
              新增斜面记录</el-button>
          </div>
        </div>
        <el-table :data="form.vaccinationSlopes" border style="width: 100%; margin-bottom: 16px;" :span-method="inoculationRowSpan">
        <el-table :data="form.vaccinationSlopes" border style="width: 100%; margin-bottom: 16px;"
          :span-method="inoculationRowSpan">
          <el-table-column prop="separateColonyCode" label="分离菌落编号" />
          <el-table-column prop="vaccinationSlopeCode" label="接种斜面编号" />
          <el-table-column prop="handleName" label="接种操作人" />
          <el-table-column prop="handleSignature" label="接种操作人签字">
            <template slot-scope="scope">
              <el-image v-if="scope.row.handleSignature" :preview-src-list="[scope.row.handleSignature]" style="width: 40px;" :src="scope.row.handleSignature" alt="操作人签字" />
              <el-image v-if="scope.row.handleSignature" :preview-src-list="[scope.row.handleSignature]"
                style="width: 40px;" :src="scope.row.handleSignature" alt="操作人签字" />
            </template>
          </el-table-column>
          <el-table-column prop="handleTime" label="接种操作时间" />
@@ -164,17 +179,18 @@
              <span v-if="scope.$index === firstInoculationOrDiscardIndex">{{ totalInoculationCount }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="preserveSignature" label="菌种保藏人签字" >
          <el-table-column prop="preserveSignature" label="菌种保藏人签字">
            <template slot-scope="scope">
              <el-image v-if="scope.row.preserveSignature" :preview-src-list="[scope.row.preserveSignature]" style="width: 40px;" :src="scope.row.preserveSignature" alt="操作人签字" />
              <el-image v-if="scope.row.preserveSignature" :preview-src-list="[scope.row.preserveSignature]"
                style="width: 40px;" :src="scope.row.preserveSignature" alt="操作人签字" />
            </template>
          </el-table-column>
          <el-table-column prop="preserveTime" label="入库保藏/废弃时间" />
          <el-table-column label="操作">
          <el-table-column label="操作" v-if="[1,3,4].includes(roleType)&&!$route.query.isDetail">
            <template slot-scope="scope">
              <el-button type="text" @click="handleEditInoculation(scope.row, scope.$index)">编辑</el-button>
              <el-button type="text" @click="handleConfirmStorageClick(scope.row, scope.$index)">确认入库</el-button>
              <el-button type="text" @click="handleDeleteInoculation(scope.$index)">删除</el-button>
              <el-button type="text" @click="handleEditInoculation(scope.row, scope.$index)" v-if="!$route.query.isDetail&&[1,4].includes(roleType)">编辑</el-button>
              <el-button type="text" @click="handleConfirmStorageClick(scope.row, scope.$index)" v-if="$route.query.isDetail&&[3].includes(roleType)">确认入库</el-button>
              <el-button type="text" @click="handleDeleteInoculation(scope.$index)" v-if="!$route.query.isDetail&&!scope.row.preserveSignature&&[1,4].includes(roleType)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -184,7 +200,7 @@
            <div>四、菌种保藏记录</div>
          </div>
          <div class="header-title-right">
            <el-button @click="handleAddPreserve" class="el-icon-circle-plus-outline" type="primary">
            <el-button @click="handleAddPreserve" v-if="!$route.query.isDetail&&[1,4].includes(roleType)" class="el-icon-circle-plus-outline" type="primary">
              新增菌种保藏记录</el-button>
          </div>
        </div>
@@ -193,48 +209,44 @@
          <el-table-column prop="verificationConclusion" label="实验验证结论" />
          <el-table-column prop="preserveMethod" label="保藏方法" />
          <el-table-column prop="preserveCode" label="保藏菌种编号" />
          <el-table-column prop="handleSignature" label="菌种操作人签字">
            <template slot-scope="scope">
              <el-image v-if="scope.row.handleSignature" :preview-src-list="[scope.row.handleSignature]"
                style="width: 40px;" :src="scope.row.handleSignature" alt="签字" />
            </template>
          </el-table-column>
          <el-table-column prop="handleTime" label="操作人" />
          <el-table-column prop="preserveSignature" label="菌种保藏人签字">
            <template slot-scope="scope">
              <el-image v-if="scope.row.preserveSignature" :preview-src-list="[scope.row.preserveSignature]" style="width: 40px;" :src="scope.row.preserveSignature" alt="签字" />
              <el-image v-if="scope.row.preserveSignature" :preview-src-list="[scope.row.preserveSignature]"
                style="width: 40px;" :src="scope.row.preserveSignature" alt="签字" />
            </template>
          </el-table-column>
          <el-table-column prop="preserveTime" label="保藏时间" />
          <el-table-column label="操作">
          <el-table-column label="操作" v-if="[1,3,4].includes(roleType)&&!$route.query.isDetail">
            <template slot-scope="scope">
              <el-button type="text" @click="handleEditPreserve(scope.row, scope.$index)">编辑</el-button>
              <el-button type="text" @click="handleDeletePreserve(scope.$index)">删除</el-button>
              <el-button type="text" @click="handleEditPreserve(scope.row, scope.$index)" v-if="!$route.query.isDetail&&[1,4].includes(roleType)">编辑</el-button>
              <el-button type="text" @click="handleConfirmPreserve(scope.row, scope.$index)" v-if="$route.query.isDetail&&[3].includes(roleType)">确认入库</el-button>
              <el-button type="text" @click="handleDeletePreserve(scope.$index)" v-if="!$route.query.isDetail&&!scope.row.preserveSignature&&[1,4].includes(roleType)">删除</el-button>
            </template>
          </el-table-column>
        </Table>
        <!-- 弹窗组件 -->
        <SeparationRecordDialog
          :visible.sync="showSeparationDialog"
          :editData="editSeparationData"
          @confirm="handleSeparationConfirm"
          @close="resetSeparationEdit"
        />
        <SlantRecordDialog
          :visible.sync="showObservationDialog"
          :editData="editObservationData"
          @ok="handleObservationConfirm"
        />
        <InoculationSlopeRecordDialog
          :visible.sync="showInoculationDialog"
          :editData="editInoculationData"
          @save="handleInoculationConfirm"
        />
        <PreserveStrainRecordDialog
          :visible.sync="showPreserveDialog"
          :editData="editPreserveData"
          @save="handlePreserveConfirm"
        />
        <ConfirmStorageDialog
          :visible.sync="showConfirmStorageDialog"
          :editData="editInoculationData"
          @confirm="handleConfirmStorage"
        />
        <div class="end-btn" style="margin-top: 20px;">
          <el-button type="primary" @click="handleSubmit(1)">发送</el-button>
        <SeparationRecordDialog :visible.sync="showSeparationDialog" :editData="editSeparationData"
          @confirm="handleSeparationConfirm" @close="resetSeparationEdit" />
        <SlantRecordDialog :visible.sync="showObservationDialog" :editData="editObservationData"
          @ok="handleObservationConfirm" />
        <InoculationSlopeRecordDialog :visible.sync="showInoculationDialog" :editData="editInoculationData"
          @save="handleInoculationConfirm" />
        <PreserveStrainRecordDialog :visible.sync="showPreserveDialog" :editData="editPreserveData"
          @save="handlePreserveConfirm" />
        <ConfirmStorageDialog :visible.sync="showConfirmStorageDialog" :editData="editInoculationData"
          @confirm="handleConfirmStorage" />
        <ConfirmPreserveDialog :visible.sync="showConfirmPreserveDialog" :editData="editPreserveData"
          @confirm="handleConfirmPreserveSubmit" />
        <div class="end-btn" style="margin-top: 20px;" v-if="!$route.query.isDetail">
          <el-button type="primary" @click="handleSubmit(1)">提交</el-button>
          <el-button type="primary" @click="handleSubmit(3)">同步给保藏人</el-button>
          <el-button type="default" @click="handleSubmit(2)">存草稿</el-button>
        </div>
      </el-form>
@@ -248,8 +260,9 @@
import InoculationSlopeRecordDialog from "./inoculation-slope-record-dialog.vue";
import PreserveStrainRecordDialog from "./preserve-strain-record-dialog.vue";
import ConfirmStorageDialog from "./confirm-storage-dialog.vue";
import ConfirmPreserveDialog from "./confirm-preserve-dialog.vue";
import {add,detail,edit} from './service'
import { add, detail, edit } from './service'
export default {
  components: {
    AiEditor,
@@ -258,6 +271,7 @@
    InoculationSlopeRecordDialog,
    PreserveStrainRecordDialog,
    ConfirmStorageDialog,
    ConfirmPreserveDialog,
  },
  name: "AddBreedingRecord",
  data() {
@@ -323,6 +337,7 @@
      showInoculationDialog: false,
      showPreserveDialog: false,
      showConfirmStorageDialog: false,
      showConfirmPreserveDialog: false,
      editSeparationIndex: null,
      editSeparationData: null,
      editObservationData: null,
@@ -330,6 +345,7 @@
      editInoculationData: null,
      editPreserveIndex: null,
      editPreserveData: null,
      roleType: JSON.parse(sessionStorage.getItem('userInfo')).roleType,  // 1.超级管理员 2.审批人 3.工程师 4.实验员
    };
  },
  computed: {
@@ -344,17 +360,17 @@
      return this.form.vaccinationSlopes.findIndex(item => item.handleType === '保存' || item.handleType === '废弃');
    }
  },
  mounted(){
    if(this.$route.query.id){
  mounted() {
    if (this.$route.query.id) {
      this.getDetail()
    }
  },
  methods: {
    async getDetail(){
      const res = await detail({id:this.$route.query.id})
      if(res.preserveSource == 1){
    async getDetail() {
      const res = await detail({ id: this.$route.query.id })
      if (res.preserveSource == 1) {
        this.activeTab = 'strain'
      }else{
      } else {
        this.activeTab = 'material'
      }
      res.vaccinationSlopes = res.vaccinationSlopes.map(item => {
@@ -366,14 +382,14 @@
      this.form = res
    },
    handleSeparationConfirm(data) {
      console.log('分离',data)
      console.log('分离', data)
      if (this.editSeparationIndex !== null) {
        // 编辑
        this.$set(this.form.separationOfCultureDishesList, this.editSeparationIndex, data);
        this.resetSeparationEdit();
      } else {
        // 新增
        console.log('新增',data)
        console.log('新增', data)
        this.form.separationOfCultureDishesList.push(data);
      }
    },
@@ -394,7 +410,7 @@
      this.editObservationData = null;
    },
    handleInoculationConfirm(data) {
      console.log('接种',data)
      console.log('接种', data)
      if (this.editInoculationIndex !== null) {
        // 编辑模式:更新指定索引的数据
        this.$set(this.form.vaccinationSlopes, this.editInoculationIndex, {
@@ -426,22 +442,24 @@
      this.editPreserveData = null;
    },
    handleSubmit(type) {
      if(this.activeTab === 'material'){
      if (this.activeTab === 'material') {
        this.form.preserveSource = 2
      }else{
      } else {
        this.form.preserveSource = 1
      }
      if(type == 1){
        this.form.isDraft = 0
      }else{
        this.form.isDraft = 1
      if (type == 1) {
        this.form.status = 1
      } else if (type == 3) {
        this.form.isDraft = 2
      } else {
        this.form.isDraft = 3
      }
      this.$refs.form.validate(async (valid) => {
        if (!valid) return;
        try {
          if(this.form.vaccinationSlopes.length > 0){
          if (this.form.vaccinationSlopes.length > 0) {
            let arr = this.form.vaccinationSlopes
            this.form.vaccinationSlopes = arr.map(item => {
              return {
@@ -450,7 +468,7 @@
              }
            })
          }
          if(this.form.id){
          if (this.form.id && this.form.isDraft == 0) {
            edit(this.form).then(res => {
              if (res.code === 200) {
                this.$message.success('编辑成功');
@@ -459,17 +477,17 @@
                this.$message.error('编辑失败');
              }
            })
          }else{
          } else {
            add(this.form).then(res => {
            if (res.code === 200) {
              this.$message.success('添加成功');
              this.$router.back();
            } else {
              this.$message.error('添加失败');
            }
          });
              if (res.code === 200) {
                this.$message.success('添加成功');
                this.$router.back();
              } else {
                this.$message.error('添加失败');
              }
            });
          }
        } catch (e) {
          this.$message.error('添加失败');
        }
@@ -561,6 +579,26 @@
    handleDeletePreserve(index) {
      this.form.culturePreservations.splice(index, 1);
    },
    handleConfirmPreserve(row, index) {
      this.editPreserveIndex = index;
      // 深拷贝当前行数据,避免直接修改原数据
      this.editPreserveData = JSON.parse(JSON.stringify(row));
      this.showConfirmPreserveDialog = true;
    },
    handleConfirmPreserveSubmit(data) {
      console.log('确认保藏', data)
      // 更新对应行的数据,保留原有数据并更新签名
      if (this.editPreserveIndex !== null) {
        this.$set(this.form.culturePreservations, this.editPreserveIndex, {
          ...this.form.culturePreservations[this.editPreserveIndex],
          preserveSignature: data.preserveSignature, // 更新签名数据
          preserveTime: data.preserveTime,
        });
      }
      this.showConfirmPreserveDialog = false;
      this.editPreserveIndex = null;
      this.editPreserveData = null;
    },
  },
};
</script>
culture/src/views/strain-library/breeding-record/confirm-preserve-dialog.vue
New file
@@ -0,0 +1,146 @@
<template>
    <el-dialog
      :visible.sync="visible"
      title=""
      width="520px"
      :close-on-click-modal="false"
      custom-class="record-detail-dialog"
      @close="handleClose"
    >
      <div class="dialog-content">
        <div class="confirm-tip">
          是否确认该项菌种信息?
          <span class="danger">确认后将无法再次编辑菌种传代项内容</span>
        </div>
        <el-form :model="form" :rules="rules" ref="form" label-position="top">
          <el-form-item required>
            <template #label>
              <span>菌种保藏人签字</span>
              <el-button type="primary" class="sign-btn" @click="showSignature = true">签名</el-button>
            </template>
            <div class="signature-area" :class="{ 'waiting': !form.preserveSignature }">
              <template v-if="form.preserveSignature">
                <img :src="form.preserveSignature" alt="菌种保藏人签字" />
              </template>
              <template v-else>
                <span class="waiting-text">等待确认</span>
              </template>
            </div>
          </el-form-item>
        </el-form>
      </div>
      <div class="footer-btns">
        <el-button @click="handleClose" style="margin-right: 16px;">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </div>
      <signature-canvas :visible.sync="showSignature" @confirm="handleSignatureConfirm" />
    </el-dialog>
  </template>
  <script>
  import SignatureCanvas from '@/components/SignatureCanvas.vue';
  import moment from 'moment';
  export default {
    name: 'ConfirmStorageDialog',
    components: { SignatureCanvas },
    props: {
      visible: {
        type: Boolean,
        default: false
      },
      data: {
        type: Object,
        default: () => ({})
      }
    },
    data() {
      return {
        form: {
          preserveSignature: '',
          preserveTime:''
        },
        rules: {
          preserveSignature: [
            { required: true, message: '请签名', trigger: 'change' }
          ]
        },
        showSignature: false
      }
    },
    methods: {
      handleClose() {
        this.$emit('update:visible', false)
      },
      handleConfirm() {
        this.$refs.form.validate(valid => {
          if (!valid) return
          const confirmData = {
            ...this.data,
            preserveTime: moment().format('YYYY-MM-DD HH:mm:ss'),
            preserveSignature: this.form.preserveSignature
          }
          this.$emit('confirm', confirmData)
          this.handleClose()
        })
      },
      handleSignatureConfirm(dataUrl) {
        this.form.preserveSignature = dataUrl
        this.showSignature = false
      }
    }
  }
  </script>
  <style lang="less" scoped>
  .confirm-tip {
    color: #f5222d;
    font-size: 16px;
    margin-bottom: 24px;
    .danger {
      margin-left: 12px;
    }
  }
  .signature-area {
    height: 120px;
    width: 100%;
    background: #F5F7FA;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #DCDFE6;
    overflow: hidden;
    padding: 0;
  }
  .signature-area.waiting {
    border-style: dashed;
    background: #FAFAFA;
  }
  .signature-area img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .waiting-text {
    color: #909399;
    font-size: 14px;
  }
  .sign-btn {
    height: 32px;
    border-radius: 4px;
    font-size: 14px;
    padding: 0 20px;
    font-weight: 400;
    margin-left: 12px;
  }
  .footer-btns {
    display: flex;
    justify-content: center;
    padding: 24px;
    padding-top: 0;
    .el-button {
      width: 150px;
    }
  }
  </style>
culture/src/views/strain-library/breeding-record/index.vue
@@ -32,11 +32,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>
@@ -45,14 +45,16 @@
      <template #table>
        <el-table-column prop="preserveSource" label="来源类型">
          <template slot-scope="scope">
            <span>{{ scope.row.preserveSource === 1 ? '来源菌株' : '来源物资'}}</span>
            <span>{{ scope.row.preserveSource === 1 ? '来源菌株' : '来源物资' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="cultureMedium" label="培养基"></el-table-column>
        <el-table-column prop="temperature" label="培养温度"></el-table-column>
        <el-table-column prop="aerobicType" label="需氧类型">
          <template slot-scope="scope">
            <span>{{ scope.row.aerobicType == 1 ? '专性需氧' :scope.row.aerobicType == 2? '专性厌氧' :scope.row.aerobicType == 3? '兼性需氧' : '耐氧厌氧'}}</span>
            <span>{{ scope.row.aerobicType == 1 ? '专性需氧' : scope.row.aerobicType == 2 ? '专性厌氧' : scope.row.aerobicType
              ==
              3 ? '兼性需氧' : '耐氧厌氧'}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="createBy" label="创建人"></el-table-column>
@@ -60,8 +62,10 @@
        <el-table-column label="操作" width="250">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
            <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
            <el-button type="text" @click="handleEdit(scope.row)"
              v-if="([1].includes(roleType) || ([1, 4].includes(roleType) && currentType != 'list'))">编辑</el-button>
            <el-button type="text" @click="handleDelete(scope.row)"
              v-if="[1].includes(roleType) || ([1, 4].includes(roleType) && currentType != 'list')">删除</el-button>
          </template>
        </el-table-column>
      </template>
@@ -71,7 +75,7 @@
</template>
<script>
import { getList,del } from './service'
import { getList, del } from './service'
import ShowDelConfirm from '@/components/showDelConfirm'
export default {
@@ -113,6 +117,7 @@
      tableData: [],
      delData: null,
      total: 0,
      roleType: JSON.parse(sessionStorage.getItem('userInfo')).roleType,
    };
  },
  created() {
@@ -184,15 +189,15 @@
      this.delData = row
    },
    handleDelConfirm() {
      del({id: this.delData.id}).then(res => {
          this.$message.success('删除成功');
          this.showDelConfirm = false
          this.getTableData();
      del({ id: this.delData.id }).then(res => {
        this.$message.success('删除成功');
        this.showDelConfirm = false
        this.getTableData();
      })
    },
    handleDetail(row) {
      this.$router.push({
        path: "/strain/add-breeding-record",
        path: "/strain/detail-breeding-record",
        query: {
          id: row.id,
          isDetail: true
@@ -201,14 +206,14 @@
    },
    handleEdit(row) {
      this.$router.push({
        path: "/strain/add-breeding-record",
        path: "/strain/edit-breeding-record",
        query: {
          id: row.id,
          isEdit: true
        }
      });
    },
    handleTypeChange(type) {
      this.currentType = type;
      this.form.isDraft = type === 'draft' ? 1 : 0;
culture/src/views/strain-library/breeding-record/preserve-strain-record-dialog.vue
@@ -41,9 +41,9 @@
              <span>操作人签名</span>
              <el-button type="primary" class="sign-btn" @click="showSignature = true">签名</el-button>
            </template>
            <div class="signature-area" :class="{ 'waiting': !form.preserveSignature }">
              <template v-if="form.preserveSignature">
                <img :src="form.preserveSignature" alt="操作人签名" />
            <div class="signature-area" :class="{ 'waiting': !form.handleSignature }">
              <template v-if="form.handleSignature">
                <img :src="form.handleSignature" alt="操作人签名" />
              </template>
              <template v-else>
                <span class="waiting-text">等待确认</span>
@@ -63,9 +63,16 @@
<script>
import SignatureCanvas from '@/components/SignatureCanvas.vue';
import moment from 'moment';
export default {
  components: { SignatureCanvas },
  props: { visible: Boolean },
  props: {
    visible: Boolean,
    editData: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      form: {
@@ -73,7 +80,8 @@
        verificationConclusion: '',
        preserveMethod: '',
        preserveCode: '',
        preserveSignature: '',
        handleTime: '',
        handleSignature: '',
      },
      rules: {
        forPreserveCode: [
@@ -95,9 +103,19 @@
      showSignature: false,
    };
  },
  watch: {
    visible(val) {
      if (val && this.editData) {
        this.form = {
          ...this.form,
          ...this.editData
        };
      }
    }
  },
  methods: {
    handleSave() {
      this.form.preserveTime = this.formatDateTime(new Date());
      this.form.handleTime = moment().format('YYYY-MM-DD HH:mm:ss');
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.$emit('save', { ...this.form });
@@ -112,23 +130,13 @@
        verificationConclusion: '',
        preserveMethod: '',
        preserveCode: '',
        preserveSignature: '',
        handleSignature: '',
        handleTime: '',
      };
    },
    handleSignatureConfirm(dataUrl) {
      this.form.preserveSignature = dataUrl;
      this.form.handleSignature = dataUrl;
      this.showSignature = false;
    },
    formatDateTime(date) {
      const pad = (n) => n < 10 ? '0' + n : n;
      return (
        date.getFullYear() + '-' +
        pad(date.getMonth() + 1) + '-' +
        pad(date.getDate()) + ' ' +
        pad(date.getHours()) + ':' +
        pad(date.getMinutes()) + ':' +
        pad(date.getSeconds())
      );
    },
  },
};
culture/src/views/strain-library/breeding-record/service.js
@@ -2,6 +2,7 @@
// 列表
export const getList = (data) => {
  console.log('qweqwe', data);
  return axios.post('/api/t-breeding-and-preservation/pageList', {
    ...data
  })