xiaweibo 3 bulan lalu
induk
melakukan
69bf87688a

+ 20 - 0
src/api/evaluationSystem/index.ts

@@ -182,6 +182,26 @@ export function saveSecurityExamineIssue(data: SaveSecurityExamineIssueRequest)
   });
 }
 
+/**
+ * 部门自评审核人
+ */
+export interface SecurityExamineSelfApproveUser {
+  id: number;
+  realname: string;
+}
+
+/**
+ * 查询部门自评审核人列表
+ * @param id 考核表ID
+ */
+export function querySecurityExamineSelfApprove(id: number) {
+  return http.request<SecurityExamineSelfApproveUser[]>({
+    url: '/securityExamine/admin/querySecurityExamineSelfApprove',
+    method: 'get',
+    params: { id },
+  });
+}
+
 /**
  * 考核对象评分项
  */

+ 70 - 12
src/views/production-safety/safetyAssessment/evaluationDepartment/components/EvaluationDepartmentFeedback.vue

@@ -55,7 +55,15 @@
               />
             </template>
           </el-table-column>
-          <el-table-column label="资料说明" prop="materialDescription" min-width="200" />
+          <el-table-column label="资料说明" prop="materialDescription" min-width="400">
+            <template #default="scope">
+              <UploadFiles
+                label="上传附件"
+                :file-list="scope.row.attachmentFileList"
+                @uploadSuccess="(files: FileItem[]) => handleRowUploadSuccess(scope.$index, files)"
+              />
+            </template>
+          </el-table-column>
         </el-table>
       </div>
     </div>
@@ -79,6 +87,7 @@
     importSecurityExamineIssueDeptDetail,
   } from '@/api/evaluationSystem';
   import type { FileItem } from '@/components/UploadFiles/types';
+  import { formatAttachmentList } from '@/components/UploadFiles/utils';
 
   const props = defineProps<{
     id: number;
@@ -221,6 +230,12 @@
     }
   };
 
+  // 行内上传附件成功
+  const handleRowUploadSuccess = (rowIndex: number, files: FileItem[]) => {
+    if (!evaluationItems.value[rowIndex]) return;
+    evaluationItems.value[rowIndex].attachmentFileList = files;
+  };
+
   // 将逗号分隔的 URL 字符串转换为 FileItem[] 格式
   const parseAttachmentsToFileList = (attachmentsStr: string | undefined): FileItem[] => {
     if (!attachmentsStr || !attachmentsStr.trim()) {
@@ -280,7 +295,8 @@
           evaluationContent: score.exContent || '', // 考核内容
           scoringMethod: score.scoringWay || '', // 评分方式
           selfScore: score.selfScore || 0, // 自评得分
-          materialDescription: score.attachments || '', // 资料说明(使用附件字段)
+          materialDescription: score.attachments || '', // 资料说明(使用附件字段,字符串)
+          attachmentFileList: parseAttachmentsToFileList(score.attachments || ''), // 对应的附件文件列表
         }));
       } else {
         evaluationItems.value = [];
@@ -300,18 +316,59 @@
         return;
       }
 
-      // 使用详情原始数据,更新自评得分和isAdd字段
+      // 使用详情原始数据,更新自评得分、加减分项及资料说明附件
+      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,
+              selfScore: item ? Number(item.selfScore) || 0 : score.selfScore || 0,
+              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: detailData.value.scores?.map((score: any) => {
-          // 找到对应的自评得分和isAdd
-          const item = evaluationItems.value.find((item) => item.id === score.id);
-          return {
-            ...score,
-            selfScore: item ? Number(item.selfScore) || 0 : score.selfScore || 0,
-            isAdd: item ? (item.isAdd !== undefined ? item.isAdd : (item.selfScore >= 0 ? 1 : 0)) : (score.isAdd !== undefined ? score.isAdd : (score.selfScore >= 0 ? 1 : 0)),
-          };
-        }) || [],
+        scores: updatedScores,
       };
 
       await updateSecurityExamineDeptSubmit(submitData);
