spring
3 天以前 39724c7cb4801b3863bb0135057e5d300f6670be
src/views/safeProduction/safetyTrainingAssessment/index.vue
@@ -2,23 +2,14 @@
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">培训名称:</span>
        <el-input v-model="searchForm.name"
                  style="width: 240px"
                  placeholder="请输入培训名称搜索"
                  @change="handleQuery"
                  clearable
                  :prefix-icon="Search" />
        <span class="search_title ml10">培训类型:</span>
        <el-select v-model="searchForm.type"
                   clearable
                   @change="handleQuery"
                   style="width: 240px">
          <el-option v-for="item in knowledgeTypeOptions"
                     :key="item.value"
                     :label="item.label"
                     :value="item.value" />
        </el-select>
        <span class="search_title">培训日期:</span>
        <el-date-picker v-model="searchForm.trainingDate"
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        @change="handleQuery"
                        type="date"
                        placeholder="请选择"
                        clearable />
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">
@@ -28,12 +19,24 @@
      <div>
        <el-button type="primary"
                   @click="openForm('add')">新增培训</el-button>
        <el-button type="primary"
                   @click="opendetail">培训记录</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-tabs v-model="searchForm.state"
               @tab-click="tabhandleQuery">
        <el-tab-pane label="未开始"
                     :name="0"></el-tab-pane>
        <el-tab-pane label="进行中"
                     :name="1"></el-tab-pane>
        <el-tab-pane label="已结束"
                     :name="2"></el-tab-pane>
      </el-tabs>
      <!-- state   状态(0:未开始1:进行中;2:已结束)    -->
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
@@ -135,6 +138,8 @@
            <el-form-item label="课程学分"
                          prop="projectCredits">
              <el-input v-model="form.projectCredits"
                        type="number"
                        min="0"
                        placeholder="请输入课程学分" />
            </el-form-item>
          </el-col>
