Procházet zdrojové kódy

检测录入附件上传

xy před 2 týdny
rodič
revize
b1d8e076b3

+ 0 - 36
yudao-ui-admin-vue3/src/api/pressure2/taskOrderFile/index.ts

@@ -1,36 +0,0 @@
-import request from '@/config/axios'
-import { buildFileUrl } from '@/utils'
-
-/** 任务单附件 API */
-export const TaskOrderFileApi = {
-  /**
-   * 上传文件并创建附件记录
-   * @param formData - 包含 file, orderId, orderItemId, equipMainType
-   */
-  uploadAndCreate: (formData: FormData) =>
-    request.post({
-      url: '/pressure2/task-order-file/upload-and-create',
-      data: formData,
-      headers: { 'Content-Type': 'multipart/form-data' }
-    }),
-
-  /**
-   * 分页查询附件列表
-   */
-  getPage: (params: Recordable) =>
-    request.get({ url: '/pressure2/task-order-file/page', params }),
-
-  /**
-   * 删除附件
-   */
-  deleteFile: (id: string) =>
-    request.delete({ url: '/pressure2/task-order-file/delete', params: { id } }),
-
-  /**
-   * 下载附件
-   */
-  downloadFile: (fileUrl: string, fileName: string) => {
-    const url = buildFileUrl(fileUrl)
-    return request.download({ url })
-  }
-}

+ 1 - 12
yudao-ui-admin-vue3/src/views/pressure2/boilerchecker/components/StatusOperationPanel.vue

@@ -597,15 +597,6 @@
       @confirm="handleRefresh"
     />
 
-    <!-- 上传附件弹窗 -->
-    <el-dialog v-model="attachmentDialogVisible" title="上传附件" width="800px" :close-on-click-modal="false">
-      <AttachmentUpload
-        :order-id="props.taskInfo?.id || ''"
-        :order-item-id="props.taskOrderItem?.id || ''"
-        :equip-main-type="200"
-      />
-    </el-dialog>
-
     <!-- 回退原因弹窗(面板收缩时使用) -->
     <el-dialog
       v-model="rejectionReasonDialogVisible"
@@ -716,7 +707,7 @@
           size="small"
         >{{ selectedItem.reportType === PressureReportType['SUGGUESTION'] ? '编制意见书' : '填写记录' }}</el-button>
         <!-- 上传附件 -->
-        <el-button type="primary" plain size="small" @click="attachmentDialogVisible = true">
+        <el-button type="primary" plain size="small" @click="handleUploadItem">
           上传附件
         </el-button>
         <!-- 撤销流程:报告审核或审批阶段,有OA流程ID且当前用户是发起人时显示 -->
@@ -920,7 +911,6 @@ import { is } from '@/utils/is'
 import _ from 'lodash'
 import { uploadFile } from '@/api/common/index'
 import ReportListUploadModal from './reportListUploadModal.vue'
-import AttachmentUpload from '@/views/pressure2/components/AttachmentUpload.vue'
 import AssociationOperationManual from './AssociationOperationManual.vue'
 import {DynamicTbInsApi} from "@/api/pressure2/dynamictbins";
 import {SpreadViewer} from "@/components/DynamicReport";
