소스 검색

Merge remote-tracking branch 'origin/feat/production-safety' into feat/production-safety

sunqijun 2 달 전
부모
커밋
0090a7ecb5

+ 2 - 5
src/api/evaluationSystem/index.ts

@@ -459,14 +459,11 @@ export function updateSecurityExamineIssueApproveAgree(id: number) {
 /**
  * 管理员端审核不通过
  */
-export function updateSecurityExamineIssueApproveDisagree(id: number, approveRejectReson?: string) {
+export function updateSecurityExamineIssueApproveDisagree(data: { id: number; approveRejectReson?: string; psemId?: number }) {
   return http.request({
     url: '/securityExamine/admin/updateSecurityExamineIssueApproveDisagree',
     method: 'put',
-    data: {
-      id,
-      approveRejectReson,
-    },
+    data,
   });
 }
 

+ 1 - 0
src/views/production-safety/risk-identification-and-control/special-equipment-manage/list.vue

@@ -305,6 +305,7 @@
   @use '@/styles/page-details-layout.scss' as *;
   @use '@/styles/page-main-layout.scss' as *;
   @use '@/styles/basic-table-action.scss' as *;
+  @use '@/views/traffic/violation/style/act-search-table.scss' as *;
 
   :deep(.el-tabs__header) {
     margin: 0;

+ 12 - 18
src/views/production-safety/safetyAssessment/evaluationDepartment/components/EvaluationDepartmentAdvancedPerson.vue

@@ -39,17 +39,9 @@
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
               <el-button @click="handleReset">重置</el-button>
-              <el-dropdown trigger="click" @command="selectDeptType">
-                <el-button type="primary" style="margin:0 10px;">
-                  添加
-                </el-button>
-                <template #dropdown>
-                  <el-dropdown-menu>
-                    <el-dropdown-item command="normal">普通部门</el-dropdown-item>
-                    <el-dropdown-item command="advanced">先进集体部门</el-dropdown-item>
-                  </el-dropdown-menu>
-                </template>
-              </el-dropdown>
+              <el-button type="primary" style="margin:0 10px;" @click="handleAdd">
+                添加
+              </el-button>
               <el-button plain  @click="handleExport">
                 导出
               </el-button>
@@ -79,7 +71,7 @@
     <!-- 添加/编辑先进个人对话框 -->
     <el-dialog
       v-model="addDialogVisible"
-      :title="`${isEditMode ? '编辑' : '新增'}先进个人 (${deptType === 'normal' ? '普通部门' : '先进集体部门'})`"
+      :title="`${isEditMode ? '编辑' : '新增'}先进个人`"
       width="800px"
       :close-on-click-modal="false"
       @close="handleDialogClose"
@@ -269,6 +261,8 @@
 
   // 考核表详情
   const evaluationDetail = ref<Partial<EvaluationTargetItem>>({});
+  // isAdvancedGroup 为 true 表示先进集体部门,false 表示普通部门
+  const isAdvancedGroup = computed(() => Boolean(route.query.isAdvancedGroup));
   const deptId = ref<number | undefined>(undefined); // 部门ID
   const psemId = ref<number | undefined>(undefined); // 考核表ID(从接口获取)
   const deptUserId = ref<number | undefined>(undefined); // 部门用户ID(从接口获取)
@@ -392,13 +386,12 @@
     handleSearch();
   };
 
-  // 选择部门类型(从下拉菜单触发
-  const selectDeptType = (type: 'normal' | 'advanced') => {
-    deptType.value = type;
+  // 点击添加:根据 isAdvancedGroup 直接打开对应弹窗(true=先进集体部门,false=普通部门
+  const handleAdd = () => {
+    deptType.value = isAdvancedGroup.value ? 'advanced' : 'normal';
     addDialogVisible.value = true;
-    
-    // 如果是先进集体部门,初始化表格数据(默认1行)
-    if (type === 'advanced') {
+
+    if (isAdvancedGroup.value) {
       advancedFormList.value = [
         {
           employeeCode: '',
@@ -690,6 +683,7 @@
           deptNames: res.deptName, // 部门端接口返回的是 deptName,不是 deptNames
           createdUserName: res.deptUserName || '-', // 部门端可能没有创建人字段,使用部门用户名
           createdAt: res.createdAt,
+          isAdvancedGroup: res.isAdvancedGroup,
         };
         // 保存部门ID、考核表ID和部门用户ID,用于提交时使用
         deptId.value = res.deptId;

+ 17 - 8
src/views/production-safety/safetyAssessment/evaluationDepartment/components/EvaluationDepartmentFeedback.vue

@@ -47,13 +47,11 @@
               <span class="required-star">*</span>自评得分
             </template>
             <template #default="scope">
-              <el-input-number
-                v-model="scope.row.selfScore"
-                :min="0"
-                :max="99999"
-                :precision="0"
-                :step="1"
+              <el-input
+                :model-value="scope.row.selfScore"
                 placeholder="请输入自评得分"
+                maxlength="5"
+                @update:model-value="(v) => handleSelfScoreInput(scope.row, v)"
                 @blur="handleScoreBlur"
               />
             </template>
@@ -70,7 +68,7 @@
               />
             </template>
           </el-table-column>
-          <el-table-column label="复核不通过原因" prop="reviewRejectReson" min-width="220"></el-table-column>
+          <el-table-column v-if="reviewRejectReson" label="复核不通过原因" prop="reviewRejectReson" min-width="220"></el-table-column>
         </el-table>
       </div>
     </div>
@@ -138,6 +136,17 @@
     }, 0);
   };
 
+  // 自评得分输入:仅允许数字,范围 0-99999
+  const handleSelfScoreInput = (row: { selfScore?: number | null }, v: string | number) => {
+    const str = String(v ?? '').replace(/\D/g, '');
+    if (str === '') {
+      row.selfScore = undefined as unknown as number;
+      return;
+    }
+    const num = Math.min(Number(str), 99999);
+    row.selfScore = num;
+  };
+
   // 自评得分失去焦点时触发(用于强制更新合计行)
   const handleScoreBlur = () => {
     // 触发响应式更新,让合计行重新计算
@@ -301,7 +310,7 @@
           evaluationItem: score.exProgram || '', // 考核项目
           evaluationContent: score.exContent || '', // 考核内容
           scoringMethod: score.scoringWay || '', // 评分方式
-          selfScore: score.selfScore || 0, // 自评得分
+          selfScore: score.selfScore, // 自评得分
           materialDescription: score.attachments || '', // 资料说明(使用附件字段,字符串)
           reviewRejectReson: score.reviewRejectReson || '', // 复核不通过原因
           attachmentFileList: parseAttachmentsToFileList(score.attachments || ''), // 对应的附件文件列表

+ 5 - 3
src/views/production-safety/safetyAssessment/evaluationDepartment/evaluationDepartment.vue

@@ -97,7 +97,7 @@
                 <!-- 已完成(1):显示反馈和先进个人申报 -->
                 <template v-else-if="Number(scope.row.status) === 1">
                   <!-- <ActionButton text="反馈" @click="handleFeedback(scope.row.id)" /> -->
-                  <ActionButton text="先进个人申报" @click="handleAdvancedPerson(scope.row.id)" />
+                  <ActionButton text="先进个人申报" @click="handleAdvancedPerson(scope.row)" />
                 </template>
                 <!-- 已作废(5):显示反馈 -->
                 <template v-else-if="Number(scope.row.status) === 5">
@@ -201,6 +201,7 @@
           deptName: item.deptName,
           scores: item.scores,
           scoreRank: item.scoreRank,
+          isAdvancedGroup: item.isAdvancedGroup,
         }));
         pagination.total = res.totalRow;
       }
@@ -244,12 +245,13 @@
     });
   };
 
