协商中再问按后台超时小时顺延并可强制清跟进时刻;工单与账号支持按筛选导出 Excel。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-13 12:34:03 +08:00
co-authored by Cursor
parent 97f0219dfd
commit 0b2f0b76c4
36 changed files with 867 additions and 64 deletions
@@ -0,0 +1,63 @@
/**
* 带鉴权下载二进制文件(Excel 等)。
* 为何:window.open 带 token 遇 JSON 错误页难提示;统一走 fetch + blob。
*/
import { useGlobSetting } from '/@/hooks/setting';
import { getToken } from '/@/utils/auth';
export type AuthDownloadParams = Record<string, string | number | undefined | null>;
/**
* GET 下载附件并触发浏览器保存。
* @param path 相对 API 路径,如 /inquiry/workOrder/view/export
* @param params query 参数(空值跳过)
* @param fallbackName 无 Content-Disposition 时的文件名
*/
export async function downloadAuthGet(
path: string,
params: AuthDownloadParams = {},
fallbackName = 'download.bin',
): Promise<void> {
const glob = useGlobSetting();
const base = (glob.apiUrl || '').replace(/\/$/, '');
const qs = new URLSearchParams();
Object.keys(params).forEach((k) => {
const v = params[k];
if (v === undefined || v === null || String(v).trim() === '') return;
qs.set(k, String(v));
});
const url = `${base}${path}${qs.toString() ? `?${qs.toString()}` : ''}`;
const token = getToken() || '';
const res = await fetch(url, {
method: 'GET',
headers: {
'X-Access-Token': String(token),
},
});
const ctype = (res.headers.get('content-type') || '').toLowerCase();
if (!res.ok || ctype.includes('application/json')) {
let msg = `下载失败 HTTP ${res.status}`;
try {
const j = await res.json();
if (j?.message) msg = String(j.message);
} catch {
/* ignore */
}
throw new Error(msg);
}
const blob = await res.blob();
let name = fallbackName;
const cd = res.headers.get('content-disposition') || '';
const m = /filename\*=UTF-8''([^;]+)|filename=\"?([^\";]+)\"?/i.exec(cd);
if (m) {
name = decodeURIComponent((m[1] || m[2] || name).trim());
}
const href = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = href;
a.download = name;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(href);
}