13404089107
2025-05-23 5d55874bee62767c1c0debadaf3d794302238072
对接接口
7个文件已添加
11个文件已修改
2853 ■■■■ 已修改文件
culture/src/components/SelectMember/index.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/chooseProject/index.vue 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/chooseProject/servce.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/add.vue 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/index.vue 242 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/separation-record-dialog.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/breeding-record/service.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/add.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue 301 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/components/evaluate/index.vue 434 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/index.vue 148 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOne/service.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue 301 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/choiceMethod/index.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/evaluate/index.vue 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/projectList/editProject.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/SelectMember/index.vue
@@ -41,8 +41,9 @@
                            </div>
                        </div>
                        <Table ref="memberTable" :row-key="row => row.userId" :data="tableData" :total="0"
                            @selection-change="handleSelectionChange" :row-class-name="tableRowClassName">
                            <el-table-column type="selection" width="55" />
                            @selection-change="handleSelectionChange" :row-class-name="tableRowClassName"
                            @row-click="handleRowClick">
                            <el-table-column type="selection" width="55" v-if="!singleSelect" />
                            <el-table-column label="角色" prop="roleName" />
                            <el-table-column label="姓名" prop="nickName" />
                            <el-table-column label="创建时间" prop="createTime" />
@@ -65,6 +66,10 @@
        projectId: {
            type: [String, Number],
            default: null
        },
        singleSelect: {
            type: Boolean,
            default: false
        }
    },
    data() {
@@ -103,7 +108,9 @@
            this.searchUserList(null);
        },
        handleSelectionChange(val) {
            this.selectData = val
            if (!this.singleSelect) {
                this.selectData = val;
            }
        },
        async searchUserList(roleId) {
            this.roleId = roleId
@@ -144,6 +151,18 @@
                return 'select-row';
            }
            return '';
        },
        handleRowClick(row) {
            if (this.singleSelect) {
                // 单选模式:直接设置选中项
                this.selectData = [row];
                // 更新表格选中状态
                this.$nextTick(() => {
                    this.tableData.forEach(item => {
                        this.$refs.memberTable.toggleRowSelection(item, item.userId === row.userId);
                    });
                });
            }
        }
    }
}
culture/src/components/chooseProject/index.vue
New file
@@ -0,0 +1,118 @@
<template>
    <div>
        <el-dialog title="选择项目组" :visible.sync="show" width="80%" @open="open" @close="$emit('close')">
            <TableCustom :queryForm="form" :total="total" :height="null">
                <template #search>
                    <el-form :model="form" label-width="140px" inline>
                        <el-form-item label="项目组名称:">
                            <el-input v-model="form.teamName" placeholder="请输入"></el-input>
                        </el-form-item>
                        <el-form-item label="项目负责人:">
                            <el-input v-model="form.personCharge" placeholder="请输入"></el-input>
                        </el-form-item>
                        <el-form-item label="创建日期:">
                            <el-date-picker v-model="form.date" type="daterange" range-separator="至"
                                start-placeholder="开始日期" end-placeholder="结束日期"
                                value-format="yyyy-MM-dd"></el-date-picker>
                        </el-form-item>
                        <el-form-item label="" class="search-btn-box">
                            <el-button type="default" @click="resetForm">重置</el-button>
                            <el-button type="primary" @click="handleSearch">查询</el-button>
                        </el-form-item>
                    </el-form>
                </template>
                <template #tableCustom>
                    <Table ref="memberTable" :height="null" :row-key="row => row.id" :data="tableData" :total="0"
                        highlight-current-row @current-change="handleCurrentChange">
                        <!-- <el-table-column type="selection" width="55" /> -->
                        <el-table-column prop="teamName" label="项目组名称"></el-table-column>
                        <el-table-column prop="personCharge" label="项目负责人"></el-table-column>
                        <el-table-column prop="staffName" label="项目组成员"></el-table-column>
                        <el-table-column prop="createTime" label="创建时间"></el-table-column>
                    </Table>
                </template>
            </TableCustom>
            <span slot="footer" class="select-member-footer">
                <el-button @click="$emit('close')">取 消</el-button>
                <el-button type="primary" @click="submitData">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<script>
import { getDataList } from './servce'
export default {
    props: {
        show: {
            type: Boolean,
            default: false
        },
        selectedData: {
            type: Object,
            default: () => ({})
        }
    },
    data() {
        return {
            form: {
                date: '',
                personCharge: '',
                pageNum: 1,
                pageSize: 10,
                startTime: '',
                endTime: '',
                teamName: '',
            },
            selectData: [],
            tableData: [],
            total: 0
        }
    },
    methods: {
        open() {
            getDataList({ ...this.form }).then(res => {
                console.log('/////////////', res);
                this.tableData = res.data.records || []
                this.total = res.data.total || 0
                if (this.selectedData && this.selectedData.id) {
                    this.selectData = this.selectedData
                    this.$nextTick(() => {
                        const row = this.tableData.find(item => item.id === this.selectedData.id)
                        if (row) {
                            this.$refs.memberTable.toggleRowSelection(row, true)
                        }
                    })
                }
            })
        },
        resetForm() {
            this.form = {
                date: '',
                personCharge: '',
                pageNum: 1,
                pageSize: 10,
                startTime: '',
                endTime: '',
                teamName: '',
            }
            this.handleSearch()
        },
        handleSearch() {
            console.log('shuju',this.form);
            this.open()
        },
        submitData(){
            this.$emit('submit',this.selectData)
        },
        handleCurrentChange(val) {
            this.selectData = val;
        },
    }
}
</script>
<style lang="less" scoped></style>
culture/src/components/chooseProject/servce.js
New file
@@ -0,0 +1,6 @@
import axios from '@/utils/request';
// 添加项目课题方案
export function getDataList(data) {
  return axios.post('/api/t_project_team/pageList', { ...data })
}
culture/src/views/strain-library/breeding-record/add.vue
@@ -31,16 +31,16 @@
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
            <el-form-item label="培养基配方" prop="mediumFormula" required>
              <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入培养基配方" />
            <el-form-item label="培养基配方" prop="formula" required>
              <el-input 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="materialCode" required>
              <el-input v-model="form.materialCode" placeholder="请输入物资编号" />
            <el-form-item label="来源物资、时间及批号" prop="sourceMaterialTimeBatchNumber" required>
              <el-input v-model="form.sourceMaterialTimeBatchNumber" placeholder="请输入物资编号" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
@@ -49,8 +49,8 @@
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="分离菌落编号" prop="materialDescription" required>
              <el-input v-model="form.materialDescription" placeholder="请输入物资描述" />
            <el-form-item label="分离菌落编号" prop="separateColonyNumber" required>
              <el-input v-model="form.separateColonyNumber" placeholder="请输入物资描述" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -62,49 +62,51 @@
        </div>
        <el-row :gutter="10">
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="培养基" prop="strainCode" required>
              <el-input v-model="form.strainCode" class="w-380" placeholder="请输入培养基" />
            <el-form-item label="培养基" prop="cultureMedium" required>
              <el-input 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="strainName" required>
              <el-input v-model="form.strainName" class="w-380" placeholder="请输入培养温度" />
            <el-form-item label="培养温度" prop="temperature" required>
              <el-input 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="mediumFormula" required>
              <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入需氧类型" />
            <el-form-item label="需氧类型" prop="aerobicType" required>
              <el-input v-model="form.aerobicType" 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="mediumFormula" required>
              <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入培养时间" />
            <el-form-item label="培养时间" prop="cultureTime" required>
              <el-input v-model="form.cultureTime" class="w-380" placeholder="请输入培养时间" />
            </el-form-item>
          </el-col>
        </el-row>
        <div class="header-title" style="margin-top: 20px;">
          <div class="header-title-left">
            <img src="@/assets/public/headercard.png" />
            <div>一、培养基分离记录</div>
            <div>一、培养皿分离记录</div>
          </div>
          <div class="header-title-right">
            <el-button @click="showSeparationDialog = true" class="el-icon-circle-plus-outline" type="primary">
            <el-button @click="handleAddSeparation" class="el-icon-circle-plus-outline" type="primary">
              新增培养皿分离记录</el-button>
          </div>
        </div>
        <Table :height="null" :queryForm="queryForm" :total="0">
          <template>
            <el-table-column prop="name" label="培养皿序号" />
            <el-table-column prop="age" label="分离菌落编号" />
            <el-table-column prop="age" label="接种操作人签字" />
            <el-table-column prop="age" label="操作时间" />
            <el-table-column prop="address" label="操作">
              <template slot-scope="scope"><el-button type="text"
                @click="handleEdit(scope.row)">编辑</el-button>
                <el-button type="text"
                @click="handleEdit(scope.row)">删除</el-button></template>
            </el-table-column>
          </template>
        <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="operatorSignature" label="接种操作人签字" >
            <template slot-scope="scope">
              <el-image  :preview-src-list="[scope.row.operatorSignature]" style="width: 40px;" :src="scope.row.operatorSignature" 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>
            </template>
          </el-table-column>
        </Table>
        <div class="header-title" style="margin-top: 20px;">
          <div class="header-title-left">
@@ -185,7 +187,9 @@
        <!-- 弹窗组件 -->
        <SeparationRecordDialog
          :visible.sync="showSeparationDialog"
          :editData="editSeparationData"
          @confirm="handleSeparationConfirm"
          @close="resetSeparationEdit"
        />
        <SlantRecordDialog
          :visible.sync="showObservationDialog"
@@ -199,8 +203,8 @@
          :visible.sync="showPreserveDialog"
          @save="handlePreserveConfirm"
        />
        <div class="end-btn">
          <el-button type="primary">发送</el-button>
        <div class="end-btn" style="margin-top: 20px;">
          <el-button type="primary" @click="handleSubmit">发送</el-button>
          <el-button type="default">存草稿</el-button>
        </div>
      </el-form>
