董国庆
2026-04-28 9dcad0c65f2564fc2fe43e21b23f9faf4a073d30
fix: 修复多个页面样式、交互及路由问题

- 修复表格样式,调整滚动条尺寸和圆角,统一操作列宽度
- 修复路由跳转逻辑,为详情页添加独立路由,避免参数传递错误
- 修复图片/文件上传组件,支持多种图片格式,优化错误处理和上传队列
- 修复评估组件数据解析逻辑,确保类型变化时正确重置
- 修复原始记录详情页文件路径处理,统一URL前缀
- 修复选择项目组件单选逻辑,优化高亮样式
- 修复多个页面标题和按钮文字,统一为“实验方案列表”等
- 修复审批撤销提示文字,明确影响范围
21个文件已修改
852 ■■■■■ 已修改文件
laboratory/src/App.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/DynamicComponent/addTableData.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/DynamicComponent/index.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/EvaluateTable/index.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/chooseProject/index.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/router/index.js 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/styles/element-variables.less 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/pilotAndProduction/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/projectTesting/add.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/chemistQa/projectTesting/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/dispatching/list.vue 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/components/addDialog.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/detail.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/addSample.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/list.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/schemeManagement/list.vue 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/testResultReport/components/evaluation-dialog.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/testResultReport/detail.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/testResultReport/list.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/deliveryAssessment/testerWorkerEvaluate/add.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/deliveryAssessment/testerWorkerEvaluate/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/App.vue
@@ -59,18 +59,18 @@
.table-container {
  ::-webkit-scrollbar {
    display: block !important;
    width: 6px;
    height: 6px;
    width: 10px;
    height: 10px;
  }
  ::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
    border-radius: 5px;
  }
  ::-webkit-scrollbar-thumb {
    background: #009688;
    border-radius: 3px;
    border-radius: 5px;
  }
  ::-webkit-scrollbar-thumb:hover {
laboratory/src/components/DynamicComponent/addTableData.vue
@@ -94,8 +94,13 @@
                      (res, file, fileList) =>
                        handleImageSuccess(res, file, fileList, header.name)
                    "
                    :on-error="
                      (err, file, fileList) =>
                        handleImageError(err, file, fileList, header.name)
                    "
                    :on-preview="handlePreview"
                    :disabled="!checkEditPermission(header)"
                    accept="image/*"
                    multiple
                  >
                    <div
@@ -107,7 +112,7 @@
                    >
                      <i class="el-icon-plus"></i>
                    </div>
                    <div slot="tip" class="el-upload__tip">只支持.jpg格式</div>
                    <div slot="tip" class="el-upload__tip">支持任意图片格式上传</div>
                  </el-upload>
                </el-form-item>
                <el-form-item
@@ -304,6 +309,17 @@
    },
  },
  methods: {
    removeUploadItem(fileList, file) {
      const list = Array.isArray(fileList) ? fileList : [];
      const nextList = list.filter((item) => item.uid !== file.uid);
      const removeIndex = list.findIndex((item) => item.uid === file.uid);
      if (removeIndex > -1) {
        list.splice(removeIndex, 1);
      }
      return nextList;
    },
    getUserOptions() {
      listByRole()
        .then((res) => {
@@ -503,11 +519,12 @@
      });
    },
    beforeImageUpload(file) {
      const isJPG = file.type === "image/jpeg";
      // const isLt2M = file.size / 1024 / 1024 < 2;
      const isImage =
        (file.type && file.type.startsWith("image/")) ||
        /\.(png|jpe?g|gif|bmp|webp|svg|ico|tiff?)$/i.test(file.name || "");
      if (!isJPG) {
        this.$message.error("上传图片只能是 JPG 格式!");
      if (!isImage) {
        this.$message.error("只能上传图片类型文件");
        return false;
      }
      return true;
@@ -518,6 +535,25 @@
      this.$refs.form && this.$refs.form.validateField(fieldName);
    },
    handleImageSuccess(res, file, fileList, fieldName) {
      if (!res || (res.code !== 200 && res.code !== "200") || !res.msg) {
        const errorMessage =
          (res && (res.msg || res.message)) || "图片上传失败";
        this.$message.error(errorMessage);
        file.status = "fail";
        file.url = "";
        const successFileList = this.removeUploadItem(fileList, file);
        this.$set(this.imageListMap, fieldName, successFileList);
        this.$set(
          this.form,
          fieldName,
          successFileList.map((f) =>
            f.url ? (f.url.startsWith("http") ? f.url : getFullUrl(f.url)) : ""
          )
        );
        this.$refs.form && this.$refs.form.validateField(fieldName);
        return;
      }
      const url = res.msg;
      file.url = getFullUrl(url);
      if (!Array.isArray(this.form[fieldName])) {
@@ -534,6 +570,43 @@
      this.$set(this.imageListMap, fieldName, fileList);
      this.$refs.form && this.$refs.form.validateField(fieldName);
    },
    handleImageError(err, file, fileList, fieldName) {
      let errorMessage = "图片上传失败";
      const rawMessage =
        (err &&
          (err.message ||
            err.response ||
            err.responseText ||
            (err.target && err.target.response))) ||
        "";
      if (typeof rawMessage === "string" && rawMessage) {
        try {
          const parsedMessage = JSON.parse(rawMessage);
          errorMessage =
            parsedMessage.msg || parsedMessage.message || errorMessage;
        } catch (e) {
          errorMessage = rawMessage;
        }
      }
      this.$message.error(errorMessage);
      file.status = "fail";
      file.url = "";
      const validFileList = this.removeUploadItem(
        (fileList || []).filter((item) => item.status !== "fail"),
        file
      );
      this.$set(this.imageListMap, fieldName, validFileList);
      this.$set(
        this.form,
        fieldName,
        validFileList.map((f) =>
          f.url ? (f.url.startsWith("http") ? f.url : getFullUrl(f.url)) : ""
        )
      );
      this.$refs.form && this.$refs.form.validateField(fieldName);
    },
    handleImageRemove(file, fileList, fieldName) {
      this.$set(
        this.form,
laboratory/src/components/DynamicComponent/index.vue
@@ -128,6 +128,10 @@
              (res, file, fileList) =>
                handleFileSuccess(res, file, fileList, idx)
            "
            :on-error="
              (err, file, fileList) =>
                handleFileError(err, file, fileList, idx)
            "
            list-type="text"
          >
            <el-button size="small" icon="el-icon-upload2">点击上传</el-button>
@@ -159,11 +163,16 @@
                (res, file, fileList) =>
                  handleImageSuccess(res, file, fileList, idx)
              "
            :on-error="
              (err, file, fileList) =>
                handleImageError(err, file, fileList, idx)
            "
              :auto-upload="true"
              :before-upload="beforeImageUpload"
              list-type="picture-card"
              :on-preview="(file) => handlePreview(file, idx)"
              class="image-uploader"
            accept="image/*"
            >
              <i class="el-icon-plus"></i>
              <div class="upload-text">上传图片</div>
@@ -179,7 +188,7 @@
                class="preview-image"
              />
            </div>
            <div class="uploaf-notice">支持.jpg .png格式</div>
            <div class="uploaf-notice">支持任意图片格式上传</div>
          </div>
        </div>
        <img
@@ -340,6 +349,17 @@
  methods: {
    getFullUrl,
    downloadFileByUrl,
    removeUploadItem(fileList, file) {
      const list = Array.isArray(fileList) ? fileList : [];
      const nextList = list.filter((item) => item.uid !== file.uid);
      const removeIndex = list.findIndex((item) => item.uid === file.uid);
      if (removeIndex > -1) {
        list.splice(removeIndex, 1);
      }
      return nextList;
    },
    getUserDisplayText(fieldName, rowData) {
      // 检查是否有对应的userInfo数据
      const userInfoKey = `${fieldName}_userInfo`;
@@ -582,9 +602,52 @@
      this.emitUpdate();
    },
    handleFileSuccess(res, file, fileList, idx) {
      if (!res || (res.code !== 200 && res.code !== "200") || !res.msg) {
        const errorMessage =
          (res && (res.msg || res.message)) || "文件上传失败";
        this.$message.error(errorMessage);
        file.status = "fail";
        file.url = "";
        this.components[idx].data.fileList = this.removeUploadItem(
          fileList,
          file
        );
        this.emitUpdate();
        return;
      }
      // 上传成功后设置真实 url
      file.url = this.getFullUrl(res.msg);
      this.components[idx].data.fileList = fileList;
      this.emitUpdate();
    },
    handleFileError(err, file, fileList, idx) {
      let errorMessage = "文件上传失败";
      const rawMessage =
        (err &&
          (err.message ||
            err.response ||
            err.responseText ||
            (err.target && err.target.response))) ||
        "";
      if (typeof rawMessage === "string" && rawMessage) {
        try {
          const parsedMessage = JSON.parse(rawMessage);
          errorMessage =
            parsedMessage.msg || parsedMessage.message || errorMessage;
        } catch (e) {
          errorMessage = rawMessage;
        }
      }
      this.$message.error(errorMessage);
      file.status = "fail";
      file.url = "";
      this.components[idx].data.fileList = this.removeUploadItem(
        (fileList || []).filter((item) => item.status !== "fail"),
        file
      );
      this.emitUpdate();
    },
    handleImageChange(idx, fileList) {
@@ -594,18 +657,61 @@
      this.emitUpdate();
    },
    handleImageSuccess(res, file, fileList, idx) {
      if (!res || (res.code !== 200 && res.code !== "200") || !res.msg) {
        const errorMessage =
          (res && (res.msg || res.message)) || "图片上传失败";
        this.$message.error(errorMessage);
        file.status = "fail";
        file.url = "";
        this.components[idx].data.imageList = this.removeUploadItem(
          fileList,
          file
        );
        this.emitUpdate();
        return;
      }
      // 上传成功后设置真实 url
      file.url = this.getFullUrl(res.msg);
      this.components[idx].data.imageList = fileList;
      this.emitUpdate();
    },
    beforeImageUpload(file) {
      const isJPG = file.type === "image/jpeg";
      const isPNG = file.type === "image/png";
      // const isLt2M = file.size / 1024 / 1024 < 2;
    handleImageError(err, file, fileList, idx) {
      let errorMessage = "图片上传失败";
      const rawMessage =
        (err &&
          (err.message ||
            err.response ||
            err.responseText ||
            (err.target && err.target.response))) ||
        "";
      if (!isJPG && !isPNG) {
        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
      if (typeof rawMessage === "string" && rawMessage) {
        try {
          const parsedMessage = JSON.parse(rawMessage);
          errorMessage =
            parsedMessage.msg || parsedMessage.message || errorMessage;
        } catch (e) {
          errorMessage = rawMessage;
        }
      }
      this.$message.error(errorMessage);
      file.status = "fail";
      file.url = "";
      this.components[idx].data.imageList = this.removeUploadItem(
        (fileList || []).filter((item) => item.status !== "fail"),
        file
      );
      this.emitUpdate();
    },
    beforeImageUpload(file) {
      const isImage =
        (file.type && file.type.startsWith("image/")) ||
        /\.(png|jpe?g|gif|bmp|webp|svg|ico|tiff?)$/i.test(file.name || "");
      if (!isImage) {
        this.$message.error("只能上传图片类型文件");
        return false;
      }
      // if (!isLt2M) {
laboratory/src/components/EvaluateTable/index.vue
@@ -154,12 +154,25 @@
                if (newVal) {
                    try {
                        const parsedData = JSON.parse(newVal)
                        this.activeIndex = parsedData
                        this.activeIndex = parsedData.map(item => ({
                            num: item.num,
                            score: item.score
                        }))
                    } catch (e) {
                        this.resetData()
                    }
                } else {
                    this.resetData()
                }
            },
            immediate: true
        },
        type: {
            handler() {
                if (!this.viewJson) {
                    this.resetData()
                }
            }
        }
    },
    data() {
@@ -331,4 +344,4 @@
        }
    }
}
</style>
</style>
laboratory/src/components/chooseProject/index.vue
@@ -24,8 +24,9 @@
                <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" /> -->
                        highlight-current-row @row-click="handleRowClick" @select="handleSelect"
                        @selection-change="handleSelectionChange">
                        <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>
@@ -66,12 +67,20 @@
                endTime: '',
                teamName: '',
            },
            selectData: [],
            selectData: null,
            tableData: [],
            total: 0
        }
    },
    methods: {
        setSingleSelection(row) {
            if (!row || !this.$refs.memberTable) {
                return;
            }
            this.$refs.memberTable.clearSelection();
            this.$refs.memberTable.toggleRowSelection(row, true);
            this.selectData = row;
        },
        open() {
            if(this.form.date && this.form.date.length === 2){
                this.form.startTime=this.form.date[0]
@@ -85,9 +94,11 @@
                    this.$nextTick(() => {
                        const row = this.tableData.find(item => item.id === this.selectedData.id)
                        if (row) {
                            this.$refs.memberTable.toggleRowSelection(row, true)
                            this.setSingleSelection(row)
                        }
                    })
                } else {
                    this.selectData = null
                }
            })
        },
