董国庆
2025-09-12 527efb36f35b471710e445972673abff45bacdac
laboratory/src/views/deliveryAssessment/QA/components/AssessmentDialog.vue
@@ -1,201 +1,282 @@
<template>
    <el-dialog :visible.sync="dialogVisible" title="课题评定详情" width="70%" @close="handleClose">
        <el-form :model="form" inline label-position="top" :rules="rules" ref="formRef">
            <el-row :gutter="20">
                <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
                    <el-form-item label="报告编号" prop="reportNo" required>
                        <el-input v-model="form.reportNo" disabled placeholder="自动生成" />
                    </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
                    <el-form-item label="报告名称" prop="reportName">
                        <el-input v-model="form.reportName" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
        <div class="content-box">
            <el-row :gutter="16">
                <el-col style="margin-top: 5px;" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
                    <Table :total="0" :height="null" :data="criteriaList" show-summary :summary-method="getSummaries"
                        :span-method="arraySpanMethod">
                        <el-table-column type="index" label="序号" width="80" />
                        <el-table-column prop="criteria" label="规程型课题评定标准" />
                        <el-table-column prop="fullScore" label="满分值" width="100" />
                        <el-table-column label="评定分值" prop="score" width="200">
                            <template #default="{ row }">
                                <el-input-number v-model="row.score" :min="0" :max="row.fullScore" :step="1" />
                            </template>
                        </el-table-column>
                        <el-table-column label="创新型课题报告评分规则">
                            <template>
                                <div>
                                    <div>1、规程型课题评定总分的满分为5分。</div>
                                    <div>2、某分项工作完成,但出现以下三种错误中的1种,则减1分:</div>
                                    <div>①有缺项、漏项;</div>
                                    <div>②或不完整清晰;</div>
                                    <div>③或工作效率人为拖延。</div>
                                    <div>3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。</div>
                                </div>
                            </template>
                        </el-table-column>
                    </Table>
                </el-col>
            </el-row>
        </div>
        <template #footer>
            <span class="select-member-footer">
                <el-button type="primary">提交评定结果</el-button>
            </span>
        </template>
    </el-dialog>
  <el-dialog
    :visible.sync="dialogVisible"
    :title="type === 'detail' ? '课题评定详情' : '课题评定'"
    width="70%"
    @close="handleClose"
  >
    <el-form
      :model="form"
      inline
      label-position="top"
      :rules="rules"
      ref="formRef"
    >
      <el-row :gutter="20">
        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
          <el-form-item label="报告编号" prop="reportNo" required>
            <el-input v-model="form.reportNo" disabled placeholder="自动生成" />
          </el-form-item>
        </el-col>
        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
          <el-form-item label="报告名称" prop="reportName">
            <el-input v-model="form.reportName" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <div class="content-box">
      <el-row :gutter="16">
        <el-col
          style="margin-top: 5px"
          :xs="24"
          :sm="24"
          :md="24"
          :lg="24"
          :xl="24"
        >
          <Table
            :total="0"
            :height="null"
            :data="criteriaList"
            show-summary
            :summary-method="getSummaries"
            :span-method="arraySpanMethod"
          >
            <el-table-column type="index" label="序号" width="80" />
            <el-table-column prop="criteria" label="规程型课题评定标准" />
            <el-table-column prop="fullScore" label="满分值" width="100" />
            <el-table-column label="评定分值" prop="score" width="200">
              <template #default="{ row }">
                <el-input-number
                  v-model="row.score"
                  :min="0"
                  :max="row.fullScore"
                  :step="1"
                />
              </template>
            </el-table-column>
            <el-table-column label="创新型课题报告评分规则">
              <template>
                <div>
                  <div>1、规程型课题评定总分的满分为5分。</div>
                  <div>
                    2、某分项工作完成,但出现以下三种错误中的1种,则减1分:
                  </div>
                  <div>①有缺项、漏项;</div>
                  <div>②或不完整清晰;</div>
                  <div>③或工作效率人为拖延。</div>
                  <div>
                    3、不能完成某分项的全部工作,或课题不涉及该分项内容,则该分项评0分。
                  </div>
                </div>
              </template>
            </el-table-column>
          </Table>
        </el-col>
      </el-row>
    </div>
    <div class="assessed" style="display:flex" v-if="evaluateInfo.status == 3">
      <div style="margin-right: 20px">评定时间:{{ evaluateInfo.evaluateTime }}</div>
      <div>评定人:{{ evaluateInfo.evaluatePersonName }}</div>
    </div>
    <template #footer v-if="evaluateInfo.status === 2 && type=='approve'">
      <span class="select-member-footer">
        <el-button type="primary" @click="handleSubmit">提交评定结果</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script>