@@ -213,7 +217,7 @@
import SlantRecordDialog from "./SlantRecordDialog.vue";
import InoculationSlopeRecordDialog from "./inoculation-slope-record-dialog.vue";
import PreserveStrainRecordDialog from "./preserve-strain-record-dialog.vue";
import {add} from './service'
export default {
  components: {
    AiEditor,
@@ -226,27 +230,50 @@
  data() {
    return {
      form: {
        strainCode: "",
        strainName: "",
        mediumFormula: "",
        materialCode: "",
        materialName: "",
        materialDescription: "",
        planName: "",
        planCode: "",
        stage: "",
        creator: "",
        createTime: "",
        approvalComment: "",
        status: "pending",
        approver: "",
        approveTime: "",
        id: '', // 主键
        strainCode: '', // 菌株编号
        strainName: '', // 菌株名称
        formula: '', // 培养基配方
        cultureMedium: '', // 培养基
        cultureTime: '', // 培养时间
        aerobicType: '', // 需氧类型
        temperature: '', // 培养温度
        status: '', // 状态
        createBy: '', // 创建人
        createTime: '', // 创建时间
        updateBy: '', // 修改人
        updateTime: '', // 修改时间
        disabled: 0, // 是否删除
        preserveSource: '', // 来源类型
        separateColonyNumber: '', // 分离菌落编号
        sourceMaterialTimeBatchNumber: '', // 来源物资存值批号
        // 下面是 array 类型字段
        culturePreservations: [],
        observationOfPetriDishes: [],
        separationOfCultureDishesList: [],
        vaccinationSlopes: [],
        // 兼容原有表单字段
        mediumFormula: '',
        materialCode: '',
        materialName: '',
        materialDescription: '',
        planName: '',
        planCode: '',
        stage: '',
        creator: '',
        approvalComment: '',
        approver: '',
        approveTime: '',
      },
      rules: {
        strainCode: [{ required: true, message: "请输入菌株编号", trigger: "blur" }],
        strainName: [{ required: true, message: "请输入菌株名称", trigger: "blur" }],
        mediumFormula: [{ required: true, message: "请输入培养基配方", trigger: "blur" }],
        materialCode: [{ required: true, message: "请输入物资编号", trigger: "blur" }],
        formula: [{ required: true, message: "请输入培养基配方", trigger: "blur" }],
        cultureMedium: [{ required: true, message: "请输入培养基", trigger: "blur" }],
        cultureTime: [{ required: true, message: "请输入培养时间", trigger: "blur" }],
        aerobicType: [{ required: true, message: "请输入需氧类型", trigger: "blur" }],
        temperature: [{ required: true, message: "请输入培养温度", trigger: "blur" }],
        sourceMaterialTimeBatchNumber: [{ required: true, message: "请输入物资编号", trigger: "blur" }],
        materialName: [{ required: true, message: "请输入物资名称", trigger: "blur" }],
        materialDescription: [{ required: true, message: "请输入物资描述", trigger: "blur" }],
      },
@@ -261,11 +288,20 @@
      showObservationDialog: false,
      showInoculationDialog: false,
      showPreserveDialog: false,
      editSeparationIndex: null,
      editSeparationData: null,
    };
  },
  methods: {
    handleSeparationConfirm(data) {
      console.log("培养皿分离记录确认", data);
      if (this.editSeparationIndex !== null) {
        // 编辑
        this.$set(this.form.separationOfCultureDishesList, this.editSeparationIndex, data);
        this.resetSeparationEdit();
      } else {
        // 新增
        this.form.separationOfCultureDishesList.push(data);
      }
    },
    handleObservationConfirm(data) {
      console.log("培养皿观察记录确认", data);
@@ -276,6 +312,36 @@
    handlePreserveConfirm(data) {
      console.log("菌种保藏记录确认", data);
    },
    handleSubmit() {
      this.$refs.form.validate(async (valid) => {
        if (!valid) return;
        try {
          await add(this.form);
          this.$message.success('添加成功');
          // 可选:跳转或重置表单
          // this.$router.push('/strain-library/breeding-record');
        } catch (e) {
          this.$message.error('添加失败');
        }
      });
    },
    handleEditSeparation(row, index) {
      this.editSeparationIndex = index;
      this.editSeparationData = { ...row };
      this.showSeparationDialog = true;
    },
    handleDeleteSeparation(index) {
      this.form.separationOfCultureDishesList.splice(index, 1);
    },
    resetSeparationEdit() {
      this.editSeparationIndex = null;
      this.editSeparationData = null;
    },
    handleAddSeparation() {
      this.editSeparationIndex = null;
      this.editSeparationData = null;
      this.showSeparationDialog = true;
    },
  },
};
</script>
culture/src/views/strain-library/breeding-record/index.vue
@@ -2,18 +2,67 @@
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total">
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="来源类型:">
            <el-input v-model="form.planName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="培养基:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="培养基配方:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
          </el-form-item>
        <el-form ref="searchForm" :model="form" :rules="rules" labelWidth="auto" inline>
          <el-form-item label="需氧类型">
            <el-input v-model="form.creator" placeholder="请输入"></el-input>
            <el-input v-model="form.aerobicType" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="创建人">
            <el-input v-model="form.createBy" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="创建时间">
            <el-date-picker v-model="form.createTime" type="date" placeholder="选择日期" value-format="yyyy-MM-dd"></el-date-picker>
          </el-form-item>
          <el-form-item label="培养基">
            <el-input v-model="form.cultureMedium" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="培养时间">
            <el-date-picker v-model="form.cultureTime" type="date" placeholder="选择日期" value-format="yyyy-MM-dd"></el-date-picker>
          </el-form-item>
          <el-form-item label="是否删除">
            <el-select v-model="form.disabled" placeholder="请选择">
              <el-option label="否" :value="0" />
              <el-option label="是" :value="1" />
            </el-select>
          </el-form-item>
          <el-form-item label="培养基配方">
            <el-input v-model="form.formula" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="主键id">
            <el-input v-model="form.id" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="来源类型">
            <el-select v-model="form.preserveSource" placeholder="请选择">
              <el-option label="来源菌株" :value="1" />
              <el-option label="来源物资" :value="2" />
            </el-select>
          </el-form-item>
          <el-form-item label="分离菌落编号">
            <el-input v-model="form.separateColonyNumber" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="来源物资存值批号">
            <el-input v-model="form.sourceMaterialTimeBatchNumber" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="form.status" placeholder="请选择">
              <el-option label="提交" :value="1" />
              <el-option label="审核通过" :value="2" />
              <el-option label="驳回" :value="3" />
            </el-select>
          </el-form-item>
          <el-form-item label="菌种编号">
            <el-input v-model="form.strainCode" 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.temperature" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="修改人">
            <el-input v-model="form.updateBy" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="修改时间">
            <el-date-picker v-model="form.updateTime" type="date" placeholder="选择日期" value-format="yyyy-MM-dd"></el-date-picker>
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
@@ -24,59 +73,54 @@
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center">
            <div
              class="title"
              :class="{ active: currentType === 'list' }"
              @click="handleTypeChange('list')"
            >
              菌种传代生产谱系图
            <div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">
              菌种选育保藏记录
            </div>
            <div
              class="drafts"
              :class="{ active: currentType === 'draft' }"
              @click="handleTypeChange('draft')"
            >
            <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
            >
            <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="stage" label="来源类型"></el-table-column>
        <el-table-column prop="creator" label="培养基"></el-table-column>
        <el-table-column prop="creator" label="培养基配方"></el-table-column>
        <el-table-column prop="createTime" label="培养温度"></el-table-column>
        <el-table-column prop="approver" label="需氧类型"></el-table-column>
        <el-table-column prop="approver" label="创建人"></el-table-column>
        <el-table-column prop="approveTime" label="创建时间"></el-table-column>
        <el-table-column prop="preserveSource" label="来源类型"></el-table-column>
        <el-table-column prop="cultureMedium" label="培养基"></el-table-column>
        <el-table-column prop="formula" label="培养基配方"></el-table-column>
        <el-table-column prop="temperature" label="培养温度"></el-table-column>
        <el-table-column prop="aerobicType" label="需氧类型"></el-table-column>
        <el-table-column prop="createBy" label="创建人"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column prop="cultureTime" label="培养时间"></el-table-column>
        <el-table-column prop="strainCode" label="菌种编号"></el-table-column>
        <el-table-column prop="strainName" label="菌种名称"></el-table-column>
        <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="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>
          </template>
        </el-table-column>
      </template>
    </TableCustom>
    <el-pagination
      :current-page="form.pageNum"
      :page-size="form.pageSize"
      :total="total"
      @current-change="handlePageChange"
      @size-change="handleSizeChange"
      layout="total, sizes, prev, pager, next, jumper"
      :page-sizes="[10, 20, 50, 100]"
      style="margin-top: 20px; text-align: right;"
    />
  </div>
</template>
<script>
import { getList } from './service'
export default {
  name: "BreedingRecord",
  components: {},
@@ -84,12 +128,43 @@
    return {
      currentType: "list", // 当前显示类型:list-列表,draft-草稿箱
      form: {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        aerobicType: '',
        createBy: '',
        createTime: '',
        cultureMedium: '',
        cultureTime: '',
        disabled: '',
        formula: '',
        id: '',
        preserveSource: '',
        separateColonyNumber: '',
        sourceMaterialTimeBatchNumber: '',
        status: '',
        strainCode: '',
        strainName: '',
        temperature: '',
        updateBy: '',
        updateTime: '',
        pageNum: 1,
        pageSize: 10,
        isDraft: 0,
      },
      rules: {
        aerobicType: [
          { required: true, message: '需氧类型不能为空', trigger: 'blur' }
        ],
        cultureMedium: [
          { required: true, message: '培养基不能为空', trigger: 'blur' }
        ],
        preserveSource: [
          { required: true, message: '来源类型不能为空', trigger: 'change' }
        ],
        strainCode: [
          { required: true, message: '菌种编号不能为空', trigger: 'blur' }
        ],
        strainName: [
          { required: true, message: '菌种名称不能为空', trigger: 'blur' }
        ],
      },
      tableData: [],
      total: 0,
@@ -159,12 +234,26 @@
  methods: {
    resetForm() {
      this.form = {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        aerobicType: '',
        createBy: '',
        createTime: '',
        cultureMedium: '',
        cultureTime: '',
        disabled: '',
        formula: '',
        id: '',
        preserveSource: '',
        separateColonyNumber: '',
        sourceMaterialTimeBatchNumber: '',
        status: '',
        strainCode: '',
        strainName: '',
        temperature: '',
        updateBy: '',
        updateTime: '',
        pageNum: 1,
        pageSize: 10,
        isDraft: this.currentType === 'draft' ? 1 : 0,
      };
    },
    handleNewStrain() {
@@ -173,8 +262,21 @@
      });
    },
    handleSearch() {
      // 实现查询逻辑
      console.log("查询条件:", this.form);
      this.$refs.searchForm.validate(valid => {
        if (valid) {
          this.form.isDraft = this.currentType === 'draft' ? 1 : 0;
          this.form.pageNum = 1;
          this.getTableData();
        }
      });
    },
    handlePageChange(page) {
      this.form.pageNum = page;
      this.getTableData();
    },
    handleSizeChange(size) {
      this.form.pageSize = size;
      this.getTableData();
    },
    getStatusType(status) {
      const statusMap = {
@@ -239,17 +341,18 @@
    },
    handleTypeChange(type) {
      this.currentType = type;
      this.form.isDraft = type === 'draft' ? 1 : 0;
      this.form.pageNum = 1;
      this.getTableData();
    },
    getTableData() {
      // 根据currentType请求不同的数据
      if (this.currentType === "list") {
        this.tableData = this.mockListData;
        this.total = this.mockListData.length;
      } else {
        this.tableData = this.mockDraftData;
        this.total = this.mockDraftData.length;
      }
      getList({ ...this.form }).then(res => {
        this.tableData = res.data.list || [];
        this.total = res.data.total || 0;
      }).catch(() => {
        this.tableData = [];
        this.total = 0;
      });
    },
  },
};
@@ -259,15 +362,18 @@
.list {
  height: 100%;
}
.flex {
  display: flex;
  align-items: center;
}
.tableTitle {
  display: flex;
  padding-bottom: 20px;
  justify-content: space-between;
  align-items: center;
  .title {
    background: #fafafc;
    border-radius: 8px 8px 0px 0px;
@@ -279,6 +385,7 @@
    width: unset;
    cursor: pointer;
  }
  .drafts {
    padding: 16px 65px;
    background: #fafafc;
@@ -290,6 +397,7 @@
    margin-left: 16px;
    cursor: pointer;
  }
  .active {
    color: #049c9a;
    background: #ffffff;
culture/src/views/strain-library/breeding-record/separation-record-dialog.vue
@@ -1,6 +1,6 @@
<template>
    <el-dialog
      title="新增培养皿分离记录"
      :title="isEdit ? '编辑培养皿分离记录' : '新增培养皿分离记录'"
      :visible.sync="visible"
      width="520px"
      :close-on-click-modal="false"
@@ -10,7 +10,7 @@
      <div class="dialog-content">
        <el-form :model="formData" label-position="top">
          <el-form-item label="分离菌落编号" required>
            <el-input v-model="formData.colonyCode" placeholder="请输入" />
            <el-input v-model="formData.separateBacterialColoniesCode" placeholder="请输入" />
          </el-form-item>
  
          <el-form-item required>
@@ -39,6 +39,7 @@
  
  <script>
  import SignatureCanvas from '@/components/SignatureCanvas.vue'
  import moment from 'moment'
  export default {
    name: 'AddRecordDialog',
    components: { SignatureCanvas },
@@ -46,28 +47,59 @@
      visible: {
        type: Boolean,
        default: false
      },
      editData: {
        type: Object,
        default: () => null
      }
    },
    data() {
      return {
        formData: {
          type: '出库',
          separateBacterialColoniesCode: '',
          operatorSignature: ''
        },
        showSignature: false
        showSignature: false,
        isEdit: false
      }
    },
    watch: {
      visible(val) {
        if (val && this.editData) {
          this.isEdit = true
          this.formData = {
            ...this.editData
          }
        } else {
          this.isEdit = false
          this.resetForm()
        }
      }
    },
    methods: {
      resetForm() {
        this.formData = {
          separateBacterialColoniesCode: '',
          operatorSignature: ''
        }
      },
      handleClose() {
        this.$emit('update:visible', false)
        this.$emit('close')
        this.resetForm()
      },
      handleConfirm() {
        if (!this.formData.operatorSignature) {
          this.$message.warning('请先签名')
          return
        }
        this.formData.createTime = moment().format('YYYY-MM-DD HH:mm:ss')
        this.$emit('confirm', this.formData)
        this.formData = {
          separateBacterialColoniesCode: '',
          operatorSignature: ''
        }
        this.handleClose()
      },
      handleSignatureConfirm(dataUrl) {
culture/src/views/strain-library/breeding-record/service.js
New file
@@ -0,0 +1,20 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-breeding-and-preservation/pageList', { ...data })
}
//新增
export const add = (data) => {
  console.log('qweqwe',data);
  return axios.post('/api/t-breeding-and-preservation/add', { ...data })
}
//编辑
export const edit = (data) => {
    console.log('qweqwe',data);
    return axios.post('/api/t-breeding-and-preservation/update', { ...data })
  }
culture/src/views/strainReportLibrary/reportLibraryOne/add.vue
@@ -12,12 +12,12 @@
                </div>
            </div>
            <Table :height="null" :queryForm="queryForm" :total="0">
            <Table :height="null" :queryForm="queryForm" :total="0" :data="projectData">
                <template>
                    <el-table-column prop="name" label="项目组名称" />
                    <el-table-column prop="age" label="项目负责人" />
                    <el-table-column prop="age" label="项目组成员" />
                    <el-table-column prop="age" label="创建时间" />
                    <el-table-column prop="teamName" label="项目组名称" />
                    <el-table-column prop="personCharge" label="项目负责人" />
                    <el-table-column prop="staffName" label="项目组成员" />
                    <el-table-column prop="createTime" label="创建时间" />
                </template>
            </Table>
            <el-form ref="form" :model="form" :rules="rules" inline label-position="top" style="margin-top: 38px">
@@ -27,8 +27,8 @@
                        <div>报告编号</div>
                    </div>
                </div>
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                <el-form-item prop="reportCode" style="margin-top: 38px">
                    <el-input v-model="form.reportCode" style="width: 100%;" placeholder="请输入报告编号" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
@@ -37,8 +37,8 @@
                        <div>报告名称</div>
                    </div>
                </div>
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                <el-form-item prop="reportName" style="margin-top: 38px">
                    <el-input v-model="form.reportName" style="width: 100%;" placeholder="请输入报告编号" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
@@ -47,8 +47,9 @@
                        <div>报告正文</div>
                    </div>
                </div>
                <el-form-item prop="name" style="margin-top: 38px">
                    <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                <el-form-item prop="reportText" style="margin-top: 38px">
                    <ai-editor ref="materialEditor" :value="form.reportText" style="width: 100%;"
                        placeholder="请输入报告正文" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
@@ -74,42 +75,94 @@
                        <div>菌种实验员</div>
                    </div>
                    <div class="header-title-right">
                        <el-button @click="showChoose = true" class="el-icon-circle-plus-outline" type="primary">
                        <el-button @click="getMember" class="el-icon-circle-plus-outline" type="primary">
                            选择菌种实验员</el-button>
                    </div>
                </div>
                <div class="member-list">
                    <div class="member-list-card">
                    <div v-if="selectedMember" class="member-list-card" v-for="(item, index) in selectedMember"
                        :key="index">
                        <div class="member-item">
                            <div class="member-title">
                                菌种实验员
                            </div>
                            <div class="member-name-box">
                                <div class="member-name">
                                    张三
                                    {{ item.nickName }}
                                </div>
                            </div>
                            <div class="member-change">
                                <div class="member-change-btn">修改</div>
                                <div class="member-change-btn" @click="handleModifyMember(item)">修改</div>
                            </div>
                        </div>
                    </div>
                    <div v-else class="member-list-card empty-state">
                        <div class="member-item">
                            <div class="member-title">
                                菌种实验员
                            </div>
                            <div class="member-name-box">
                                <div class="empty-text">请选择菌种实验员</div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="table" style="margin-top: 38px">
                    <el-table :data="assessmentTable" border style="width: 100%" :show-summary="true"
                        :span-method="tableSpanMethod" :summary-method="getTableSummary">
                        <el-table-column prop="category" label="菌种实验员专业能力考核项" width="180"></el-table-column>
                        <el-table-column prop="score" label="该项评分" width="120">
                            <template slot-scope="scope">
                                <el-radio-group v-if="scope.row.category !== '5.实验失败'"
                                    v-model="scope.row.selectedScore">
                                    <el-radio :label="0">0分</el-radio>
                                    <el-radio :label="1">1分</el-radio>
                                    <el-radio :label="2">2分</el-radio>
                                </el-radio-group>
                                <el-radio-group v-else v-model="scope.row.selectedScore">
                                    <el-radio :label="0">否0分</el-radio>
                                    <el-radio :label="-3">是-3分</el-radio>
                                </el-radio-group>
                            </template>
                        </el-table-column>
                        <el-table-column prop="criteria" label="该项评分参考标准"></el-table-column>
                        <el-table-column prop="desc" label="评分规则说明">
                            <template slot-scope="scope">
                                <p> 【0分】 实验操作失误或实验方案设计无效导致实验失败、数据不可用。</p>
                                <p> 【1分】存在操作有误及实验过程出现问题,没有严格按照操作规程运行;如实验准备不充分,取样遗漏等。</p>
                                <p> 【2分】完整按照操作规程及实验室管理制度运行,无任何问题。</p>
                            </template>
                        </el-table-column>
                        <el-table-column prop="rule" label="考评规则">
                            <template slot-scope="scope">
                                菌种工程师以分题内容考核菌种实验员。
                            </template>
                        </el-table-column>
                    </el-table>
                </div>
                <div class="end-btn" style="margin-top: 38px">
                    <el-button type="primary">发送</el-button>
                    <el-button type="default">存草稿</el-button>
                    <el-button type="primary" @click="addData">发送</el-button>
                    <el-button type="default" @click="saveData">存草稿</el-button>
                </div>
            </el-form>
        </Card>
        <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
        <SelectMember ref="selectMember" @submit="selectUser" :singleSelect="true" />
    </div>
</template>
<script>
import { Card } from 'element-ui';
import AiEditor from '@/components/AiEditor'
import ChooseProject from '@/components/chooseProject/index.vue'
import SelectMember from '@/components/SelectMember'
import { add } from './service'
export default {
    components: { AiEditor },
    components: { AiEditor, ChooseProject, SelectMember },
    data() {
        return {
            form: {
@@ -123,17 +176,173 @@
                approver: "",
                approveTime: ""
            },
            projectData: [], // 存储选中的项目组数据
            fileList: [], // 附件列表
            showChoose: false,
            radio1: 1,
            rules: {},
            rules: {
                reportCode: [
                    { required: true, message: '请输入报告编号', trigger: 'blur' }
                ],
                reportName: [
                    { required: true, message: '请输入报告名称', trigger: 'blur' }
                ]
            },
            status: "1",
            remark: "",
            queryForm: {
            }
            },
            assessmentTable: [
                {
                    category: '1.该分题的菌种专业知识',
                    selectedScore: 0,
                    criteria: '1.1 能讲生物学基础,掌握各类微生物形态特性、生化特性及鉴定方法。1.2 菌种选育技术,了解掌握自然选育、诱变选育、基因工程育种。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '2.操作能力',
                    selectedScore: 0,
                    criteria: '1.菌种分离无菌操作规范 2.菌种培养无菌操作规范 3.菌种保存无菌操作规范 4.菌种鉴定无菌操作规范',
                    desc: '',
                    rule: ''
                },
                {
                    category: '3.仪器设备使用',
                    selectedScore: 0,
                    criteria: '能正确使用实验仪器,如移液器、恒温箱等,操作规范。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '4.实验数据记录与分析',
                    selectedScore: 0,
                    criteria: '实验数据记录及时、准确、完整,能简单分析数据。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '5.实验失败',
                    selectedScore: 0,
                    criteria: '无论何种原因,本次实验失败。',
                    desc: '',
                    rule: ''
                }
            ],
            selectedMember: null, // 存储选中的菌种实验员
        }
    }
    },
    computed: {
        totalScore() {
            return this.assessmentTable.reduce((sum, row) => sum + Number(row.selectedScore), 0)
        }
    },
    methods: {
        addData() {
            console.log('qeqweqeqwqrew',this.form,this.projectData);
            this.$refs.form.validate(async (valid) => {
                if (!valid) return;
                if (this.$refs.materialEditor.getContent() == '<p></p>') {
                    this.$message.error('请输入报告正文')
                    return
                }
                if (!this.projectData.length) {
                    this.$message.warning('请选择项目组');
                    return;
                }
                if (!this.selectedMember || !this.selectedMember[0]) {
                    this.$message.warning('请选择菌种实验员');
                    return;
                }
                try {
                    const params = {
                        isDraft: 0,
                        evaluateId:this.selectedMember[0].id,
                        projectId: this.projectData[0].id,
                        reportCode: this.form.reportCode,
                        reportContent: this.$refs.materialEditor.getContent(),
                        reportName: this.form.reportName,
                        reportType: 1
                    };
                    add(params).then(res => {
                        if (res.code == 200) {
                            this.$message.success('发送成功');
                            this.$router.push('/strainReportLibrary/reportLibraryOne');
                        }
                    })
                } catch (e) {
                    this.$message.error('发送失败');
                }
            });
        },
        saveData() {
            this.$refs.form.validate(async (valid) => {
                if (!valid) return;
                try {
                    const params = {
                        isDraft: 1,
                        projectId: this.projectData[0].id,
                        evaluateId:this.selectedMember[0].id,
                        reportCode: this.form.reportCode,
                        reportContent: this.$refs.materialEditor.getContent(),
                        reportName: this.form.reportName,
                        reportType: 1
                    };
                    add(params).then(res => {
                        if (res.code == 200) {
                            this.$message.success('保存成功');
                            this.$router.push('/strainReportLibrary/reportLibraryOne');
                        }
                    })
                } catch (e) {
                    this.$message.error('保存失败');
                }
            });
        }, getProjectData(data) {
            this.projectData = [data]; // 将选中的项目组数据存储到数组中
            this.showChoose = false
        },
        selectUser(data) {
            this.selectedMember = data;
            console.log('qweqweqwe', data);
            this.$refs.selectMember.close()
        },
        getMember() {
            this.$refs.selectMember.open(null);
        },
        handleModifyMember(member) {
            this.$refs.selectMember.open(member);
        },
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则说明(desc)和考评规则(rule)列合并所有行
            // desc列索引为3,rule列索引为4(从0开始)
            if (columnIndex === 3 || columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.assessmentTable.length, 1]; // 合并所有行
                } else {
                    return [0, 0]; // 其他行隐藏
                }
            }
            return [1, 1];
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 1) {
                    sums[index] = this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
    },
}
</script>
@@ -224,6 +433,15 @@
                rgba(5, 160, 193, 0.2) 0%,
                rgba(5, 242, 194, 0) 70%);
        &.empty-state {
            background: #f5f7fa;
            .empty-text {
                color: #909399;
                font-size: 14px;
            }
        }
        .member-item {
            height: 100%;
            display: flex;
culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog :title="dialogTitle"  :visible.sync="visible" width="80%" po :close-on-click-modal="false"
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
        @close="handleClose">
        <div class="approval-dialog">
        <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
            <!-- 左侧审批内容 -->
            <div class="approval-content">
                <Card class="approval-content-card">
@@ -12,13 +12,12 @@
                                <div>所属项目组</div>
                            </div>
                        </div>
                        <Table :height="null" :queryForm="queryForm" :total="0" @currentChange="handleCurrentChange"
                            @sizeChange="handleSizeChange">
                        <Table :height="null" :total="0" :data="tableData">
                            <template>
                                <el-table-column prop="name" label="项目组名称" />
                                <el-table-column prop="age" label="项目负责人" />
                                <el-table-column prop="age" label="项目组成员" />
                                <el-table-column prop="age" label="创建时间" />
                                <el-table-column prop="teamName" label="项目组名称" />
                                <el-table-column prop="personCharge" label="项目负责人" />
                                <el-table-column prop="staffName" label="项目组成员" />
                                <el-table-column prop="createTime" label="创建时间" />
                            </template>
                        </Table>
@@ -31,9 +30,10 @@
                                    <div>报告编号</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportCode" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                    placeholder="请输入报告编号" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -41,9 +41,10 @@
                                    <div>报告名称</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportName" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportName" style="width: 100%;"
                                    placeholder="请输入报告名称" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -51,9 +52,53 @@
                                    <div>报告正文</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportText" style="margin-top: 38px">
                                <ai-editor :readOnly="true" :value="form.reportText" style="width: 100%;"
                                    placeholder="请输入报告正文" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
                                    <img src="@/assets/public/headercard.png" />
                                    <div>菌种实验员操作评定</div>
                                </div>
                            </div>
                            <div class="table" style="margin-top: 38px">
                                <el-table :data="assessmentTable" border style="width: 100%" :show-summary="true"
                                    :span-method="tableSpanMethod" :summary-method="getTableSummary">
                                    <el-table-column prop="category" label="菌种实验员专业能力考核项" width="180"></el-table-column>
                                    <el-table-column prop="score" label="该项评分" width="120">
                                        <template slot-scope="scope">
                                            <el-radio-group v-if="scope.row.category !== '5.实验失败'"
                                                v-model="scope.row.selectedScore">
                                                <el-radio :label="0">0分</el-radio>
                                                <el-radio :label="1">1分</el-radio>
                                                <el-radio :label="2">2分</el-radio>
                                            </el-radio-group>
                                            <el-radio-group v-else v-model="scope.row.selectedScore">
                                                <el-radio :label="0">否0分</el-radio>
                                                <el-radio :label="-3">是-3分</el-radio>
                                            </el-radio-group>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="criteria" label="该项评分参考标准"></el-table-column>
                                    <el-table-column prop="desc" label="评分规则说明">
                                        <template slot-scope="scope">
                                            <p> 【0分】 实验操作失误或实验方案设计无效导致实验失败、数据不可用。</p>
                                            <p> 【1分】存在操作有误及实验过程出现问题,没有严格按照操作规程运行;如实验准备不充分,取样遗漏等。</p>
                                            <p> 【2分】完整按照操作规程及实验室管理制度运行,无任何问题。</p>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="rule" label="考评规则">
                                        <template slot-scope="scope">
                                            菌种工程师以分题内容考核菌种实验员。
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </div>
                        </el-form>
                    </template>
@@ -63,21 +108,20 @@
            <!-- 右侧审批流程 -->
            <div class="approval-flow">
                <div class="flow-content">
                    <approval-process :status="form.status" :submit-time="form.createTime" :approver="form.approver"
                        :approve-time="form.approveTime" />
                    <approval-process :processData="form.processData" />
                </div>
            </div>
        </div>
        <div class="approval-dialog-approve">
        <div class="approval-dialog-approve" v-if="!obj.isDetail">
            <el-row :span="24">
                <el-col :span="12">
                    <div class="status">
                        <div class="status-title">审批结果</div>
                        <div class="status-content">
                            <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1">
                            <div class="resolve" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                                通过
                            </div>
                            <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                            <div class="reject" :class="status == '3' && 'activeStatus'" @click.stop="status = 3">
                                驳回
                            </div>
                        </div>
@@ -94,8 +138,8 @@
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="handleClose" >取 消</el-button>
            <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">通过</el-button>
            <el-button @click="handleClose">{{ obj.isDetail ? '关闭' : '取 消' }}</el-button>
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
        </div>
    </el-dialog>
</template>
@@ -103,6 +147,8 @@
<script>
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
// import { getDetail } from '../../service';
export default {
    name: "ApprovalDialog",
@@ -119,27 +165,74 @@
            type: String,
            default: "approve", // approve-审批,view-查看
        },
        data: {
        obj: {
            type: Object,
            default: () => ({}),
            default: () => {
                return {
                    isDetail: false
                }
            },
        },
    },
    data() {
        return {
            form: {
                planName: "",
                planCode: "",
                stage: "",
                creator: "",
                reportCode: "",
                reportName: "",
                reportText: "",
                teamName: "",
                createBy: "",
                createTime: "",
                status: "",
                approvalComment: "",
                status: "pending",
                approver: "",
                approveTime: ""
                approveTime: "",
                processData: [],
                updateBy: "",
                auditRemark: "",
                auditPersonName: "",
                auditTime: ""
            },
            radio1: 1,
            assessmentTable: [
                {
                    category: '1.该分题的菌种专业知识',
                    selectedScore: 0,
                    criteria: '1.1 能讲生物学基础,掌握各类微生物形态特性、生化特性及鉴定方法。1.2 菌种选育技术,了解掌握自然选育、诱变选育、基因工程育种。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '2.操作能力',
                    selectedScore: 0,
                    criteria: '1.菌种分离无菌操作规范 2.菌种培养无菌操作规范 3.菌种保存无菌操作规范 4.菌种鉴定无菌操作规范',
                    desc: '',
                    rule: ''
                },
                {
                    category: '3.仪器设备使用',
                    selectedScore: 0,
                    criteria: '能正确使用实验仪器,如移液器、恒温箱等,操作规范。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '4.实验数据记录与分析',
                    selectedScore: 0,
                    criteria: '实验数据记录及时、准确、完整,能简单分析数据。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '5.实验失败',
                    selectedScore: 0,
                    criteria: '无论何种原因,本次实验失败。',
                    desc: '',
                    rule: ''
                }
            ],
            tableData: [],
            rules: {},
            status: "1",
            status: "2",
            remark: "",
        };
    },
@@ -147,41 +240,131 @@
        dialogTitle() {
            return this.type === "approve" ? "审批" : "审批详情";
        },
    },
    watch: {
        data: {
            handler(val) {
                if (val) {
                    this.form = { ...val };
                }
            },
            immediate: true,
        },
        totalScore() {
            return this.assessmentTable.reduce((sum, item) => sum + (item.selectedScore || 0), 0);
        }
    },
    methods: {
        open() {
            if (!this.obj.id) {
                this.$message.error('缺少必要参数');
                return;
            }
            // getDetail(this.obj.id).then(res => {
            //     const data = res.data || res;
            //     this.form = {
            //         ...this.form,
            //         ...data,
            //         processData: []
            //     };
            //     this.tableData = data.projectTeam ?
            //         [{ ...data.projectTeam, staffName: data.staffNames || '' }] :
            //         [];
            //     let processData = [];
            //     // 提交节点
            //     processData.push({
            //         type: "primary",
            //         mode: "list",
            //         fields: [
            //             { label: "提交人:", value: data.updateBy || "" },
            //             { label: "提交时间:", value: data.createTime || "" },
            //         ]
            //     });
            //     if (data.status == 2 || data.status == 3) {
            //         processData.push({
            //             type: data.status === 2 ? "primary" : "danger",
            //             mode: "list",
            //             fields: [
            //                 { label: "审批意见:", value: data.auditRemark || "" },
            //                 { label: "审核人:", value: data.auditPersonName || "" },
            //                 { label: "审核时间:", value: data.auditTime || "" },
            //             ]
            //         });
            //     } else {
            //         processData.push({
            //             type: "warning",
            //             mode: "list",
            //             fields: [
            //                 { label: "等待审核" },
            //             ],
            //         });
            //     }
            //     if (data.status == 2) {
            //         processData.push({
            //             type: "warning",
            //             mode: "list",
            //             fields: [{ label: "等待评定" }],
            //         });
            //     }
            //     if (data.status == 3) {
            //         processData.push({
            //             type: "success",
            //             mode: "list",
            //             fields: [
            //                 { label: "已评定" },
            //                 { label: "评定人:", value: data.evaluatePersonName || "" },
            //                 { label: "评定时间:", value: data.evaluateTime || "" }
            //             ],
            //         });
            //     }
            //     this.form.processData = processData;
            // }).catch(err => {
            //     this.$message.error('获取详情失败');
            // });
        },
        handleClose() {
            this.$emit("close");
            this.form.approvalComment = "";
        },
        handleApprove() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则说明(desc)和考评规则(rule)列合并所有行
            // desc列索引为3,rule列索引为4(从0开始)
            if (columnIndex === 3 || columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.assessmentTable.length, 1]; // 合并所有行
                } else {
                    return [0, 0]; // 其他行隐藏
                }
            }
            return [1, 1];
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 1) {
                    sums[index] =this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        handleApprove() {
            this.$emit("approve", {
                ...this.form,
                status: "approved",
                statuss: this.status,
                remark: this.remark
            });
        },
        handleReject() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("reject", {
                ...this.form,
                status: "rejected",
            });
        handleCurrentChange(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.form.pageSize = size
            this.getList()
        },
    },
};
@@ -211,7 +394,7 @@
        background: #ffffff;
        box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
        border-radius: 10px;
        .flow-title {
            font-size: 16px;
            font-weight: bold;
culture/src/views/strainReportLibrary/reportLibraryOne/components/evaluate/index.vue
New file
@@ -0,0 +1,434 @@
<template>
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
        @close="handleClose">
        <div class="approval-dialog">
            <!-- 左侧审批内容 -->
            <div class="approval-content">
                    <template>
                        <el-form ref="form" :model="form" :rules="rules" inline label-position="top">
                            <div style="display: flex;">
                                <div>
                                    <div class="header-title" style="width: 100%;">
                                        <div class="header-title-left">
                                            <img src="@/assets/public/headercard.png" />
                                            <div>报告编号</div>
                                        </div>
                                    </div>
                                    <el-form-item prop="reportCode">
                                        <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                            placeholder="请输入报告编号" />
                                    </el-form-item>
                                </div>
                                <div style="margin-left: 100px;">
                                    <div class="header-title" style="width: 100%;">
                                        <div class="header-title-left">
                                            <img src="@/assets/public/headercard.png" />
                                            <div>报告名称</div>
                                        </div>
                                    </div>
                                    <el-form-item prop="reportName" >
                                        <el-input disabled v-model="form.reportName" style="width: 100%;"
                                            placeholder="请输入报告名称" />
                                    </el-form-item>
                                </div>
                            </div>
                            <div class="table">
                                <el-table :data="assessmentTable" border style="width: 100%" :show-summary="true"
                                    :span-method="tableSpanMethod" :summary-method="getTableSummary">
                                    <el-table-column prop="category" label="菌种实验员专业能力考核项" width="180"></el-table-column>
                                    <el-table-column prop="score" label="该项评分" width="120">
                                        <template slot-scope="scope">
                                            <el-radio-group v-if="scope.row.category !== '5.实验失败'"
                                                v-model="scope.row.selectedScore">
                                                <el-radio :label="0">0分</el-radio>
                                                <el-radio :label="1">1分</el-radio>
                                                <el-radio :label="2">2分</el-radio>
                                            </el-radio-group>
                                            <el-radio-group v-else v-model="scope.row.selectedScore">
                                                <el-radio :label="0">否0分</el-radio>
                                                <el-radio :label="-3">是-3分</el-radio>
                                            </el-radio-group>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="criteria" label="该项评分参考标准"></el-table-column>
                                    <el-table-column prop="desc" label="评分规则说明">
                                        <template slot-scope="scope">
                                            <p> 【0分】 实验操作失误或实验方案设计无效导致实验失败、数据不可用。</p>
                                            <p> 【1分】存在操作有误及实验过程出现问题,没有严格按照操作规程运行;如实验准备不充分,取样遗漏等。</p>
                                            <p> 【2分】完整按照操作规程及实验室管理制度运行,无任何问题。</p>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="rule" label="考评规则">
                                        <template slot-scope="scope">
                                            菌种工程师以分题内容考核菌种实验员。
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </div>
                        </el-form>
                    </template>
                    <!-- <SelectMember ref="selectMember" /> -->
            </div>
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">提交评定结果</el-button>
        </div>
    </el-dialog>
</template>
<script>
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
// import { getDetail } from '../../service';
export default {
    name: "ApprovalDialog",
    components: {
        ApprovalProcess,
        AiEditor
    },
    props: {
        visible: {
            type: Boolean,
            default: false,
        },
        type: {
            type: String,
            default: "approve", // approve-审批,view-查看
        },
        obj: {
            type: Object,
            default: () => {
                return {
                    isDetail: false
                }
            },
        },
    },
    data() {
        return {
            form: {
                reportCode: "",
                reportName: "",
                reportText: "",
                teamName: "",
                createBy: "",
                createTime: "",
                status: "",
                approvalComment: "",
                approver: "",
                approveTime: "",
                processData: [],
                updateBy: "",
                auditRemark: "",
                auditPersonName: "",
                auditTime: ""
            },
            assessmentTable: [
                {
                    category: '1.该分题的菌种专业知识',
                    selectedScore: 0,
                    criteria: '1.1 能讲生物学基础,掌握各类微生物形态特性、生化特性及鉴定方法。1.2 菌种选育技术,了解掌握自然选育、诱变选育、基因工程育种。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '2.操作能力',
                    selectedScore: 0,
                    criteria: '1.菌种分离无菌操作规范 2.菌种培养无菌操作规范 3.菌种保存无菌操作规范 4.菌种鉴定无菌操作规范',
                    desc: '',
                    rule: ''
                },
                {
                    category: '3.仪器设备使用',
                    selectedScore: 0,
                    criteria: '能正确使用实验仪器,如移液器、恒温箱等,操作规范。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '4.实验数据记录与分析',
                    selectedScore: 0,
                    criteria: '实验数据记录及时、准确、完整,能简单分析数据。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '5.实验失败',
                    selectedScore: 0,
                    criteria: '无论何种原因,本次实验失败。',
                    desc: '',
                    rule: ''
                }
            ],
            tableData: [],
            rules: {},
            status: "2",
            remark: "",
        };
    },
    computed: {
        dialogTitle() {
            return this.type === "approve" ? "菌种工程师操作评定" : "菌种工程师操作评定详情";
        },
        totalScore() {
            return this.assessmentTable.reduce((sum, item) => sum + (item.selectedScore || 0), 0);
        }
    },
    methods: {
        open() {
        },
        handleClose() {
            this.$emit("close");
            this.form.approvalComment = "";
        },
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则说明(desc)和考评规则(rule)列合并所有行
            // desc列索引为3,rule列索引为4(从0开始)
            if (columnIndex === 3 || columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.assessmentTable.length, 1]; // 合并所有行
                } else {
                    return [0, 0]; // 其他行隐藏
                }
            }
            return [1, 1];
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 1) {
                    sums[index] = this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        handleApprove() {
            this.$emit("approve", {
                ...this.form,
                statuss: this.status,
                remark: this.remark
            });
        },
        handleCurrentChange(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.form.pageSize = size
            this.getList()
        },
    },
};
</script>
<style scoped lang="less">
::v-deep .el-dialog__header {
    border-bottom: 1px solid #e4e7ed;
}
.approval-dialog {
    .approval-content {
        background: #ffffff;
        border-radius: 10px;
    }
    .approval-flow {
        padding: 40px 20px;
        // width: 405px;
        flex: 2;
        background: #ffffff;
        border-radius: 10px;
        .flow-title {
            font-size: 16px;
            font-weight: bold;
            margin-bottom: 20px;
            color: #303133;
        }
        .flow-content {
            height: calc(100% - 40px);
            overflow-y: auto;
            .el-form--inline .el-form-item {
                margin-right: 83px;
            }
        }
    }
}
.approval-content-card {
    box-shadow: none !important;
}
.header-title {
    // display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 20px;
    gap: 13px;
    .header-title-left {
        display: flex;
        align-items: center;
        gap: 13px;
        margin-top: 38px;
        img {
            width: 12px;
            height: 19px;
        }
        div {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
            &:before {
                content: "*";
                color: #f56c6c;
                margin-right: 4px;
            }
        }
        span {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
        }
    }
    .header-title-left :first-child {
        margin-top: 0;
    }
}
.header-title:first-child {
    .header-title-left {
        margin-top: 0;
    }
}
.item-title {
    padding-left: 25px;
    span {
        flex-shrink: 0;
        font-weight: bold;
        font-size: 14px;
        color: #222222;
        line-height: 27px;
        font-family: "Source Han Sans CN Bold Bold";
        margin: 18px 0;
        &:before {
            content: "*";
            color: #f56c6c;
            margin-right: 4px;
        }
    }
}
.approval-dialog-approve {
    align-content: center;
    .status {
        margin-right: 40px;
        max-width: 60%;
    }
    //   align-items: center;
    .status-title {
        color: #222222;
        font-family: "SourceHanSansCN-Medium";
        line-height: 14px;
        margin-bottom: 16px;
    }
    .status-content {
        display: flex;
        align-items: center;
        width: 100%;
        gap: 16px;
        background: #ffffff;
        border-radius: 10px;
        border: 1px solid rgba(4, 156, 154, 0.5);
        .resolve {
            border-radius: 10px;
            flex: 1;
            font-size: 16px;
            // padding: 5px 55px;
            font-weight: 400;
            color: #333333;
            cursor: pointer;
            line-height: 32px;
            display: flex;
            align-items: center;
            justify-content: center
        }
        .reject {
            flex: 1;
            border-radius: 10px;
            font-size: 16px;
            line-height: 32px;
            // padding: 5px 55px;
            font-weight: 400;
            color: #333333;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center
        }
        .activeStatus {
            background: #ebfefd;
            color: #049c9a;
            box-shadow: 0px 0px 6px 0px rgba(10, 109, 108, 0.25);
            border-radius: 10px;
        }
    }
    .remark-title {
        color: #222222;
        font-family: "SourceHanSansCN-Medium";
        line-height: 14px;
        margin-bottom: 16px;
    }
}
.dialog-footer {
    align-items: center;
    display: flex;
    justify-content: center;
    gap: 20px;
    button {
        width: 150px;
    }
}
</style>
culture/src/views/strainReportLibrary/reportLibraryOne/index.vue
@@ -10,15 +10,15 @@
                <p>2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题。</p>
            </div>
        </el-card>
        <TableCustom :queryForm="queryForm" :total="total" @currentChange="handleCurrentChange"
        <TableCustom :tableData="tableData" :queryForm="queryForm"  :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.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.teamName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告名称:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.reportName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="创建日期:">
                        <el-date-picker v-model="form.date" type="daterange" range-separator="至"