@@ -110,11 +121,40 @@
        submitData(){
            this.$emit('submit',this.selectData)
        },
        handleCurrentChange(val) {
            this.selectData = val;
        handleSelectionChange(selection) {
            if (!selection || selection.length === 0) {
                this.selectData = null;
            }
        },
        handleSelect(selection, row) {
            if (!row) {
                return;
            }
            const selectedRow = selection.find((item) => item.id === row.id);
            if (selectedRow) {
                this.setSingleSelection(row);
            } else {
                this.selectData = null;
            }
        },
        handleRowClick(row) {
            if (!row) {
                return;
            }
            if (this.selectData && this.selectData.id === row.id) {
                this.$refs.memberTable.clearSelection();
                this.selectData = null;
                return;
            }
            this.setSingleSelection(row);
        },
    }
}
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
::v-deep .el-table__row.current-row > td,
::v-deep .el-table__row.selection-row > td {
    background: #ebffff !important;
}
</style>
laboratory/src/router/index.js
@@ -317,6 +317,16 @@
                            keepAlive: true,
                        },
                        component: () => import("../views/dataManagement/sampleManage/addSample"),
                    },
                    {
                        path: "detailSample",
                        name: "detailSample",
                        meta: {
                            title: "样品详情",
                            hide: true,
                            keepAlive: true,
                        },
                        component: () => import("../views/dataManagement/sampleManage/addSample"),
                    }, {
                        path: "record",
                        meta: {
@@ -660,6 +670,16 @@
                component: () => import("../views/chemistQa/projectTesting/add.vue"),
            },
            {
                path: "detail",
                name: "DetailProjectTesting",
                meta: {
                    title: "检测项详情",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/chemistQa/projectTesting/add.vue"),
            },
            {
                path: "addDetectionReport",
                meta: {
                    title: "新增报告",
@@ -899,6 +919,17 @@
            },
            {
                // 工艺工程师
                path: "detailTesterWorkerEvaluate",
                name: 'DetailTesterWorkerEvaluate',
                meta: {
                    title: "实验员工作评定详情",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/deliveryAssessment/testerWorkerEvaluate/add"),
            },
            {
                // 工艺工程师
                path: "chemistEvaluate",
                meta: {
                    title: "化验师工作评定",
laboratory/src/styles/element-variables.less
@@ -98,4 +98,10 @@
::selection {
  background: fade(@theme-color, 20%);
}
}
.el-table__cell {
  .cell{
    display: flex;
    justify-content: space-around;
  }
}
laboratory/src/views/chemistQa/pilotAndProduction/index.vue
@@ -33,7 +33,7 @@
                <div class="table-setting">
                    <div class="flex a-center">
                        <div class="table-title" :class="{ active: currentType == 'list' }" @click="handleTypeChange('list')">
                            中试、生产验证试验检验分析报告
                            实验、中试、生产验证试验检验分析报告
                        </div>
                        <div v-if="isChemist" class="table-tit" :class="{ active: currentType == 'draft' }" @click="handleTypeChange('draft')">
                            草稿箱
laboratory/src/views/chemistQa/projectTesting/add.vue
@@ -120,6 +120,7 @@
import chooseProject from '@/components/chooseProject'
import ShowDelConfirm from "@/components/showDelConfirm/index.vue";
import { addData, editData, getDetail,revokedReport,deleteDetail } from './service'
import { mapState } from "vuex";
export default {
  name: "AddProjectTesting",
@@ -133,6 +134,7 @@
            isDetail: false,
            currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱
            expandRowKeys: [],
            allReportTableData: [],
            reportTableData: [],
            reportTotal: 0,
            form: {
@@ -164,35 +166,33 @@
        }
    },
    mounted() {
    const routeName = this.$route.name;
    if (routeName === "EditProjectTesting" && this.$route.query.id) {
      if (this.$route.query.type === 'detail') {
        this.isDetail = true
      } else if (this.$route.query.type === 'edit') {
        this.isEdit = true
      }
      this.getDetail()
    }
    if (this.$route.query.itemId) {
      this.itemId = this.$route.query.itemId
    }
  },
  activated() {
    const routeId = this.$route.query.id;
    const routeName = this.$route.name;
    // 如果是编辑路由,且id发生变化,重新加载数据
    if (routeName === "EditProjectTesting" && routeId && routeId !== this.form.id) {
      if (this.$route.query.type === 'detail') {
        this.isDetail = true
      } else if (this.$route.query.type === 'edit') {
        this.isEdit = true
      }
      this.getDetail()
    }
    // 如果是新增路由,不重置表单,保留用户填写的数据
  },
        this.initPageMode();
        this.initRouteData();
    },
    activated() {
        this.initPageMode();
        this.itemId = this.$route.query.itemId || null;
        const routeId = this.$route.query.id;
        if ((this.isEdit || this.isDetail) && routeId && routeId !== this.form.id) {
            this.getDetail();
        }
    },
    computed: {
        ...mapState(["tagList"])
    },
    methods: {
        initPageMode() {
            const routeName = this.$route.name;
            this.isEdit = routeName === 'EditProjectTesting';
            this.isDetail = routeName === 'DetailProjectTesting';
        },
        initRouteData() {
            this.itemId = this.$route.query.itemId || null;
            if ((this.isEdit || this.isDetail) && this.$route.query.id) {
                this.getDetail();
            }
        },
        getDetail() {
            getDetail(this.$route.query.id).then(res => {
                if (res) {
@@ -220,6 +220,14 @@
            this.$forceUpdate()
            this.showChoose = false
        },
        backToListAndCloseTag() {
            const currentPath = this.$route.path;
            this.$router.push('/chemistQa/projectTesting');
            this.$store.commit(
                "SET_TAGLIST",
                this.tagList.filter((item) => item.path !== currentPath)
            );
        },
        submit() {
            if (this.tableData.length === 0) {
                this.$message.error('请选择项目组')
@@ -236,7 +244,7 @@
                    request.then(res => {
                        if (res.code === 200) {
                            this.$message.success(this.isEdit ? '修改成功' : '提交成功')
                            this.$router.push('/chemistQa/projectTesting')
                            this.backToListAndCloseTag()
                        } else {
                            this.$message.error(res.msg || (this.isEdit ? '修改失败' : '提交失败'))
                        }
@@ -263,7 +271,7 @@
                    request.then(res => {
                        if (res.code === 200) {
                            this.$message.success(this.isEdit ? '修改成功' : '保存成功')
                            this.$router.push('/chemistQa/projectTesting')
                            this.backToListAndCloseTag()
                        } else {
                            this.$message.error(res.msg || (this.isEdit ? '修改失败' : '保存失败'))
                        }
@@ -292,7 +300,7 @@
                path: '/chemistQa/addDetectionReport',
                query: {
                    id: row.id,
                    itemId: this.$route.query.id,
                    itemId: this.form.id || this.$route.query.id,
                    type: 'detail'
                }
            })
@@ -319,7 +327,7 @@
                path: '/chemistQa/addDetectionReport',
                query: {
                    id: row.id,
                    itemId: this.$route.query.id,
                    itemId: this.form.id || this.$route.query.id,
                    type: 'edit'
                }
            })
@@ -536,4 +544,4 @@
        margin-bottom: 20px;
    }
}
</style>
</style>
laboratory/src/views/chemistQa/projectTesting/index.vue
@@ -309,8 +309,7 @@
            this.$router.push({
                path: '/chemistQa/edit',
                query: {
                    id: row.id,
                    type: 'edit'
                    id: row.id
                }
            })
        },
@@ -331,13 +330,11 @@
        },
        handleDetail(row) {
            if (this.isChemist) {
                // 化验师角色使用原有逻辑
                // 化验师角色进入独立详情路由
                this.$router.push({
                    path: '/chemistQa/add',
                    path: '/chemistQa/detail',
                    query: {
                        id: row.id,
                        // itemId: row.itemId,
                        type: 'detail'
                        id: row.id
                    }
                })
            } else {
@@ -491,7 +488,7 @@
            this.currentAction = 'revoke';
            this.confirmType = 'revoke';
            this.confirmTitle = '确认要撤销这条审批吗?';
            this.confirmTip = '撤销后工艺工程师将无法收到此条审批信息';
            this.confirmTip = '撤销后,审批人将无法收到此条审批信息';
            this.showDelConfirm = true;
        },
        handleWithdraw(row) {
@@ -687,4 +684,4 @@
        margin-bottom: 20px;
    }
}
</style>
</style>
laboratory/src/views/dataManagement/dispatching/list.vue
@@ -3,6 +3,7 @@
    <TableCustom :queryForm="form"
     :tableData="tableData"
     :total="total"
     :height="null"
      @handleCurrentChange="handleCurrentChange" 
      @handleSizeChange="handleSizeChange">
      <template #search>
laboratory/src/views/dataManagement/originalRecordTest/components/addDialog.vue
@@ -108,7 +108,12 @@
</template>
<script>
import { customUploadRequest, getFullUrl } from "@/utils/utils";
import apiConfig from "@/utils/baseurl";
import {
  customUploadRequest,
  getAllocateIp,
  getFullUrl,
} from "@/utils/utils";
export default {
  name: "AddDialog",
  props: {
@@ -179,6 +184,10 @@
      },
      photoList: [],
      spectrumList: [],
      photoUploadQueue: [],
      isPhotoUploading: false,
      spectrumUploadQueue: [],
      isSpectrumUploading: false,
    };
  },
  computed: {
@@ -198,6 +207,27 @@
    },
  },
  methods: {
    normalizeRelativeUrl(url) {
      if (!url) return "";
      const prefixes = [getAllocateIp(), apiConfig.showImgUrl].filter(Boolean);
      const matchedPrefix = prefixes.find((prefix) => url.startsWith(prefix));
      return matchedPrefix ? url.slice(matchedPrefix.length) : url;
    },
    buildUploadItem(file) {
      const rawUrl = this.normalizeRelativeUrl(file.rawUrl || file.url || "");
      return {
        name: file.name || "",
        rawUrl,
        url: getFullUrl(rawUrl),
        status: "success",
      };
    },
    buildSubmitFileList(fileList) {
      return (fileList || []).map((file) => ({
        name: file.name || "",
        url: this.normalizeRelativeUrl(file.rawUrl || file.url || ""),
      }));
    },
    setFormData(data) {
      // 设置基础表单数据
      this.form.dataCode = data.dataCode;
@@ -216,11 +246,7 @@
            typeof data.dataPictures === "string"
              ? JSON.parse(data.dataPictures)
              : data.dataPictures;
          this.photoList = pictures.map((photo) => ({
            name: photo.name,
            url: photo.url,
            status: "success",
          }));
          this.photoList = pictures.map((photo) => this.buildUploadItem(photo));
        } catch (e) {
          console.error("解析照片数据失败:", e);
          this.photoList = [];
@@ -236,11 +262,7 @@
            typeof data.dataFiles === "string"
              ? JSON.parse(data.dataFiles)
              : data.dataFiles;
          this.spectrumList = files.map((file) => ({
            name: file.name,
            url: file.url,
            status: "success",
          }));
          this.spectrumList = files.map((file) => this.buildUploadItem(file));
        } catch (e) {
          console.error("解析图谱数据失败:", e);
          this.spectrumList = [];
@@ -259,6 +281,10 @@
      this.$refs.form?.resetFields();
      this.photoList = [];
      this.spectrumList = [];
      this.photoUploadQueue = [];
      this.isPhotoUploading = false;
      this.spectrumUploadQueue = [];
      this.isSpectrumUploading = false;
      this.form = {
        dataCode: "",
        dataTitle: "",
@@ -292,40 +318,73 @@
            dataType: Array.isArray(this.form.dataType)
              ? this.form.dataType.join(",")
              : this.form.dataType,
            dataFiles: JSON.stringify(this.spectrumList),
            dataPictures: JSON.stringify(this.photoList),
            dataFiles: JSON.stringify(this.buildSubmitFileList(this.spectrumList)),
            dataPictures: JSON.stringify(
              this.buildSubmitFileList(this.photoList)
            ),
          };
          this.$emit("success", submitData);
        }
      });
    },
    // 真实图片上传
    handlePhotoUpload(options) {
      const { file, onSuccess, onError } = options;
      customUploadRequest({
        file,
        onSuccess: (res) => {
          console.log('res',res)
          if (res.code == 200) {
            const fileObj = {
              name: file.name,
              url: getFullUrl(res.msg || res.data || ""),
              status: "success",
            };
            this.photoList.push(fileObj);
            // this.$refs.form.validateField("photos");
            this.$message.success("图片上传成功");
            onSuccess(res);
          } else {
            this.$message.error(res.message || "图片上传失败");
            onError();
          }
        },
        onError: (err) => {
          this.$message.error("图片上传失败");
          onError(err);
        },
    uploadSingleFile(file) {
      return new Promise((resolve, reject) => {
        customUploadRequest({
          file,
          onSuccess: resolve,
          onError: reject,
        });
      });
    },
    getUploadErrorMessage(err, defaultMessage) {
      if (
        err &&
        err.response &&
        err.response.data &&
        (err.response.data.msg || err.response.data.message)
      ) {
        return err.response.data.msg || err.response.data.message;
      }
      return (err && err.message) || defaultMessage;
    },
    // 真实图片上传,按选择顺序串行上传
    handlePhotoUpload(options) {
      this.photoUploadQueue.push(options);
      this.processPhotoUploadQueue();
    },
    async processPhotoUploadQueue() {
      if (this.isPhotoUploading || !this.photoUploadQueue.length) {
        return;
      }
      this.isPhotoUploading = true;
      const { file, onSuccess, onError } = this.photoUploadQueue.shift();
      try {
        const res = await this.uploadSingleFile(file);
        if (res.code == 200) {
          const fileObj = {
            name: file.name,
            rawUrl: this.normalizeRelativeUrl(res.msg || res.data || ""),
            url: getFullUrl(res.msg || res.data || ""),
            status: "success",
          };
          this.photoList.push(fileObj);
          this.$message.success("图片上传成功");
          onSuccess && onSuccess(res);
        } else {
          const errorMessage = res.msg || res.message || "图片上传失败";
          this.$message.error(errorMessage);
          onError && onError(new Error(errorMessage));
        }
      } catch (err) {
        const errorMessage = this.getUploadErrorMessage(err, "图片上传失败");
        this.$message.error(errorMessage);
        onError && onError(err);
      } finally {
        this.isPhotoUploading = false;
        this.processPhotoUploadQueue();
      }
    },
    handlePhotoRemove(file) {
      const index = this.photoList.findIndex((item) => item.name === file.name);
@@ -334,32 +393,44 @@
        // this.$refs.form.validateField("photos");
      }
    },
    // 真实图谱上传
    // 真实图谱上传,按选择顺序串行上传
    handleSpectrumUpload(options) {
      const { file, onSuccess, onError } = options;
      customUploadRequest({
        file,
        onSuccess: (res) => {
          if (res.code === 200) {
            const fileObj = {
              name: file.name,
              url: getFullUrl(res.msg || res.data || ""),
              status: "success",
            };
            this.spectrumList.push(fileObj);
            // this.$refs.form.validateField('spectrums');
            this.$message.success("文件上传成功");
            onSuccess(res);
          } else {
            this.$message.error(res.message || "文件上传失败");
            onError();
          }
        },
        onError: (err) => {
          this.$message.error("文件上传失败");
          onError(err);
        },
      });
      this.spectrumUploadQueue.push(options);
      this.processSpectrumUploadQueue();
    },
    async processSpectrumUploadQueue() {
      if (this.isSpectrumUploading || !this.spectrumUploadQueue.length) {
        return;
      }
      this.isSpectrumUploading = true;
      const { file, onSuccess, onError } = this.spectrumUploadQueue.shift();
      try {
        const res = await this.uploadSingleFile(file);
        if (res.code === 200) {
          const fileObj = {
            name: file.name,
            rawUrl: this.normalizeRelativeUrl(res.msg || res.data || ""),
            url: getFullUrl(res.msg || res.data || ""),
            status: "success",
          };
          this.spectrumList.push(fileObj);
          this.$message.success("文件上传成功");
          onSuccess && onSuccess(res);
        } else {
          const errorMessage = res.msg || res.message || "文件上传失败";
          this.$message.error(errorMessage);
          onError && onError(new Error(errorMessage));
        }
      } catch (err) {
        const errorMessage = this.getUploadErrorMessage(err, "文件上传失败");
        this.$message.error(errorMessage);
        onError && onError(err);
      } finally {
        this.isSpectrumUploading = false;
        this.processSpectrumUploadQueue();
      }
    },
    handleSpectrumRemove(file) {
      const index = this.spectrumList.findIndex(
laboratory/src/views/dataManagement/originalRecordTest/detail.vue
@@ -148,6 +148,8 @@
import AiEditor from '@/components/AiEditor'
import moment from 'moment'
import { getDetail, update } from './service'
import apiConfig from '@/utils/baseurl'
import { getAllocateIp, getFullUrl } from '@/utils/utils'
import { mapState } from "vuex";
export default {
@@ -200,6 +202,20 @@
    ...mapState(["tagList", "isFold"]),
  },
  methods: {
    normalizeRelativeUrl(url) {
      if (!url) return '';
      const prefixes = [getAllocateIp(), apiConfig.showImgUrl].filter(Boolean);
      const matchedPrefix = prefixes.find((prefix) => url.startsWith(prefix));
      return matchedPrefix ? url.slice(matchedPrefix.length) : url;
    },
    buildDisplayFile(file) {
      const rawUrl = this.normalizeRelativeUrl(file.rawUrl || file.url || '');
      return {
        ...file,
        rawUrl,
        url: getFullUrl(rawUrl)
      };
    },
    // 获取详情
    getDetail() {
      const id = this.$route.query.id;
@@ -234,8 +250,8 @@
                sampleCode: item.dataCode || '',
                testData: item.dataTitle || '',
                resultText: item.resultText || '',
                photos: item.dataPictures ? item.dataPictures.split(',').map(url => ({ url })) : [],
                spectrums: item.dataFiles ? JSON.parse(item.dataFiles) : [],
                photos: item.dataPictures ? item.dataPictures.split(',').map(url => this.buildDisplayFile({ url })) : [],
                spectrums: item.dataFiles ? JSON.parse(item.dataFiles).map(file => this.buildDisplayFile(file)) : [],
                createTime: item.createTime || moment().format('YYYY-MM-DD HH:mm:ss')
              }));
            } else {
@@ -320,12 +336,21 @@
        .catch(() => { });
    },
    handleTaskSubmit(formData) {
      const photos = formData.dataPictures
        ? JSON.parse(formData.dataPictures).map((photo) =>
            this.buildDisplayFile(photo)
          )
        : [];
      const spectrums = formData.dataFiles
        ? JSON.parse(formData.dataFiles).map((file) => this.buildDisplayFile(file))
        : [];
      const newData = {
        sampleCode: formData.dataCode,
        testData: formData.dataTitle,
        resultText: this.isEdit && this.currentEditIndex > -1 ? this.taskTableData[this.currentEditIndex].resultText : '',
        photos: formData.dataPictures ? JSON.parse(formData.dataPictures) : [],
        spectrums: formData.dataFiles ? JSON.parse(formData.dataFiles) : [],
        photos,
        spectrums,
        createTime: this.isEdit ? this.taskTableData[this.currentEditIndex].createTime : moment().format('YYYY-MM-DD HH:mm:ss')
      };
      if (this.isEdit && this.currentEditIndex > -1) {
@@ -439,8 +464,15 @@
            dataType: item.photos && item.spectrums ? '1,2' :
              item.photos ? '1' :
                item.spectrums ? '2' : '',
            dataFiles: JSON.stringify(item.spectrums || []),
            dataPictures: (item.photos || []).map(photo => photo.url).join(','),
            dataFiles: JSON.stringify(
              (item.spectrums || []).map(file => ({
                name: file.name || '',
                url: this.normalizeRelativeUrl(file.rawUrl || file.url || '')
              }))
            ),
            dataPictures: (item.photos || [])
              .map(photo => this.normalizeRelativeUrl(photo.rawUrl || photo.url || ''))
              .join(','),
            originalId: this.form.id,
            resultText: item.resultText || ''
          }))
@@ -603,4 +635,4 @@
    margin-bottom: 0;
  }
}
</style>
</style>
laboratory/src/views/dataManagement/sampleManage/addSample.vue
@@ -313,24 +313,22 @@
  created() {
    const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
    this.userRole = userInfo.roleType || '';
    // 获取路由参数
    const { id, type } = this.$route.query;
    if (id) {
      this.pageType = type || 'detail';
      this.getDetailData(id);
    }
    this.initPageMode();
    this.initRouteData();
  },
  activated() {
    const routeId = this.$route.query.id;
    const routeName = this.$route.name;
    console.log('routeName routeName',routeName)
    // 如果是编辑路由,且id发生变化,重新加载数据
    if (routeName === "EditSample" && routeId && routeId !== this.sampleId) {
    this.initPageMode();
    // 如果是编辑/详情路由,且id发生变化,重新加载数据
    if (
      (routeName === "editSample" || routeName === "detailSample") &&
      routeId &&
      routeId !== this.sampleId
    ) {
      this.sampleId = routeId;
      const { type } = this.$route.query;
      this.pageType = type || 'detail';
      this.getDetailData(routeId);
    }
    // 如果是新增路由,不重置表单,保留用户填写的数据
@@ -346,6 +344,23 @@
  },
  methods: {
    getFullUrl,
    initPageMode() {
      const routeName = this.$route.name;
      if (routeName === 'editSample') {
        this.pageType = 'edit';
      } else if (routeName === 'detailSample') {
        this.pageType = 'detail';
      } else {
        this.pageType = 'add';
      }
    },
    initRouteData() {
      const routeId = this.$route.query.id;
      if ((this.pageType === 'edit' || this.pageType === 'detail') && routeId) {
        this.sampleId = routeId;
        this.getDetailData(routeId);
      }
    },
    // 获取详情数据
    async getDetailData(id) {
      this.sampleId = id;
@@ -485,10 +500,11 @@
      });
    },
    back() {
      this.$router.back();
      const currentPath = this.$route.path;
      this.$router.push('/sampleManage/manage');
      this.$store.commit(
        "SET_TAGLIST",
        this.tagList.filter((item) => item.path !== this.$route.path)
        this.tagList.filter((item) => item.path !== currentPath)
      );
    },
    // 添加存草稿方法
@@ -678,4 +694,4 @@
    // margin-top: 20px;
  }
}
</style>
</style>
laboratory/src/views/dataManagement/sampleManage/list.vue
@@ -67,7 +67,7 @@
            {{ getSampleStatus(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
        <el-table-column label="操作" width="200" fixed="right">
          <template slot-scope="scope">
            <el-button v-if="currentType == 'list'" type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            <template v-if="currentType == 'draft'">
@@ -215,8 +215,7 @@
      this.$router.push({
        path: "/sampleManage/editSample",
        query: {
          id: row.id,
          type: 'edit'
          id: row.id
        }
      });
    },
@@ -228,10 +227,9 @@
    },
    handleDetail(id) {
      this.$router.push({
        path: "/sampleManage/addSample",
        path: "/sampleManage/detailSample",
        query: {
          id: id,
          type: 'detail'
          id: id
        }
      });
    },
@@ -302,4 +300,4 @@
    }
  }
}
</style>
</style>
laboratory/src/views/dataManagement/schemeManagement/list.vue
@@ -34,7 +34,7 @@
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center flex-wrap">
            <div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">项目课题方案列表
            <div class="title" :class="{ active: currentType === 'list' }" @click="handleTypeChange('list')">实验方案列表
            </div>
            <div v-if="userRole == '3' || userRole == '5'" class="drafts" :class="{ active: currentType === 'draft' }"
              @click="handleTypeChange('draft')">草稿箱</div>
