178 lines
6.7 KiB
TypeScript
178 lines
6.7 KiB
TypeScript
/**
|
|
* 报价模板 API(主账 /inquiry/quoteTemplate)。
|
|
* 列表/上传/映射/启停/样例预览;禁止浏览器直连对象存储填表以外的 TMS/LLM。
|
|
*/
|
|
import { defHttp } from '/@/utils/http/axios';
|
|
import { useGlobSetting } from '/@/hooks/setting';
|
|
import { getToken } from '/@/utils/auth';
|
|
|
|
enum Api {
|
|
list = '/inquiry/quoteTemplate/list',
|
|
upload = '/inquiry/quoteTemplate/upload',
|
|
version = '/inquiry/quoteTemplate/version',
|
|
versions = '/inquiry/quoteTemplate/versions',
|
|
mapping = '/inquiry/quoteTemplate/mapping',
|
|
enable = '/inquiry/quoteTemplate/enable',
|
|
disable = '/inquiry/quoteTemplate/disable',
|
|
setDefault = '/inquiry/quoteTemplate/setDefault',
|
|
editMeta = '/inquiry/quoteTemplate/editMeta',
|
|
delete = '/inquiry/quoteTemplate/delete',
|
|
previewSample = '/inquiry/quoteTemplate/previewSample',
|
|
previewSheet = '/inquiry/quoteTemplate/previewSheet',
|
|
previewSnapshot = '/inquiry/quoteTemplate/previewSnapshot',
|
|
download = '/inquiry/quoteTemplate/download',
|
|
reparse = '/inquiry/quoteTemplate/reparse',
|
|
}
|
|
|
|
export const getTemplateList = (params) => defHttp.get({ url: Api.list, params });
|
|
|
|
/**
|
|
* 上传模板文件(新建或追加版本)。
|
|
* 禁止手写 Content-Type: multipart/form-data:缺 boundary 会被 Tomcat 直接拒收。
|
|
* FormData 交给浏览器自动带 boundary;解析可能超过默认 10 秒,单独放宽超时。
|
|
*/
|
|
export const uploadTemplate = (data: FormData) =>
|
|
defHttp.post(
|
|
{
|
|
url: Api.upload,
|
|
data,
|
|
timeout: 120 * 1000,
|
|
},
|
|
{ errorMessageMode: 'message' },
|
|
);
|
|
|
|
export const getTemplateVersion = (versionId: string) =>
|
|
defHttp.get({ url: Api.version, params: { versionId } });
|
|
|
|
/** 上传原表 Excel 样式快照(格子原文 + 黄区/映射;旧接口保留) */
|
|
export const getTemplateSheetPreview = (versionId: string) =>
|
|
defHttp.get({ url: Api.previewSheet, params: { versionId }, timeout: 60 * 1000 });
|
|
|
|
/**
|
|
* 原表截图预览(主账本机 LibreOffice 转 PNG/PDF)。
|
|
* 走 blob:带鉴权;首次转换可能较慢。
|
|
*/
|
|
export async function fetchTemplateSnapshotBlob(versionId: string): Promise<{ blob: Blob; contentType: string }> {
|
|
const glob = useGlobSetting();
|
|
const base = (glob.apiUrl || '').replace(/\/$/, '');
|
|
const url = `${base}${Api.previewSnapshot}?versionId=${encodeURIComponent(versionId)}`;
|
|
const token = getToken() || '';
|
|
const controller = new AbortController();
|
|
const timer = window.setTimeout(() => controller.abort(), 150 * 1000);
|
|
try {
|
|
const res = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
'X-Access-Token': String(token),
|
|
},
|
|
signal: controller.signal,
|
|
});
|
|
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();
|
|
return { blob, contentType: ctype || blob.type || 'application/octet-stream' };
|
|
} finally {
|
|
window.clearTimeout(timer);
|
|
}
|
|
}
|
|
|
|
export const listTemplateVersions = (templateId: string) =>
|
|
defHttp.get({ url: Api.versions, params: { templateId } });
|
|
|
|
export const saveTemplateMapping = (versionId: string, mappingJson: string) =>
|
|
defHttp.put({ url: Api.mapping, data: { versionId, mappingJson } });
|
|
|
|
export const enableTemplate = (templateId: string, versionId: string) =>
|
|
defHttp.post({ url: Api.enable, params: { templateId, versionId } });
|
|
|
|
export const disableTemplate = (templateId: string) =>
|
|
defHttp.post({ url: Api.disable, params: { templateId } });
|
|
|
|
/**
|
|
* 删除模板逻辑头及全部版本;不可恢复。
|
|
* 走 POST(与 Jeecg 惯例一致):部分网关/Nginx 对 DELETE 会直接 404。
|
|
* joinParamsToUrl:非 GET 时 axios 会把 params 挪进 JSON 体,必须拼到查询串给 @RequestParam。
|
|
*/
|
|
export const deleteTemplate = (templateId: string) =>
|
|
defHttp.post(
|
|
{ url: Api.delete, params: { templateId } },
|
|
{ joinParamsToUrl: true },
|
|
);
|
|
|
|
export const setTemplateDefault = (templateId: string, isDefault = true) =>
|
|
defHttp.post({ url: Api.setDefault, params: { templateId, isDefault } });
|
|
|
|
/** 只改名称/业务/关键词/默认标记,不换文件;走 JSON 体对接主账 @RequestBody */
|
|
export const editTemplateMeta = (data) => defHttp.put({ url: Api.editMeta, data });
|
|
|
|
/**
|
|
* 对最新 Excel 版重新提交 AI 异步解析(已解析也可点;解析中跳过)。
|
|
*/
|
|
export const reparseTemplate = (templateId: string) =>
|
|
defHttp.post(
|
|
{ url: Api.reparse, params: { id: templateId }, timeout: 60 * 1000 },
|
|
{ joinParamsToUrl: true },
|
|
);
|
|
|
|
/**
|
|
* 带鉴权下载样例预览 / 原文件。
|
|
* window.open+query token 遇 500 JSON 时浏览器只显示失败;改为 blob 下载并提示 message。
|
|
*/
|
|
export async function downloadTemplateFile(kind: 'previewSample' | 'download', versionId: string, fileNameHint?: string) {
|
|
const glob = useGlobSetting();
|
|
const base = (glob.apiUrl || '').replace(/\/$/, '');
|
|
const path = kind === 'previewSample' ? Api.previewSample : Api.download;
|
|
const url = `${base}${path}?versionId=${encodeURIComponent(versionId)}`;
|
|
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 = fileNameHint || (kind === 'previewSample' ? 'preview.xlsx' : 'template.bin');
|
|
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);
|
|
}
|
|
|
|
/** 带 token 下载样例预览 / 原文件(新窗口,兼容旧调用) */
|
|
export function buildTemplateFileUrl(kind: 'previewSample' | 'download', versionId: string) {
|
|
const glob = useGlobSetting();
|
|
const base = (glob.apiUrl || '').replace(/\/$/, '');
|
|
const path = kind === 'previewSample' ? Api.previewSample : Api.download;
|
|
const token = getToken() || '';
|
|
return `${base}${path}?versionId=${encodeURIComponent(versionId)}&token=${encodeURIComponent(String(token))}`;
|
|
}
|