@@ -27,12 +27,23 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></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-form-item label="菌种实验员:">
                        <el-select v-model="form.experimentName" placeholder="请选择" @change="handleExperimentChange">
                            <el-option
                                v-for="item in experimentList"
                                :key="item.id"
                                :label="item.name"
                                :value="item.name">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
                        <el-button type="default" style="margin-right: 10px;">重置</el-button>
                        <el-button type="default" style="margin-right: 10px;" @click="resetForm">重置</el-button>
                        <el-button type="primary">查询</el-button>
                    </el-form-item>
                </el-form>
@@ -41,39 +52,42 @@
                <el-button @click="handleAddProject" class="el-icon-plus" type="primary">
                    新增报告</el-button>
                <div class="table-setting">
                    <div class="table-title">
                    <div class="table-tit" :class="!isDraft&&'table-title'" @click="handleTabChange(false)">
                        报告列表
                    </div>
                    <div class="table-tit">
                    <div class="table-tit" :class="isDraft&&'table-title'" @click="handleTabChange(true)">
                        草稿箱
                    </div>
                </div>
            </template>
            <template #table>
                <el-table-column prop="name" label="所属项目组" />
                <el-table-column prop="age" label="报告编号" />
                <el-table-column prop="age" label="报告名称" />
                <el-table-column prop="age" label="菌种实验员" />
                <el-table-column prop="age" label="创建人" />
                <el-table-column prop="age" label="创建时间" />
                <el-table-column prop="age" label="状态">
                <el-table-column prop="teamName" label="所属项目组" />
                <el-table-column prop="reportCode" label="报告编号" />
                <el-table-column prop="reportName" label="报告名称" />
                <el-table-column prop="experimentName" label="菌种实验员">
                </el-table-column>
                <el-table-column prop="createBy" label="创建人" />
                <el-table-column prop="createTime" label="创建时间" />
                <el-table-column prop="status" label="状态">
                    <template #default="{ row }">
                        <el-tag v-if="row.status == 1" type="success">待审核</el-tag>
                        <el-tag v-else-if="row.status == 0" type="success">已通过</el-tag>
                        <el-tag v-else type="danger">已驳回</el-tag>
                        <el-tag v-if="row.status == 1" type="warning">待审核</el-tag>
                        <el-tag v-else-if="row.status == 2" type="info">待评定</el-tag>
                        <el-tag v-else-if="row.status == 3" type="success">已评定</el-tag>
                        <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag>
                    </template>
                </el-table-column>
                <el-table-column prop="age" label="操作">
                <el-table-column label="操作">
                    <template #default="{ row }">
                        <el-button type="text">审核</el-button>
                        <el-button type="text">详情</el-button>
                        <el-button type="text" @click="handleAudit(row)">审核</el-button>
                        <el-button type="text" @click="handleDetail(row)">详情</el-button>
                    </template>
                </el-table-column>
            </template>
        </TableCustom>
        <Approval :visible="showApproval" @close="showApproval = false" />
        <Evaluate :visible="showEvaluate" @close="showEvaluate = false" />
        <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
        <ShowDelConfirm :title="changeStatusTitle" :tip="changeStatusTip" :show="changeStatus"
            @close="changeStatus = false" @confirm="handleChangeStatusConfirm" />
