Parcourir la source

Merge branch 'feat/production-safety' of http://192.168.6.110/product-group-fe/sfy-safety-group/sfy-safety into feat/production-safety

sunqijun il y a 1 mois
Parent
commit
83e18537c0
16 fichiers modifiés avec 183 ajouts et 50 suppressions
  1. 1 2
      src/api/sensor-group/index.ts
  2. 6 0
      src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanManagementDept/areaCheckPlanManagementDept.vue
  3. 2 0
      src/views/production-safety/implement-safety-duty/non-public-area-responsibilities/list.vue
  4. 2 0
      src/views/production-safety/implement-safety-duty/non-public-list-responsibilities/list.vue
  5. 2 0
      src/views/production-safety/implement-safety-duty/public-area-responsibilities/list.vue
  6. 2 0
      src/views/production-safety/implement-safety-duty/public-list-responsibilities/list.vue
  7. 2 1
      src/views/production-safety/implement-safety-duty/responsibility-notice-manage-admin/components/NotifySend.vue
  8. 2 0
      src/views/production-safety/implement-safety-duty/responsibility-notice-manage-admin/list.vue
  9. 6 1
      src/views/production-safety/risk-identification-and-control/key-site-sensor-manage/CameraGroupListAndTree/CameraGroupList/CameraGroup.vue
  10. 28 3
      src/views/production-safety/risk-identification-and-control/key-site-sensor-manage/CameraGroupListAndTree/CameraGroupList/CameraTreeOfGroupList.vue
  11. 2 2
      src/views/production-safety/risk-identification-and-control/labor-products-requisition-manage/list.vue
  12. 25 4
      src/views/production-safety/safetyAssessment/evaluationDepartment/components/EvaluationDepartmentFeedback.vue
  13. 15 2
      src/views/production-safety/safetyAssessment/evaluationDepartment/evaluationDepartment.vue
  14. 67 32
      src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemDetail.vue
  15. 1 1
      src/views/production-safety/safetyAssessment/evaluationSystem/configs/tables.ts
  16. 20 2
      src/views/production-safety/safetyAssessment/evaluationSystem/evaluationSystem.vue

+ 1 - 2
src/api/sensor-group/index.ts

@@ -93,9 +93,8 @@ export function updateSensorInGroupApi(data: UpdateSensorInGroupReq) {
  */
 export function deleteSensorFromGroupApi(data: DeleteSensorFromGroupReq) {
   return http.request({
-    url: '/sensor/deleteSensorFromGroup',
+    url: `/sensor/deleteSensorFromGroup?groupId=${data.groupId}&deviceNo=${data.deviceNo}`,
     method: 'delete',
-    params: data,
   });
 }
 

+ 6 - 0
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanManagementDept/areaCheckPlanManagementDept.vue

@@ -90,6 +90,12 @@
             <template #needSigneeSign="scope">
               <span>{{ scope.row.needSigneeSign === true ? '是' : scope.row.needSigneeSign === false ? '否' : '-' }}</span>
             </template>
+            <template #planEndTime="scope">
+              <span>{{ scope.row.planEndTime ? scope.row.planEndTime : '-' }}</span>
+            </template>
+            <template #planStartTime="scope">
+              <span>{{ scope.row.planStartTime ? scope.row.planStartTime : '-' }}</span>
+            </template>
             <template #action="scope">
               <div class="action-container--div" style="justify-content: left">
                 <ActionButton text="查看" @click="handleView(scope.row.id)" />

+ 2 - 0
src/views/production-safety/implement-safety-duty/non-public-area-responsibilities/list.vue

@@ -16,6 +16,7 @@
               name: 'areaAddResponsibilities:nonPublic',
             })
           "
+          :icon="Plus"
           >添加
         </el-button>
         <el-button @click="batchImportVisible = true">导入</el-button>
@@ -159,6 +160,7 @@
   } from '@/api/production-safety/responsibility-implementation';
   import urlJoin from 'url-join';
   import { BatchImport } from '@/components/batch-import';