@@ -58,7 +58,7 @@
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right">
        <el-table-column label="操作" fixed="right" width="250">
          <template slot-scope="scope">
            <!-- 草稿箱模式下,只显示编辑和详情 -->
            <template v-if="currentType === 'draft'">
laboratory/src/views/dataManagement/testResultReport/components/evaluation-dialog.vue
@@ -1,6 +1,7 @@
<template>
  <el-dialog :visible.sync="dialogVisible" :title="dialogTitle" width="79.17%" @close="handleClose">
    <EvaluateTable ref="evaluateTable" :viewJson="viewJson" :type="type == 'labTechnician' ? 1 : type == 'experimenter' ? 2 : 3" />
    <EvaluateTable :key="`${type}-${targetId || 'empty'}-${viewJson || 'empty'}`" ref="evaluateTable" :viewJson="viewJson"
      :type="type == 'labTechnician' ? 1 : type == 'experimenter' ? 2 : 3" />
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="handleSubmit" class="submit-btn">确认评定结果</el-button>
    </div>
@@ -24,6 +25,10 @@
    viewJson: {
      type: String,
      default: ''
    },
    targetId: {
      type: [String, Number],
      default: ''
    }
  },
  data() {
@@ -40,6 +45,13 @@
    modelValue: {
      handler(val) {
        this.dialogVisible = val;
        if (val) {
          this.$nextTick(() => {
            if (this.$refs.evaluateTable && !this.viewJson) {
              this.$refs.evaluateTable.resetData();
            }
          });
        }
      },
      immediate: true,
    },
@@ -80,4 +92,4 @@
    min-width: 80px;
  }
}
</style>
</style>
laboratory/src/views/dataManagement/testResultReport/detail.vue
@@ -228,16 +228,23 @@
        <div class="evaluate-card-cotent">
          <template v-if="selectedProcessEngineer">
            <template v-if="selectedProcessEngineer.data">
              <div class="evaluate-table-wrapper" @click="handleEvaluate('processEngineer')">
              <div class="evaluate-table-wrapper" @click="handleProcessEngineerEvaluate">
                <EvaluateTable class="evaluate-table" :isReadonly="true" :type="1"
                  :viewJson="selectedProcessEngineer.data.resultEvaluateJson" />
              </div>
            </template>
            <template v-else>
              <div class="no-data">暂未评定</div>
              <div v-if="
              <!-- 原逻辑保留:详情态下审批人和管理员可直接进入工艺工程师评定 -->
              <!-- <div v-if="
                isView && form.status == 2 && (userRole == 1 || userRole == 2)
              " class="to-evaluate" @click="handleEvaluate('processEngineer')">
              " class="to-evaluate" @click="handleEvaluate('processEngineer')"> -->
              <div v-if="
                !isApproverDetailView &&
                isView &&
                form.status == 2 &&
                (userRole == 1 || userRole == 2)
              " class="to-evaluate" @click="handleProcessEngineerEvaluate">
                去评价
              </div>
            </template>