@@ -82,29 +96,45 @@
<script>
import Approval from './components/approval'
import Evaluate from './components/evaluate'
import { getList } from './service'
export default {
    name: 'ProjectList',
    components: {
        Approval
        Approval,
        Evaluate
    },
    data() {
        return {
            form: {
                name: ''
                teamName: '',
                reportName: '',
                date: [],
                status: '',
                experimentName: ''
            },
            tableData: [],
            showDelConfirm: false,
            rowId: '',
            changeStatus: false,
            showApproval: false,
            showEvaluate: false,
            changeStatusTitle: '',
            changeStatusTip: '',
            queryForm: {
                pageSize: 10,
                pageNum: 1
                pageNum: 1,
            },
            total: 0
            total: 0,
            isDraft: false,
            experimentList: []
        }
    },
    mounted() {
        this.getLists()
        this.getExperimentList()
    },
    methods: {
        handleAddProject() {
@@ -118,7 +148,7 @@
            this.showDelConfirm = false
            this.msgsuccess('删除成功')
            this.rowId = ''
            this.getList()
            this.getLists()
        },
        handleChangeStatus(row, status) {
            this.rowId = row.id
@@ -132,18 +162,71 @@
            this.rowId = ''
            this.changeStatusTitle = ''
            this.changeStatusTip = ''
            this.getList()
            this.getLists()
        },
        handleCurrentChange(page) {
            this.queryForm.pageNum = page
            this.getList()
            this.getLists()
        },
        handleSizeChange(size) {
            this.queryForm.pageSize = size
            this.getList()
            this.getLists()
        },
        getList() {
        handleTabChange(isDraft) {
            this.isDraft = isDraft
            this.form.status = ''
            this.getLists()
        },
        getLists() {
            const params = {
                pageNum: this.queryForm.pageNum,
                pageSize: this.queryForm.pageSize,
                teamName: this.form.teamName,
                reportName: this.form.reportName,
                startTime: this.form.date && this.form.date[0] ? this.form.date[0] : '',
                endTime: this.form.date && this.form.date[1] ? this.form.date[1] : '',
                status: this.form.status,
                isDraft: this.isDraft ? 1 : 0,
                reportType: 1
            }
            getList(params).then(res => {
                if (res.code === 200) {
                    this.total = res.data.total
                    this.tableData = res.data.records
                }
            })
        },
        resetForm() {
            this.form = {
                teamName: '',
                reportName: '',
                date: [],
                status: '',
                experimentName: ''
            }
            this.getLists()
        },
        handleAudit(row) {
            this.showApproval = true
        },
        handleDetail(row) {
            // 这里可以添加查看详情的逻辑
        },
        handleExperimentChange(val) {
            this.getLists()
        },
        handleExperimentEdit(row, val) {
            // 这里可以添加编辑实验员的接口调用
            console.log('编辑实验员', row, val)
        },
        // 获取实验员列表
        getExperimentList() {
            // 这里调用获取实验员列表的接口
            this.experimentList = [
                { id: 1, name: '实验员1' },
                { id: 2, name: '实验员2' },
                { id: 3, name: '实验员3' }
            ]
        }
    }
}
@@ -194,7 +277,6 @@
    border: 1px solid #DCDFE6;
    width: 166px;
    height: 50px;
    background: #FFFFFF;
    border-radius: 8px 8px 0px 0px;
    display: flex;
    align-items: center;
@@ -203,7 +285,7 @@
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
    color: #049C9A;
    color: rgba(96, 98, 102, 1);
    line-height: 27px;
}
culture/src/views/strainReportLibrary/reportLibraryOne/service.js
New file
@@ -0,0 +1,12 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-strain-report/pageListAll', { ...data })
}
export const add = (data) => {
  console.log('qweqwe',data);
  return axios.post('/api/t-strain-report/add', { ...data })
}
culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue
@@ -27,9 +27,9 @@
                        <div>报告编号</div>
                    </div>
                </div>
                <form-item prop="name" style="margin-top: 38px">
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                </form-item>
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
@@ -37,9 +37,9 @@
                        <div>报告名称</div>
                    </div>
                </div>
                <form-item prop="name" style="margin-top: 38px">
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                </form-item>
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
@@ -47,20 +47,87 @@
                        <div>报告正文</div>
                    </div>
                </div>
                <form-item prop="name" style="margin-top: 38px">
                <el-form-item prop="name" style="margin-top: 38px">
                    <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                </form-item>
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>附件</div>
                    </div>
                </div>
                <form-item prop="name" style="margin-top: 38px">
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </form-item>
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>菌种实验员操作评定</div>
                    </div>
                </div>
                <div class="header-title" style="width: 100%;display: flex; align-items: center;">
                    <div class="header-title-left mt-unset">
                        <!-- <img src="@/assets/public/headercard.png" /> -->
                        <div>菌种实验员</div>
                    </div>
                    <div class="header-title-right">
                        <el-button @click="showChoose = true" class="el-icon-circle-plus-outline" type="primary">
                            选择菌种实验员</el-button>
                    </div>
                </div>
                <div class="member-list">
                    <div class="member-list-card">
                        <div class="member-item">
                            <div class="member-title">
                                菌种实验员
                            </div>
                            <div class="member-name-box">
                                <div class="member-name">
                                    张三
                                </div>
                            </div>
                            <div class="member-change">
                                <div class="member-change-btn">修改</div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="table" style="margin-top: 38px">
                    <el-table :data="assessmentTable" border style="width: 100%" :show-summary="true"
                        :span-method="tableSpanMethod" :summary-method="getTableSummary">
                        <el-table-column prop="category" label="菌种实验员专业能力考核项" width="180"></el-table-column>
                        <el-table-column prop="score" label="该项评分" width="120">
                            <template slot-scope="scope">
                                <el-radio-group v-if="scope.row.category !== '5.实验失败'" v-model="scope.row.selectedScore">
                                    <el-radio :label="0">0分</el-radio>
                                    <el-radio :label="1">1分</el-radio>
                                    <el-radio :label="2">2分</el-radio>
                                </el-radio-group>
                                <el-radio-group v-else v-model="scope.row.selectedScore">
                                    <el-radio :label="0">否0分</el-radio>
                                    <el-radio :label="-3">是-3分</el-radio>
                                </el-radio-group>
                            </template>
                        </el-table-column>
                        <el-table-column prop="criteria" label="该项评分参考标准"></el-table-column>
                        <el-table-column prop="desc" label="评分规则说明">
                            <template slot-scope="scope">
                                <p> 【0分】 实验操作失误或实验方案设计无效导致实验失败、数据不可用。</p>
                                <p> 【1分】存在操作有误及实验过程出现问题,没有严格按照操作规程运行;如实验准备不充分,取样遗漏等。</p>
                                <p> 【2分】完整按照操作规程及实验室管理制度运行,无任何问题。</p>
                            </template>
                        </el-table-column>
                        <el-table-column prop="rule" label="考评规则">
                            <template slot-scope="scope">
                                菌种工程师以分题内容考核菌种实验员。
                            </template>
                        </el-table-column>
                    </el-table>
                </div>
                <div class="end-btn" style="margin-top: 38px">
                    <el-button type="primary">发送</el-button>