+  import { Plus } from '@element-plus/icons-vue';
 
   import { downloadFile } from '@/views/disaster/utils';
   import { useGlobSetting } from '@/hooks/setting';

+ 2 - 0
src/views/production-safety/implement-safety-duty/non-public-list-responsibilities/list.vue

@@ -16,6 +16,7 @@
               name: 'addResponsibilities:nonPublic',
             })
           "
+          :icon="Plus"
           >添加
         </el-button>
         <el-button @click="batchImportVisible = true">导入</el-button>
@@ -191,6 +192,7 @@
   import { getAllDepartments } from '@/api/auth/dept';
   import { useUserInfoHook } from '@/views/disaster/hooks';
   import { downloadByData } from '@/utils/file/download';
+  import { Plus } from '@element-plus/icons-vue';
 
   const { id } = useUserInfoHook();
   const router = useRouter();

+ 2 - 0
src/views/production-safety/implement-safety-duty/public-area-responsibilities/list.vue

@@ -16,6 +16,7 @@
               name: 'areaAddResponsibilities:public',
             })
           "
+          :icon="Plus"
           >添加
         </el-button>
         <el-button plain  @click="batchImportVisible = true">
@@ -163,6 +164,7 @@
   } from '@/api/production-safety/responsibility-implementation';
   import urlJoin from 'url-join';
   import { BatchImport } from '@/components/batch-import';
+  import { Plus } from '@element-plus/icons-vue';
 
   import { downloadFile } from '@/views/disaster/utils';
   import { useGlobSetting } from '@/hooks/setting';

+ 2 - 0
src/views/production-safety/implement-safety-duty/public-list-responsibilities/list.vue

@@ -16,6 +16,7 @@
               name: 'addResponsibilities:public',
             })
           "
+          :icon="Plus"
           >添加
         </el-button>
         <el-button @click="batchImportVisible = true">导入</el-button>
@@ -182,6 +183,7 @@
   } from '@/api/production-safety/responsibility-implementation';
   import urlJoin from 'url-join';
   import { BatchImport } from '@/components/batch-import';
+  import { Plus } from '@element-plus/icons-vue';
 
   import { downloadFile } from '@/views/disaster/utils';
   import { useGlobSetting } from '@/hooks/setting';

+ 2 - 1
src/views/production-safety/implement-safety-duty/responsibility-notice-manage-admin/components/NotifySend.vue

@@ -20,7 +20,7 @@
           <el-date-picker v-model="formValue.planEndTime" placeholder="请选择日期" style="width: 200px" />
         </el-form-item>
         <el-form-item label="通知区域" prop="safetyAreaData">
-          <el-button @click="handleAddArea" type="primary">添加</el-button>
+          <el-button @click="handleAddArea" type="primary" :icon="Plus">添加</el-button>
         </el-form-item>
         <el-table :data="currentTableData" v-if="formValue.safetyAreaData.length" style="width: 100%; margin: 20px 0 0">
           <!-- <el-table-column type="index" label="序号" width="80" /> -->
@@ -82,6 +82,7 @@
   import { uniqBy, omit } from 'lodash-es';
   import dayjs from 'dayjs';
   import { safetyNoticeAdminIssuedNotice } from '@/api/production-safety/responsibility-implementation';
+  import { Plus } from '@element-plus/icons-vue';
 
   const props = defineProps<{
     type: number;

+ 2 - 0
src/views/production-safety/implement-safety-duty/responsibility-notice-manage-admin/list.vue

@@ -20,6 +20,7 @@
               },
             })
           "
+          :icon="Plus"
           >添加
         </el-button></div
       >
@@ -219,6 +220,7 @@
   import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
   import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
   import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
+  import { Plus } from '@element-plus/icons-vue';
 
   import NotifySend from './components/NotifySend.vue';
 

+ 6 - 1
src/views/production-safety/risk-identification-and-control/key-site-sensor-manage/CameraGroupListAndTree/CameraGroupList/CameraGroup.vue

@@ -59,7 +59,12 @@
   </div>
 
   <div>