@@ -248,8 +255,15 @@
        <el-button type="primary" class="save-btn" @click="handleSubmit(1)">提交</el-button>
        <el-button @click="handleSubmit(-1)">存草稿</el-button>
      </div>
      <div class="add-project-footer" v-if="isView && form.status == 2 && (userRole == 1 || userRole == 2)">
        <el-button type="primary" class="save-btn" @click="handleEvaluate('processEngineer')">工艺工程师评定</el-button>
      <!-- 原逻辑保留:详情态下审批人和管理员显示工艺工程师评定按钮 -->
      <!-- <div class="add-project-footer" v-if="isView && form.status == 2 && (userRole == 1 || userRole == 2)"> -->
      <div class="add-project-footer" v-if="
        !isApproverDetailView &&
        isView &&
        form.status == 2 &&
        (userRole == 1 || userRole == 2)
      ">
        <el-button type="primary" class="save-btn" @click="handleProcessEngineerEvaluate">工艺工程师评定</el-button>
        <!-- <el-button @click="handleSubmit(-1)">存草稿</el-button> -->
      </div>
    </el-form>
@@ -258,6 +272,7 @@
      @submit="handleSchedulingSelect" />
    <!-- 评价弹窗 -->
    <evaluation-dialog :modelValue="evaluationDialogVisible" :type="currentEvaluationType"
      :target-id="currentEvaluationTargetId"
      :viewJson="currentEvaluationData ? currentEvaluationData : ''" @update:modelValue="updateEvaluationDialogVisible"
      @submit="handleEvaluationSubmit" />
    <!-- 检验结果详情弹窗 -->