@@ -74,6 +141,7 @@
<script>
import { Card } from 'element-ui';
import AiEditor from '@/components/AiEditor'
export default {
    components: { AiEditor },
    data() {
@@ -97,14 +165,88 @@
            remark: "",
            queryForm: {
            }
            },
            assessmentTable: [
                {
                    category: '1.该分题的菌种专业知识',
                    selectedScore: 0,
                    criteria: '1.1 能讲生物学基础,掌握各类微生物形态特性、生化特性及鉴定方法。1.2 菌种选育技术,了解掌握自然选育、诱变选育、基因工程育种。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '2.操作能力',
                    selectedScore: 0,
                    criteria: '1.菌种分离无菌操作规范 2.菌种培养无菌操作规范 3.菌种保存无菌操作规范 4.菌种鉴定无菌操作规范',
                    desc: '',
                    rule: ''
                },
                {
                    category: '3.仪器设备使用',
                    selectedScore: 0,
                    criteria: '能正确使用实验仪器,如移液器、恒温箱等,操作规范。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '4.实验数据记录与分析',
                    selectedScore: 0,
                    criteria: '实验数据记录及时、准确、完整,能简单分析数据。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '5.实验失败',
                    selectedScore: 0,
                    criteria: '无论何种原因,本次实验失败。',
                    desc: '',
                    rule: ''
                }
            ],
        }
    }
    },
    computed: {
        totalScore() {
            return this.assessmentTable.reduce((sum, row) => sum + Number(row.selectedScore), 0)
        }
    },
    methods: {
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则说明(desc)和考评规则(rule)列合并所有行
            // desc列索引为3,rule列索引为4(从0开始)
            if (columnIndex === 3 || columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.assessmentTable.length, 1]; // 合并所有行
                } else {
                    return [0, 0]; // 其他行隐藏
                }
            }
            return [1, 1];
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 1) {
                    sums[index] =this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
    },
}
</script>
<style lang="less" scoped>
.mt-unset {
    margin-top: unset !important;
}
.header-title {
    display: flex;
    align-items: center;
@@ -159,15 +301,102 @@
    }
}
.end-btn{
.end-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    button{
    button {
        width: 180px;
        height: 36px;
        // background: #409EFF; 
    }
}
.member-list {
    margin-top: 18px;
    display: flex;
    flex-wrap: wrap;
    gap: 28px;
    .member-list-card {
        width: 340px;
        height: 400px;
        border-radius: 8px;
        border: 1px solid #dcdfe6;
        background: linear-gradient(to bottom,
                rgba(5, 160, 193, 0.2) 0%,
                rgba(5, 242, 194, 0) 70%);
        .member-item {
            height: 100%;
            display: flex;
            flex-direction: column;
            .member-title {
                margin-top: 20px;
                width: 100%;
                font-family: "Source Han Sans CN Bold Bold";
                font-weight: bold;
                font-size: 16px;
                color: rgba(0, 0, 0, 0.8);
                line-height: 16px;
                text-align: center;
            }
            .flex1 {
                flex: 1;
            }
            .member-name-box {
                flex: 1;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .member-name-box-2 {
                flex: 1;
                padding: 0 20px;
                padding-top: 40px;
                display: grid;
                grid-template-columns: repeat(4, 1fr);
                gap: 20px;
                justify-items: center;
                align-items: start;
            }
            .member-name {
                width: 60px;
                height: 60px;
                background: #7d8b79;
                border-radius: 50%;
                text-align: center;
                line-height: 60px;
                font-weight: 500;
                font-size: 16px;
                color: #ffffff;
                margin: 0;
            }
            .member-change {
                display: flex;
                justify-content: center;
                padding: 10px 0;
                margin-top: auto;
                cursor: pointer;
                .member-change-btn {
                    background: #fff1f0;
                    border-radius: 4px;
                    border: 1px solid #ffccc7;
                    padding: 1px 8px;
                    font-weight: 400;
                    font-size: 12px;
                    color: #ff4d4f;
                }
            }
        }
    }
}
</style>
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog :title="dialogTitle"  :visible.sync="visible" width="80%" po :close-on-click-modal="false"
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
        @close="handleClose">
        <div class="approval-dialog">
        <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
            <!-- 左侧审批内容 -->
            <div class="approval-content">
                <Card class="approval-content-card">
@@ -12,13 +12,12 @@
                                <div>所属项目组</div>
                            </div>
                        </div>
                        <Table :height="null" :queryForm="queryForm" :total="0" @currentChange="handleCurrentChange"
                            @sizeChange="handleSizeChange">
                        <Table :height="null" :total="0" :data="tableData">
                            <template>
                                <el-table-column prop="name" label="项目组名称" />
                                <el-table-column prop="age" label="项目负责人" />
                                <el-table-column prop="age" label="项目组成员" />
                                <el-table-column prop="age" label="创建时间" />
                                <el-table-column prop="teamName" label="项目组名称" />
                                <el-table-column prop="personCharge" label="项目负责人" />
                                <el-table-column prop="staffName" label="项目组成员" />
                                <el-table-column prop="createTime" label="创建时间" />
                            </template>
                        </Table>
@@ -31,9 +30,10 @@
                                    <div>报告编号</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportCode" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                    placeholder="请输入报告编号" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -41,9 +41,10 @@
                                    <div>报告名称</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportName" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportName" style="width: 100%;"
                                    placeholder="请输入报告名称" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -51,9 +52,53 @@
                                    <div>报告正文</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportText" style="margin-top: 38px">
                                <ai-editor :readOnly="true" :value="form.reportText" style="width: 100%;"
                                    placeholder="请输入报告正文" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
                                    <img src="@/assets/public/headercard.png" />
                                    <div>菌种实验员操作评定</div>
                                </div>
                            </div>
                            <div class="table" style="margin-top: 38px">
                                <el-table :data="assessmentTable" border style="width: 100%" :show-summary="true"
                                    :span-method="tableSpanMethod" :summary-method="getTableSummary">
                                    <el-table-column prop="category" label="菌种实验员专业能力考核项" width="180"></el-table-column>
                                    <el-table-column prop="score" label="该项评分" width="120">
                                        <template slot-scope="scope">
                                            <el-radio-group v-if="scope.row.category !== '5.实验失败'"
                                                v-model="scope.row.selectedScore">
                                                <el-radio :label="0">0分</el-radio>
                                                <el-radio :label="1">1分</el-radio>
                                                <el-radio :label="2">2分</el-radio>
                                            </el-radio-group>
                                            <el-radio-group v-else v-model="scope.row.selectedScore">
                                                <el-radio :label="0">否0分</el-radio>
                                                <el-radio :label="-3">是-3分</el-radio>
                                            </el-radio-group>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="criteria" label="该项评分参考标准"></el-table-column>
                                    <el-table-column prop="desc" label="评分规则说明">
                                        <template slot-scope="scope">
                                            <p> 【0分】 实验操作失误或实验方案设计无效导致实验失败、数据不可用。</p>
                                            <p> 【1分】存在操作有误及实验过程出现问题,没有严格按照操作规程运行;如实验准备不充分,取样遗漏等。</p>
                                            <p> 【2分】完整按照操作规程及实验室管理制度运行,无任何问题。</p>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="rule" label="考评规则">
                                        <template slot-scope="scope">
                                            菌种工程师以分题内容考核菌种实验员。
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </div>
                        </el-form>
                    </template>
@@ -63,21 +108,20 @@
            <!-- 右侧审批流程 -->
            <div class="approval-flow">
                <div class="flow-content">
                    <approval-process :status="form.status" :submit-time="form.createTime" :approver="form.approver"
                        :approve-time="form.approveTime" />
                    <approval-process :processData="form.processData" />
                </div>
            </div>
        </div>
        <div class="approval-dialog-approve">
        <div class="approval-dialog-approve" v-if="!obj.isDetail">
            <el-row :span="24">
                <el-col :span="12">
                    <div class="status">
                        <div class="status-title">审批结果</div>
                        <div class="status-content">
                            <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1">
                            <div class="resolve" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                                通过
                            </div>
                            <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                            <div class="reject" :class="status == '3' && 'activeStatus'" @click.stop="status = 3">
                                驳回
                            </div>
                        </div>
@@ -94,8 +138,8 @@
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="handleClose" >取 消</el-button>
            <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">通过</el-button>
            <el-button @click="handleClose">{{ obj.isDetail ? '关闭' : '取 消' }}</el-button>
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
        </div>
    </el-dialog>
</template>
@@ -103,6 +147,8 @@
<script>
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
// import { getDetail } from '../../service';
export default {
    name: "ApprovalDialog",
@@ -119,27 +165,74 @@
            type: String,
            default: "approve", // approve-审批,view-查看
        },
        data: {
        obj: {
            type: Object,
            default: () => ({}),
            default: () => {
                return {
                    isDetail: false
                }
            },
        },
    },
    data() {
        return {
            form: {
                planName: "",
                planCode: "",
                stage: "",
                creator: "",
                reportCode: "",
                reportName: "",
                reportText: "",
                teamName: "",
                createBy: "",
                createTime: "",
                status: "",
                approvalComment: "",
                status: "pending",
                approver: "",
                approveTime: ""
                approveTime: "",
                processData: [],
                updateBy: "",
                auditRemark: "",
                auditPersonName: "",
                auditTime: ""
            },
            radio1: 1,
            assessmentTable: [
                {
                    category: '1.该分题的菌种专业知识',
                    selectedScore: 0,
                    criteria: '1.1 能讲生物学基础,掌握各类微生物形态特性、生化特性及鉴定方法。1.2 菌种选育技术,了解掌握自然选育、诱变选育、基因工程育种。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '2.操作能力',
                    selectedScore: 0,
                    criteria: '1.菌种分离无菌操作规范 2.菌种培养无菌操作规范 3.菌种保存无菌操作规范 4.菌种鉴定无菌操作规范',
                    desc: '',
                    rule: ''
                },
                {
                    category: '3.仪器设备使用',
                    selectedScore: 0,
                    criteria: '能正确使用实验仪器,如移液器、恒温箱等,操作规范。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '4.实验数据记录与分析',
                    selectedScore: 0,
                    criteria: '实验数据记录及时、准确、完整,能简单分析数据。',
                    desc: '',
                    rule: ''
                },
                {
                    category: '5.实验失败',
                    selectedScore: 0,
                    criteria: '无论何种原因,本次实验失败。',
                    desc: '',
                    rule: ''
                }
            ],
            tableData: [],
            rules: {},
            status: "1",
            status: "2",
            remark: "",
        };
    },
@@ -147,41 +240,131 @@
        dialogTitle() {
            return this.type === "approve" ? "审批" : "审批详情";
        },
    },
    watch: {
        data: {
            handler(val) {
                if (val) {
                    this.form = { ...val };
                }
            },
            immediate: true,
        },
        totalScore() {
            return this.assessmentTable.reduce((sum, item) => sum + (item.selectedScore || 0), 0);
        }
    },
    methods: {
        open() {
            if (!this.obj.id) {
                this.$message.error('缺少必要参数');
                return;
            }
            // getDetail(this.obj.id).then(res => {
            //     const data = res.data || res;
            //     this.form = {
            //         ...this.form,
            //         ...data,
            //         processData: []
            //     };
            //     this.tableData = data.projectTeam ?
            //         [{ ...data.projectTeam, staffName: data.staffNames || '' }] :
            //         [];
            //     let processData = [];
            //     // 提交节点
            //     processData.push({
            //         type: "primary",
            //         mode: "list",
            //         fields: [
            //             { label: "提交人:", value: data.updateBy || "" },
            //             { label: "提交时间:", value: data.createTime || "" },
            //         ]
            //     });
            //     if (data.status == 2 || data.status == 3) {
            //         processData.push({
            //             type: data.status === 2 ? "primary" : "danger",
            //             mode: "list",
            //             fields: [
            //                 { label: "审批意见:", value: data.auditRemark || "" },
            //                 { label: "审核人:", value: data.auditPersonName || "" },
            //                 { label: "审核时间:", value: data.auditTime || "" },
            //             ]
            //         });
            //     } else {
            //         processData.push({
            //             type: "warning",
            //             mode: "list",
            //             fields: [
            //                 { label: "等待审核" },
            //             ],
            //         });
            //     }
            //     if (data.status == 2) {
            //         processData.push({
            //             type: "warning",
            //             mode: "list",
            //             fields: [{ label: "等待评定" }],
            //         });
            //     }
            //     if (data.status == 3) {
            //         processData.push({
            //             type: "success",
            //             mode: "list",
            //             fields: [
            //                 { label: "已评定" },
            //                 { label: "评定人:", value: data.evaluatePersonName || "" },
            //                 { label: "评定时间:", value: data.evaluateTime || "" }
            //             ],
            //         });
            //     }
            //     this.form.processData = processData;
            // }).catch(err => {
            //     this.$message.error('获取详情失败');
            // });
        },
        handleClose() {
            this.$emit("close");
            this.form.approvalComment = "";
        },
        handleApprove() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则说明(desc)和考评规则(rule)列合并所有行
            // desc列索引为3,rule列索引为4(从0开始)
            if (columnIndex === 3 || columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.assessmentTable.length, 1]; // 合并所有行
                } else {
                    return [0, 0]; // 其他行隐藏
                }
            }
            return [1, 1];
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 1) {
                    sums[index] =this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        handleApprove() {
            this.$emit("approve", {
                ...this.form,
                status: "approved",
                statuss: this.status,
                remark: this.remark
            });
        },
        handleReject() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("reject", {
                ...this.form,
                status: "rejected",
            });
        handleCurrentChange(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.form.pageSize = size
            this.getList()
        },
    },
};
@@ -211,7 +394,7 @@
        background: #ffffff;
        box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
        border-radius: 10px;
        .flow-title {
            font-size: 16px;
            font-weight: bold;
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/choiceMethod/index.vue
New file
@@ -0,0 +1,114 @@
<template>
  <el-dialog
    :visible.sync="visible"
    width="600px"
    title="菌种报告评定"
    class="choice-method-dialog"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <div class="choice-method-content">
      <div class="choice-method-title">请选择评定标准:</div>
      <div class="choice-method-btns">
        <div
          class="choice-btn"
          :class="{ active: selected === 'innovate' }"
          @click="selected = 'innovate'"
        >
          创新型课题评定标准
        </div>
        <div
          class="choice-btn"
          :class="{ active: selected === 'regular' }"
          @click="selected = 'regular'"
        >
          规程型课题评定标准
        </div>
      </div>
      <div class="choice-method-footer">
        <el-button type="primary" :disabled="!selected" @click="handleNext">下一步</el-button>
      </div>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: "ChoiceMethodDialog",
  props: {
    visible: Boolean
  },
  data() {
    return {
      selected: null
    };
  },
  methods: {
    handleClose() {
      this.$emit("close");
    },
    handleNext() {
      this.$emit("next", this.selected);
    }
  }
};
</script>
<style scoped lang="less">
.choice-method-dialog {
  ::v-deep .el-dialog__header {
    border-bottom: 1px solid #e4e7ed;
  }
}
.choice-method-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 300px;
  justify-content: center;
}
.choice-method-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 32px;
  color: #222;
}
.choice-method-btns {
  display: flex;
  gap: 40px;
  margin-bottom: 40px;
  .choice-btn {
    width: 260px;
    height: 120px;
    background: #04796b;
    color: #fff;
    font-size: 22px;
    font-weight: bold;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0.85;
    transition: all 0.2s;
    &.active, &:hover {
    background: linear-gradient(to bottom, #0ACBCA 0%, #049C9A 100%);
      opacity: 1;
      box-shadow: 0 0 12px 0 rgba(0,150,136,0.18);
    }
  }
}
.choice-method-footer {
  display: flex;
  justify-content: center;
  width: 100%;
  .el-button {
    width: 220px;
    height: 48px;
    font-size: 20px;
    border-radius: 8px;
  }
}
</style>
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/evaluate/index.vue
New file
@@ -0,0 +1,371 @@
<template>
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" :close-on-click-modal="false"
        @close="handleClose">
        <div class="evaluate-dialog-layout">
            <!-- 左侧评分规则说明 -->
            <div class="evaluate-rule-panel">
                <div class="rule-title">设立课题规则</div>
                <div class="rule-content">
                    <ol>
                        <li>根据可研报告、产品构思设计的工艺研究路线,一条工艺路线设立一个课题。如果一个课题中有多个化合物需要开发研究,则每个化合物作为一个分题;分题归集到该课题中,最终形成课题报告。不同课题报告中的分题不能重复使用
                        </li>
                        <li>在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题。</li>
                    </ol>
                </div>
            </div>
            <!-- 右侧评定表及表单 -->
            <div class="evaluate-main-panel">
                <el-form ref="form" :model="form" :rules="rules" label-position="top" class="evaluate-form">
                    <div style="display: flex;">
                        <div>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
                                    <img src="@/assets/public/headercard.png" />
                                    <div>报告编号</div>
                                </div>
                            </div>
                            <el-form-item prop="reportCode">
                                <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                    placeholder="请输入报告编号" />
                            </el-form-item>
                        </div>
                        <div style="margin-left: 100px;">
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
                                    <img src="@/assets/public/headercard.png" />
                                    <div>报告名称</div>
                                </div>
                            </div>
                            <el-form-item prop="reportName">
                                <el-input disabled v-model="form.reportName" style="width: 100%;"
                                    placeholder="请输入报告名称" />
                            </el-form-item>
                        </div>
                    </div>
                    <el-table :data="currentAssessmentTable" border style="width: 100%; margin-top: 20px;" :show-summary="true"
                        :summary-method="getTableSummary" :span-method="tableSpanMethod">
                        <el-table-column prop="index" label="序号" width="60">
                            <template slot-scope="scope">{{ scope.row.index }}</template>
                        </el-table-column>
                        <el-table-column prop="standard" :label="type == 1 || type == '1' ? '规程型课题评定标准' : '创新型课题评定标准'">
                            <template slot-scope="scope">{{ scope.row.standard }}</template>
                        </el-table-column>
                        <el-table-column prop="fullScore" label="满分值" width="80">
                            <template slot-scope="scope">{{ scope.row.fullScore }}</template>
                        </el-table-column>
                        <el-table-column prop="selectedScore" label="评定分值" width="120">
                            <template slot-scope="scope">
                                <el-input v-model.number="scope.row.selectedScore" :max="scope.row.fullScore" :min="0"
                                    type="number" placeholder="请输入" />
                            </template>
                        </el-table-column>
                        <el-table-column prop="rule" :label="type == 1 || type == '1' ? '规程型课题报告评分规则' : '创新型课题报告评分规则'">
                            <template slot-scope="scope">
                                <span v-if="scope.$index === 0 && (type == 1 || type == '1')">
                                    1. 规程型课题评定总分的满分为5分。<br>
                                    2. 某分项工作完成,但出现以下三种错误中的1种,则减1分:<br>
                                    ①有缺项、漏项;②或不完整衔接;③或工作被多人拖延。<br>
                                    3. 不能完成该分项的全部工作,或课题不涉及该分项内容,则该分项评0分。
                                </span>
                                <span v-if="scope.$index === 0 && (type == 2 || type == '2')">
                                    1. 各分项评满分,应满足以下四项要求:<br>
                                    ①分项内容:清晰、系统、完整,结构逻辑清晰,无缺项;<br>
                                    ②团队工作运行顺畅,计划时间高效。<br>
                                    ③工作结果完成度高。<br>
                                    ④课题文档报告完成度高。<br>
                                    2. 某分项工作完成,但出现以下三种错误中的1种,则减1分:<br>
                                    ①有缺项、漏项;<br>
                                    ②或不完整衔接;<br>
                                    ③或工作被多人拖延。<br>
                                    3. 某分项工作基本完成,但出现三种错误中的2-3种,则减2分:<br>
                                    ①有缺项、漏项;<br>
                                    ②或不完整衔接;<br>
                                    ③或工作被多人拖延。<br>
                                    4. 不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。
                                </span>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-form>
            </div>
        </div>
        <div class="evaluate-footer-btns">
            <el-button @click="$emit('back')">返回上一步</el-button>
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">提交评定结果</el-button>
        </div>
    </el-dialog>
</template>
<script>
export default {
    name: "ApprovalDialog",
    props: {
        visible: {
            type: Boolean,
            default: false,
        },
        type: {
            type: String,
            default: () => '2',
        },
        obj: {
            type: Object,
            default: () => ({ isDetail: false }),
        },
    },
    data() {
        return {
            form: {
                reportCode: "",
                reportName: "",
            },
            assessmentTable1: [
                {
                    index: 1,
                    standard: '文献资料调查:全面性,系统性,编撰逻辑清晰,表达规范',
                    fullScore: 1,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 2,
                    standard: '专业/技术路线与方法:合理性、可行性;实验设计科学,能实现研究目标,方法先进、完整、可靠;',
                    fullScore: 2,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 3,
                    standard: '课题报告完成度高,预期研究结果是否具有技术价值的应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。',
                    fullScore: 3,
                    selectedScore: 0,
                    rule: ''
                }
            ],
            assessmentTable2: [
                {
                    index: 1,
                    standard: '课题各标准性,报告的逻辑性:研究目标是否清晰、具体;研究工作内容合理性,是否围绕目标展开,是否具有结构性和系统性。',
                    fullScore: 3,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 2,
                    standard: '文献资料调查:全面性,系统性编辑逻辑清晰,表达规范',
                    fullScore: 2,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 3,
                    standard: '专业/技术路线与方法:合理性、可行性;实验设计科学,能实现研究目标,方法先进、完整、可靠;',
                    fullScore: 3,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 4,
                    standard: '实验过程组织性:团队工作运行顺畅,计划时间高效,样本准备的条件良好,实验进度高效,实验结果完成度高。',
                    fullScore: 2,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 5,
                    standard: '实验结果分析:实验科学规范,逻辑严密,过程完整无误。不存在无用流程,具有实际应用价值,结果的实际效果可对比分析。',
                    fullScore: 3,
                    selectedScore: 0,
                    rule: ''
                },
                {
                    index: 6,
                    standard: '课题报告完成度高,预期研究结果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险,市场风险和管理风险。',
                    fullScore: 2,
                    selectedScore: 0,
                    rule: ''
                }
            ],
            rules: {},
        };
    },
    computed: {
        currentAssessmentTable() {
            return this.type == 1 || this.type == '1' ? this.assessmentTable1 : this.assessmentTable2;
        },
        fullScore() {
            return this.type == 1 || this.type == '1'
                ? this.assessmentTable1.reduce((sum, item) => sum + (item.fullScore || 0), 0)
                : this.assessmentTable2.reduce((sum, item) => sum + (item.fullScore || 0), 0);
        },
        totalScore() {
            return this.currentAssessmentTable.reduce((sum, item) => sum + (item.selectedScore || 0), 0);
        },
        dialogTitle() {
            return this.type === "approve" ? "检测项评定" : "检测项评定详情";
        }
    },
    methods: {
        open() { },
        handleClose() {
            this.$emit("close");
        },
        getTableSummary(param) {
            const { columns } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                } else if (index === 2) {
                    sums[index] = this.fullScore + '分';
                } else if (index === 3) {
                    sums[index] = this.totalScore + '分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        handleApprove() {
            this.$emit("approve", {
                ...this.form,
                assessmentTable: this.currentAssessmentTable,
                totalScore: this.totalScore
            });
        },
        tableSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 评分规则列合并所有行
            if (columnIndex === 4) {
                if (rowIndex === 0) {
                    return [this.currentAssessmentTable.length, 1];
                } else {
                    return [0, 0];
                }
            }
            return [1, 1];
        },
    },
};
</script>
<style scoped lang="less">
.evaluate-dialog-layout {
    display: flex;
    flex-direction: row;
    min-height: 390px;
    height: 100%;
    align-items: stretch;
}
.evaluate-rule-panel {
    width: 200px;
    background: #fff;
    border-radius: 8px;
    padding: 24px 24px 0 24px;
    margin-right: 24px;
    font-size: 14px;
    color: #333;
    box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.06);
    border: 1px solid #ebeef5;
    display: flex;
    flex-direction: column;
    min-height: 373px;
    padding-top: 24px;
    .rule-title {
        font-weight: bold;
        font-size: 16px;
        margin-bottom: 10px;
        color: #222;
    }
    .rule-content {
        margin-bottom: 16px;
        line-height: 1.8;
        color: #444;
    }
    ol {
        padding-left: 18px;
        margin: 0;
    }
    li {
        margin-bottom: 8px;
    }
}
.evaluate-main-panel {
    flex: 1;
    background: #fff;
    border-radius: 8px;
    padding: 24px 24px 0 24px;
    display: flex;
    flex-direction: column;
    height: 100%;
    .evaluate-form {
        margin-bottom: 0;
        flex: 1;
        display: flex;
        flex-direction: column;
    }
}
.evaluate-footer-btns {
    display: flex;
    justify-content: center;
    gap: 20px;
    margin: 32px 0 18px 0;
}
.header-title {
    // display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 20px;
    gap: 13px;
    .header-title-left {
        display: flex;
        align-items: center;
        gap: 13px;
        // margin-top: 38px;
        img {
            width: 12px;
            height: 19px;
        }
        div {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
            &:before {
                content: "*";
                color: #f56c6c;
                margin-right: 4px;
            }
        }
        span {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
        }
    }
    .header-title-left :first-child {
        margin-top: 0;
    }
}
</style>
culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue
@@ -20,9 +20,6 @@
                    <el-form-item label="报告名称:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告编号:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="创建日期:">
                        <el-date-picker v-model="form.date" type="daterange" range-separator="至"
                            start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