-  const handleAdvancedPerson = (id: number) => {
+  const handleAdvancedPerson = (row: any) => {
     router.push({
       name: 'EvaluationDepartmentItem',
       query: {
-        id,
+        id: row.id,
         operate: 'evaluationDepartment-advanced-person',
+        isAdvancedGroup: row.isAdvancedGroup,
       },
     });
   };

+ 92 - 13
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemFeedback.vue

@@ -48,7 +48,7 @@
           <el-table-column label="加减分项" prop="scoreType" min-width="120" />
           <el-table-column label="自评得分" prop="selfScore" min-width="120">
             <template #default="scope">
-              {{ scope.row.selfScore === 0 || scope.row.selfScore === null || scope.row.selfScore === undefined ? '' : scope.row.selfScore }}
+              {{ scope.row.selfScore }}
             </template>
           </el-table-column>
           <el-table-column label="资料说明" prop="materialDescription" min-width="200">
@@ -77,10 +77,10 @@
             </template>
           </el-table-column>
           <el-table-column label="复核人姓名" prop="reviewUserName" min-width="120" />
-          <el-table-column label="复核得分" prop="reviewScore" min-width="180">
+          <el-table-column label="复核得分" prop="reviewScore" min-width="200">
             <template #default="scope">
               <el-input-number
-                v-if="scope.row.isReviewInput"
+                v-if="!isAudit && scope.row.isReviewInput"
                 v-model="scope.row.reviewScore"
                 :min="0"
                 :max="99999"
@@ -89,19 +89,19 @@
                 placeholder="请输入复核得分"
                 @blur="handleScoreBlur"
               />
-              <span v-else>{{ scope.row.reviewScore === 0 || scope.row.reviewScore === null || scope.row.reviewScore === undefined ? '' : scope.row.reviewScore }}</span>
+              <span v-else>{{ scope.row.reviewScore }}</span>
             </template>
           </el-table-column>
           <el-table-column label="复核不通过原因" prop="reviewRejectReson" min-width="220">
             <template #default="scope">
               <el-input
-                v-if="isSelfApproveButton"
+                v-if="!isAudit && isSelfApproveButton"
                 v-model="scope.row.reviewRejectReson"
                 type="textarea"
                 :rows="2"
                 placeholder="请输入复核不通过原因"
               />
-              <span v-else>{{ scope.row.reviewRejectReson || '-' }}</span>
+              <span v-else>{{ scope.row.reviewRejectReson}}</span>
             </template>
           </el-table-column>
         </el-table>
@@ -112,6 +112,8 @@
     <el-button @click="router.back()">取消</el-button>
     <el-button v-if="!isAudit && isSelfApproveButton" @click="openRejectDialog('review')">复核不通过</el-button>
     <el-button v-if="isAudit" @click="openRejectDialog('approve')">审核不通过</el-button>
+    <el-button v-if="!isAudit && isSelfApproveButton" type="primary" @click="handleSubmitItem">保存</el-button>
+
     <el-button v-if="!isFromDeptView" type="primary" @click="handleSubmit">{{ getSubmitButtonText }}</el-button>
   </footer>
 
@@ -185,7 +187,7 @@
     if (isSelfApproveButton.value) {
       return '提交';
     }
-    return '复核提交';
+    return '保存';
   });
 
   // 拒绝原因弹窗相关
