From a0aa77dfda73a7988786480e9223a1588f25f04d Mon Sep 17 00:00:00 2001 From: root Date: Sat, 17 Oct 2026 11:07:00 +0800 Subject: [PATCH] feat: filename-aware attachment download endpoint (Content-Disposition), preview download uses it (no popup flash) --- .../components/common/AttachmentPreview.tsx | 32 ++--- app/src/lib/api.ts | 15 ++ scripts/test-integration.mjs | 5 + sync-server/src/index.mjs | 13 ++ ...Page-jK4FA0_C.js => AdminPage-CWJ8-9ih.js} | 6 +- ...-isIkaoEY.js => DashboardPage-Bf-zXsd3.js} | 2 +- ...age-bPRaXE60.js => GradesPage-CIPJ6CjP.js} | 2 +- ...ge-BywtKaT6.js => RecordsPage-DIF8PoaR.js} | 2 +- ...e-Bk6-Aip_.js => TaxonomyPage-O2veOaVJ.js} | 2 +- ...Page-h2tDsqAZ.js => TypesPage-PKuM2qPG.js} | 2 +- .../{card-C3qAWMF6.js => card-abtg_WiG.js} | 2 +- .../{index-GKqw9oy7.js => index-B7s6g2Bv.js} | 130 +++++++++--------- ...6TcAI3P.js => mammoth.browser-C-9y1qqX.js} | 2 +- ...Chart-CZ5C9jzK.js => useChart-oVrBsOjL.js} | 2 +- sync-server/www/index.html | 2 +- 15 files changed, 120 insertions(+), 99 deletions(-) rename sync-server/www/assets/{AdminPage-jK4FA0_C.js => AdminPage-CWJ8-9ih.js} (97%) rename sync-server/www/assets/{DashboardPage-isIkaoEY.js => DashboardPage-Bf-zXsd3.js} (94%) rename sync-server/www/assets/{GradesPage-bPRaXE60.js => GradesPage-CIPJ6CjP.js} (99%) rename sync-server/www/assets/{RecordsPage-BywtKaT6.js => RecordsPage-DIF8PoaR.js} (99%) rename sync-server/www/assets/{TaxonomyPage-Bk6-Aip_.js => TaxonomyPage-O2veOaVJ.js} (97%) rename sync-server/www/assets/{TypesPage-h2tDsqAZ.js => TypesPage-PKuM2qPG.js} (98%) rename sync-server/www/assets/{card-C3qAWMF6.js => card-abtg_WiG.js} (89%) rename sync-server/www/assets/{index-GKqw9oy7.js => index-B7s6g2Bv.js} (58%) rename sync-server/www/assets/{mammoth.browser-D6TcAI3P.js => mammoth.browser-C-9y1qqX.js} (99%) rename sync-server/www/assets/{useChart-CZ5C9jzK.js => useChart-oVrBsOjL.js} (92%) diff --git a/app/src/components/common/AttachmentPreview.tsx b/app/src/components/common/AttachmentPreview.tsx index d4a171b..e45d5c3 100644 --- a/app/src/components/common/AttachmentPreview.tsx +++ b/app/src/components/common/AttachmentPreview.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { Download, Loader2 } from 'lucide-react'; import { Button, Dialog, useToast } from '@/components/ui'; import { readFull } from '@/lib/att-cache'; +import { attachmentDownload } from '@/lib/api'; import type { Attachment } from '@/lib/types'; export type AttKind = 'image' | 'pdf' | 'text' | 'audio' | 'video' | 'docx' | 'xlsx' | 'other'; @@ -23,14 +24,6 @@ function b64ToUint8(dataB64: string): Uint8Array { return Uint8Array.from(atob(dataB64), c => c.charCodeAt(0)) as Uint8Array; } -function forceDownload(fileName: string, mime: string | undefined | null, dataB64: string) { - const url = URL.createObjectURL(new Blob([b64ToUint8(dataB64)], { type: mime || 'application/octet-stream' })); - const a = document.createElement('a'); - a.href = url; - a.download = fileName; - a.click(); - setTimeout(() => URL.revokeObjectURL(url), 60_000); -} const KIND_LABEL: Record = { image: '图片', pdf: 'PDF 文档', text: '文本文件', audio: '音频', video: '视频', @@ -109,22 +102,17 @@ export function AttachmentPreview({ att, onClose }: { att: Attachment | null; on footer={att ? ( <>