@@ -361,6 +376,7 @@
        3: "已封存",
      },
      currentEvaluationData: null, // 添加当前评价数据
      currentEvaluationTargetId: null,
      userRole: "",
      // 原始检测项列表--新增
      formMore: {
@@ -571,8 +587,21 @@
    handleSelectProcessEngineer(engineer) {
      this.selectedProcessEngineer = engineer;
    },
    handleProcessEngineerEvaluate() {
      if (this.isApproverDetailView) {
        // 原逻辑保留:审批人详情态下点击后会继续执行工艺工程师评定
        // this.handleEvaluate("processEngineer");
        return;
      }
      this.handleEvaluate("processEngineer");
    },
    // 去评价
    handleEvaluate(type) {
      if (this.isApproverDetailView && type == "processEngineer") {
        // 原逻辑保留:详情态审批人此前允许打开工艺工程师评定弹窗
        // this.evaluationDialogVisible = true;
        return;
      }
      if (
        this.$route.query.type == "view" &&
        type != "processEngineer" &&
@@ -582,14 +611,19 @@
        return;
      }
      this.currentEvaluationType = type;
      this.currentEvaluationData = null;
      this.currentEvaluationTargetId = null;
      // 根据类型获取当前选中人员的评定数据
      if (type == "labTechnician" && this.selectedLabTechnician) {
        this.currentEvaluationTargetId = this.selectedLabTechnician.id;
        this.currentEvaluationData =
          this.selectedLabTechnician.data?.resultEvaluateJson;
      } else if (type == "experimenter" && this.selectedExperimenter) {
        this.currentEvaluationTargetId = this.selectedExperimenter.id;
        this.currentEvaluationData =
          this.selectedExperimenter.data?.resultEvaluateJson;
      } else if (type == "processEngineer" && this.selectedProcessEngineer) {
        this.currentEvaluationTargetId = this.selectedProcessEngineer.id;
        this.currentEvaluationData =
          this.selectedProcessEngineer.data?.resultEvaluateJson;
      }
@@ -661,6 +695,7 @@
      }
      this.evaluationDialogVisible = false;
      this.currentEvaluationData = null;
      this.currentEvaluationTargetId = null;
    },
    // 将分数转换为评定值
    getEvaluateValue(score) {
@@ -725,6 +760,7 @@
      this.evaluationDialogVisible = value;
      if (!value) {
        this.currentEvaluationData = null; // 关闭弹窗时清空数据
        this.currentEvaluationTargetId = null;
      }
    },
    handleSchedulingClose() {
@@ -1197,8 +1233,12 @@
    },
  },
  computed: {
    ...mapState(["tagList", "isFold"]),
    isView() {
      return this.$route.query.type == "view";
    },
    isApproverDetailView() {
      return this.isView && this.userRole == 2;
    },
  },
};
@@ -1314,7 +1354,7 @@
    gap: 16px;
    .evaluate-card-people-item {
      width: 125px;
      min-width: 125px;
      background: #ffffff;
      border-radius: 6px;
      padding: 10px 5px;
@@ -1384,4 +1424,4 @@
    opacity: 0.8;
  }
}
</style>
</style>
laboratory/src/views/dataManagement/testResultReport/list.vue
@@ -148,7 +148,7 @@
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180">
        <el-table-column fixed="right" label="操作" width="250">
          <template slot-scope="scope">
            <template v-if="currentType === 'list'">
              <template v-if="isProcessEngineer">
