This commit is contained in:
@@ -0,0 +1,555 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user