ソースを参照

Merge branch 'stable' of http://39.98.153.250:9080/yudao/yudao-admin-yiqun into stable

xzc 1 週間 前
コミット
c7d0b81386

+ 10 - 141
yudao-ui-admin-vue3/src/views/pressure2/boilerchecker/components/StatusOperationPanel.vue

@@ -744,106 +744,15 @@
   />
 
   <!-- 上传整改材料弹窗 -->
-  <Dialog
-    v-model="ectificationMaterialsVisible"
-    title="上传整改材料"
-    width="750px"
-    style="margin-bottom: 0px; height: 100vh"
-    top="0vh"
-    :scroll="true"
-    height="100vh"
-    :maxHeight="'calc(100vh - 55px - 60px - 63px)'"
-    @close="handleClosePectificationMaterialsDialog"
-  >
-    <div v-loading="ectificationMaterialsLoading" class="rectification-dialog">
-      <!-- 检验意见通知书上传 -->
-      <div class="upload-section required">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-document"></i>
-            <span class="section-title">检验意见通知书</span>
-            <span class="required-mark">*</span>
-          </div>
-          <span class="section-tip">仅支持PDF格式,限1个文件</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationUrl"
-            apiUrl="infra/file/upload"
-            :limit="1"
-            :disabled="ectificationMaterialsData.rectificationUrl.length >= 1 || ectificationMaterialsLoading"
-            accept=".pdf"
-            :default-file-name="selectedItem?.reportName || '检验意见通知书'"
-          />
-        </div>
-      </div>
-
-      <!-- 整改图片上传 -->
-      <div class="upload-section">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-image"></i>
-            <span class="section-title">整改图片</span>
-          </div>
-          <span class="section-tip">支持JPG、PNG格式,最多20张,单个不超过2MB</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationImage"
-            apiUrl="infra/file/upload"
-            :limit="20"
-            :disabled="ectificationMaterialsData.rectificationImage.length >= 20 || ectificationMaterialsLoading"
-            accept=".jpg,.jpeg,.png"
-            :multiple="true"
-            :maxSize="2097152"
-          />
-        </div>
-      </div>
-
-      <!-- 整改视频上传 -->
-      <div class="upload-section">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-video"></i>
-            <span class="section-title">整改视频</span>
-          </div>
-          <span class="section-tip">支持MP4格式,最多5个,单个不超过10MB</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationVideo"
-            apiUrl="infra/file/upload"
-            :limit="5"
-            :disabled="ectificationMaterialsData.rectificationVideo.length >= 5 || ectificationMaterialsLoading"
-            accept=".mp4"
-            :multiple="true"
-            :maxSize="10485760"
-          />
-        </div>
-      </div>
-
-      <!-- 温馨提示 -->
-      <div class="info-tips">
-        <i class="icon-info"></i>
-        <div class="tips-content">
-          <p class="tips-title">温馨提示:</p>
-          <p>1. 请确保上传的文件清晰可辨,以便审核</p>
-          <p>2. 整改材料将作为审核依据,请如实上传</p>
-        </div>
-      </div>
-    </div>
-    
-    <template #footer>
-      <el-button @click="()=> ectificationMaterialsVisible = false">取消</el-button>
-      <el-button 
-        :loading="ectificationMaterialsLoading" 
-        type="primary" 
-        @click="handleSubmitChangeEctificationMaterialsDialog"
-      >
-        确定提交
-      </el-button>
-    </template>
-  </Dialog>
+  <RectificationMaterialsDialog
+    :visible="ectificationMaterialsVisible"
+    :report-name="selectedItem?.reportName"
+    :detail="checkBookDetail"
+    :submit-api="BoilerTaskOrderApi.inspectionOpinionRectifyApi"
+    :editable="true"
+    @close="ectificationMaterialsVisible = false"
+    @success="handleRefresh"
+  />
 
   <CustomDialog
     ref="customUnitDialogRef"
@@ -909,6 +818,7 @@
 <script setup lang="tsx">
 import SmartTable from '@/components/SmartTable/SmartTable'
 import RectificationUpload from '@/views/pressure2/components/RectificationUpload.vue'
+import RectificationMaterialsDialog from '@/views/pressure2/components/RectificationMaterialsDialog.vue'
 import { computed, nextTick, reactive, ref, watch } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 import { InfoFilled, View, Back, Right, WarningFilled, VideoPlay } from '@element-plus/icons-vue'