laboratory/src/views/deliveryAssessment/testerWorkerEvaluate/add.vue
@@ -122,6 +122,7 @@
import ExperimentalScheduling from "@/views/dataManagement/schemeManagement/components/experimental-scheduling";
import { getEvaluateChemist, add ,getEvaluateDetailById,update} from "./service.js";
import moment from "moment";
import { mapState } from "vuex";
export default {
  name: "AddTesterWorkerEvaluate",
@@ -132,6 +133,7 @@
  data() {
    return {
      evaluateId: "",
      editId: "",
      showScheduling: false,
      participantsData: [],
      selectedParticipants: [],
@@ -156,11 +158,17 @@
  activated() {
    const routeId = this.$route.query.id;
    const routeName = this.$route.name;
    // 如果是编辑路由,且id发生变化,重新加载数据
    if (routeName === "EditTesterWorkerEvaluate" && routeId && routeId !== this.evaluateId) {
    this.initPageMode();
    // 如果是编辑/详情路由,且id发生变化,重新加载数据
    if (
      (routeName === "EditTesterWorkerEvaluate" ||
        routeName === "DetailTesterWorkerEvaluate") &&
      routeId &&
      routeId !== this.evaluateId
    ) {
      this.evaluateId = routeId;
      this.isEdit = this.$route.query.type == "view" ? false : true;
      this.editId = routeId;
      this.loadEditData();
    }
@@ -169,16 +177,28 @@
  mounted() {
    const routeId = this.$route.query.id;
    const routeName = this.$route.name;
    // 如果是编辑路由,加载数据
    if (routeName === "EditTesterWorkerEvaluate" && routeId) {
    this.initPageMode();
    // 如果是编辑/详情路由,加载数据
    if (
      (routeName === "EditTesterWorkerEvaluate" ||
        routeName === "DetailTesterWorkerEvaluate") &&
      routeId
    ) {
      this.evaluateId = routeId;
      this.isEdit = this.$route.query.type == "view" ? false : true;
      this.editId = routeId;
      this.loadEditData();
    }
  },
  computed: {
    ...mapState(["tagList"]),
  },
  methods: {
    initPageMode() {
      const routeName = this.$route.name;
      this.isEdit = routeName !== "DetailTesterWorkerEvaluate";
    },
    loadEditData(){
      getEvaluateDetailById({ id: this.editId }).then((res) => { 
        if(res.experimentDispatch){
@@ -253,6 +273,14 @@
      };
      return scoreMap[score] || 0; // 默认返回失误
    },
    backToListAndCloseTag() {
      const currentPath = this.$route.path;
      this.$router.push("/deliveryAssessment/testerWorkerEvaluate");
      this.$store.commit(
        "SET_TAGLIST",
        this.tagList.filter((item) => item.path !== currentPath)
      );
    },
    submitForm() {
      const evaluateTable = this.$refs.evaluateTable;
      if (!evaluateTable) {
@@ -279,7 +307,7 @@
        update({...evaluateData,id:this.editId}).then((res) => { 
          if (res.code == 200) {
          this.$message.success("编辑成功");
          this.$router.back();
          this.backToListAndCloseTag();
        } else {
          this.$message.error(res.msg || "编辑失败");
        }
@@ -289,7 +317,7 @@
      add(evaluateData).then((res) => {
        if (res.code == 200) {
          this.$message.success("保存成功");
          this.$router.back();
          this.backToListAndCloseTag();
        } else {
          this.$message.error(res.msg || "保存失败");
        }
@@ -423,4 +451,4 @@
    width: 220px;
  }
}
</style>
</style>
laboratory/src/views/deliveryAssessment/testerWorkerEvaluate/index.vue
@@ -186,17 +186,15 @@
      });
    },
    handleDetail(row) {
      // 详情逻辑后续补充
      this.$router.push({
        path: "/deliveryAssessment/addTesterWorkerEvaluate",
        query: { id: row.id, type: 'view' },
        path: "/deliveryAssessment/detailTesterWorkerEvaluate",
        query: { id: row.id },
      });
    },
    handleEdit(row) {
      // 编辑逻辑后续补充
      this.$router.push({
        path: "/deliveryAssessment/editTesterWorkerEvaluate",
        query: { id: row.id, type: 'edit' },
        query: { id: row.id },
      });
    },
    handleDelete(row) {