@@ -42,10 +39,10 @@
            </template>
            <template #setting>
                <el-button @click="handleAddProject" class="el-icon-plus" type="primary">
                    新增可研报告</el-button>
                    新增报告</el-button>
                <div class="table-setting">
                    <div class="table-title">
                        可研报告库
                        报告列表
                    </div>
                    <div class="table-tit">
                        草稿箱
@@ -57,6 +54,7 @@
                <el-table-column prop="name" label="所属项目组" />
                <el-table-column prop="age" label="报告编号" />
                <el-table-column prop="age" label="报告名称" />
                <el-table-column prop="age" label="菌种实验员" />
                <el-table-column prop="age" label="创建人" />
                <el-table-column prop="age" label="创建时间" />
                <el-table-column prop="age" label="状态">
@@ -76,6 +74,8 @@
        </TableCustom>
        <Approval :visible="showApproval" @close="showApproval = false" />
        <Evaluate :visible="showEvaluate" @close="showEvaluate = false" />
        <ChoiceMethod :visible="showChoiceMethod" @close="showChoiceMethod = false" />
        <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
        <ShowDelConfirm :title="changeStatusTitle" :tip="changeStatusTip" :show="changeStatus"
            @close="changeStatus = false" @confirm="handleChangeStatusConfirm" />
