75 lines
2.6 KiB
TypeScript
75 lines
2.6 KiB
TypeScript
|
|
/**
|
|||
|
|
* 功能:配送合同 PDF 附件的上传、失败清理与鉴权预览客户端。
|
|||
|
|
* 版本:v1.0.0
|
|||
|
|
*/
|
|||
|
|
import { getToken } from '@/utils/auth';
|
|||
|
|
|
|||
|
|
const platformApiBaseURL =
|
|||
|
|
import.meta.env.VITE_API_BASE_URL ||
|
|||
|
|
'http://localhost:12426/heqi/platform/v1';
|
|||
|
|
|
|||
|
|
export type ContractAttachmentMetadata = {
|
|||
|
|
has_file: boolean;
|
|||
|
|
available: boolean;
|
|||
|
|
requires_reupload: boolean;
|
|||
|
|
display_name: string;
|
|||
|
|
version: string;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export type ContractAttachmentUploadReply = {
|
|||
|
|
receipt: string;
|
|||
|
|
cleanup_token: string;
|
|||
|
|
display_name: string;
|
|||
|
|
size: number;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
type ApiEnvelope<T> = { code?: number; message?: string; details?: T };
|
|||
|
|
|
|||
|
|
/** 返回当前登录凭证请求头。 */
|
|||
|
|
function authorizationHeaders(): Record<string, string> {
|
|||
|
|
const token = getToken();
|
|||
|
|
return token ? { Authorization: token } : {};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 上传经过前端预检的单个 PDF,服务端仍会验证真实内容。 */
|
|||
|
|
async function upload(file: File): Promise<ContractAttachmentUploadReply> {
|
|||
|
|
const form = new FormData();
|
|||
|
|
form.append('file', file);
|
|||
|
|
const response = await fetch(
|
|||
|
|
`${platformApiBaseURL}/gasorder_contract/attachment/upload`,
|
|||
|
|
{ method: 'POST', headers: authorizationHeaders(), body: form },
|
|||
|
|
);
|
|||
|
|
const payload = (await response.json()) as ApiEnvelope<ContractAttachmentUploadReply>;
|
|||
|
|
if (!response.ok || payload.code !== 0 || !payload.details) {
|
|||
|
|
throw new Error(payload.message || '合同附件上传失败');
|
|||
|
|
}
|
|||
|
|
return payload.details;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 使用受签名保护的清理凭证删除尚未绑定的临时文件。 */
|
|||
|
|
async function cleanup(cleanupToken: string): Promise<void> {
|
|||
|
|
const response = await fetch(
|
|||
|
|
`${platformApiBaseURL}/gasorder_contract/attachment/cleanup`,
|
|||
|
|
{
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: { 'Content-Type': 'application/json', ...authorizationHeaders() },
|
|||
|
|
body: JSON.stringify({ cleanup_token: cleanupToken }),
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
if (!response.ok) throw new Error('临时合同附件清理失败');
|
|||
|
|
const payload = (await response.json()) as ApiEnvelope<{ deleted: boolean }>;
|
|||
|
|
if (payload.code !== 0) throw new Error(payload.message || '临时合同附件清理失败');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 获取鉴权 PDF Blob;内部存储 URI 始终不会暴露给浏览器。 */
|
|||
|
|
async function load(identity: string): Promise<Blob> {
|
|||
|
|
const response = await fetch(
|
|||
|
|
`${platformApiBaseURL}/gasorder_contract/${encodeURIComponent(identity)}/attachment`,
|
|||
|
|
{ headers: authorizationHeaders() },
|
|||
|
|
);
|
|||
|
|
if (!response.ok) throw new Error('合同附件不可用,请重新上传');
|
|||
|
|
return response.blob();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const contractAttachmentApi = { upload, cleanup, load };
|