Kaynağa Gözat

[Bugfix 0000] 修复ai助手不能预览文件的bug

wangkeyi 2 hafta önce
ebeveyn
işleme
64cfbb1abf

+ 15 - 3
src/views/ventAI/manageAssistent/api/report.ts

@@ -8,11 +8,23 @@ enum Api {
 }
 
 /**
- * 报告下载
- * 从 URL 或文件名中提取纯文件名,构建 /api/download/report/{filename} 地址
+ * 把后端返回的报告地址归一成走 /ventAI 代理的下载地址。
+ *
+ * 后端实际返回过两种形式:`http://<host>/api/download/report/<file>`(绝对地址)与
+ * `/api/download/report/<file>`(相对路径)。后者缺 /ventAI 前缀,直接交给浏览器会打到前端自己的源上
+ * (dev 是 Vite,没有 /api 路由)从而 404。这里统一重建成 /ventAI/api/download/report/<file>,
+ * 与其余接口一致走代理,dev 与生产都不依赖后端返回的 Host。
+ *
+ * 注意地址里的文件名是已百分号编码的,必须先解码再编码,否则会双重编码导致后端找不到文件。
  */
 export const buildReportDownloadUrl = (urlOrFilename: string) => {
-  const filename = urlOrFilename.split('/').pop() || urlOrFilename;
+  const raw = urlOrFilename.split('/').pop() || urlOrFilename;
+  let filename = raw;
+  try {
+    filename = decodeURIComponent(raw);
+  } catch {
+    // 含非法百分号序列时按原样处理
+  }
   return `${Api.downloadReport}${encodeURIComponent(filename)}`;
 };
 

+ 6 - 3
src/views/ventAI/manageAssistent/hooks/useChatStream.ts

@@ -1,6 +1,7 @@
 import { nextTick, toRaw } from 'vue';
 import type { AskUserQuestion, Message, Task, ThinkingStep, SseEvent } from '/@/views/ventAI/manageAssistent/types/index';
 import { normalizeLineBreaks } from '/@/views/ventAI/manageAssistent/lib/index';
+import { buildReportDownloadUrl } from '/@/views/ventAI/manageAssistent/api';
 
 // 工具名 → 中文智能体名(agent 分组标题用)。仅本模块使用,随事件映射一起内聚在此
 const AGENT_NAME_MAP: Record<string, string> = {
@@ -206,7 +207,8 @@ export const useChatStream = (hooks: ChatStreamHooks) => {
         });
         if (data.download_url) {
           if (!aiMsg.downloadFiles) aiMsg.downloadFiles = [];
-          aiMsg.downloadFiles.push({ url: data.download_url, filename: data.filename || '文件' });
+          // 与历史加载一致:后端返回的报告地址前缀不稳定,入状态前统一归一(见 buildReportDownloadUrl)
+          aiMsg.downloadFiles.push({ url: buildReportDownloadUrl(data.download_url), filename: data.filename || '文件' });
         }
         break;
       }
@@ -276,8 +278,9 @@ export const useChatStream = (hooks: ChatStreamHooks) => {
 
       case 'word_download':
         if (normalizedContent) {
-          aiMsg.wordDownloadUrl = normalizedContent;
-          streamingTask.wordUrl = normalizedContent;
+          const reportUrl = buildReportDownloadUrl(normalizedContent);
+          aiMsg.wordDownloadUrl = reportUrl;
+          streamingTask.wordUrl = reportUrl;
         }
         break;
 

+ 3 - 2
src/views/ventAI/manageAssistent/hooks/useChatTasks.ts

@@ -1,7 +1,7 @@
 import { computed, ref } from 'vue';
 import dayjs from 'dayjs';
 import { message } from 'ant-design-vue';
-import { editSessionTitle, getHistoryList, pinSession } from '/@/views/ventAI/manageAssistent/api';
+import { buildReportDownloadUrl, editSessionTitle, getHistoryList, pinSession } from '/@/views/ventAI/manageAssistent/api';
 import type { Message, Task } from '/@/views/ventAI/manageAssistent/types/index';
 import { normalizeLineBreaks } from '/@/views/ventAI/manageAssistent/lib/index';
 
@@ -162,7 +162,8 @@ export const useChatTasks = () => {
       } else if (item.role === 'assistant') {
         const msg: Message = { id: item.id, type: 'ai', content: normalizedContent, time, createdAt };
         if (item.report_url && item.report_filename) {
-          msg.downloadFiles = [{ url: item.report_url, filename: item.report_filename }];
+          // 后端返回的报告地址前缀不稳定(绝对地址 / 缺 /ventAI 的相对路径),入前端状态前统一归一
+          msg.downloadFiles = [{ url: buildReportDownloadUrl(item.report_url), filename: item.report_filename }];
         }
         if (item.citations) {
           // 历史接口返回 citations 为扁平数组,SSE 事件返回 { items, model_only },统一归一化