feat(web-admin): add ListExportDropdown and Excel blob download helper

Support filtered-result primary action and optional export-selected menu.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-21 17:01:49 +08:00
1 parent eb4233f23f
commit 3643a3b14e
2 files changed
+185

No files matched your search

@@ -0,0 +1,41 @@
/** 从 Content-Disposition 解析文件名;失败则用 fallback */
export function filenameFromContentDisposition(
header: string | undefined,
fallback: string
): string {
if (!header) return fallback
const utf8 = /filename\*\s*=\s*UTF-8''([^;]+)/i.exec(header)
if (utf8?.[1]) {
try {
return decodeURIComponent(utf8[1].trim().replace(/["']/g, ''))
} catch {
/* ignore */
}
}
const plain = /filename\s*=\s*("?)([^";]+)\1/i.exec(header)
if (plain?.[2]) return plain[2].trim()
return fallback
}
export function triggerBlobDownload(blob: Blob, filename: string): void {
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = filename
link.click()
URL.revokeObjectURL(url)
}
/** Axios 成功时若拦截器已把 data 设为 Blob,直接用;否则兼容 { data: Blob, headers } */
export function pickBlobFromExportResponse(res: any): { blob: Blob; filenameHeader?: string } {
if (res instanceof Blob) {
return { blob: res }
}
if (res?.data instanceof Blob) {
return {
blob: res.data,
filenameHeader: res.headers?.['content-disposition'] || res.headers?.['Content-Disposition']
}
}
throw new Error('导出响应不是文件')
}