@@ -181,51 +186,164 @@
    </el-dialog>
    <!-- 查看知识详情弹窗 -->
    <el-dialog v-model="viewDialogVisible"
               title="培训详情"
               title="结果明细"
               width="900px"
               :close-on-click-modal="false">
      <div class="knowledge-detail">
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="培训名称"
                                :span="2">
            <span class="detail-title">{{ currentKnowledge.name }}</span>
          </el-descriptions-item>
          <el-descriptions-item label="培训编码">
            {{ currentKnowledge.code }}
          </el-descriptions-item>
          <el-descriptions-item label="培训类型">
            <el-tag type="info">
              <!-- {{ getTypeLabel(currentKnowledge.type) }} -->
        <el-descriptions size="mini"
                         style="margin-left: 60px;"
                         :column="3">
          <el-descriptions-item label="课程编号:">{{ currentKnowledge.courseCode }}</el-descriptions-item>
          <el-descriptions-item label="培训内容:">{{ currentKnowledge.trainingContent }}</el-descriptions-item>
          <el-descriptions-item label="状态:">
            <el-tag :type="currentKnowledge.status === 0 ? 'success' : (currentKnowledge.status === 1 ? 'success' : 'info')">
              {{ currentKnowledge.status === 0 ? '未开始' : (currentKnowledge.status === 1 ? '进行中' : '已结束') }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="所在位置">
            {{ currentKnowledge.location }}
          <el-descriptions-item label="培训讲师:">
            {{ currentKnowledge.trainingLecturer }}
          </el-descriptions-item>
          <el-descriptions-item label="管控措施">
            {{ currentKnowledge.controlMeasures }}
          <el-descriptions-item label="培训开始时间:">
            {{ currentKnowledge.trainingDate + ' ' + currentKnowledge.openingTime }}
          </el-descriptions-item>
          <el-descriptions-item label="库存数量">
            {{ currentKnowledge.stockQty }}
          <el-descriptions-item label="培训结束时间:">
            {{ currentKnowledge.trainingDate + ' ' + currentKnowledge.endTime }}
          </el-descriptions-item>
          <el-descriptions-item label="管控责任人">
            {{ currentKnowledge.principalUserId }}
          <el-descriptions-item label="培训目标:">
            {{ currentKnowledge.trainingObjectives }}
          </el-descriptions-item>
          <el-descriptions-item label="责任人联系电话">
            {{ currentKnowledge.principalMobile }}
          <el-descriptions-item label="参加对象:">
            {{ currentKnowledge.participants }}
          </el-descriptions-item>
          <el-descriptions-item label="风险等级">
            <el-tag :type="getTypeTagType(currentKnowledge.riskLevel)">
              {{ currentKnowledge.riskLevel }}
          <el-descriptions-item label="培训方式:">
            <el-tag type="primary">
              {{ getTrainingModeLabel(currentKnowledge.trainingMode) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="规格 / 风险描述">
            {{ currentKnowledge.specInfo }}
          <el-descriptions-item label="培训地点:">
            {{ currentKnowledge.placeTraining }}
          </el-descriptions-item>
          <el-descriptions-item label="课时:">
            {{ currentKnowledge.classHour }}
          </el-descriptions-item>
          <el-descriptions-item label="课程学分:">
            {{ currentKnowledge.projectCredits }}
          </el-descriptions-item>
          <el-descriptions-item label="报名人数:">
            {{ currentKnowledge.nums }}
          </el-descriptions-item>
          <el-descriptions-item label="附件列表:">
            <el-button type="primary"
                       size="small"
                       @click="downLoadFile(endform)">附件列表</el-button>
          </el-descriptions-item>
        </el-descriptions>
        <el-divider style="margin: 20px 0;" />
        <el-form ref="formRef"
                 :model="form"
                 :rules="rules"
                 label-width="130px">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="评价人:"
                            prop="courseCode">
                <el-input v-model="endform.assessmentUserName"
                          disabled
                          placeholder="请选择评价人" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="评价时间:"
                            prop="trainingDate">
                <el-date-picker style="width: 100%"
                                disabled
                                v-model="endform.assessmentDate"
                                value-format="YYYY-MM-DD"
                                format="YYYY-MM-DD"
                                type="date"
                                placeholder="请选择"
                                clearable />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="考核方式:"
                            prop="assessmentMethod">
                <el-input v-model="endform.assessmentMethod"
                          placeholder="请选择考核方式" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="本次课程综合评价:"
                            prop="comprehensiveAssessment">
                <el-input v-model="endform.comprehensiveAssessment"
                          placeholder="请输入本次课程综合评价" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-form-item label="培训摘要:"
                        prop="trainingAbstract">
            <el-input v-model="endform.trainingAbstract"
                      type="textarea"
                      :rows="2"
                      placeholder="请输入培训摘要" />
          </el-form-item>
          <!-- <el-row :gutter="30">
            <el-col :span="24">
              <el-form-item label="附件材料:"
                            prop="remark">
                <el-upload v-model:file-list="fileList"
                           :action="upload.url"
                           multiple
                           ref="fileUpload"
                           auto-upload
                           :headers="upload.headers"
                           :before-upload="handleBeforeUpload"
                           :on-error="handleUploadError"
                           :on-success="handleUploadSuccess"
                           :on-remove="handleRemove">
                  <el-button type="primary"
                             v-if="operationType !== 'view'">上传</el-button>
                  <template #tip
                            v-if="operationType !== 'view'">
                    <div class="el-upload__tip">
                      文件格式支持
                      doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z
                    </div>
                  </template>
                </el-upload>
              </el-form-item>
            </el-col>
          </el-row> -->
        </el-form>
        <el-table style="margin-top: 20px;"
                  :data="endform.safeTrainingDetailsDtoList"
                  border
                  fit
                  highlight-current-row>
          <el-table-column prop="nickName"
                           label="姓名" />
          <el-table-column prop="phonenumber"
                           label="电话号码" />
          <el-table-column prop="examinationResults"
                           label="考核结果">
            <template #default="scope">
              <el-select v-model="scope.row.examinationResults"
                         placeholder="请选择考核结果">
                <el-option label="合格"
                           value="合格" />
                <el-option label="不合格"
                           value="不合格" />
              </el-select>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm2">提交</el-button>
          <el-button @click="viewDialogVisible = false">关闭</el-button>
        </span>
      </template>
@@ -265,7 +383,13 @@
    safeTrainingFileListPage,
    safeTrainingFileAdd,
    safeTrainingFileDel,
    safeTrainingSign,
    safeTrainingGet,
    safeTrainingSave,
  } from "@/api/safeProduction/safetyTrainingAssessment.js";
  import useUserStore from "@/store/modules/user";
  import dayjs from "dayjs";
  const userStore = useUserStore();
  // 表单验证规则
  const rules = {
@@ -284,12 +408,17 @@
    ],
    classHour: [{ required: true, message: "请输入课时", trigger: "blur" }],
  };
  const upload = reactive({
    // 上传的地址
    url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
    // 设置上传的请求头部
    headers: { Authorization: "Bearer " + getToken() },
  });
  // 响应式数据
  const data = reactive({
    searchForm: {
      name: "",
      type: "",
      trainingDate: "",
      state: 0,
    },
    tableLoading: false,
    page: {
@@ -342,6 +471,13 @@
    );
    return item ? item.label : val;
  };
  // 切换tab查询
  const tabhandleQuery = val => {
    searchForm.value.state = val.paneName;
    console.log(searchForm.value.state, "searchForm.value.state");
    handleQuery();
  };
  // 表单引用
  const formRef = ref();
  const riskLevelOptions = ref([
@@ -351,56 +487,69 @@
    { value: "重大风险", label: "重大风险" },
  ]);
  const fileList = ref([]);
  // 表格列配置
  const tableColumn = ref([
    {
      label: "课程编号",
      prop: "courseCode",
      width: 150,
      showOverflowTooltip: true,
    },
    {
      label: "培训日期",
      prop: "trainingDate",
      width: 120,
      showOverflowTooltip: true,
    },
    {
      label: "开始时间",
      prop: "openingTime",
      width: 120,
      showOverflowTooltip: true,
    },
    {
      label: "结束时间",
      prop: "endTime",
      width: 120,
      showOverflowTooltip: true,
    },
    {
      label: "培训目标",
      prop: "trainingObjectives",
      width: 200,
      showOverflowTooltip: true,
    },
    {
      label: "参加对象",
      prop: "participants",
      width: 200,
      showOverflowTooltip: true,
    },
    {
      label: "培训内容",
      prop: "trainingContent",
      width: 200,
      showOverflowTooltip: true,
    },
    {
      label: "培训讲师",
      prop: "trainingLecturer",
      width: 200,
      showOverflowTooltip: true,
    },
    {
      label: "项目学分",
      prop: "projectCredits",
      width: 120,
      showOverflowTooltip: true,
    },
    {
      label: "培训方式",
      prop: "trainingMode",
      width: 120,
      showOverflowTooltip: true,
      formatData: params => {
        return getTrainingModeLabel(params);
@@ -409,11 +558,19 @@
    {
      label: "培训地点",
      prop: "placeTraining",
      width: 200,
      showOverflowTooltip: true,
    },
    {
      label: "课时",
      prop: "classHour",
      width: 120,
      showOverflowTooltip: true,
    },
    {
      label: "报名人数",
      prop: "nums",
      width: 120,
      showOverflowTooltip: true,
    },
    {
@@ -421,27 +578,47 @@
      label: "操作",
      align: "center",
      fixed: "right",
      width: 200,
      width: 300,
      operation: [
        {
          name: "签到",
          type: "text",
          disabled: row => row.state !== 1,
          clickFun: row => {
            signIn(row);
          },
        },
        {
          name: "编辑",
          type: "text",
          disabled: row => row.state !== 0,
          clickFun: row => {
            openForm("edit", row);
          },
        },
        {
          name: "导出",
          type: "danger",
          type: "text",
          clickFun: row => {
            exportKnowledge(row);
          },
          color: "#C49000",
        },
        {
          name: "附件",
          type: "danger",
          type: "text",
          clickFun: row => {
            downLoadFile(row);
          },
          color: "#007AFF",
        },
        {
          name: "结果明细",
          type: "text",
          // disabled: row => row.state !== 2,
          clickFun: row => {
            viewResultDetail(row);
          },
        },
        // {
@@ -457,12 +634,133 @@
  const userList = ref([]);
  // 生命周期
  onMounted(() => {
    getCurrentFactoryName();
    getList();
    startAutoRefresh();
    userListNoPage().then(res => {
      userList.value = res.data;
    });
  });
  const endform = ref({
    assessmentUserId: "", //评价人
    assessmentUserName: "", //评价人姓名
    assessmentMethod: "", //考核方式
    assessmentDate: "", //评价时间
    comprehensiveAssessment: "", //综合评价
    trainingAbstract: "", //培训摘要
    safeTrainingFileList: [], //培训附件
    safeTrainingDetailsDtoList: [], //考核结果详情
  });
  const operationType = ref("edit");
  const viewResultDetail = row => {
    // fileList.value = [];
    operationType.value = "edit";
    safeTrainingGet({ id: row.id }).then(res => {
      if (res.code === 200) {
        console.log(res.data, "res.data");
        currentKnowledge.value = JSON.parse(JSON.stringify(res.data));
        currentKnowledge.value.nums = row.nums;
        viewDialogVisible.value = true;
        endform.value = { ...res.data };
        endform.value.assessmentUserName = endform.value.assessmentUserName
          ? endform.value.assessmentUserName
          : currentUserName.value;
        endform.value.assessmentUserId = endform.value.assessmentUserId
          ? endform.value.assessmentUserId
          : currentUserId.value;
        endform.value.assessmentDate = dayjs().format("YYYY-MM-DD");
      } else {
        proxy.$modal.msgError(res.msg || "查询详情失败");
      }
    });
  };
  // 上传前校检
  function handleBeforeUpload(file) {
    proxy.$modal.loading("正在上传文件,请稍候...");
    return true;
  }
  // 上传失败
  function handleUploadError(err) {
    proxy.$modal.msgError("上传文件失败");
    proxy.$modal.closeLoading();
  }
  // 上传成功回调
  function handleUploadSuccess(res, file, uploadFiles) {
    proxy.$modal.closeLoading();
    if (res.code === 200) {
      // 确保 tempFileIds 存在且为数组
      if (!endform.value.safeTrainingFileList) {
        endform.value.safeTrainingFileList = [];
      }
      endform.value.safeTrainingFileList.push({
        id: res.data.tempId,
        fileName: res.data.originalName,
        url: res.data.tempPath,
        safeTrainingId: currentKnowledge.value.id,
      });
      proxy.$modal.msgSuccess("上传成功");
    } else {
      proxy.$modal.msgError(res.msg);
      proxy.$refs.fileUpload.handleRemove(file);
    }
  }
  // 移除文件
  function handleRemove(file) {
    if (operationType.value === "edit") {
      let index = endform.value.safeTrainingFileList.findIndex(
        item => item.fileName === file.name
      );
      if (index !== -1) {
        endform.value.safeTrainingFileList.splice(index, 1);
      }
    }
  }
  const submitForm2 = () => {
    endform.value.safeTrainingDetailsDtoList.forEach((item, index) => {
      if (!item.examinationResults) {
        proxy.$modal.msgError(`请选择${item.nickName}的考核结果`);
        return;
      }
    });
    console.log(endform.value, "endform.value");
    proxy.$modal.loading("正在提交,请稍候...");
    safeTrainingSave(endform.value).then(res => {
      proxy.$modal.closeLoading();
      if (res.code === 200) {
        proxy.$modal.msgSuccess("提交成功");
        getList();
        viewDialogVisible.value = false;
      } else {
        proxy.$modal.msgError(res.msg || "提交失败");
      }
    });
  };
  const opendetail = row => {
    proxy.$router.push({
      path: "/safeProduction/safetyTrainingAssessmentDetail",
    });
  };
  const signIn = row => {
    ElMessageBox.confirm("确认签到吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      safeTrainingSign({
        safeTrainingId: row.id,
        userId: currentUserId.value,
      }).then(res => {
        if (res.code === 200) {
          proxy.$modal.msgSuccess("签到成功");
          getList();
        } else {
          proxy.$modal.msgError(res.msg || "签到失败");
        }
      });
    });
  };
  // 处理用户选择变化
  const handleUserChange = userId => {
@@ -627,7 +925,7 @@
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement("a");
        link.href = url;
        link.download = `培训记录_${row.courseCode}.xlsx`;
        link.download = `培训记录_${row.courseCode}.docx`;
        // 模拟点击下载
        document.body.appendChild(link);
@@ -670,6 +968,13 @@
  const handleSelectionChange = selection => {
    selectedIds.value = selection.map(item => item.id);
  };
  const currentUserId = ref("");
  const currentUserName = ref("");
  const getCurrentFactoryName = async () => {
    let res = await userStore.getInfo();
    currentUserId.value = res.user.userId;
    currentUserName.value = res.user.nickName;
  };
  // 打开表单
  const openForm = (type, row = null) => {
@@ -710,12 +1015,6 @@
      });
    }
    dialogVisible.value = true;
  };
  // 查看培训详情
  const viewKnowledge = row => {
    currentKnowledge.value = { ...row };
    viewDialogVisible.value = true;
  };
  // 获取类型标签类型