@@ -1437,53 +1347,12 @@ const executePass = (params: Record<string, any>, type: number) => {
 }
 
 // 上传整改材料
-const ectificationMaterialsData = ref<any>({
-  rectificationUrl: [],
-  rectificationImage: [],
-  rectificationVideo: [],
-})
 const ectificationMaterialsVisible = ref(false)
-const ectificationMaterialsLoading = ref(false)
 
 const handleRectificationMaterials = () => {
-  const detail = checkBookDetail.value || {}
-  ectificationMaterialsData.value = {
-    rectificationUrl: detail.rectificationUrl ? detail.rectificationUrl.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-    rectificationImage: detail.rectificationImage ? detail.rectificationImage.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-    rectificationVideo: detail.rectificationVideo ? detail.rectificationVideo.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-  }
   ectificationMaterialsVisible.value = true
 }
 
-const handleClosePectificationMaterialsDialog = () => {
-  ectificationMaterialsVisible.value = false
-}
-
-const handleSubmitChangeEctificationMaterialsDialog = async () => {
-  if (ectificationMaterialsData.value?.rectificationUrl?.length == 0) {
-    return ElMessage.error('请上传证明材料')
-  }
-  ectificationMaterialsLoading.value = true
-  try {
-    const data = {
-      reportId: props.selectedItem?.id || '',
-      businessType: 1,
-      rectificationUrl: ectificationMaterialsData.value?.rectificationUrl?.length ? ectificationMaterialsData.value?.rectificationUrl?.map(item => item.url)?.join(',') : '',
-      rectificationImage: ectificationMaterialsData.value?.rectificationImage?.length ? ectificationMaterialsData.value?.rectificationImage?.map(item => item.url)?.join(',') : '',
-      rectificationVideo: ectificationMaterialsData.value?.rectificationVideo?.length ? ectificationMaterialsData.value?.rectificationVideo?.map(item => item.url)?.join(',') : '',
-    }
-    const response = await BoilerTaskOrderApi.inspectionOpinionRectifyApi(data)
-    if (response) {
-      ectificationMaterialsLoading.value = false
-      ElMessage.success('上传成功')
-      ectificationMaterialsVisible.value = false
-      emit('refresh')
-    }
-  } catch (error) {
-    ectificationMaterialsLoading.value = false
-  }
-}
-
 // 获取检验员名称
 const getCheckersName = (): string => {
   if (!props.selectedItem?.checkUsers || props.selectedItem.checkUsers.length === 0) {

+ 266 - 0
yudao-ui-admin-vue3/src/views/pressure2/components/RectificationMaterialsDialog.vue

@@ -0,0 +1,266 @@
+<template>
+  <Dialog
+    :model-value="visible"
+    @update:model-value="$emit('close')"
+    title="上传整改材料"
+    width="750px"
+    style="margin-bottom: 0px; height: 100vh"
+    top="0vh"
+    :scroll="true"
+    height="100vh"
+    :maxHeight="'calc(100vh - 55px - 60px - 63px)'"
+    @close="$emit('close')"
+  >
+    <div v-loading="loading" class="rectification-dialog">
+      <!-- 检验意见通知书上传 -->
+      <div class="upload-section required">
+        <div class="section-header">
+          <div class="header-left">
+            <i class="icon-document"></i>
+            <span class="section-title">检验意见通知书</span>
+            <span class="required-mark">*</span>
+          </div>
+          <span class="section-tip">仅支持PDF格式,限1个文件</span>
+        </div>
+        <div class="upload-area">
+          <RectificationUpload
+            v-model:fileList="formData.rectificationUrl"
+            apiUrl="infra/file/upload"
+            :limit="1"
+            :disabled="formData.rectificationUrl.length >= 1 || loading"
+            accept=".pdf"
+            :default-file-name="reportName || '检验意见通知书'"
+            :readonly="!editable"
+          />
+        </div>
+      </div>
+
+      <!-- 整改图片上传 -->
+      <div class="upload-section">
+        <div class="section-header">
+          <div class="header-left">
+            <i class="icon-image"></i>
+            <span class="section-title">整改图片</span>
+          </div>
+          <span class="section-tip">支持JPG、PNG格式,最多20张,单个不超过2MB</span>
+        </div>
+        <div class="upload-area">
+          <RectificationUpload
+            v-model:fileList="formData.rectificationImage"
+            apiUrl="infra/file/upload"
+            :limit="20"
+            :disabled="formData.rectificationImage.length >= 20 || loading"
+            accept=".jpg,.jpeg,.png"
+            :multiple="true"
+            :maxSize="2097152"
+            :readonly="!editable"
+          />
+        </div>
+      </div>
+
+      <!-- 整改视频上传 -->
+      <div class="upload-section">
+        <div class="section-header">
+          <div class="header-left">
+            <i class="icon-video"></i>
+            <span class="section-title">整改视频</span>
+          </div>
+          <span class="section-tip">支持MP4格式,最多5个,单个不超过10MB</span>
+        </div>
+        <div class="upload-area">
+          <RectificationUpload
+            v-model:fileList="formData.rectificationVideo"
+            apiUrl="infra/file/upload"
+            :limit="5"
+            :disabled="formData.rectificationVideo.length >= 5 || loading"
+            accept=".mp4"
+            :multiple="true"
+            :maxSize="10485760"
+            :readonly="!editable"
+          />
+        </div>
+      </div>
+
+      <!-- 温馨提示 -->
+      <div class="info-tips">
+        <i class="icon-info"></i>
+        <div class="tips-content">
+          <p class="tips-title">温馨提示:</p>
+          <p>1. 请确保上传的文件清晰可辨,以便审核</p>
+          <p>2. 整改材料将作为审核依据,请如实上传</p>
+        </div>
+      </div>
+    </div>
+    
+    <template #footer>
+      <el-button @click="$emit('close')">取消</el-button>
+      <el-button 
+        v-if="editable"
+        :loading="loading" 
+        type="primary" 
+        @click="handleSubmit"
+      >
+        确定提交
+      </el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+import { ElMessage } from 'element-plus'
+import RectificationUpload from './RectificationUpload.vue'
+
+interface RectificationMaterialsData {
+  rectificationUrl: { url: string; name?: string }[]
+  rectificationImage: { url: string; name?: string }[]
+  rectificationVideo: { url: string; name?: string }[]
+}
+
+const props = defineProps<{
+  visible: boolean
+  reportName?: string
+  detail?: Record<string, any>
+  submitApi?: (data: any) => Promise<any>
+  editable?: boolean
+}>()
+
+const emit = defineEmits<{
+  close: []
+  success: []
+}>()
+
+const loading = ref(false)
+const formData = ref<RectificationMaterialsData>({
+  rectificationUrl: [],
+  rectificationImage: [],
+  rectificationVideo: [],
+})
+
+watch(() => props.visible, (val) => {
+  if (val) {
+    initData()
+  }
+})
+
+const initData = () => {
+  const detail = props.detail || {}
+  formData.value = {
+    rectificationUrl: detail.rectificationUrl ? detail.rectificationUrl.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
+    rectificationImage: detail.rectificationImage ? detail.rectificationImage.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
+    rectificationVideo: detail.rectificationVideo ? detail.rectificationVideo.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
+  }
+}
+
+const handleSubmit = async () => {
+  if (formData.value?.rectificationUrl?.length == 0) {
+    return ElMessage.error('请上传证明材料')
+  }
+  if (!props.submitApi) return
+  loading.value = true
+  try {
+    const data = {
+      reportId: props.detail?.id || '',
+      businessType: 1,
+      rectificationUrl: formData.value.rectificationUrl.length ? formData.value.rectificationUrl.map(item => item.url).join(',') : '',
+      rectificationImage: formData.value.rectificationImage.length ? formData.value.rectificationImage.map(item => item.url).join(',') : '',
+      rectificationVideo: formData.value.rectificationVideo.length ? formData.value.rectificationVideo.map(item => item.url).join(',') : '',
+    }
+    const response = await props.submitApi(data)
+    if (response) {
+      ElMessage.success('上传成功')
+      emit('success')
+      emit('close')
+    }
+  } catch (error) {
+    // handled by API
+  } finally {
+    loading.value = false
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.rectification-dialog {
+  .upload-section {
+    margin-bottom: 20px;
+    padding: 16px;
+    border: 1px solid #ebeef5;
+    border-radius: 8px;
+    background: #fafbfc;
+
+  }
+
+  .section-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 12px;
+  }
+
+  .header-left {
+    display: flex;
+    align-items: center;
+    gap: 6px;
+  }
+
+  .section-title {
+    font-size: 14px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .required-mark {
+    color: #f56c6c;
+  }
+
+  .section-tip {
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .upload-area {
+    min-height: 40px;
+  }
+
+  .info-tips {
+    display: flex;
+    gap: 8px;
+    padding: 12px;
+    background: #f0f9ff;
+    border: 1px solid #b3d8ff;
+    border-radius: 6px;
+    margin-top: 20px;
+
+    .tips-content {
+      p {
+        margin: 0;
+        font-size: 12px;
+        color: #606266;
+        line-height: 1.8;
+      }
+      .tips-title {
+        font-weight: 600;
+        color: #409eff;
+      }
+    }
+  }
+
+  .icon-document::before {
+    content: "📄";
+  }
+
+  .icon-image::before {
+    content: "🖼️";
+  }
+
+  .icon-video::before {
+    content: "🎬";
+  }
+
+  .icon-info::before {
+    content: "ℹ️";
+  }
+
+}
+</style>

+ 5 - 4
yudao-ui-admin-vue3/src/views/pressure2/components/RectificationUpload.vue

@@ -11,7 +11,7 @@
     :multiple="multiple"
   >
     <slot name="trigger">
-      <el-button :disabled="disabled">
+      <el-button :disabled="disabled || readonly">
         <el-icon><Upload /></el-icon>
         上传文件
       </el-button>
@@ -24,7 +24,7 @@
       <el-icon :size="18"><Document /></el-icon>
       <span class="pdf-file-name" :title="displayName(file)">{{ displayName(file) }}</span>
       <span class="pdf-action download" @click="handleDownload(file)">下载</span>
-      <span class="pdf-action" @click="handleRemove(file)">删除</span>
+      <span v-if="!readonly" class="pdf-action" @click="handleRemove(file)">删除</span>
     </div>
   </div>
 
@@ -47,7 +47,7 @@
       </div>
       <div class="item-footer">
         <span class="item-name" :title="file.name">{{ file.name }}</span>
-        <div class="item-actions">
+        <div v-if="!readonly" class="item-actions">
           <span class="action-btn" @click.stop="handleDownload(file)">下载</span>
           <span class="action-btn delete" @click.stop="handleRemove(file)">删除</span>
         </div>
@@ -90,7 +90,8 @@ const props = defineProps({
   maxSize: { type: Number, default: 0 },
   multiple: { type: Boolean, default: false },
   apiUrl: { type: String, required: true },
-  defaultFileName: { type: String, default: '' }
+  defaultFileName: { type: String, default: '' },
+  readonly: { type: Boolean, default: false }
 })
 
 const emit = defineEmits(['update:fileList'])

+ 38 - 72
yudao-ui-admin-vue3/src/views/pressure2/inspectionOpinion/reportIndexBoilerTab.vue

@@ -274,11 +274,12 @@
             <!-- <el-button link type="primary" @click="openUpdateSituationDialog(row)">
               情况备注
             </el-button> -->
-            <el-button link type="primary" v-if="filerFileUrlShowFn(row)" @click="handleFilePreview(row)"> 查看附件 </el-button>
+            <el-button link type="primary" v-if="filerFileUrlShowFn(row)" @click="handlePreviewFiles(row)"> 查看附件 </el-button>
             <el-button
                   link
                   type="primary"
-                  @click="handleViewPdf(row)"
+                  :disabled="!row.opinionReportedUrl"
+                  @click="handleViewReport(row.opinionReportedUrl)"
                 >
                   系统生成检验意见书
                 </el-button>
@@ -700,11 +701,12 @@
       >
     </template>
   </CustomDialog>
-  <ReportListUploadModal
-    ref="reportListUploadModalRef"
-    :flag="true"
-    :selectedItem="currentReport"
-    :reportList="allReportList"
+  <RectificationMaterialsDialog
+    :visible="previewFilesVisible"
+    :report-name="previewRow?.reportName"
+    :detail="previewRow"
+    :editable="false"
+    @close="previewFilesVisible = false"
   />
  <unitContainerForm ref="unitContainerFormRef" />
 
@@ -721,7 +723,7 @@
 import { ref, reactive } from 'vue'
 import VuePdfEmbed from 'vue-pdf-embed'
 import unitContainerForm from '@/components/unitContainerForm/index.vue'
-import ReportListUploadModal from '@/views/pressure/checker/components/reportListUploadModal.vue'
+import RectificationMaterialsDialog from '@/views/pressure2/components/RectificationMaterialsDialog.vue'
 import {
   PressureBoilerCheckTypeMap,
   PressureCheckerMyTaskStatusMap,
@@ -754,8 +756,8 @@ import { buildFileUrl } from '@/utils'
 import { useUserStoreWithOut } from '@/store/modules/user'
 import PdfPreviewDialog from "@/views/pressure2/boilertaskorder/PdfPreviewDialog.vue";
 const message = useMessage() // 消息弹窗
-const reportListUploadModalRef = ref<InstanceType<typeof ReportListUploadModal>>()
-const allReportList = ref<any>([])
+const previewFilesVisible = ref(false)
+const previewRow = ref<any>({})
 
 // 表单数据
 const recipientRow = ref<Record<string, any>>({})
@@ -860,16 +862,15 @@ const getDeptDataList = async () => {
   deptDataList.value = res || []
 }
 const filerFileUrlShowFn = (row) => {
-  if (row?.attachment || row?.image || row?.video) {
+  if (row?.rectificationImage || row?.rectificationUrl || row?.rectificationVideo) {
     return true
   }else {
     return false
   }
 }
-const handleFilePreview = (row) => {
-  currentReport.value = row
-  allReportList.value = [{id: row.id, reportName: row.reportName}]
-  reportListUploadModalRef.value?.openModal(false, currentReport.value)
+const handlePreviewFiles = (row) => {
+  previewRow.value = row
+  previewFilesVisible.value = true
 }
 /**
  * 获取列表数据
@@ -1146,64 +1147,29 @@ const handleBatchReport = (businessType: any) => {
           getList()
         }
       } else {
-        // loading.value = true
-        // const result = await BoilerTaskOrderApi.downloadReport(params)
-        // loading.value = false
-
-        let downData: any[] = []
-        list.forEach((row) => {
-          downData.push({
-            taskStatus: 100,
-            resultTemplateId: '',
-            templateId: row.templateId,
-            reportUrl: '',
-            id: row.reportId,
-          })
-        })
-
-        const loadingInstance = ElLoading.service({
-          fullscreen: true,
-          text: '正在下载...'
-        })
-
-        try {
-
-          // 调用 API 获取 ZIP blob
-          const zipBlob = await PipeInputApi.handleDownload(downData)
-
-          if (zipBlob) {
-            // 创建临时 URL
-            const zipUrl = URL.createObjectURL(zipBlob)
-
-            const fileName =
-              '检验意见通知' +
-              `${businessType === 2 ? '报告办结' : '隐患上报'}(${formatDate(
-                new Date(),
-                'YYYY年MM月DD日'
-              )})` +
-              '.zip'
-            // 创建隐藏的 a 标签触发下载
-            const link = document.createElement('a')
-            link.href = zipUrl
-            link.download = fileName
-            document.body.appendChild(link)
-            link.click()
-
-            // 清理 DOM 和 URL
-            document.body.removeChild(link)
-            URL.revokeObjectURL(zipUrl)
-
-            ElMessage.success('下载成功')
-          } else {
-            ElMessage.error('获取下载文件失败')
-          }
+        loading.value = true
+        const result = await BoilerTaskOrderApi.downloadReport(params)
+        loading.value = false
+        if (result) {
+          const url = buildFileUrl(result)
+          fetch(url)
+            .then(response => response.blob())
+            .then(blob => {
+              const blobUrl = window.URL.createObjectURL(blob)
+              const a = document.createElement('a')
+              a.href = blobUrl
+              const fileName =
+                '检验意见通知' +
+                `${businessType === 2 ? '报告办结' : '隐患上报'}(${formatDate(new Date(), 'YYYY年MM月DD日')})` +
+                '.zip'
+              a.download = fileName
+              document.body.appendChild(a)
+              a.click()
+              document.body.removeChild(a)
+              window.URL.revokeObjectURL(blobUrl)
+            })
+            .catch(() => ElMessage.error('下载失败'))
           getList()
-
-        }catch (error) {
-          console.error('下载失败:', error)
-          ElMessage.error('下载失败')
-        } finally {
-          loadingInstance.close()
         }
 
       }

+ 37 - 71
yudao-ui-admin-vue3/src/views/pressure2/inspectionOpinion/reportIndexPipeTab.vue

@@ -274,11 +274,12 @@
             <!-- <el-button link type="primary" @click="openUpdateSituationDialog(row)">
               情况备注
             </el-button> -->
-            <el-button link type="primary" v-if="filerFileUrlShowFn(row)" @click="handleFilePreview(row)"> 查看附件 </el-button>
+            <el-button link type="primary" v-if="filerFileUrlShowFn(row)" @click="handlePreviewFiles(row)"> 查看附件 </el-button>
             <el-button
                   link
                   type="primary"
-                  @click="handleViewPdf(row)"
+                  :disabled="!row.opinionReportedUrl"
+                  @click="handleViewReport(row.opinionReportedUrl)"
                 >
                   系统生成检验意见书
                 </el-button>
@@ -700,11 +701,12 @@
       >
     </template>
   </CustomDialog>
-  <ReportListUploadModal
-    ref="reportListUploadModalRef"
-    :flag="true"
-    :selectedItem="currentReport"
-    :reportList="allReportList"
+  <RectificationMaterialsDialog
+    :visible="previewFilesVisible"
+    :report-name="previewRow?.reportName"
+    :detail="previewRow"
+    :editable="false"
+    @close="previewFilesVisible = false"
   />
  <unitContainerForm ref="unitContainerFormRef" />
 
@@ -721,7 +723,7 @@
 import { ref, reactive } from 'vue'
 import VuePdfEmbed from 'vue-pdf-embed'
 import unitContainerForm from '@/components/unitContainerForm/index.vue'
-import ReportListUploadModal from '@/views/pressure/checker/components/reportListUploadModal.vue'
+import RectificationMaterialsDialog from '@/views/pressure2/components/RectificationMaterialsDialog.vue'
 import {
   PressurePipeCheckTypeMap,
   PressureCheckerMyTaskStatusMap,
@@ -754,8 +756,8 @@ import { buildFileUrl } from '@/utils'
 import { useUserStoreWithOut } from '@/store/modules/user'
 import PdfPreviewDialog from "@/views/pressure2/boilertaskorder/PdfPreviewDialog.vue";
 const message = useMessage() // 消息弹窗
-const reportListUploadModalRef = ref<InstanceType<typeof ReportListUploadModal>>()
-const allReportList = ref<any>([])
+const previewFilesVisible = ref(false)
+const previewRow = ref<any>({})
 
 // 表单数据
 const recipientRow = ref<Record<string, any>>({})
@@ -866,10 +868,9 @@ const filerFileUrlShowFn = (row) => {
     return false
   }
 }
-const handleFilePreview = (row) => {
-  currentReport.value = row
-  allReportList.value = [{id: row.id, reportName: row.reportName}]
-  reportListUploadModalRef.value?.openModal(false, currentReport.value)
+const handlePreviewFiles = (row) => {
+  previewRow.value = row
+  previewFilesVisible.value = true
 }
 /**
  * 获取列表数据
@@ -1146,64 +1147,29 @@ const handleBatchReport = (businessType: any) => {
           getList()
         }
       } else {
-        // loading.value = true
-        // const result = await PipeTaskOrderApi.downloadReport(params)
-        // loading.value = false
-
-        let downData: any[] = []
-        list.forEach((row) => {
-          downData.push({
-            taskStatus: 100,
-            resultTemplateId: '',
-            templateId: row.templateId,
-            reportUrl: '',
-            id: row.reportId,
-          })
-        })
-
-        const loadingInstance = ElLoading.service({
-          fullscreen: true,
-          text: '正在下载...'
-        })
-
-        try {
-
-          // 调用 API 获取 ZIP blob
-          const zipBlob = await PipeInputApi.handleDownload(downData)
-
-          if (zipBlob) {
-            // 创建临时 URL
-            const zipUrl = URL.createObjectURL(zipBlob)
-
-            const fileName =
-              '检验意见通知' +
-              `${businessType === 2 ? '报告办结' : '隐患上报'}(${formatDate(
-                new Date(),
-                'YYYY年MM月DD日'
-              )})` +
-              '.zip'
-            // 创建隐藏的 a 标签触发下载
-            const link = document.createElement('a')
-            link.href = zipUrl
-            link.download = fileName
-            document.body.appendChild(link)
-            link.click()
-
-            // 清理 DOM 和 URL
-            document.body.removeChild(link)
-            URL.revokeObjectURL(zipUrl)
-
-            ElMessage.success('下载成功')
-          } else {
-            ElMessage.error('获取下载文件失败')
-          }
+        loading.value = true
+        const result = await PipeTaskOrderApi.downloadReport(params)
+        loading.value = false
+        if (result) {
+          const url = buildFileUrl(result)
+          fetch(url)
+            .then(response => response.blob())
+            .then(blob => {
+              const blobUrl = window.URL.createObjectURL(blob)
+              const a = document.createElement('a')
+              a.href = blobUrl
+              const fileName =
+                '检验意见通知' +
+                `${businessType === 2 ? '报告办结' : '隐患上报'}(${formatDate(new Date(), 'YYYY年MM月DD日')})` +
+                '.zip'
+              a.download = fileName
+              document.body.appendChild(a)
+              a.click()
+              document.body.removeChild(a)
+              window.URL.revokeObjectURL(blobUrl)
+            })
+            .catch(() => ElMessage.error('下载失败'))
           getList()
-
-        }catch (error) {
-          console.error('下载失败:', error)
-          ElMessage.error('下载失败')
-        } finally {
-          loadingInstance.close()
         }
 
       }

+ 10 - 141
yudao-ui-admin-vue3/src/views/pressure2/pipechecker/components/StatusOperationPanel.vue

@@ -746,106 +746,15 @@
   />
 
   <!-- 上传整改材料弹窗 -->
-  <Dialog
-    v-model="ectificationMaterialsVisible"
-    title="上传整改材料"
-    width="750px"
-    style="margin-bottom: 0px; height: 100vh"
-    top="0vh"
-    :scroll="true"
-    height="100vh"
-    :maxHeight="'calc(100vh - 55px - 60px - 63px)'"
-    @close="handleClosePectificationMaterialsDialog"
-  >
-    <div v-loading="ectificationMaterialsLoading" class="rectification-dialog">
-      <!-- 检验意见通知书上传 -->
-      <div class="upload-section required">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-document"></i>
-            <span class="section-title">检验意见通知书</span>
-            <span class="required-mark">*</span>
-          </div>
-          <span class="section-tip">仅支持PDF格式,限1个文件</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationUrl"
-            apiUrl="infra/file/upload"
-            :limit="1"
-            :disabled="ectificationMaterialsData.rectificationUrl.length >= 1 || ectificationMaterialsLoading"
-            accept=".pdf"
-            :default-file-name="selectedItem?.reportName || '检验意见通知书'"
-          />
-        </div>
-      </div>
-
-      <!-- 整改图片上传 -->
-      <div class="upload-section">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-image"></i>
-            <span class="section-title">整改图片</span>
-          </div>
-          <span class="section-tip">支持JPG、PNG格式,最多20张,单个不超过2MB</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationImage"
-            apiUrl="infra/file/upload"
-            :limit="20"
-            :disabled="ectificationMaterialsData.rectificationImage.length >= 20 || ectificationMaterialsLoading"
-            accept=".jpg,.jpeg,.png"
-            :multiple="true"
-            :maxSize="2097152"
-          />
-        </div>
-      </div>
-
-      <!-- 整改视频上传 -->
-      <div class="upload-section">
-        <div class="section-header">
-          <div class="header-left">
-            <i class="icon-video"></i>
-            <span class="section-title">整改视频</span>
-          </div>
-          <span class="section-tip">支持MP4格式,最多5个,单个不超过10MB</span>
-        </div>
-        <div class="upload-area">
-          <RectificationUpload
-            v-model:fileList="ectificationMaterialsData.rectificationVideo"
-            apiUrl="infra/file/upload"
-            :limit="5"
-            :disabled="ectificationMaterialsData.rectificationVideo.length >= 5 || ectificationMaterialsLoading"
-            accept=".mp4"
-            :multiple="true"
-            :maxSize="10485760"
-          />
-        </div>
-      </div>
-
-      <!-- 温馨提示 -->
-      <div class="info-tips">
-        <i class="icon-info"></i>
-        <div class="tips-content">
-          <p class="tips-title">温馨提示:</p>
-          <p>1. 请确保上传的文件清晰可辨,以便审核</p>
-          <p>2. 整改材料将作为审核依据,请如实上传</p>
-        </div>
-      </div>
-    </div>
-    
-    <template #footer>
-      <el-button @click="()=> ectificationMaterialsVisible = false">取消</el-button>
-      <el-button 
-        :loading="ectificationMaterialsLoading" 
-        type="primary" 
-        @click="handleSubmitChangeEctificationMaterialsDialog"
-      >
-        确定提交
-      </el-button>
-    </template>
-  </Dialog>
+  <RectificationMaterialsDialog
+    :visible="ectificationMaterialsVisible"
+    :report-name="selectedItem?.reportName"
+    :detail="checkBookDetail"
+    :submit-api="PipeTaskOrderApi.inspectionOpinionRectifyApi"
+    :editable="true"
+    @close="ectificationMaterialsVisible = false"
+    @success="handleRefresh"
+  />
 
   <CustomDialog
     ref="customUnitDialogRef"
@@ -911,6 +820,7 @@
 <script setup lang="tsx">
 import SmartTable from '@/components/SmartTable/SmartTable'
 import RectificationUpload from '@/views/pressure2/components/RectificationUpload.vue'
+import RectificationMaterialsDialog from '@/views/pressure2/components/RectificationMaterialsDialog.vue'
 import {computed, defineAsyncComponent, nextTick, reactive, ref, watch} from 'vue'
 import {useRoute} from 'vue-router'
 import { InfoFilled, View, Back, Right, WarningFilled, VideoPlay } from '@element-plus/icons-vue'
@@ -1408,53 +1318,12 @@ const executePass = (params: Record<string, any>, type: number) => {
 }
 
 // 上传整改材料
-const ectificationMaterialsData = ref<any>({
-  rectificationUrl: [],
-  rectificationImage: [],
-  rectificationVideo: [],
-})
 const ectificationMaterialsVisible = ref(false)
-const ectificationMaterialsLoading = ref(false)
 
 const handleRectificationMaterials = () => {
-  const detail = checkBookDetail.value || {}
-  ectificationMaterialsData.value = {
-    rectificationUrl: detail.rectificationUrl ? detail.rectificationUrl.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-    rectificationImage: detail.rectificationImage ? detail.rectificationImage.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-    rectificationVideo: detail.rectificationVideo ? detail.rectificationVideo.split(',').filter(Boolean).map((url: string) => ({ url })) : [],
-  }
   ectificationMaterialsVisible.value = true
 }
 
-const handleClosePectificationMaterialsDialog = () => {
-  ectificationMaterialsVisible.value = false
-}
-
-const handleSubmitChangeEctificationMaterialsDialog = async () => {
-  if (ectificationMaterialsData.value?.rectificationUrl?.length == 0) {
-    return ElMessage.error('请上传证明材料')
-  }
-  ectificationMaterialsLoading.value = true
-  try {
-    const data = {
-      reportId: props.selectedItem?.id || '',
-      businessType: 1,
-      rectificationUrl: ectificationMaterialsData.value?.rectificationUrl?.length ? ectificationMaterialsData.value?.rectificationUrl?.map(item => item.url)?.join(',') : '',
-      rectificationImage: ectificationMaterialsData.value?.rectificationImage?.length ? ectificationMaterialsData.value?.rectificationImage?.map(item => item.url)?.join(',') : '',
-      rectificationVideo: ectificationMaterialsData.value?.rectificationVideo?.length ? ectificationMaterialsData.value?.rectificationVideo?.map(item => item.url)?.join(',') : '',
-    }
-    const response = await PipeTaskOrderApi.inspectionOpinionRectifyApi(data)
-    if (response) {
-      ectificationMaterialsLoading.value = false
-      ElMessage.success('上传成功')
-      ectificationMaterialsVisible.value = false
-      emit('refresh')
-    }
-  } catch (error) {
-    ectificationMaterialsLoading.value = false
-  }
-}
-
 // 获取检验员名称
 const getCheckersName = (): string => {
   if (!props.selectedItem?.checkUsers || props.selectedItem.checkUsers.length === 0) {