Files
kaidi/frontend/src/api/archive.ts
T
2026-08-17 14:08:40 +08:00

556 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { AxiosResponse } from 'axios';
import { request } from '@/utils/request';
import { commandHeaders } from './command';
export const ARCHIVE_API_BASE = '/archives';
const array = <T>(value: T[] | null | undefined): T[] => (Array.isArray(value) ? value : []);
export interface ArchivePageMeta {
page: number;
size: number;
totalElements: number;
totalPages: number;
}
export interface ArchiveReference {
publicId: string;
businessNo: string;
name: string;
}
export interface ArchivePackageItem {
publicId: string;
itemType: string;
itemName: string;
objectType?: string | null;
objectPublicId?: string | null;
filePublicId?: string | null;
fileName?: string | null;
fileSha256?: string | null;
required: boolean;
status: string;
missingReason?: string | null;
returnReason?: string | null;
notApplicableReason?: string | null;
notApplicableRequestedByName?: string | null;
notApplicableRequestedAt?: string | null;
notApplicableReviewedByName?: string | null;
notApplicableReviewedAt?: string | null;
notApplicableReviewOpinion?: string | null;
allowedActions: string[];
}
export interface ArchivePackageAction {
sequenceNo: number;
actionCode: string;
fromStatus?: string | null;
toStatus?: string | null;
opinion?: string | null;
actorName?: string | null;
occurredAt: string;
manifestSha256?: string | null;
}
export interface ArchivePackageObjectSnapshot {
publicId: string;
itemType: string;
objectType: string;
objectPublicId: string;
objectBusinessNo?: string | null;
objectName?: string | null;
objectStatus: string;
objectVersion?: number | null;
objectFormType?: string | null;
sourceVersionPublicId?: string | null;
snapshotSha256: string;
capturedAt: string;
}
export interface ArchivePackage {
publicId: string;
businessNo: string;
company: ArchiveReference;
project: ArchiveReference;
packageVersion: number;
rootPackagePublicId?: string | null;
supersedesPackagePublicId?: string | null;
revisionReason?: string | null;
ruleVersion: string;
completeness: string;
missingCount: number;
retentionYears: number;
retentionExpiresOn?: string | null;
retentionStatus: 'PENDING' | 'ACTIVE' | 'DUE_SOON' | 'EXPIRED' | 'FROZEN';
physicalLocation?: string | null;
frozen: boolean;
status: string;
manifestSha256?: string | null;
submittedByName?: string | null;
reviewedByName?: string | null;
submittedAt?: string | null;
archivedAt?: string | null;
updatedAt: string;
version: number;
allowedActions: string[];
items: ArchivePackageItem[];
objectSnapshots: ArchivePackageObjectSnapshot[];
actions: ArchivePackageAction[];
}
export interface ArchiveFile {
publicId: string;
displayName: string;
mediaType: string;
originalType?: string | null;
sizeBytes: number;
sha256: string;
scanStatus: string;
companyPublicId: string;
companyName: string;
projectPublicId: string;
projectBusinessNo: string;
projectName: string;
contractPublicId?: string | null;
counterpartyPublicId?: string | null;
formType?: string | null;
documentType: string;
seriesPublicId: string;
versionNo: number;
archiveStatus: string;
borrowStatus?: string | null;
packagePublicId?: string | null;
packageStatus?: string | null;
uploadedBy: string;
uploadedAt: string;
sensitive: boolean;
allowedActions: string[];
}
export interface ArchiveFileDetail {
file: ArchiveFile;
versions: ArchiveFile[];
borrows: ArchiveBorrow[];
}
export interface ArchiveBorrow {
publicId: string;
businessNo: string;
filePublicId: string;
fileName: string;
projectPublicId: string;
projectName: string;
purpose: string;
dueAt: string;
status: string;
applicantName: string;
approvedByName?: string | null;
approvedAt?: string | null;
reviewOpinion?: string | null;
returnCondition?: string | null;
returnedByName?: string | null;
returnedAt?: string | null;
version: number;
allowedActions: string[];
}
export interface ArchivePackageQuery {
view?: 'prepare' | 'check' | 'returned' | 'archived';
companyId?: string;
projectId?: string;
status?: string;
completeness?: string;
frozen?: boolean;
keyword?: string;
sort?: string;
page: number;
size: number;
}
export interface ArchiveFileQuery {
companyId?: string;
projectId?: string;
contractId?: string;
counterpartyId?: string;
formType?: string;
fileName?: string;
uploadedBy?: string;
uploadedDateFrom?: string;
uploadedDateTo?: string;
originalType?: string;
archiveStatus?: string;
scanStatus?: string;
sort?: string;
page: number;
size: number;
}
export interface ArchiveBorrowQuery {
status?: string;
keyword?: string;
page: number;
size: number;
}
export interface ArchivePackageCreatePayload {
projectId: string;
retentionYears?: number;
physicalLocation?: string;
}
export interface ArchivePackageCommandPayload {
version: number;
opinion?: string;
returnItemIds?: string[];
}
export interface ArchiveFreezePayload {
version: number;
reason: string;
}
export interface ArchivePackageRevisionPayload {
version: number;
reason: string;
}
export interface ArchiveNotApplicablePayload {
version: number;
reason: string;
}
export interface ArchiveNotApplicableReviewPayload {
version: number;
approved: boolean;
opinion: string;
}
export interface ArchiveFileMetadata {
projectId: string;
packageId?: string;
packageItemId?: string;
contractId?: string;
counterpartyId?: string;
formType?: string;
fileType: string;
originalType?: string;
replacesFileId?: string;
replacementReason?: string;
notApplicableReason?: string;
}
export interface ArchiveBorrowCreatePayload {
fileId: string;
purpose: string;
dueAt: string;
}
export interface ArchiveBorrowCommandPayload {
version: number;
opinion?: string;
returnCondition?: string;
}
interface PageEnvelope<T> {
data: T[];
meta: ArchivePageMeta;
requestId: string;
}
export function normalizeArchivePackageItem(item: Partial<ArchivePackageItem> | null | undefined): ArchivePackageItem {
return { ...(item || {}), allowedActions: array(item?.allowedActions) } as ArchivePackageItem;
}
export function normalizeArchivePackage(value: Partial<ArchivePackage> | null | undefined): ArchivePackage {
const item = value || {};
return {
...item,
allowedActions: array(item.allowedActions),
items: array(item.items).map(normalizeArchivePackageItem),
objectSnapshots: array(item.objectSnapshots),
actions: array(item.actions),
} as ArchivePackage;
}
export function normalizeArchiveFile(value: Partial<ArchiveFile> | null | undefined): ArchiveFile {
return { ...(value || {}), allowedActions: array(value?.allowedActions) } as ArchiveFile;
}
export function normalizeArchiveBorrow(value: Partial<ArchiveBorrow> | null | undefined): ArchiveBorrow {
return { ...(value || {}), allowedActions: array(value?.allowedActions) } as ArchiveBorrow;
}
export function normalizeArchiveFileDetail(value: Partial<ArchiveFileDetail> | null | undefined): ArchiveFileDetail {
return {
...(value || {}),
file: normalizeArchiveFile(value?.file),
versions: array(value?.versions).map(normalizeArchiveFile),
borrows: array(value?.borrows).map(normalizeArchiveBorrow),
} as ArchiveFileDetail;
}
export function archiveErrorText(error: unknown, fallback: string): string {
const value = error as Error & { status?: number; code?: string; fieldErrors?: Record<string, string> };
const fields = value.fieldErrors ? Object.values(value.fieldErrors).join(';') : '';
if (value.status === 401) return '登录会话已失效,请重新登录后重试。';
if (value.status === 403) return '当前身份没有访问该数据或执行该操作的权限。';
if (value.status === 404) return '记录不存在、已被删除或当前身份无权查看。';
if (value.code === 'VERSION_CONFLICT' || value.status === 409)
return value.message || '数据已发生变化,请刷新后重试。';
if (value.status === 422) {
return fields
? `${value.message || '当前条件不满足业务规则'}:${fields}`
: value.message || '当前条件不满足业务规则,请检查后重试。';
}
if (value.status && value.status >= 500) return value.message || '服务处理失败,请稍后重试。';
return fields ? `${value.message || fallback}:${fields}` : value.message || fallback;
}
async function page<T>(url: string, params: Record<string, unknown>) {
const envelope = await request.get<PageEnvelope<T>>({ url, params }, { isTransformResponse: false });
return {
items: array(envelope.data),
meta: envelope.meta || {
page: Number(params.page) || 1,
size: Number(params.size) || 20,
totalElements: 0,
totalPages: 0,
},
requestId: envelope.requestId,
};
}
export function getArchivePackages(params: ArchivePackageQuery) {
return page<ArchivePackage>(`${ARCHIVE_API_BASE}/packages`, params as unknown as Record<string, unknown>).then(
(result) => ({
...result,
items: result.items.map(normalizeArchivePackage),
}),
);
}
export function getArchivePackage(publicId: string) {
return request.get<ArchivePackage>({ url: `${ARCHIVE_API_BASE}/packages/${publicId}` }).then(normalizeArchivePackage);
}
export function createArchivePackage(payload: ArchivePackageCreatePayload, idempotencyKey?: string) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages`,
data: payload,
...commandHeaders('archive-package-create', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function checkArchivePackage(publicId: string, payload: ArchivePackageCommandPayload, idempotencyKey?: string) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/check`,
data: payload,
...commandHeaders('archive-package-check', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function submitArchivePackage(publicId: string, payload: ArchivePackageCommandPayload, idempotencyKey?: string) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/submit`,
data: payload,
...commandHeaders('archive-package-submit', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function returnArchivePackage(publicId: string, payload: ArchivePackageCommandPayload, idempotencyKey?: string) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/return`,
data: payload,
...commandHeaders('archive-package-return', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function reviseArchivePackage(
publicId: string,
payload: ArchivePackageRevisionPayload,
idempotencyKey?: string,
) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/revise`,
data: payload,
...commandHeaders('archive-package-revise', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function archiveArchivePackage(
publicId: string,
payload: ArchivePackageCommandPayload,
idempotencyKey?: string,
) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/archive`,
data: payload,
...commandHeaders('archive-package-archive', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function freezeArchivePackage(publicId: string, payload: ArchiveFreezePayload, idempotencyKey?: string) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/freeze`,
data: payload,
...commandHeaders('archive-package-freeze', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function unfreezeArchivePackage(
publicId: string,
payload: ArchivePackageCommandPayload,
idempotencyKey?: string,
) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${publicId}/unfreeze`,
data: payload,
...commandHeaders('archive-package-unfreeze', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function markArchiveItemNotApplicable(
packageId: string,
itemId: string,
payload: ArchiveNotApplicablePayload,
idempotencyKey?: string,
) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${packageId}/items/${itemId}/not-applicable`,
data: payload,
...commandHeaders('archive-item-not-applicable', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function reviewArchiveItemNotApplicable(
packageId: string,
itemId: string,
payload: ArchiveNotApplicableReviewPayload,
idempotencyKey?: string,
) {
return request
.post<ArchivePackage>({
url: `${ARCHIVE_API_BASE}/packages/${packageId}/items/${itemId}/not-applicable/review`,
data: payload,
...commandHeaders('archive-item-not-applicable-review', idempotencyKey),
})
.then(normalizeArchivePackage);
}
export function getArchiveFiles(params: ArchiveFileQuery) {
return page<ArchiveFile>(`${ARCHIVE_API_BASE}/files`, params as unknown as Record<string, unknown>).then(
(result) => ({
...result,
items: result.items.map(normalizeArchiveFile),
}),
);
}
export function getArchiveFile(publicId: string) {
return request
.get<ArchiveFileDetail>({ url: `${ARCHIVE_API_BASE}/files/${publicId}` })
.then(normalizeArchiveFileDetail);
}
export function rescanArchiveFile(publicId: string, idempotencyKey?: string) {
return request
.post<ArchiveFile>({
url: `${ARCHIVE_API_BASE}/files/${publicId}/rescan`,
data: {},
...commandHeaders('archive-file-rescan', idempotencyKey),
})
.then(normalizeArchiveFile);
}
export function getArchiveFileContent(publicId: string, preview = false) {
return request.get<AxiosResponse<Blob>>(
{ url: `${ARCHIVE_API_BASE}/files/${publicId}/content`, params: { preview }, responseType: 'blob' },
{ isReturnNativeResponse: true },
);
}
export function uploadArchiveFile(metadata: ArchiveFileMetadata, file: File, idempotencyKey?: string) {
const formData = new FormData();
formData.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
formData.append('file', file, file.name);
return request
.post<ArchiveFile>({
url: `${ARCHIVE_API_BASE}/files`,
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
...commandHeaders('archive-file-upload', idempotencyKey).headers,
},
})
.then(normalizeArchiveFile);
}
export function getArchiveBorrows(params: ArchiveBorrowQuery) {
return page<ArchiveBorrow>(`${ARCHIVE_API_BASE}/borrows`, params as unknown as Record<string, unknown>).then(
(result) => ({
...result,
items: result.items.map(normalizeArchiveBorrow),
}),
);
}
export function createArchiveBorrow(payload: ArchiveBorrowCreatePayload, idempotencyKey?: string) {
return request
.post<ArchiveBorrow>({
url: `${ARCHIVE_API_BASE}/borrows`,
data: payload,
...commandHeaders('archive-borrow-create', idempotencyKey),
})
.then(normalizeArchiveBorrow);
}
export function approveArchiveBorrow(publicId: string, payload: ArchiveBorrowCommandPayload, idempotencyKey?: string) {
return request
.post<ArchiveBorrow>({
url: `${ARCHIVE_API_BASE}/borrows/${publicId}/approve`,
data: payload,
...commandHeaders('archive-borrow-approve', idempotencyKey),
})
.then(normalizeArchiveBorrow);
}
export function rejectArchiveBorrow(publicId: string, payload: ArchiveBorrowCommandPayload, idempotencyKey?: string) {
return request
.post<ArchiveBorrow>({
url: `${ARCHIVE_API_BASE}/borrows/${publicId}/reject`,
data: payload,
...commandHeaders('archive-borrow-reject', idempotencyKey),
})
.then(normalizeArchiveBorrow);
}
export function returnArchiveBorrow(publicId: string, payload: ArchiveBorrowCommandPayload, idempotencyKey?: string) {
return request
.post<ArchiveBorrow>({
url: `${ARCHIVE_API_BASE}/borrows/${publicId}/return`,
data: payload,
...commandHeaders('archive-borrow-return', idempotencyKey),
})
.then(normalizeArchiveBorrow);
}