@@ -2355,7 +2345,6 @@ const handleShowVersionInfo = (item) => {
 
 
 // 检验项目添加上传附件功能
-const attachmentDialogVisible = ref(false)
 const reportListUploadModalRef = ref<InstanceType<typeof ReportListUploadModal>>()
 const handleUploadItem = () => {
   reportListUploadModalRef.value?.openModal(route.query.type === 'BoilerMyTask')

+ 19 - 6
yudao-ui-admin-vue3/src/views/pressure2/boilerchecker/components/reportListUploadModal.vue

@@ -105,7 +105,7 @@
           class="flex items-center w-full p-[10px] hover:bg-gray-100 rounded-6px"
         >
           <!-- <el-tooltip :content="path"> -->
-          <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{{ path }}</span>
+          <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{{ changedReportMap[currentReportId].attachmentName[index] || path }}</span>
           <!-- </el-tooltip>  -->
           <div class="ml-10px flex gap-[10px] cursor-pointer">
             <el-icon
@@ -239,8 +239,11 @@ const handleConfirm = () => {
   const params = reportIds.map((item) => ({
     reportId: item,
     attachment: changedReportMap.value[item].attachment.join(','),
+    attachmentName: changedReportMap.value[item].attachmentName.join(','),
     image: changedReportMap.value[item].image.join(','),
-    video: changedReportMap.value[item].video.join(',')
+    imageName: changedReportMap.value[item].imageName.join(','),
+    video: changedReportMap.value[item].video.join(','),
+    videoName: changedReportMap.value[item].videoName.join(',')
   }))
   loading.value = true
   BoilerTaskOrderApi.reportItemUploadBatch({ items: params })
@@ -264,18 +267,22 @@ const uploadConfig = {
   accept,
   //   limit: 1,
   drag: true,
-  onSuccess: (response: any) => {
+  onSuccess: (response: any, uploadFile: any) => {
     console.log('response:', response)
     if (response.code !== 0) return ElMessage.error(response.msg)
     ElMessage.success('附件上传成功')
     // 根据文件类型,根据当前选中的报告id,添加到不同的数组中
     const fileType = response.data.split('.').pop()?.toLowerCase()
+    const originalName = uploadFile?.name || response.data.substring(response.data.lastIndexOf('/') + 1)
     if (['docx', 'pdf'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].attachment.push(response.data)
+      changedReportMap.value[currentReportId.value].attachmentName.push(originalName)
     } else if (['png', 'jpg', 'jpeg'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].image.push(response.data)
+      changedReportMap.value[currentReportId.value].imageName.push(originalName)
     } else if (['mp4'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].video.push(response.data)
+      changedReportMap.value[currentReportId.value].videoName.push(originalName)
     }
   },
   onError: (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles): void => {
@@ -305,16 +312,19 @@ const handleReportChange = (val) => {
   if (val) setCurrentReportIdFile(props.reportList.find((item) => item.id === val))
 }
 const changedReportMap = ref<
-  Record<string, { image: string[]; video: string[]; attachment: string[] }>
+  Record<string, { image: string[]; imageName: string[]; video: string[]; videoName: string[]; attachment: string[]; attachmentName: string[] }>
 >({}) // 已经编辑过的报告的数据统计
 const setCurrentReportIdFile = (selectedItem) => {
-  const { id, image, video, attachment } = selectedItem
+  const { id, image, imageName, video, videoName, attachment, attachmentName } = selectedItem
   currentReportId.value = filterReportList.value.find((item) => item.id === id)?.id || ''
   if (!changedReportMap.value[id]) {
     changedReportMap.value[id] = {
       image: image ? image.split(',') : [],
+      imageName: imageName ? imageName.split(',') : [],
       video: video ? video.split(',') : [],
-      attachment: attachment ? attachment.split(',') : []
+      videoName: videoName ? videoName.split(',') : [],
+      attachment: attachment ? attachment.split(',') : [],
+      attachmentName: attachmentName ? attachmentName.split(',') : []
     }
   }
 }
@@ -326,10 +336,13 @@ const previewUrl = ref('')
 const handleDelete = (index: number, type: 'image' | 'video' | 'attachment') => {
   if (type === 'image') {
     changedReportMap.value[currentReportId.value].image.splice(index, 1)
+    changedReportMap.value[currentReportId.value].imageName.splice(index, 1)
   } else if (type === 'video') {
     changedReportMap.value[currentReportId.value].video.splice(index, 1)
+    changedReportMap.value[currentReportId.value].videoName.splice(index, 1)
   } else {
     changedReportMap.value[currentReportId.value].attachment.splice(index, 1)
+    changedReportMap.value[currentReportId.value].attachmentName.splice(index, 1)
   }
 }
 const handlePreview = (path: string, type: 'video' | 'image' | 'attachment') => {

+ 0 - 240
yudao-ui-admin-vue3/src/views/pressure2/components/AttachmentUpload.vue

@@ -1,240 +0,0 @@
-<template>
-  <div class="attachment-upload">
-    <!-- 上传按钮 -->
-    <el-upload
-      action="#"
-      :file-list="uploadFileList"
-      :before-upload="beforeUpload"
-      :http-request="handleUpload"
-      :show-file-list="false"
-      :multiple="true"
-      :disabled="!canUpload"
-    >
-      <el-button type="primary" :disabled="!canUpload">
-        <el-icon><UploadFilled /></el-icon>
-        添加附件
-      </el-button>
-    </el-upload>
-
-    <!-- 已上传附件列表 -->
-    <div v-if="localFileList.length > 0" class="attachment-list">
-      <div v-for="file in localFileList" :key="file.id" class="attachment-item">
-        <div class="attachment-row-top">
-          <el-icon :size="18" class="file-icon"><Document /></el-icon>
-          <span class="file-name">{{ file.fileName }}</span>
-        </div>
-        <div class="attachment-row-bottom">
-          <span class="upload-time" v-if="file.createTime">{{ formatDate(file.createTime) }}</span>
-          <div class="attachment-actions">
-            <el-button type="primary" link size="small" @click="handlePreview(file)">
-              <el-icon><View /></el-icon>
-              预览
-            </el-button>
-            <el-button type="primary" link size="small" @click="handleDownload(file)">
-              <el-icon><Download /></el-icon>
-              下载
-            </el-button>
-            <el-button type="danger" link size="small" @click="handleDelete(file)">
-              <el-icon><Delete /></el-icon>
-              删除
-            </el-button>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, onMounted } from 'vue'
-import { UploadFilled, Document, View, Download, Delete } from '@element-plus/icons-vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { TaskOrderFileApi } from '@/api/pressure2/taskOrderFile'
-import { buildFileUrl } from '@/utils'
-import { formatDate } from '@/utils/formatTime'
-import request from '@/config/axios'
-
-const props = defineProps({
-  /** 任务单ID */
-  orderId: {
-    type: String,
-    default: ''
-  },
-  /** 检验设备单ID */
-  orderItemId: {
-    type: String,
-    default: ''
-  },
-  /** 设备类型 200锅炉 300管道 */
-  equipMainType: {
-    type: Number,
-    default: 0
-  },
-  /** 是否可上传 */
-  canUpload: {
-    type: Boolean,
-    default: true
-  }
-})
-
-// 本地文件列表
-const localFileList = ref<Recordable[]>([])
-// 上传组件显示用的空列表
-const uploadFileList = ref<Recordable[]>([])
-
-// 页面加载时自动获取附件列表
-onMounted(() => {
-  fetchFileList()
-})
-
-const beforeUpload = (file: File) => {
-  const maxSize = 50 * 1024 * 1024
-  if (file.size > maxSize) {
-    ElMessage.error('文件大小不能超过50MB')
-    return false
-  }
-  return true
-}
-
-// 处理文件上传
-const handleUpload = async (options: Recordable) => {
-  const { file } = options
-  const formData = new FormData()
-  formData.append('file', file)
-  formData.append('orderId', props.orderId || '')
-  formData.append('orderItemId', props.orderItemId || '')
-  formData.append('equipMainType', String(props.equipMainType))
-
-  try {
-    const res = await TaskOrderFileApi.uploadAndCreate(formData)
-    if (res) {
-      ElMessage.success('文件上传成功')
-      fetchFileList()
-    }
-  } catch (error: any) {
-    ElMessage.error(error?.message || '文件上传失败')
-  }
-}
-
-// 预览附件
-const handlePreview = (file: Recordable) => {
-  const url = buildFileUrl(file.fileUrl)
-  window.open(url, '_blank')
-}
-
-// 下载附件 - 使用 blob 方式确保触发下载而不是浏览器打开
-const handleDownload = async (file: Recordable) => {
-  try {
-    const url = buildFileUrl(file.fileUrl)
-    const blob = await request.download({ url })
-    const blobUrl = URL.createObjectURL(blob as unknown as Blob)
-    const link = document.createElement('a')
-    link.href = blobUrl
-    link.download = file.fileName || '下载文件'
-    document.body.appendChild(link)
-    link.click()
-    document.body.removeChild(link)
-    URL.revokeObjectURL(blobUrl)
-  } catch (error: any) {
-    ElMessage.error('下载失败')
-  }
-}
-
-// 删除附件
-const handleDelete = async (file: Recordable) => {
-  try {
-    await ElMessageBox.confirm('确认删除该附件?', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
-    await TaskOrderFileApi.deleteFile(file.id)
-    ElMessage.success('删除成功')
-    fetchFileList()
-  } catch (error: any) {
-    if (error !== 'cancel') {
-      ElMessage.error(error?.message || '删除失败')
-    }
-  }
-}
-
-// 刷新附件列表
-const fetchFileList = async () => {
-  if (!props.orderItemId) return
-  try {
-    const res = await TaskOrderFileApi.getPage({
-      orderItemId: props.orderItemId,
-      pageNo: 1,
-      pageSize: 100
-    })
-    if (res?.list) {
-      localFileList.value = res.list
-    }
-  } catch (error: any) {
-    console.error('获取附件列表失败:', error)
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.attachment-upload {
-  .attachment-list {
-    margin-top: 12px;
-
-    .attachment-item {
-      display: flex;
-      flex-direction: column;
-      padding: 10px 12px;
-      margin-bottom: 8px;
-      border: 1px solid var(--el-border-color-light);
-      border-radius: 4px;
-      background-color: var(--el-fill-color-lighter);
-      transition: background-color 0.2s;
-
-      &:hover {
-        background-color: var(--el-fill-color-light);
-      }
-
-      .attachment-row-top {
-        display: flex;
-        align-items: flex-start;
-        gap: 8px;
-        margin-bottom: 6px;
-
-        .file-icon {
-          flex-shrink: 0;
-          margin-top: 2px;
-          color: var(--el-color-primary);
-        }
-
-        .file-name {
-          flex: 1;
-          font-size: 13px;
-          line-height: 1.5;
-          word-break: break-all;
-          color: var(--el-text-color-primary);
-        }
-      }
-
-      .attachment-row-bottom {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        padding-left: 26px;
-
-        .upload-time {
-          font-size: 12px;
-          color: var(--el-text-color-secondary);
-        }
-
-        .attachment-actions {
-          display: flex;
-          align-items: center;
-          gap: 4px;
-          margin-left: auto;
-        }
-      }
-    }
-  }
-}
-</style>

+ 1 - 12
yudao-ui-admin-vue3/src/views/pressure2/pipechecker/components/StatusOperationPanel.vue

@@ -596,15 +596,6 @@
       @confirm="handleRefresh"
     />
 
-    <!-- 上传附件弹窗 -->
-    <el-dialog v-model="attachmentDialogVisible" title="上传附件" width="800px" :close-on-click-modal="false">
-      <AttachmentUpload
-        :order-id="props.taskInfo?.id || ''"
-        :order-item-id="props.taskOrderItem?.id || ''"
-        :equip-main-type="300"
-      />
-    </el-dialog>
-
     <!-- 回退原因弹窗(面板收缩时使用) -->
     <el-dialog
       v-model="rejectionReasonDialogVisible"
@@ -715,7 +706,7 @@
           size="small"
         >{{ selectedItem.reportType === PressureReportType['SUGGUESTION'] ? '编制意见书' : '填写记录' }}</el-button>
         <!-- 上传附件 -->
-        <el-button type="primary" plain size="small" @click="attachmentDialogVisible = true">
+        <el-button type="primary" plain size="small" @click="handleUploadItem">
           上传附件
         </el-button>
         <!-- 撤销流程:报告审核或审批阶段,有OA流程ID且当前用户是发起人时显示 -->
@@ -912,7 +903,6 @@ import {is} from '@/utils/is'
 import _ from 'lodash'
 import {uploadFile} from '@/api/common/index'
 import ReportListUploadModal from './reportListUploadModal.vue'
-import AttachmentUpload from '@/views/pressure2/components/AttachmentUpload.vue'
 import AssociationOperationManual from './AssociationOperationManual.vue'
 import {SpreadViewer} from "@/components/DynamicReport";
 import {InitParams} from "@/components/DynamicReport/SpreadInterface";
@@ -2237,7 +2227,6 @@ const handleShowVersionInfo = (item) => {
 
 
 // 检验项目添加上传附件功能
-const attachmentDialogVisible = ref(false)
 const reportListUploadModalRef = ref<InstanceType<typeof ReportListUploadModal>>()
 const handleUploadItem = () => {
   reportListUploadModalRef.value?.openModal(route.query.type === 'PipeMyTask')

+ 19 - 6
yudao-ui-admin-vue3/src/views/pressure2/pipechecker/components/reportListUploadModal.vue

@@ -105,7 +105,7 @@
           class="flex items-center w-full p-[10px] hover:bg-gray-100 rounded-6px"
         >
           <!-- <el-tooltip :content="path"> -->
-          <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{{ path }}</span>
+          <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{{ changedReportMap[currentReportId].attachmentName[index] || path }}</span>
           <!-- </el-tooltip>  -->
           <div class="ml-10px flex gap-[10px] cursor-pointer">
             <el-icon
@@ -239,8 +239,11 @@ const handleConfirm = () => {
   const params = reportIds.map((item) => ({
     reportId: item,
     attachment: changedReportMap.value[item].attachment.join(','),
+    attachmentName: changedReportMap.value[item].attachmentName.join(','),
     image: changedReportMap.value[item].image.join(','),
-    video: changedReportMap.value[item].video.join(',')
+    imageName: changedReportMap.value[item].imageName.join(','),
+    video: changedReportMap.value[item].video.join(','),
+    videoName: changedReportMap.value[item].videoName.join(',')
   }))
   loading.value = true
   PipeTaskOrderApi.reportItemUploadBatch({ items: params })
@@ -264,18 +267,22 @@ const uploadConfig = {
   accept,
   //   limit: 1,
   drag: true,
-  onSuccess: (response: any) => {
+  onSuccess: (response: any, uploadFile: any) => {
     console.log('response:', response)
     if (response.code !== 0) return ElMessage.error(response.msg)
     ElMessage.success('附件上传成功')
     // 根据文件类型,根据当前选中的报告id,添加到不同的数组中
     const fileType = response.data.split('.').pop()?.toLowerCase()
+    const originalName = uploadFile?.name || response.data.substring(response.data.lastIndexOf('/') + 1)
     if (['docx', 'pdf'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].attachment.push(response.data)
+      changedReportMap.value[currentReportId.value].attachmentName.push(originalName)
     } else if (['png', 'jpg', 'jpeg'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].image.push(response.data)
+      changedReportMap.value[currentReportId.value].imageName.push(originalName)
     } else if (['mp4'].includes(fileType)) {
       changedReportMap.value[currentReportId.value].video.push(response.data)
+      changedReportMap.value[currentReportId.value].videoName.push(originalName)
     }
   },
   onError: (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles): void => {
@@ -305,16 +312,19 @@ const handleReportChange = (val) => {
   if (val) setCurrentReportIdFile(props.reportList.find((item) => item.id === val))
 }
 const changedReportMap = ref<
-  Record<string, { image: string[]; video: string[]; attachment: string[] }>
+  Record<string, { image: string[]; imageName: string[]; video: string[]; videoName: string[]; attachment: string[]; attachmentName: string[] }>
 >({}) // 已经编辑过的报告的数据统计
 const setCurrentReportIdFile = (selectedItem) => {
-  const { id, image, video, attachment } = selectedItem
+  const { id, image, imageName, video, videoName, attachment, attachmentName } = selectedItem
   currentReportId.value = filterReportList.value.find((item) => item.id === id)?.id || ''
   if (!changedReportMap.value[id]) {
     changedReportMap.value[id] = {
       image: image ? image.split(',') : [],
+      imageName: imageName ? imageName.split(',') : [],
       video: video ? video.split(',') : [],
-      attachment: attachment ? attachment.split(',') : []
+      videoName: videoName ? videoName.split(',') : [],
+      attachment: attachment ? attachment.split(',') : [],
+      attachmentName: attachmentName ? attachmentName.split(',') : []
     }
   }
 }
@@ -326,10 +336,13 @@ const previewUrl = ref('')
 const handleDelete = (index: number, type: 'image' | 'video' | 'attachment') => {
   if (type === 'image') {
     changedReportMap.value[currentReportId.value].image.splice(index, 1)
+    changedReportMap.value[currentReportId.value].imageName.splice(index, 1)
   } else if (type === 'video') {
     changedReportMap.value[currentReportId.value].video.splice(index, 1)
+    changedReportMap.value[currentReportId.value].videoName.splice(index, 1)
   } else {
     changedReportMap.value[currentReportId.value].attachment.splice(index, 1)
+    changedReportMap.value[currentReportId.value].attachmentName.splice(index, 1)
   }
 }
 const handlePreview = (path: string, type: 'video' | 'image' | 'attachment') => {

+ 40 - 85
yudao-ui-admin-vue3/src/views/pressure2/reportArchivingBoiler/detail.vue

@@ -86,6 +86,10 @@ const getDetail = () => {
   FetchApis.getDetail(detailParams.value)
     .then((res) => {
       detailData.value = res || {}
+      // 附件数据已为 {url, name} 格式,直接使用
+      detailData.value.imageList = res.images || []
+      detailData.value.videoList = res.videos || []
+      detailData.value.attachmentList = res.attachments || []
     })
     .finally(() => {
       loadDone()
@@ -349,58 +353,40 @@ const detailTableSchema = reactive<TableItem[]>([
     dataField: 'itemFiles'
   },
   {
-    title: '上传附件',
+    title: '图片附件',
     columns: [
-      {
-        label: '序号',
-        fieldProps: {
-          type: 'index',
-          align: 'center',
-          width: 55
-        }
-      },
-      {
-        label: '文件名称',
-        prop: 'fileName',
-        fieldProps: {
-          align: 'center',
-          minWidth: 200,
-          showOverflowTooltip: true
-        }
-      },
-      {
-        label: '上传时间',
-        prop: 'createTime',
-        fieldProps: {
-          align: 'center',
-          minWidth: 160
-        },
-        render: (_row, value) => {
-          return formatDate(value, 'YYYY-MM-DD HH:mm:ss') || '-'
-        }
-      },
-      {
-        label: '操作',
-        prop: 'operation',
-        fieldProps: {
-          align: 'center',
-          minWidth: 200
-        },
-        render: (row) => {
-          return (
-            <>
-              <el-button type="primary" link onClick={() => handleAttachmentPreview(row)}>
-                预览
-              </el-button>
-              <el-button type="primary" link onClick={() => handleAttachmentDownload(row)}>
-                下载
-              </el-button>
-            </>
-          )
-        }
-      }
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '预览', prop: 'url', fieldProps: { align: 'center', minWidth: 200 },
+        render: (row) => <el-image style="width: 100px; height: 80px" src={buildFileUrl(row.url)} fit="cover" preview-teleported /> },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 100 },
+        render: (row) => <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button> }
+    ],
+    dataField: 'imageList'
+  },
+  {
+    title: '视频附件',
+    columns: [
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '文件名称', prop: 'name', fieldProps: { align: 'center', minWidth: 200, showOverflowTooltip: true } },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 100 },
+        render: (row) => <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button> }
+    ],
+    dataField: 'videoList'
+  },
+  {
+    title: '文档附件',
+    columns: [
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '文件名称', prop: 'name', fieldProps: { align: 'center', minWidth: 250, showOverflowTooltip: true } },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 150 },
+        render: (row) => (
+          <>
+            <el-button type="primary" link onClick={() => window.open(buildFileUrl(row.url), '_blank')}>预览</el-button>
+            <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button>
+          </>
+        ) }
     ],
-    dataField: 'attachmentFiles'
+    dataField: 'attachmentList'
   }
 ])
 
@@ -869,28 +855,15 @@ const handlePreviewOrder = (row) => {
 
 const showAssociationOperationManual = ref(false)
 
-// 附件预览
-const handleAttachmentPreview = (row: Recordable) => {
-  const url = buildFileUrl(row.fileUrl)
-  const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']
-  const ext = row.fileName?.substring(row.fileName.lastIndexOf('.')).toLowerCase()
-  if (imageExts.includes(ext)) {
-    docPdfUrls.value = [url]
-    showDocPdfDialog.value = true
-  } else {
-    window.open(url, '_blank')
-  }
-}
-
 // 附件下载
-const handleAttachmentDownload = async (row: Recordable) => {
+const handleAttachmentDownload = async (url: string) => {
   try {
-    const url = buildFileUrl(row.fileUrl)
-    const blob = await request.download({ url })
+    const fullUrl = buildFileUrl(url)
+    const blob = await request.download({ url: fullUrl })
     const blobUrl = URL.createObjectURL(blob as unknown as Blob)
     const link = document.createElement('a')
     link.href = blobUrl
-    link.download = row.fileName || '下载文件'
+    link.download = url.substring(url.lastIndexOf('/') + 1) || '下载文件'
     document.body.appendChild(link)
     link.click()
     document.body.removeChild(link)
@@ -900,24 +873,6 @@ const handleAttachmentDownload = async (row: Recordable) => {
   }
 }
 
-// 附件删除
-const handleAttachmentDelete = async (row: Recordable) => {
-  try {
-    await ElMessageBox.confirm('确认删除该附件?', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
-    await request.delete({ url: '/pressure2/task-order-file/delete', params: { id: row.id } })
-    ElMessage.success('删除成功')
-    getDetail()
-  } catch (error: any) {
-    if (error !== 'cancel') {
-      ElMessage.error(error?.message || '删除失败')
-    }
-  }
-}
-
 onMounted(() => {
   getDetail()
 })

+ 6 - 1
yudao-ui-admin-vue3/src/views/pressure2/reportArchivingBoiler/index.api.ts

@@ -16,5 +16,10 @@ export interface DetailData {
   inspectionItems: Recordable[]
   itemFiles: Recordable[]
   taskListFiles: Recordable[]
-  attachmentFiles: Recordable[]
+  images: Recordable[]
+  videos: Recordable[]
+  attachments: Recordable[]
+  imageList?: Recordable[]
+  videoList?: Recordable[]
+  attachmentList?: Recordable[]
 }

+ 40 - 85
yudao-ui-admin-vue3/src/views/pressure2/reportArchivingPipe/detail.vue

@@ -86,6 +86,10 @@ const getDetail = () => {
   FetchApis.getDetail(detailParams.value)
     .then((res) => {
       detailData.value = res || {}
+      // 附件数据已为 {url, name} 格式,直接使用
+      detailData.value.imageList = res.images || []
+      detailData.value.videoList = res.videos || []
+      detailData.value.attachmentList = res.attachments || []
     })
     .finally(() => {
       loadDone()
@@ -349,58 +353,40 @@ const detailTableSchema = reactive<TableItem[]>([
     dataField: 'itemFiles'
   },
   {
-    title: '上传附件',
+    title: '图片附件',
     columns: [
-      {
-        label: '序号',
-        fieldProps: {
-          type: 'index',
-          align: 'center',
-          width: 55
-        }
-      },
-      {
-        label: '文件名称',
-        prop: 'fileName',
-        fieldProps: {
-          align: 'center',
-          minWidth: 200,
-          showOverflowTooltip: true
-        }
-      },
-      {
-        label: '上传时间',
-        prop: 'createTime',
-        fieldProps: {
-          align: 'center',
-          minWidth: 160
-        },
-        render: (_row, value) => {
-          return formatDate(value, 'YYYY-MM-DD HH:mm:ss') || '-'
-        }
-      },
-      {
-        label: '操作',
-        prop: 'operation',
-        fieldProps: {
-          align: 'center',
-          minWidth: 200
-        },
-        render: (row) => {
-          return (
-            <>
-              <el-button type="primary" link onClick={() => handleAttachmentPreview(row)}>
-                预览
-              </el-button>
-              <el-button type="primary" link onClick={() => handleAttachmentDownload(row)}>
-                下载
-              </el-button>
-            </>
-          )
-        }
-      }
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '预览', prop: 'url', fieldProps: { align: 'center', minWidth: 200 },
+        render: (row) => <el-image style="width: 100px; height: 80px" src={buildFileUrl(row.url)} fit="cover" preview-teleported /> },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 100 },
+        render: (row) => <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button> }
+    ],
+    dataField: 'imageList'
+  },
+  {
+    title: '视频附件',
+    columns: [
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '文件名称', prop: 'name', fieldProps: { align: 'center', minWidth: 200, showOverflowTooltip: true } },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 100 },
+        render: (row) => <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button> }
+    ],
+    dataField: 'videoList'
+  },
+  {
+    title: '文档附件',
+    columns: [
+      { label: '序号', fieldProps: { type: 'index', align: 'center', width: 55 } },
+      { label: '文件名称', prop: 'name', fieldProps: { align: 'center', minWidth: 250, showOverflowTooltip: true } },
+      { label: '操作', prop: 'operation', fieldProps: { align: 'center', minWidth: 150 },
+        render: (row) => (
+          <>
+            <el-button type="primary" link onClick={() => window.open(buildFileUrl(row.url), '_blank')}>预览</el-button>
+            <el-button type="primary" link onClick={() => handleAttachmentDownload(row.url)}>下载</el-button>
+          </>
+        ) }
     ],
-    dataField: 'attachmentFiles'
+    dataField: 'attachmentList'
   }
 ])
 
@@ -870,28 +856,15 @@ const handlePreviewOrder = (row) => {
 
 const showAssociationOperationManual = ref(false)
 
-// 附件预览
-const handleAttachmentPreview = (row: Recordable) => {
-  const url = buildFileUrl(row.fileUrl)
-  const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']
-  const ext = row.fileName?.substring(row.fileName.lastIndexOf('.')).toLowerCase()
-  if (imageExts.includes(ext)) {
-    docPdfUrls.value = [url]
-    showDocPdfDialog.value = true
-  } else {
-    window.open(url, '_blank')
-  }
-}
-
 // 附件下载
-const handleAttachmentDownload = async (row: Recordable) => {
+const handleAttachmentDownload = async (url: string) => {
   try {
-    const url = buildFileUrl(row.fileUrl)
-    const blob = await request.download({ url })
+    const fullUrl = buildFileUrl(url)
+    const blob = await request.download({ url: fullUrl })
     const blobUrl = URL.createObjectURL(blob as unknown as Blob)
     const link = document.createElement('a')
     link.href = blobUrl
-    link.download = row.fileName || '下载文件'
+    link.download = url.substring(url.lastIndexOf('/') + 1) || '下载文件'
     document.body.appendChild(link)
     link.click()
     document.body.removeChild(link)
@@ -901,24 +874,6 @@ const handleAttachmentDownload = async (row: Recordable) => {
   }
 }
 
-// 附件删除
-const handleAttachmentDelete = async (row: Recordable) => {
-  try {
-    await ElMessageBox.confirm('确认删除该附件?', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
-    await request.delete({ url: '/pressure2/task-order-file/delete', params: { id: row.id } })
-    ElMessage.success('删除成功')
-    getDetail()
-  } catch (error: any) {
-    if (error !== 'cancel') {
-      ElMessage.error(error?.message || '删除失败')
-    }
-  }
-}
-
 onMounted(() => {
   getDetail()
 })

+ 6 - 1
yudao-ui-admin-vue3/src/views/pressure2/reportArchivingPipe/index.api.ts

@@ -16,5 +16,10 @@ export interface DetailData {
   inspectionItems: Recordable[]
   itemFiles: Recordable[]
   taskListFiles: Recordable[]
-  attachmentFiles: Recordable[]
+  images: Recordable[]
+  videos: Recordable[]
+  attachments: Recordable[]
+  imageList?: Recordable[]
+  videoList?: Recordable[]
+  attachmentList?: Recordable[]
 }