From cd65fdeabc462afd4fe99e4c789a243bf9b64ee6 Mon Sep 17 00:00:00 2001
From: shimai <shimai@example.com>
Date: Fri, 27 Feb 2026 16:28:27 +0800
Subject: [PATCH] fix:修复调解协议无法下载

---
 web-app/src/components/dashboard/TabContainer.jsx |   67 ++++++++++++++++++++++++++++++++-
 1 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index cd5b0dc..639d7b2 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -6,6 +6,7 @@
 import MediationAgreementAPIService from '../../services/MediationAgreementAPIService';
 import { getMergedParams } from '../../utils/urlParams';
 import { message, Spin, Tag, Modal, Button, Input, Image } from 'antd';
+import config from '../../config/env';
 
 const { TextArea } = Input;
 
@@ -1290,6 +1291,32 @@
     });
   };
 
+  const resolveDownloadFileName = (contentDisposition) => {
+    if (!contentDisposition) return '';
+    const utf8Match = contentDisposition.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);
+    if (utf8Match?.[1]) {
+      try {
+        return decodeURIComponent(utf8Match[1]);
+      } catch (err) {
+        return utf8Match[1];
+      }
+    }
+    const fileNameMatch = contentDisposition.match(/filename\s*=\s*"?([^"]+)"?/i);
+    if (fileNameMatch?.[1]) return fileNameMatch[1];
+    return '';
+  };
+
+  const triggerFileDownload = (blob, fileName) => {
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = fileName;
+    document.body.appendChild(link);
+    link.click();
+    link.remove();
+    window.URL.revokeObjectURL(url);
+  };
+
   // 首次加载协议内容
   const loadAgreement = async () => {
     if (!caseId) {
@@ -1341,11 +1368,45 @@
     if (!caseId) return;
     setActionLoading(prev => ({ ...prev, download: true }));
     try {
-      await MediationAgreementAPIService.downloadAgreement(caseId);
-      message.success('协议下载成功!');
+      const token = localStorage.getItem('access_token');
+      const response = await fetch(`${config.baseURL}/api/v1/medi-agreement/download`, {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          ...(token ? { Authorization: `Bearer ${token}` } : {})
+        },
+        body: JSON.stringify({ caseId }),
+        credentials: config.withCredentials ? 'include' : 'omit'
+      });
+
+      const contentType = response.headers.get('Content-Type') || '';
+      if (contentType.includes('application/pdf')) {
+        if (!response.ok) {
+          throw new Error('下载协议失败,请稍后重试');
+        }
+        const blob = await response.blob();
+        const contentDisposition = response.headers.get('Content-Disposition') || '';
+        const fileName = resolveDownloadFileName(contentDisposition) || '调解协议书.pdf';
+        triggerFileDownload(blob, fileName);
+        message.success('协议下载成功!');
+        return;
+      }
+
+      const data = await response.json();
+      if (data?.code !== 200 && data?.code !== 201) {
+        throw new Error(data?.message || '下载协议失败,请稍后重试');
+      }
+      if (data?.data?.needConfirm || data?.message === '待确认') {
+        message.warning('协议待确认,请先确认协议');
+        return;
+      }
+      if (data?.data?.agreeContent) {
+        setAgreementContent(data.data.agreeContent);
+      }
+      message.success(data?.message || '已返回协议内容');
     } catch (err) {
       console.error('下载协议失败:', err);
-      message.error('下载协议失败,请稍后重试');
+      message.error(err?.message || '下载协议失败,请稍后重试');
     } finally {
       setActionLoading(prev => ({ ...prev, download: false }));
     }

--
Gitblit v1.8.0