xiaweibo 3 meses atrás
pai
commit
2457ed82cd

+ 1 - 1
src/api/evaluationSystem/index.ts

@@ -164,7 +164,7 @@ export function updateSecurityExamine(data: UpdateSecurityExamineRequest) {
 export interface SaveSecurityExamineIssueRequest {
   id: number;
   deptNames: string; // 部门名称(逗号分隔)
-  deptIds: number; // 部门ID(单个
+  deptIds: number[]; // 部门ID(多选
   getUserGroupId?: number; // 分组ID
   deptSelfApproveUserId?: number; // 部门自评审核人ID
   planStartTime?: string; // 计划开始时间

+ 2 - 2
src/router/routers/production-safety-router/hiddenTroubleInvestigationAndGovernance.ts

@@ -49,7 +49,7 @@
         path: 'hidden-trouble-review-management',
         component: '/production-safety/hiddenTroubleInvestigationAndGovernance/hiddenTroubleReviewManagement/hiddenTroubleReviewManagement',
         meta: {
-          title: '隐患审核管理',
+          title: '员工上报隐患管理(管理员审核)',
           icon: 'OverviewIcon',
           isRoot: false,
           hidden: false,
@@ -63,7 +63,7 @@
         path: 'hidden-trouble-review-management-item',
         component: '/production-safety/hiddenTroubleInvestigationAndGovernance/hiddenTroubleReviewManagement/hiddenTroubleReviewManagementItem',
         meta: {
-          title: '隐患审核管理详情',
+          title: '员工上报隐患管理(管理员审核)详情',
           icon: 'OverviewIcon',
           isRoot: false,
           hidden: true,

+ 11 - 2
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/employeeReportHiddenTroubleManagement/components/employeeReportHiddenTroubleManagementDetail.vue

@@ -87,8 +87,17 @@
   const operate = computed(() => (route.query.operate as string) || 'employee-report-hidden-trouble-view');
   const currentId = computed(() => Number(route.query.id));
 
-  const isViewMode = computed(() => operate.value === 'employee-report-hidden-trouble-view');
-  const isApproveMode = computed(() => operate.value === 'employee-report-hidden-trouble-approve');
+  // 支持员工上报与管理员审核两套 operate
+  const isViewMode = computed(
+    () =>
+      operate.value === 'employee-report-hidden-trouble-view' ||
+      operate.value === 'hidden-trouble-review-view',
+  );
+  const isApproveMode = computed(
+    () =>
+      operate.value === 'employee-report-hidden-trouble-approve' ||
+      operate.value === 'hidden-trouble-review-approve',
+  );
 
   const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
     useFormConfigHook(ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES);

+ 29 - 16
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/hiddenTroubleReviewManagement/configs/tables.ts

@@ -7,56 +7,69 @@ export const TABLE_OPTIONS = {
   maxHeight: 'calc(70vh - 150px)',
 };
 
+// 员工上报隐患管理表格列(与员工上报隐患管理复用)
 export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
   {
-    label: '号',
+    label: '号',
     type: 'index',
     align: 'center',
     width: '80px',
   },
   {
-    label: '物品名称',
-    prop: 'itemName',
+    label: '隐患问题',
+    prop: 'hazardDesc',
     align: 'left',
-    minWidth: '120px',
+    minWidth: '180px',
+  },
+  {
+    label: '隐患地点',
+    prop: 'location',
+    align: 'left',
+    minWidth: '150px',
+  },
+  {
+    label: '上报时间',
+    prop: 'reportTime',
+    align: 'left',
+    minWidth: '180px',
   },
   {
-    label: '入库日期',
-    prop: 'warehouseDate',
+    label: '提交类型',
+    prop: 'sourceTypeName',
     align: 'left',
     minWidth: '120px',
   },
   {
-    label: '物品数量',
-    prop: 'itemQuantity',
-    align: 'center',
+    label: '姓名',
+    prop: 'reporterName',
+    align: 'left',
     minWidth: '120px',
   },
   {
-    label: '经办人',
-    prop: 'handler',
+    label: '工号',
+    prop: 'reporterJobNo',
     align: 'left',
     minWidth: '120px',
   },
   {
-    label: '备注',
-    prop: 'remarks',
+    label: '联系电话',
+    prop: 'reporterMobile',
     align: 'left',
-    minWidth: '150px',
+    minWidth: '140px',
   },
   {
     label: '状态',
     prop: 'status',
     slot: 'status',
     align: 'center',
-    minWidth: '100px',
+    minWidth: '120px',
   },
   {
     label: '操作',
     prop: 'action',
     slot: 'action',
     fixed: 'right',
-    width: '180px',
+    width: '200px',
     align: 'left',
   },
 ];

+ 92 - 87
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/hiddenTroubleReviewManagement/hiddenTroubleReviewManagement.vue

@@ -1,14 +1,14 @@
 <template>
   <div class="safety-platform-container">
     <header class="safety-platform-container__header">
-      <div class="breadcrumb-title"> 院级文件管理 </div>
+      <div class="breadcrumb-title"> 员工上报隐患管理(管理员审核) </div>
     </header>
     <main class="safety-platform-container__main">
       <div class="search-table-container">
         <header>
           <div style="position: relative">
             <el-button type="primary" class="search-table-container--button" @click="handleCreate">
-              添加
+              新增
             </el-button>
             <el-button plain class="search-table-container--button" @click="handleImport">
               导入
@@ -21,35 +21,34 @@
           <div class="act-search">
             <section class="select-box">
               <div class="select-box--item">
-                <span>文件名称/编号:</span>
+                <span>隐患问题:</span>
                 <el-input
                   v-model="tableQuery.queryParam.keyword"
-                  placeholder="搜索文件名称或编号"
+                  placeholder="请输入隐患问题、地点、姓名、工号或联系电话"
                   class="act-search-input"
                 />
               </div>
-              <div class="select-box--item">
-                <span>分类:</span>
-                <el-select
-                  v-model="tableQuery.queryParam.classifyName"
-                  placeholder="请选择分类"
-                  clearable
-                >
-                  <el-option label="外部院级文件" value="外部院级文件" />
-                  <el-option label="内部院级文件" value="内部院级文件" />
-                </el-select>
-              </div>
               <div class="select-box--item">
                 <span>状态:</span>
                 <el-select
-                  v-model="tableQuery.queryParam.status"
+                  v-model="tableQuery.queryParam.statusType"
                   placeholder="请选择状态"
                   clearable
                 >
-                  <el-option label="启用" :value="1" />
-                  <el-option label="禁用" :value="0" />
+                  <el-option label="全部" :value="0" />
+                  <el-option label="待审核" :value="1" />
+                  <el-option label="审核通过" :value="2" />
+                  <el-option label="审核不通过" :value="3" />
                 </el-select>
               </div>
+              <div class="select-box--item">
+                <span>任务来源:</span>
+                <el-input
+                  v-model="tableQuery.queryParam.sourceTypeName"
+                  placeholder="请输入任务来源"
+                  class="act-search-input"
+                />
+              </div>
             </section>
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
@@ -68,20 +67,29 @@
           >
             <template #status="scope">
               <span>
-                {{ scope.row.status === 1 ? '启用' : scope.row.status === 0 ? '禁用' : '-' }}
+                {{ getStatusTypeName(scope.row.statusType ?? getStatusType(scope.row.status)) }}
               </span>
             </template>
             <template #action="scope">
               <div class="action-container--div" style="justify-content: left">
-                <ActionButton text="编辑" @click="handleEdit(scope.row.id)" />
-                <ActionButton
-                  text="删除"
-                  :popconfirm="{
-                    title: '确定要删除?',
-                  }"
-                  @confirm="handleDelete(scope.row.id)"
-                />
-                <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                <!-- 待审核:显示审核和查看 -->
+                <template v-if="scope.row.status === 1">
+                  <ActionButton text="审核" @click="handleApprove(scope.row.id)" />
+                  <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                </template>
+                <!-- 审核通过(需求部门通过或安全部门通过):显示查看和入账 -->
+                <template v-else-if="scope.row.status === 2 || scope.row.status === 4">
+                  <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                  <ActionButton text="入账" @click="handleAccount(scope.row.id)" />
+                </template>
+                <!-- 审核不通过(需求部门驳回或安全部门驳回):显示查看 -->
+                <template v-else-if="scope.row.status === 3 || scope.row.status === 5">
+                  <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                </template>
+                <!-- 其他状态:显示查看 -->
+                <template v-else>
+                  <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                </template>
               </div>
             </template>
           </BasicTable>
@@ -111,11 +119,12 @@
   import { useRouter } from 'vue-router';
   import type { QueryPageRequest } from '@/types/basic-query';
   import {
-    queryAcademyFilePage,
-    deleteAcademyFile,
-    exportAcademyFile,
-    type ProductionSafetyFileQuery,
-  } from '@/api/production-safety-system';
+    queryHiddenDangerPage,
+    exportHiddenDanger,
+    accountEmployeeHazardReport,
+    type QueryHiddenDangerReq,
+    type HiddenDanger,
+  } from '@/api/production-safety';
   import { downloadByData } from '@/utils/file/download';
   import BatchImport from '@/components/batch-import/BatchImport.vue';
   import { useGlobSetting } from '@/hooks/setting';
@@ -128,17 +137,30 @@
 
   const { tableConfig, pagination } = useTableConfig(INVENTORY_TABLE_COLUMNS, TABLE_OPTIONS);
 
-  const tableData = ref<any[]>([]);
+  const tableData = ref<HiddenDanger[]>([]);
+
+  // 将 status (1-7) 转换为 statusType (1-3)
+  const getStatusType = (status: number): number => {
+    if (status === 1) return 1;
+    if (status === 2 || status === 4 || status === 6) return 2;
+    if (status === 3 || status === 5 || status === 7) return 3;
+    return 0;
+  };
+
+  const getStatusTypeName = (statusType: number): string => {
+    if (statusType === 1) return '待审核';
+    if (statusType === 2) return '审核通过';
+    if (statusType === 3) return '审核不通过';
+    return '-';
+  };
 
-  const tableQuery = reactive<QueryPageRequest<ProductionSafetyFileQuery>>({
+  const tableQuery = reactive<QueryPageRequest<QueryHiddenDangerReq>>({
     pageNumber: pagination.pageNumber,
     pageSize: pagination.pageSize,
     queryParam: {
-      keyword: '', // 文件名称/编号(模糊查询)
-      status: 1, // 状态:1-启用,0-禁用
-      classifyName: '', // 分类名称:外部院级文件/内部院级文件
-      startDate: '', // 上传日期范围-开始日期
-      endDate: '', // 上传日期范围-结束日期
+      keyword: '',
+      statusType: undefined,
+      sourceTypeName: '',
     },
   });
 
@@ -154,28 +176,16 @@
     getTableData();
   };
 
-
   async function getTableData() {
     tableConfig.loading = true;
     try {
-      const res = await queryAcademyFilePage(tableQuery);
+      const res = await queryHiddenDangerPage(tableQuery);
       if (res) {
-        // 映射返回数据字段到表格字段
-        tableData.value = res.records.map((item) => ({
-          id: item.id,
-          fileName: item.fileName, // 文件名称
-          fileCode: item.fileCode, // 文件编号
-          classifyName: item.classifyName, // 分类名称
-          fileVersion: item.fileVersion, // 文件版本号
-          fileFormat: item.fileFormat, // 文件格式
-          releaseDate: item.releaseDate, // 发布日期
-          status: item.status, // 状态:1-启用,0-禁用
-          uploadTime: item.uploadTime || item.createdAt, // 上传时间
-        }));
-        pagination.total = res.total || 0;
+        tableData.value = res.records || [];
+        pagination.total = res.totalRow || 0;
       }
     } catch (e) {
-      console.error('获取院级文件列表失败:', e);
+      console.error('获取隐患上报列表失败:', e);
       tableData.value = [];
       pagination.total = 0;
     } finally {
@@ -191,18 +201,15 @@
 
   const handleReset = () => {
     tableQuery.queryParam.keyword = '';
-    tableQuery.queryParam.status = undefined;
-    tableQuery.queryParam.classifyName = '';
-    tableQuery.queryParam.startDate = '';
-    tableQuery.queryParam.endDate = '';
+    tableQuery.queryParam.statusType = undefined;
+    tableQuery.queryParam.sourceTypeName = '';
     handleSearch();
   };
 
-  // 批量导入
   const batchImportVisible = ref(false);
   const { urlPrefix } = useGlobSetting();
-  const importApiUrl = ref(urlJoin(urlPrefix, '/productionSafety/academyFile/import'));
-  const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/import-academy-file-template.xlsx');
+  const importApiUrl = ref(urlJoin(urlPrefix, '/api/employeeHazardReport/importEmployeeHazardReport'));
+  const templateUrl = ref('');
 
   const handleImport = () => {
     batchImportVisible.value = true;
@@ -215,21 +222,19 @@
 
   const handleDownload = async () => {
     try {
-      const exportParams: ProductionSafetyFileQuery = {
+      const exportParams: QueryHiddenDangerReq = {
         keyword: tableQuery.queryParam.keyword || undefined,
-        status: tableQuery.queryParam.status,
-        classifyName: tableQuery.queryParam.classifyName || undefined,
-        startDate: tableQuery.queryParam.startDate || undefined,
-        endDate: tableQuery.queryParam.endDate || undefined,
+        statusType: tableQuery.queryParam.statusType,
+        sourceTypeName: tableQuery.queryParam.sourceTypeName || undefined,
       };
-      const response = await exportAcademyFile(exportParams);
+      const response = await exportHiddenDanger(exportParams);
       if (response) {
-        const fileName = `院级文件管理_${new Date().toISOString().split('T')[0]}.xlsx`;
+        const fileName = `员工上报隐患管理(管理员审核)_${new Date().toISOString().split('T')[0]}.xlsx`;
         downloadByData(response, fileName);
         ElMessage.success('导出成功');
       }
     } catch (e) {
-      console.error('导出院级文件失败:', e);
+      console.error('导出隐患上报失败:', e);
       ElMessage.error('导出失败,请重试');
     }
   };
@@ -243,37 +248,37 @@
     });
   };
 
-  const handleEdit = (id: number) => {
+  const handleView = (id: number) => {
     router.push({
       name: 'hiddenTroubleReviewManagementItem',
       query: {
         id,
-        operate: 'hidden-trouble-review-edit',
+        operate: 'hidden-trouble-review-view',
       },
     });
   };
 
-  const handleDelete = async (id: number) => {
-    try {
-      await deleteAcademyFile(id);
-      ElMessage.success('删除成功');
-      getTableData();
-    } catch (e) {
-      console.error('删除院级文件失败:', e);
-      ElMessage.error('删除失败,请重试');
-    }
-  };
-
-  const handleView = (id: number) => {
+  const handleApprove = (id: number) => {
     router.push({
       name: 'hiddenTroubleReviewManagementItem',
       query: {
         id,
-        operate: 'hidden-trouble-review-view',
+        operate: 'hidden-trouble-review-approve',
       },
     });
   };
 
+  const handleAccount = async (hazardId: number) => {
+    try {
+      await accountEmployeeHazardReport(hazardId);
+      ElMessage.success('入账成功');
+      getTableData();
+    } catch (e) {
+      console.error('入账失败:', e);
+      ElMessage.error('入账失败,请重试');
+    }
+  };
+
   onMounted(() => {
     getTableData();
   });
@@ -284,4 +289,4 @@
   @use '@/styles/page-main-layout.scss' as *;
   @use '@/styles/basic-table-action.scss' as *;
   @use '@/views/traffic/violation/style/act-search-table.scss' as *;
-</style>
+</style>

+ 8 - 7
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/hiddenTroubleReviewManagement/hiddenTroubleReviewManagementItem.vue

@@ -4,7 +4,7 @@
       <BreadcrumbBack />
       <span class="breadcrumb-title">{{ headerTitle }}</span>
     </header>
-    <HiddenTroubleReviewManagementDetail />
+    <EmployeeReportHiddenTroubleManagementDetail />
   </div>
 </template>
 
@@ -12,7 +12,7 @@
   import { computed } from 'vue';
   import { useRoute } from 'vue-router';
   import BreadcrumbBack from '@/components/BreadcrumbBack.vue';
-  import HiddenTroubleReviewManagementDetail from './components/hiddenTroubleReviewManagementDetail.vue';
+  import EmployeeReportHiddenTroubleManagementDetail from '../employeeReportHiddenTroubleManagement/components/employeeReportHiddenTroubleManagementDetail.vue';
 
   const route = useRoute();
   const operate = route.query.operate as string;
@@ -20,13 +20,15 @@
   const headerTitle = computed(() => {
     switch (operate) {
       case 'hidden-trouble-review-create':
-        return '新增隐患审核';
+        return '新增员工上报隐患(管理员审核)';
       case 'hidden-trouble-review-edit':
-        return '编辑隐患审核';
+        return '编辑员工上报隐患(管理员审核)';
       case 'hidden-trouble-review-view':
-        return '查看隐患审核';
+        return '查看员工上报隐患(管理员审核)';
+      case 'hidden-trouble-review-approve':
+        return '审核员工上报隐患(管理员审核)';
       default:
-        return '未知操作';
+        return '查看员工上报隐患(管理员审核)';
     }
   });
 </script>
@@ -41,4 +43,3 @@
     gap: 8px !important;
   }
 </style>
-

+ 28 - 4
src/views/production-safety/safetyAssessment/evaluationDepartment/components/EvaluationDepartmentFeedback.vue

@@ -1,5 +1,13 @@
 <template>
   <main class="safety-platform-container__main">
+    <!-- 复核不通过提示条:仅在 evaluationDepartment-feedback 且 reviewRejectReson 有值时显示 -->
+    <el-alert
+      v-if="isFeedbackOperate && reviewRejectReson"
+      type="error"
+      :title="`复核不通过原因:${reviewRejectReson}`"
+      show-icon
+      class="reject-alert"
+    />
     <el-form ref="formRef" :model="ruleFormData" :rules="formRules" label-width="auto" class="evaluation-form">
       <el-form-item label="考核信息标题:" prop="evaluationTitle">
         <el-input v-model="ruleFormData.evaluationTitle" placeholder="请输入考核信息标题" disabled />
@@ -59,8 +67,8 @@
 </template>
 
 <script setup lang="ts">
-  import { onMounted, ref } from 'vue';
-  import { useRouter } from 'vue-router';
+  import { computed, onMounted, ref } from 'vue';
+  import { useRouter, useRoute } from 'vue-router';
   import { ElMessage } from 'element-plus';
   import type { FormInstance } from 'element-plus';
   import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
@@ -77,6 +85,10 @@
   }>();
 
   const router = useRouter();
+  const route = useRoute();
+
+  // 判断是否为 evaluationDepartment-feedback(反馈)
+  const isFeedbackOperate = computed(() => route.query.operate === 'evaluationDepartment-feedback');
 
   const formRef = ref<FormInstance>();
   const ruleFormData = ref({
@@ -95,10 +107,18 @@
   // 保存详情原始数据,用于提交
   const detailData = ref<any>(null);
 
-  // 计算总计
+  // 复核拒绝原因(用于顶部提示条,仅 evaluationDepartment-feedback 时展示)
+  const reviewRejectReson = computed(() => {
+    const val = detailData.value?.reviewRejectReson;
+    return val && String(val).trim() ? String(val).trim() : '';
+  });
+
+  // 计算总计:根据加减分项计算,加分项加自评得分,减分项减自评得分
   const getTotalScore = () => {
     return evaluationItems.value.reduce((sum, item) => {
-      return sum + (Number(item.selfScore) || 0);
+      const score = Number(item.selfScore) || 0;
+      const isAdd = item.isAdd === 1 || item.scoreType === '加分项';
+      return isAdd ? sum + score : sum - score;
     }, 0);
   };
 
@@ -311,6 +331,10 @@
 <style scoped lang="scss">
   @use '@/styles/page-details-layout.scss' as *;
 
+  .reject-alert {
+    margin-bottom: 20px;
+  }
+
   .evaluation-form {
     display: flex;
     flex-direction: column;

+ 35 - 6
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemFeedback.vue

@@ -1,5 +1,13 @@
 <template>
   <main class="safety-platform-container__main">
+    <!-- 反馈审核不通过提示条:仅在 evaluationSystem-feedback 且 approveRejectReson 有值时显示 -->
+    <el-alert
+      v-if="isFeedbackOperate && approveRejectReson"
+      type="error"
+      :title="approveRejectReson"
+      show-icon
+      class="reject-alert"
+    />
     <el-form ref="formRef" :model="ruleFormData" :rules="formRules" label-width="auto" class="evaluation-form">
       <el-form-item label="考核信息标题:" prop="evaluationTitle">
         <el-input v-model="ruleFormData.evaluationTitle" placeholder="请输入考核信息标题" disabled />
@@ -86,7 +94,7 @@
 </template>
 
 <script setup lang="ts">
-  import { computed, onMounted, ref, watch } from 'vue';
+  import { computed, ref, watch } from 'vue';
   import { useRouter, useRoute } from 'vue-router';
   import { ElMessage } from 'element-plus';
   import type { FormInstance } from 'element-plus';
@@ -113,6 +121,9 @@
   // 判断是评分还是审核
   const isAudit = computed(() => route.query.operate === 'evaluationSystem-audit');
 
+  // 判断是否为 evaluationSystem-feedback(反馈/评分)
+  const isFeedbackOperate = computed(() => route.query.operate === 'evaluationSystem-feedback');
+
   // 判断是否从部门考核结果视图进入(如果是,则不显示提交按钮)
   const isFromDeptView = computed(() => route.query.fromDeptView === 'true');
 
@@ -175,17 +186,27 @@
   // 是否显示复核不通过按钮(从详情接口获取)
   const isSelfApproveButton = ref(false);
 
-  // 计算自评得分总计
+  // 审批拒绝原因(用于顶部提示条,仅 evaluationSystem-feedback 时展示)
+  const approveRejectReson = computed(() => {
+    const val = detailData.value?.approveRejectReson;
+    return val && String(val).trim() ? String('审核不通过原因:' + val).trim() : '';
+  });
+
+  // 计算自评得分总计:根据加减分项计算,加分项加、减分项减(与复核得分规则一致)
   const getTotalScore = () => {
     return evaluationItems.value.reduce((sum, item) => {
-      return sum + (Number(item.selfScore) || 0);
+      const score = Number(item.selfScore) || 0;
+      const isAdd = item.isAdd === 1 || item.scoreType === '加分项';
+      return isAdd ? sum + score : sum - score;
     }, 0);
   };
 
-  // 计算复核得分总计
+  // 计算复核得分总计:根据加减分项计算,加分项加、减分项减(与自评得分规则一致)
   const getTotalReviewScore = () => {
     return evaluationItems.value.reduce((sum, item) => {
-      return sum + (Number(item.reviewScore) || 0);
+      const score = Number(item.reviewScore) || 0;
+      const isAdd = item.isAdd === 1 || item.scoreType === '加分项';
+      return isAdd ? sum + score : sum - score;
     }, 0);
   };
 
@@ -207,8 +228,12 @@
       } else if (column.property === 'scoreType') {
         // 加减分项列显示"总计:"
         sums[index] = '总计:';
+      } else if (column.property === 'selfScore') {
+        // 自评得分列显示总分(按加减分项规则计算)
+        const total = getTotalScore();
+        sums[index] = `${total}分`;
       } else if (column.property === 'reviewScore') {
-        // 复核得分列显示总分,即使为0也显示
+        // 复核得分列显示总分(按加减分项规则计算,与自评得分一致)
         const total = getTotalReviewScore();
         sums[index] = `${total}分`;
       } else {
@@ -456,6 +481,10 @@
 <style scoped lang="scss">
   @use '@/styles/page-details-layout.scss' as *;
 
+  .reject-alert {
+    margin-bottom: 20px;
+  }
+
   .evaluation-form {
     display: flex;
     flex-direction: column;

+ 22 - 11
src/views/production-safety/safetyAssessment/evaluationSystem/evaluationSystem.vue

@@ -194,12 +194,15 @@
           <el-form-item label="部门名称:">
             <el-cascader
               ref="issueDeptCascaderRef"
-              v-model="issueDeptId"
+              v-model="issueDeptIds"
               :options="deptTree"
               :props="cascaderDeptProp"
               :show-all-levels="false"
-              placeholder="请选择部门"
+              placeholder="请选择部门(可多选)"
               filterable
+              clearable
+              collapse-tags
+              collapse-tags-tooltip
               style="width: 100%"
               @change="handleIssueDeptChange"
             />
@@ -331,7 +334,7 @@
     userGroupId: undefined as number | undefined,
     deptSelfApproveUserId: undefined as number | undefined, // 部门自评审核人ID
   });
-  const issueDeptId = ref<number | null>(null);
+  const issueDeptIds = ref<number[]>([]);
 
   // 用户组(用于选择用户名称)
   const userGroupOptions = ref<PersonGroupListItem[]>([]);
@@ -348,6 +351,7 @@
     value: 'id',
     label: 'deptName',
     emitPath: false,
+    multiple: true,
   };
 
   const getDeptTreeData = async () => {
@@ -499,20 +503,26 @@
   };
 
   // 下发
-  const handleIssue = (id: number) => {
+  const handleIssue = async (id: number) => {
     currentIssueId.value = id;
     issueForm.departmentName = '';
     issueForm.startDate = '';
     issueForm.endDate = '';
     issueForm.userGroupId = undefined;
     issueForm.deptSelfApproveUserId = undefined;
-    issueDeptId.value = null;
+    issueDeptIds.value = [];
     issueDialogVisible.value = true;
+    // 弹窗打开时才加载下发弹窗所需数据
+    await Promise.all([
+      getDeptTreeData(),
+      getUserGroupOptions(),
+      getDeptSelfApproveUserList(),
+    ]);
   };
 
   const handleIssueDeptChange = () => {
-    const nodes = issueDeptCascaderRef.value?.getCheckedNodes?.();
-    issueForm.departmentName = nodes?.[0]?.label ?? '';
+    const nodes = issueDeptCascaderRef.value?.getCheckedNodes?.() ?? [];
+    issueForm.departmentName = nodes.map((n: { label?: string; pathLabels?: string[] }) => n.pathLabels?.join('/') || n.label || '').filter(Boolean).join(',');
   };
 
   const handleIssueConfirm = async () => {
@@ -520,6 +530,10 @@
       ElMessage.error('缺少考核表ID');
       return;
     }
+    if (!issueDeptIds.value?.length) {
+      ElMessage.error('请至少选择一个部门');
+      return;
+    }
 
     // 验证日期:开始日期不能大于结束日期
     if (issueForm.startDate && issueForm.endDate) {
@@ -535,7 +549,7 @@
       const payload = {
         id: currentIssueId.value,
         deptNames: issueForm.departmentName,
-        deptIds: issueDeptId.value || 0,
+        deptIds: issueDeptIds.value,
         getUserGroupId: issueForm.userGroupId,
         deptSelfApproveUserId: issueForm.deptSelfApproveUserId,
         planStartTime: issueForm.startDate || undefined,
@@ -677,9 +691,6 @@
 
   onMounted(() => {
     getTableData();
-    getDeptTreeData();
-    getUserGroupOptions();
-    getDeptSelfApproveUserList();
   });
 </script>