@@ -480,9 +482,9 @@
           evaluationItem: score.exProgram || '', // 考核项目
           evaluationContent: score.exContent || '', // 考核内容
           scoringMethod: score.scoringWay || '', // 评分方式
-          selfScore: score.selfScore || 0, // 自评得分
+          selfScore: score.selfScore, // 自评得分
           reviewUserName: score.reviewUserName || '-', // 复核人姓名(从详情顶层获取)
-          reviewScore: score.reviewScore || 0, // 复核得分
+          reviewScore: score.reviewScore, // 复核得分
           reviewRejectReson: score.reviewRejectReson || '', // 复核不通过原因
           materialDescription: score.attachments || '', // 资料说明(使用附件字段,字符串)
           attachmentFileList: parseAttachmentsToFileList(score.attachments || ''), // 资料说明对应的附件文件列表
@@ -572,11 +574,11 @@
         if (isSelfApproveButton.value) {
           // isSelfApproveButton 为 true,调用复核同意接口
           await updateSecurityExamineIssueReviewAgree(submitData);
-          ElMessage.success('复核同意操作成功');
+          ElMessage.success('提交操作成功');
         } else {
           // isSelfApproveButton 为 false,调用提交接口
-          await updateSecurityExamineIssueReviewAgree(submitData);
-          ElMessage.success('复核提交成功');
+          await updateSecurityExamineIssueReviewSubmit(submitData);
+          ElMessage.success('保存成功');
         }
       }
       router.back();
@@ -585,6 +587,78 @@
       ElMessage.error(e?.message || '提交失败,请重试');
     }
   };