@@ -330,6 +387,7 @@
 
 <style scoped lang="scss">
   @use '@/styles/page-details-layout.scss' as *;
+  @use '@/styles/basic-table-file.scss' as *;
 
   .reject-alert {
     margin-bottom: 20px;

+ 1 - 8
src/views/production-safety/safetyAssessment/evaluationDepartment/configs/tables.ts

@@ -7,14 +7,7 @@ export const TABLE_OPTIONS = {
   maxHeight: 'calc(70vh - 150px)',
 };
 
-export const EVALUATION_DEPARTMENT_TABLE_COLUMNS: TableColumnProps[] = [
-  {
-    prop: 'select',
-    label: '',
-    type: 'selection',
-    align: 'center',
-    width: '80px',
-  },
+export const EVALUATION_DEPARTMENT_TABLE_COLUMNS: TableColumnProps[] = [  
   {
     label: '编号',
     type: 'index',

+ 69 - 12
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemFeedback.vue

@@ -43,7 +43,15 @@
           <el-table-column label="评分方式" prop="scoringMethod" min-width="150" />
           <el-table-column label="加减分项" prop="scoreType" min-width="120" />
           <el-table-column label="自评得分" prop="selfScore" min-width="120" />
-          <el-table-column label="资料说明" prop="materialDescription" min-width="200" />
+          <el-table-column label="资料说明" prop="materialDescription" min-width="400">
+            <template #default="scope">
+              <UploadFiles
+                label="上传附件"
+                :file-list="scope.row.attachmentFileList"
+                @uploadSuccess="(files) => handleRowUploadSuccess(scope.$index, files)"
+              />
+            </template>
+          </el-table-column>
           <el-table-column label="复核人姓名" prop="reviewUserName" min-width="120" />
           <el-table-column label="复核得分" prop="reviewScore" min-width="180">
             <template #default="scope">
@@ -110,6 +118,7 @@
     importSecurityExamineIssueDeptDetail,
   } from '@/api/evaluationSystem';
   import type { FileItem } from '@/components/UploadFiles/types';
+  import { formatAttachmentList } from '@/components/UploadFiles/utils';
 
   const props = defineProps<{
     id: number;
@@ -313,6 +322,12 @@
     }
   };
 
+  // 行内上传附件成功
+  const handleRowUploadSuccess = (rowIndex: number, files: FileItem[]) => {
+    if (!evaluationItems.value[rowIndex]) return;
+    evaluationItems.value[rowIndex].attachmentFileList = files;
+  };
+
   // 将逗号分隔的 URL 字符串转换为 FileItem[] 格式
   const parseAttachmentsToFileList = (attachmentsStr: string | undefined): FileItem[] => {
     if (!attachmentsStr || !attachmentsStr.trim()) {
@@ -386,7 +401,8 @@
           selfScore: score.selfScore || 0, // 自评得分
           reviewUserName: score.reviewUserName || '-', // 复核人姓名(从详情顶层获取)
           reviewScore: score.reviewScore || 0, // 复核得分
-          materialDescription: score.attachments || '', // 资料说明(使用附件字段)
+          materialDescription: score.attachments || '', // 资料说明(使用附件字段,字符串)
+          attachmentFileList: parseAttachmentsToFileList(score.attachments || ''), // 资料说明对应的附件文件列表
           isReviewInput: score.isReviewInput == true, // 是否显示复核得分输入框
         }));
       } else {
@@ -407,18 +423,59 @@
         return;
       }
 