-    <el-dialog v-model="showCameraTreeDialog" width="500" :title="`添加传感器至“${cameraGroup.groupName}”区域`">
+    <el-dialog
+      v-model="showCameraTreeDialog"
+      width="500"
+      destroy-on-close
+      :title="`添加传感器至“${cameraGroup.groupName}”区域`"
+    >
       <CameraTreeOfGroupList :cameraGroup="cameraGroup" @close="showCameraTreeDialog = false" />
     </el-dialog>
   </div>

+ 28 - 3
src/views/production-safety/risk-identification-and-control/key-site-sensor-manage/CameraGroupListAndTree/CameraGroupList/CameraTreeOfGroupList.vue

@@ -47,7 +47,12 @@
   import { storeToRefs } from 'pinia';
   import { VideoCamera, WarningFilled, Search } from '@element-plus/icons-vue';
   import { useCameraGroupList } from '@/store/modules/useCameraGroupList';
-  import { queryDeviceListApi, updateSensorInGroupApi } from '@/api/sensor-group';
+  import {
+    batchSaveSensor2GroupApi,
+    deleteSensorFromGroupApi,
+    queryDeviceListApi,
+    saveSensor2GroupApi,
+  } from '@/api/sensor-group';
   import type { DeviceListItem, SensorGroupView, SensorDeviceViewItem } from '@/api/sensor-group/type';
   import Thumbnail from '@/components/thumbnail/Thumbnail.vue';
 