+  const handleSubmitItem = async () => {
+    const res = await handleValidate();
+    if (!res) return;
+    try {
+      if (!detailData.value) {
+        ElMessage.error('数据加载失败,请刷新后重试');
+        return;
+      }
+
+      // 使用详情原始数据,更新复核得分、加减分项及资料说明附件
+      const updatedScores =
+        (await Promise.all(
+          (detailData.value.scores || []).map(async (score: any) => {
+            const item = evaluationItems.value.find((row) => row.id === score.id);
+
+            // 处理资料说明附件:将 UploadFiles 返回的文件列表转换为逗号分隔的 URL 字符串
+            let attachments = score.attachments || '';
+            if (item && Array.isArray(item.attachmentFileList)) {
+              const existingFiles: string[] = [];
+              const newFiles: any[] = [];
+
+              item.attachmentFileList.forEach((file: any) => {
+                if (file.fileUrl && !file.file) {
+                  existingFiles.push(file.fileUrl);
+                } else {
+                  newFiles.push(file);
+                }
+              });
+
+              let uploadedUrls: string[] = [];
+              if (newFiles.length > 0) {
+                const uploadedFiles = await formatAttachmentList(newFiles);
+                uploadedUrls = uploadedFiles
+                  .map((f: any) => f.fileUrl || f.url || '')
+                  .filter((url: string) => url);
+              }
+
+              attachments = [...existingFiles, ...uploadedUrls].filter((url) => url).join(',');
+            }
+
+            return {
+              ...score,
+              reviewScore: item ? Number(item.reviewScore) || 0 : score.reviewScore || 0,
+              reviewRejectReson: item ? item.reviewRejectReson || '' : score.reviewRejectReson || '',
+              isAdd: item
+                ? item.isAdd !== undefined
+                  ? item.isAdd
+                  : item.selfScore >= 0
+                    ? 1
+                    : 0
+                : score.isAdd !== undefined
+                  ? score.isAdd
+                  : score.selfScore >= 0
+                    ? 1
+                    : 0,
+              attachments,
+            };
+          }),
+        )) || [];
+
+      const submitData = {
+        ...detailData.value,
+        scores: updatedScores,
+      };
+      await updateSecurityExamineIssueReviewSubmit(submitData);
+      ElMessage.success('保存成功');
+      router.back();
+    } catch (e: any) {
+      console.error('提交失败:', e);
+      ElMessage.error(e?.message || '提交失败,请重试');
+    }
+  };
 
   const confirmReject = async () => {
     if (!rejectReason.value || !rejectReason.value.trim()) {
@@ -602,7 +676,12 @@
         await updateSecurityExamineIssueReviewDisagree(submitData);
         ElMessage.success('复核不通过操作成功');
       } else {
-        await updateSecurityExamineIssueApproveDisagree(props.id, rejectReason.value.trim());
+        const submitData = {
+          id: props.id,
+          approveRejectReson: rejectReason.value.trim(),
+          psemId: detailData.value.psemId,
+        };
+        await updateSecurityExamineIssueApproveDisagree(submitData);
         ElMessage.success('审核不通过操作成功');
       }
       closeRejectDialog();

+ 1 - 1
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationTarget.vue

@@ -461,7 +461,7 @@
               isAdvancedGroup: item.isAdvancedGroup || false, // 是否先进集体(需要接口返回,暂时使用 false)
               departmentSort: item.scoreRank || 0, // 部门排序(使用排名)
               departmentLeader: item.deptUserName || '-', // 部门负责人
-              baseScore: item.baseNum || 0, // 基础分,默认为100
+              baseScore: item.basicNum || 0, // 基础分,默认为100
               reviewSum: item.reviewSum || 0, // 总分数
               addSum: item.addSum || 0, // 加分项分数
               subSum: item.subSum || 0, // 减分项分数

+ 2 - 2
src/views/production-safety/safetyAssessment/evaluationSystem/configs/status.ts

@@ -1,7 +1,7 @@
 // 安全考核管理状态配置(搜索条件使用数值状态码)
 // 0-未下发 / 2-待反馈 / 3-待复核 / 4-待审核 / 5-已作废 / 1-已完成
 export const EVALUATION_SYSTEM_STATUS_OPTIONS = [
-  { label: '未下发', value: 0 },
+  // { label: '未下发', value: 0 },
   { label: '待反馈', value: 2 },
   { label: '待复核', value: 3 },
   { label: '待审核', value: 4 },
@@ -10,7 +10,7 @@ export const EVALUATION_SYSTEM_STATUS_OPTIONS = [
 ];
 
 export const EVALUATION_SYSTEM_STATUS_LABEL: Record<string, string> = {
-  '0': '未下发',
+  // '0': '未下发',
   '2': '待反馈',
   '3': '待复核',
   '4': '待审核',

+ 6 - 6
src/views/production-safety/safetyAssessment/evaluationSystem/configs/targetTables.ts

@@ -94,12 +94,6 @@ export const EVALUATION_ADVANCED_GROUP_TABLE_COLUMNS: TableColumnProps[] = [
     align: 'center',
     minWidth: '100px',
   },
-  {
-    label: '总分数',
-    prop: 'reviewSum',
-    align: 'center',
-    minWidth: '100px',
-  },
   {
     label: '加分项分数',
     prop: 'addSum',
@@ -112,6 +106,12 @@ export const EVALUATION_ADVANCED_GROUP_TABLE_COLUMNS: TableColumnProps[] = [
     align: 'center',
     minWidth: '120px',
   },
+  {
+    label: '总分数',
+    prop: 'reviewSum',
+    align: 'center',
+    minWidth: '100px',
+  },
   {
     label: '操作',
     slot: 'action',

+ 1 - 1
src/views/production-safety/safetyAssessment/evaluationSystem/evaluationSystem.vue

@@ -546,7 +546,7 @@
       getTableData();
     } catch (e) {
       console.error('下发失败:', e);
-      ElMessage.error('下发失败,请重试');
+      ElMessage.error(e?.data || '下发失败,请重试');
     }
   };