@@ -84,11 +84,15 @@
<script>
import Approval from './components/approval'
import Evaluate from './components/evaluate'
import ChoiceMethod from './components/choiceMethod'
export default {
    name: 'ProjectList',
    components: {
        Approval
        Approval,
        Evaluate,
        ChoiceMethod
    },
    data() {
        return {
@@ -99,6 +103,8 @@
            rowId: '',
            changeStatus: false,
            showApproval: false,
            showEvaluate: false,
            showChoiceMethod: false,
            changeStatusTitle: '',
            changeStatusTip: '',
            queryForm: {
@@ -110,7 +116,7 @@
    },
    methods: {
        handleAddProject() {
            this.$router.push('/reportLibrary/add')
            this.$router.push('/strainReportLibrary/add')
        },
        handleDel(row) {
            this.rowId = row.id
laboratory/src/views/projectList/editProject.vue
@@ -44,10 +44,13 @@
    name: 'EddProject',
    data() {
        return {
            form: {},
            form: {
                teamName: '',
                personCharge: ''
            },
            rules: {
                teamName: [{ required: true, message: '请输入项目组名称', trigger: 'blur' }],
                personCharge: [{ required: true, message: '请输入项目组描述', trigger: 'blur' }]
                personCharge: [{ required: true, message: '请输入项目组负责人', trigger: 'blur' }]
            },
            selectMemberData: [],
            // 角色配置常量
@@ -95,7 +98,7 @@
                    }
                    editProject(data).then(res => {
                        if (res.code == 200) {
                            this.$message.success('添加成功')
                            this.$message.success('修改成功')
                            this.$router.push({ name: 'ProjectList' })
                        }
                    })
@@ -120,21 +123,10 @@
            }
        },
        selectUser(data) {
            for (const [roleId, config] of Object.entries(this.ROLE_CONFIG)) {
                const members = data.filter(item => item.roleName === config.label);
                if (members.length > config.limit) {
                    this.$message.error(`${config.label}最多只能选择${config.limit}个`);
                    return
                }
            }
            this.selectMemberData = data;
            this.$refs.selectMember.close();
        },
        editUserList() {
            this.$refs.selectMember.open();
            this.$nextTick(() => {
                this.$refs.selectMember.setSelection(this.selectMemberData);
            });
            this.$refs.selectMember.open(this.selectMemberData);
        }
    }
}