@@ -110,9 +115,29 @@
     saving.value = true;
     try {
       const checkedNodes = (treeRef.value?.getCheckedNodes() as any[]) || [];
-      const deviceNoList = checkedNodes.map((n) => n.code as string);
+      const checkedDeviceNoList = checkedNodes.map((n) => n.code as string);
+      const initialDeviceNoList = initialCheckedKeys.value;
+      const addedDeviceNoList = checkedDeviceNoList.filter((deviceNo) => !initialDeviceNoList.includes(deviceNo));
+      const removedDeviceNoList = initialDeviceNoList.filter((deviceNo) => !checkedDeviceNoList.includes(deviceNo));
 
-      await updateSensorInGroupApi({ groupId: props.cameraGroup.id, deviceNoList });
+      if (removedDeviceNoList.length > 0) {
+        await Promise.all(
+          removedDeviceNoList.map((deviceNo) => deleteSensorFromGroupApi({ groupId: props.cameraGroup.id, deviceNo })),
+        );
+      }
+
+      if (addedDeviceNoList.length === 1) {
+        await saveSensor2GroupApi({
+          groupId: props.cameraGroup.id,
+          deviceNo: addedDeviceNoList[0],
+          orderNum: props.cameraGroup.details.length + 1,
+        });
+      } else if (addedDeviceNoList.length > 1) {
+        await batchSaveSensor2GroupApi({
+          groupId: props.cameraGroup.id,
+          deviceNoList: addedDeviceNoList,
+        });
+      }
 
       // 更新本地状态
       const newSensors: SensorDeviceViewItem[] = checkedNodes.map((n) => ({

+ 2 - 2
src/views/production-safety/risk-identification-and-control/labor-products-requisition-manage/list.vue

@@ -25,7 +25,7 @@
               style="width: 170px"
             />
           </el-form-item>
-          <el-form-item label="状态">
+          <!-- <el-form-item label="状态">
             <el-select
               v-model="queryParams.queryParam.status"
               placeholder="请选择状态"
@@ -35,7 +35,7 @@
               <el-option label="启用" :value="1" />
               <el-option label="禁用" :value="0" />
             </el-select>
-          </el-form-item>
+          </el-form-item> -->
         </el-form>
         <div>
           <el-button type="primary" @click="queryTableList">查询</el-button>

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

@@ -13,8 +13,18 @@
         <el-input v-model="ruleFormData.evaluationTitle" placeholder="请输入考核信息标题" disabled />
       </el-form-item>
       <el-form-item label="上传附件文档:" prop="attachmentDocument">
-        <div class="upload-files-disabled">
-          <UploadFiles label="上传附件" :file-list="ruleFormData.attachmentDocument" @uploadSuccess="handleUploadSuccess" />
+        <div class="file-list">
+          <div class="file-item" v-for="file in ruleFormData.attachmentDocument" :key="file.fileId">
+            <span class="file-item--name">{{ file.fileName }}</span>
+            <div class="file-item--footer">
+              <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
+                >预览</el-button
+              >
+              <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                >下载</el-button
+              >
+            </div>
+          </div>
         </div>
       </el-form-item>
       <el-form-item label="评分说明:" prop="scoringDescription">
@@ -72,6 +82,9 @@
         </el-table>
       </div>
     </div>
+
+    <PreviewOnline ref="previewOnlineRef" />
+
   </main>
   <footer class="safety-platform-container__footer">
     <el-button @click="router.back()">取消</el-button>
@@ -93,13 +106,15 @@
   } from '@/api/evaluationSystem';
   import type { FileItem } from '@/components/UploadFiles/types';
   import { formatAttachmentList } from '@/components/UploadFiles/utils';
-
+  import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
+  import { downloadFile } from '@/views/disaster/utils';
   const props = defineProps<{
     id: number;
   }>();
 
   const router = useRouter();
   const route = useRoute();
+  const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
 
   // 判断是否为 evaluationDepartment-feedback(反馈)
   const isFeedbackOperate = computed(() => route.query.operate === 'evaluationDepartment-feedback');
@@ -326,7 +341,7 @@ const spanMethod = ({ row, column, rowIndex, columnIndex }) => {
 
       // 映射表单字段
       ruleFormData.value.evaluationTitle = detail.exName || ''; // 考核表名称
-      ruleFormData.value.attachmentDocument = parseAttachmentsToFileList(detail.attachments); // 附件文档
+      ruleFormData.value.attachmentDocument = JSON.parse(detail.attachments || '[]'); // 附件文档
       ruleFormData.value.scoringDescription = detail.ratingDescribe; // 评分说明(接口暂无此字段,留空)
 
       // 映射考核项目列表(scores 数组)
@@ -444,6 +459,12 @@ const spanMethod = ({ row, column, rowIndex, columnIndex }) => {
     }
   };
 
+  const previewOnline = (url: string | undefined, type) => {
+    if (url) {
+      previewOnlineRef.value?.open(url, type);
+    }
+  };
+
   onMounted(() => {
     getDetail();
   });

+ 15 - 2
src/views/production-safety/safetyAssessment/evaluationDepartment/evaluationDepartment.vue

@@ -66,7 +66,7 @@
               </span>
             </template>
             <template #evaluationDocument="scope">
-              <div
+              <!-- <div
                 class="file-container--div"
                 v-for="item in parseAttachments(scope.row.evaluationDocument)"
                 :key="item.fileUrl"
@@ -86,6 +86,19 @@
                   :src="DownloadIcon"
                   @click="downloadFile(item.fileUrl, item.fileName)"
                 />
+              </div> -->
+              <div class="file-list">
+                <div class="file-item" v-for="file in scope.row.evaluationDocument" :key="file.fileId">
+                  <span class="file-item--name">{{ file.fileName }}</span>
+                  <div class="file-item--footer">
+                    <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
+                      >预览</el-button
+                    >
+                    <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                      >下载</el-button
+                    >
+                  </div>
+                </div>
               </div>
             </template>
             <template #action="scope">
@@ -193,7 +206,7 @@
           evaluationTableName: item.exName, // 考核表名称
           status: item.status, // 状态(使用数字状态码)
           statusName: item.statusName, // 状态名称
-          evaluationDocument: item.attachments, // 考核文档
+          evaluationDocument: JSON.parse(item.attachments || '[]'), // 考核文档
           plannedCompletionTime: item.planEndTime || '-', // 计划完成时间(使用计划结束时间)
           // 保留原始数据,供其他操作使用
           psemId: item.psemId,

+ 67 - 32
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemDetail.vue

@@ -5,11 +5,32 @@
         <el-input v-model="ruleFormData.evaluationTableName" placeholder="请输入考核表名称" :disabled="isViewMode" />
       </el-form-item>
       <el-form-item label="上传附件文档:" prop="attachmentDocument">
-        <UploadFiles
+        <!-- <UploadFiles
           label="上传附件"
           :file-list="ruleFormData.attachmentDocument"
           @uploadSuccess="handleUploadSuccess"
+        /> -->
+        <UploadFiles
+          v-if="!isViewMode"
+          label="上传文件"
+          :maxCount="10"
+          :file-list="ruleFormData.attachmentDocument"
+          :allow-all-file-types="true"
+          @uploadSuccess="(list: FileItem[]) => handleUploadSuccess(list)"
         />
+        <div class="file-list" v-else>
+          <div class="file-item" v-for="file in ruleFormData.attachmentDocument" :key="file.fileId">
+            <span class="file-item--name">{{ file.fileName }}</span>
+            <div class="file-item--footer">
+              <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
+                >预览</el-button
+              >
+              <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                >下载</el-button
+              >
+            </div>
+          </div>
+        </div>
       </el-form-item>
       <el-form-item label="评分说明:" prop="scoringDescription">
         <el-input
@@ -123,6 +144,9 @@
         </span>
       </template>
     </el-dialog>
+
+    <PreviewOnline ref="previewOnlineRef" />
+
   </main>
   <footer class="safety-platform-container__footer">
     <el-button @click="router.back()">取消</el-button>
@@ -154,6 +178,8 @@
   import { formatAttachmentList } from '@/components/UploadFiles/utils';
   import { queryAvailableUserList } from '@/api/production-safety/responsibility-implementation';
   import { downloadByData } from '@/utils/file/download';
+  import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
+  import { downloadFile } from '@/views/disaster/utils';
 
   const props = defineProps<{
     id?: number;
@@ -161,6 +187,7 @@
 
   const router = useRouter();
   const route = useRoute();
+  const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
 
   const operate = computed(() => (route.query.operate as string) || 'evaluationSystem-create');
   const isCreateMode = computed(() => operate.value === 'evaluationSystem-create');
@@ -228,6 +255,12 @@
     });
   };
 
+  const previewOnline = (url: string | undefined, type) => {
+    if (url) {
+      previewOnlineRef.value?.open(url, type);
+    }
+  };
+
   const handleUploadSuccess = (files: any[]) => {
     ruleFormData.value.attachmentDocument = files;
   };
@@ -613,8 +646,8 @@
       ruleFormData.value.scoringDescription = detail.ratingDescribe || '';
 
       // 转换附件文档:将逗号分隔的URL字符串转换为FileItem数组
-      ruleFormData.value.attachmentDocument = convertAttachmentsToFileItems(detail.attachments || '');
-
+      ruleFormData.value.attachmentDocument = JSON.parse(detail.attachments || '[]');
+      
       // 填充考核项目列表
       if (detail.exContents && detail.exContents.length > 0) {
         // 详情接口返回的数据视为已持久化的数据,保留 id / psemId
@@ -675,33 +708,35 @@
     }
 
     try {
-      // 处理附件文档:先上传文件获取 URL,然后提取 fileUrl,多个用逗号分隔
-      let attachments = '';
-      if (ruleFormData.value.attachmentDocument && ruleFormData.value.attachmentDocument.length > 0) {
-        // 分离已有URL的文件和新上传的文件
-        const existingFiles: string[] = [];
-        const newFiles: any[] = [];
-
-        ruleFormData.value.attachmentDocument.forEach((file: any) => {
-          // 如果文件已经有 fileUrl 且没有 file 对象,说明是已有文件
-          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((file: any) => file.fileUrl || file.url || '').filter((url: string) => url);
-        }
-
-        // 合并已有URL和新上传的URL
-        attachments = [...existingFiles, ...uploadedUrls].filter((url: string) => url).join(',');
-      }
+      // // 处理附件文档:先上传文件获取 URL,然后提取 fileUrl,多个用逗号分隔
+      // let attachments = '';
+      // if (ruleFormData.value.attachmentDocument && ruleFormData.value.attachmentDocument.length > 0) {
+      //   // 分离已有URL的文件和新上传的文件
+      //   const existingFiles: string[] = [];
+      //   const newFiles: any[] = [];
+
+      //   ruleFormData.value.attachmentDocument.forEach((file: any) => {
+      //     // 如果文件已经有 fileUrl 且没有 file 对象,说明是已有文件
+      //     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((file: any) => file.fileUrl || file.url || '').filter((url: string) => url);
+      //   }
+
+      //   // 合并已有URL和新上传的URL
+      //   attachments = [...existingFiles, ...uploadedUrls].filter((url: string) => url).join(',');
+      // }
+
+      const attachments = await formatAttachmentList(ruleFormData.value.attachmentDocument);
 
       // 映射考核项目列表,添加序号
       const exContents: EvaluationContent[] = evaluationItems.value.map((item, index) => {
@@ -729,7 +764,7 @@
         const payload = {
           id: props.id, // 编辑时必须传ID
           exName: ruleFormData.value.evaluationTableName || '', // 考核表名称
-          attachments, // 考核文档
+          attachments: JSON.stringify(attachments), // 考核文档
           ratingDescribe: ruleFormData.value.scoringDescription || '', // 评分说明
           deptNames: '', // 下发部门(编辑时为空)
           deptIds: [], // 下发部门ID数组(编辑时为空)
@@ -749,7 +784,7 @@
         const payload = {
           id: 0, // 新增时为0
           exName: ruleFormData.value.evaluationTableName || '', // 考核表名称
-          attachments, // 考核文档
+          attachments: JSON.stringify(attachments), // 考核文档
           ratingDescribe: ruleFormData.value.scoringDescription || '', // 评分说明
           deptNames: '', // 下发部门(创建时为空)
           deptIds: [], // 下发部门ID数组(创建时为空)

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

@@ -52,7 +52,7 @@ export const EVALUATION_SYSTEM_TABLE_COLUMNS: TableColumnProps[] = [
     // prop: 'evaluationDocument',
     slot: 'evaluationDocument',
     align: 'left',
-    minWidth: '150px',
+    minWidth: '300px',
   },
   {
     label: '计划完成时间',

+ 20 - 2
src/views/production-safety/safetyAssessment/evaluationSystem/evaluationSystem.vue

@@ -71,7 +71,7 @@
               <span class="evaluation-table-name">{{ scope.row.evaluationTableName }}</span>
             </template>
             <template #evaluationDocument="scope">
-              <div
+              <!-- <div
                 class="file-container--div"
                 v-for="item in parseAttachments(scope.row.evaluationDocument)"
                 :key="item.fileUrl"
@@ -91,6 +91,24 @@
                   :src="DownloadIcon"
                   @click="downloadFile(item.fileUrl, item.fileName)"
                 />
+              </div> -->
+              <div class="file-list">
+                <div class="file-item" v-for="file in scope.row.evaluationDocument" :key="file.fileId">
+                  <!-- <img
+                    class="file-container--div__icon"
+                    @click="previewOnline(file.fileUrl, file.fileType as keyof typeof FILE_TYPE_ICON)"
+                    :src="FILE_TYPE_ICON[file.fileType]"
+                  /> -->
+                  <span class="file-item--name">{{ file.fileName }}</span>
+                  <div class="file-item--footer">
+                    <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
+                      >预览</el-button
+                    >
+                    <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                      >下载</el-button
+                    >
+                  </div>
+                </div>
               </div>
             </template>
             <template #status="scope">
@@ -418,7 +436,7 @@
           issueCount: item.issueNum, // 下发数(接口未返回,暂时设为0)
           feedbackCount: item.replyNum, // 反馈数(接口未返回,暂时设为0)
           feedbackRatio: item.replyRate, // 反馈比例(接口未返回,暂时设为0%)
-          evaluationDocument: item.attachments, // 考核文档
+          evaluationDocument: JSON.parse(item.attachments || '[]'), // 考核文档
           plannedCompletionTime:
             item.planStartTime && item.planEndTime
               ? `${item.planStartTime} 至 ${item.planEndTime}`