-      // 使用详情原始数据,更新复核得分和isAdd字段
+      // 使用详情原始数据,更新复核得分、加减分项及资料说明附件
+      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,
+              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: detailData.value.scores?.map((score: any) => {
-          // 找到对应的复核得分和isAdd
-          const item = evaluationItems.value.find((item) => item.id === score.id);
-          return {
-            ...score,
-            reviewScore: item ? Number(item.reviewScore) || 0 : score.reviewScore || 0,
-            isAdd: item ? (item.isAdd !== undefined ? item.isAdd : (item.selfScore >= 0 ? 1 : 0)) : (score.isAdd !== undefined ? score.isAdd : (score.selfScore >= 0 ? 1 : 0)),
-          };
-        }) || [],
+        scores: updatedScores,
       };
 
       if (isAudit.value) {

+ 9 - 13
src/views/production-safety/safetyAssessment/evaluationSystem/evaluationSystem.vue

@@ -201,7 +201,7 @@
               @change="handleIssueDeptChange"
             />
           </el-form-item>
-          <el-form-item label="用户名称:">
+          <el-form-item label="用户名称分组:">
             <el-select
               v-model="issueForm.userGroupId"
               placeholder="请选择用户组"
@@ -287,6 +287,7 @@
     deleteSecurityExamine,
     saveSecurityExamineIssue,
     updateSecurityExamineRepeal,
+    querySecurityExamineSelfApprove,
   } from '@/api/evaluationSystem';
   import type { EvaluationSystemQueryParam } from '@/api/evaluationSystem';
   import { ElMessage } from 'element-plus';
@@ -298,8 +299,7 @@
   import type { DeptTree } from '@/types/dept/type';
   import { queryUserGroupPage } from '@/api/system/person-group';
   import type { PersonGroupListItem } from '@/types/person-group/type';
-  import { queryAvailableUserList } from '@/api/production-safety/responsibility-implementation';
-  import type { UserLisItem } from '@/api/system/user-operate';
+  import type { SecurityExamineSelfApproveUser } from '@/api/evaluationSystem';
 
   const router = useRouter();
 
@@ -329,7 +329,7 @@
   const userGroupOptions = ref<PersonGroupListItem[]>([]);
 
   // 部门自评审核人用户列表
-  const deptSelfApproveUserList = ref<UserLisItem[]>([]);
+  const deptSelfApproveUserList = ref<SecurityExamineSelfApproveUser[]>([]);
 
   // 部门树(复用物品领取记录的部门字段下拉框逻辑)
   const issueDeptCascaderRef = ref();
@@ -367,15 +367,11 @@
     }
   };
 
-  // 获取部门自评审核人用户列表
-  const getDeptSelfApproveUserList = async () => {
+  // 获取部门自评审核人用户列表(根据考核表ID查询)
+  const getDeptSelfApproveUserList = async (id: number) => {
     try {
-      const res = await queryAvailableUserList({
-        pageNumber: 1,
-        pageSize: 9999,
-        queryParam: {}, // 不传递 deptId 参数
-      });
-      deptSelfApproveUserList.value = res?.records || [];
+      const res = await querySecurityExamineSelfApprove(id);
+      deptSelfApproveUserList.value = res || [];
     } catch (e) {
       console.error('获取部门自评审核人列表失败:', e);
       deptSelfApproveUserList.value = [];
@@ -503,7 +499,7 @@
     issueDeptIds.value = [];
     issueDialogVisible.value = true;
     // 弹窗打开时才加载下发弹窗所需数据
-    await Promise.all([getDeptTreeData(), getUserGroupOptions(), getDeptSelfApproveUserList()]);
+    await Promise.all([getDeptTreeData(), getUserGroupOptions(), getDeptSelfApproveUserList(id)]);
   };
 
   const handleIssueDeptChange = () => {

+ 1 - 2
src/views/production-safety/safetyAssessment/pointDeduction/components/PointDeductionDetail.vue

@@ -14,7 +14,7 @@
       </template>
       <template #deductionReason>
         <el-select
-          v-if="!isViewMode"
+          :disabled="isViewMode"
           v-model="ruleFormData.hiddenDangerId"
           placeholder="请选择扣分原因"
           filterable
@@ -29,7 +29,6 @@
             :value="item.id"
           />
         </el-select>
-        <span v-else>{{ ruleFormData.deductionReason || '-' }}</span>
       </template>
     </BasicForm>
   </main>