import { getDetailById, evaluate } from "../service.js";
export default {
    name: 'AssessmentDialog',
    props: {
        modelValue: {
            type: Boolean,
            default: false
        },
        reportData: {
            type: Object,
            default: () => { }
        }
  name: "AssessmentDialog",
  props: {
    modelValue: {
      type: Boolean,
      default: false,
    },
    data() {
    id: {
      type: String,
    //   required: true,
    default: () => "",
    },
    type: {
      type: String,
      default: "detail", // 'detail' 或 'evaluate'
    },
  },
  data() {
    return {
      dialogVisible: false,
      form: {
        reportNo: "",
        reportName: "",
      },
      rules: {
        reportName: [
          { required: true, message: "请输入报告名称", trigger: "blur" },
        ],
      },
      criteriaList: [
        {
          criteria: "文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范",
          fullScore: 1,
          score: 0,
        },
        {
          criteria:
            "专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;",
          fullScore: 2,
          score: 0,
        },
        {
          criteria:
            "课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。",
          fullScore: 3,
          score: 0,
        },
      ],
      evaluateInfo: {},
    };
  },
  watch: {
    modelValue: {
      handler(val) {
        this.dialogVisible = val;
        if (val) {
          this.fetchDataById();
        }
      },
      immediate: true,
    },
    id: {
      handler(val) {
        if (this.dialogVisible && val) {
          this.fetchDataById();
        }
      },
      immediate: true,
    },
    type: {
      handler(val) {
        // 可根据type切换详情/评定模式
      },
      immediate: true,
    },
  },
  methods: {
    async fetchDataById() {
      try {
        const res = await getDetailById({id:this.id});
        const data = res || {};
        this.form.reportNo = data.reportCode || "";
        this.form.reportName = data.reportTitle || "";
        this.evaluateInfo = { ...data };
        // 评定分数
        if (data.evaluateScore) {
          const scores = data.evaluateScore.split(",").map(Number);
          this.criteriaList.forEach((item, idx) => {
            item.score = scores[idx] || 0;
          });
        } else {
          this.criteriaList.forEach((item) => (item.score = 0));
        }
      } catch (e) {
        // 错误处理
      }
    },
    handleClose() {
        this.$emit("close", false);
    },
    async handleSubmit() {
      try {
        await this.$refs.formRef.validate();
        const totalScore = this.criteriaList.reduce(
          (sum, item) => sum + (item.score || 0),
          0
        );
        const assessmentData = {
          id: this.evaluateInfo.id,
          evaluateScore: this.criteriaList
            .map((item) => item.score || 0)
            .join(","),
        };
        // 这里可以调用evaluate接口
        evaluate(assessmentData).then((res) => {
          if (res.code == 200) {
            this.$message.success("提交成功");
            this.handleClose();
          }else{
            this.$message.error(res.message)
          }
        });
      } catch (error) {
        // 表单验证失败
      }
    },
    getSummaries(param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "合计";
          return;
        }
        const values = data.map((item) => Number(item[column.property]));
        if (!values.every((value) => isNaN(value))) {
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
          sums[index] += " 分";
        } else {
          sums[index] = "";
        }
      });
      return sums;
    },
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 4 && rowIndex == 0) {
        return {
            dialogVisible: false,
            form: {
                reportNo: '',
                reportName: '',
            },
            rules: {
                reportName: [
                    { required: true, message: '请输入报告名称', trigger: 'blur' }
                ],
            },
            criteriaList: [
                {
                    criteria: '文献资料调查:全面性,系统性 编辑逻辑清晰,表达规范',
                    fullScore: 1,
                    score: 0,
                },
                {
                    criteria: '专业/技术路线与方法:合理性、可行性;实验设计科学、能实现研究目标,方法先进、完整、可靠;',
                    fullScore: 2,
                    score: 0,
                },
                {
                    criteria: '课题报告完成度高,预期研究结果果是否具有技术价值和应用价值。风险识别:识别了潜在的技术风险、市场风险和管理风险。',
                    fullScore: 3,
                    score: 0,
                },
            ]
        }
          rowspan: 6,
          colspan: 1,
        };
      } else if (rowIndex !== 0 && columnIndex === 4) {
        return [0, 0];
      }
    },
    watch: {
        modelValue: {
            handler(val) {
                this.dialogVisible = val;
            },
            immediate: true
        },
        reportData: {
            handler(val) {
                if (val) {
                    this.form.reportNo = val.reportNo || '';
                    this.form.reportName = val.reportName || '';
                }
            },
            immediate: true
        }
    },
    methods: {
        handleClose() {
            this.$emit('update:modelValue', false);
        },
        async handleSubmit() {
            try {
                await this.$refs.formRef.validate();
                const totalScore = this.criteriaList.reduce((sum, item) => sum + (item.score || 0), 0);
                const assessmentData = {
                    ...this.form,
                    totalScore,
                    criteriaScores: this.criteriaList.map(item => ({
                        criteria: item.criteria,
                        score: item.score || 0
                    }))
                };
                this.$emit('submit', assessmentData);
                this.handleClose();
            } catch (error) {
                // 表单验证失败
            }
        },
        getSummaries(param) {
            const { columns, data } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                    return;
                }
                const values = data.map(item => Number(item[column.property]));
                if (!values.every(value => isNaN(value))) {
                    sums[index] = values.reduce((prev, curr) => {
                        const value = Number(curr);
                        if (!isNaN(value)) {
                            return prev + curr;
                        } else {
                            return prev;
                        }
                    }, 0);
                    sums[index] += ' 分';
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        arraySpanMethod({ row, column, rowIndex, columnIndex }) {
            if (columnIndex === 4 && rowIndex == 0) {
                return {
                    rowspan: 6,
                    colspan: 1
                }
            } else if (rowIndex !== 0 && columnIndex === 4) {
                return [0, 0]
            }
        }
    }
}
  },
};
</script>
<style lang="less" scoped>
.content-box {
  &-left {
    margin-top: 5px;
    display: flex;
    flex-direction: column;
    border: 1px solid #ebeef5;
    border-radius: 8px 8px 0px 0px;
    font-size: 12px;
    &-left {
        margin-top: 5px;
        display: flex;
        flex-direction: column;
        border: 1px solid #EBEEF5;
        border-radius: 8px 8px 0px 0px;
        font-size: 12px;
        &-th {
            line-height: 40px;
            background: #FAFAFA !important;
            color: #909399;
            padding: 0 10px;
            font-weight: bold;
        }
        &-body {
            padding: 0 10px;
            line-height: 23px;
        }
    &-th {
      line-height: 40px;
      background: #fafafa !important;
      color: #909399;
      padding: 0 10px;
      font-weight: bold;
    }
    &-body {
      padding: 0 10px;
      line-height: 23px;
    }
  }
}
</style>