feat: hook document list to leaudit list api
This commit is contained in:
+209
-122
@@ -130,6 +130,57 @@ export interface DocumentVersionUI {
|
||||
previous_manual_count?: number | null; // 上一版本人工数量
|
||||
}
|
||||
|
||||
interface LeauditHistoryVersion {
|
||||
documentId: number;
|
||||
fileId?: number | null;
|
||||
versionNo: number;
|
||||
fileName?: string | null;
|
||||
fileExt?: string | null;
|
||||
processingStatus?: string | null;
|
||||
runStatus?: string | null;
|
||||
resultStatus?: string | null;
|
||||
updatedAt?: string | null;
|
||||
}
|
||||
|
||||
interface LeauditListItem {
|
||||
documentId: number;
|
||||
internalDocumentNo: number;
|
||||
versionGroupKey: string;
|
||||
versionNo: number;
|
||||
rootVersionId: number;
|
||||
previousVersionId?: number | null;
|
||||
typeId?: number | null;
|
||||
typeCode?: string | null;
|
||||
region: string;
|
||||
normalizedName?: string | null;
|
||||
fileId?: number | null;
|
||||
fileName?: string | null;
|
||||
fileExt?: string | null;
|
||||
mimeType?: string | null;
|
||||
fileSize?: number | null;
|
||||
ossUrl?: string | null;
|
||||
processingStatus?: string | null;
|
||||
currentRunId?: number | null;
|
||||
runStatus?: string | null;
|
||||
resultStatus?: string | null;
|
||||
totalScore?: number | null;
|
||||
passedCount?: number | null;
|
||||
failedCount?: number | null;
|
||||
skippedCount?: number | null;
|
||||
updatedAt?: string | null;
|
||||
hasHistory?: boolean;
|
||||
totalVersions?: number;
|
||||
historyVersions?: LeauditHistoryVersion[];
|
||||
}
|
||||
|
||||
interface LeauditListPage {
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
documents: LeauditListItem[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件扩展名
|
||||
* @param filename 文件名
|
||||
@@ -140,6 +191,61 @@ function getFileExtension(filename: string): string {
|
||||
return parts.length > 1 ? parts.pop()?.toLowerCase() || '' : '';
|
||||
}
|
||||
|
||||
function mapProcessingStatusToFileStatus(status?: string | null): string {
|
||||
const normalized = (status || '').toLowerCase();
|
||||
if (normalized === 'completed') return 'Processed';
|
||||
if (normalized === 'failed') return 'Failed';
|
||||
if (normalized === 'running' || normalized === 'queued' || normalized === 'dispatch') return 'Evaluationing';
|
||||
if (normalized === 'waiting' || normalized === 'pending') return 'Waiting';
|
||||
return 'Waiting';
|
||||
}
|
||||
|
||||
function mapLeauditDocToAuditStatus(doc: {
|
||||
processingStatus?: string | null;
|
||||
runStatus?: string | null;
|
||||
passedCount?: number | null;
|
||||
failedCount?: number | null;
|
||||
}): number {
|
||||
const processingStatus = (doc.processingStatus || '').toLowerCase();
|
||||
const runStatus = (doc.runStatus || '').toLowerCase();
|
||||
|
||||
if (runStatus === 'queued' || runStatus === 'running' || processingStatus === 'running') {
|
||||
return 2;
|
||||
}
|
||||
if (processingStatus === 'waiting' || processingStatus === 'pending') {
|
||||
return 0;
|
||||
}
|
||||
if (processingStatus === 'failed') {
|
||||
return -1;
|
||||
}
|
||||
if ((doc.failedCount || 0) > 0) {
|
||||
return -1;
|
||||
}
|
||||
if ((doc.passedCount || 0) > 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function typeNameFromCode(typeCode?: string | null): string {
|
||||
if (!typeCode) return '未知类型';
|
||||
const typeMap: Record<string, string> = {
|
||||
'contract.sale': '购销合同',
|
||||
'contract.purchase': '采购合同',
|
||||
'contract.lease': '租赁合同',
|
||||
'contract.service': '服务合同',
|
||||
};
|
||||
if (typeMap[typeCode]) return typeMap[typeCode];
|
||||
return typeCode;
|
||||
}
|
||||
|
||||
function buildDocumentNumber(doc: LeauditListItem | LeauditHistoryVersion): string {
|
||||
if ('versionNo' in doc && doc.versionNo) {
|
||||
return `v${doc.versionNo}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评查结果
|
||||
* @param id 评查结果ID
|
||||
@@ -401,20 +507,12 @@ export async function getDocumentTypesByIds(ids: number[], frontendJWT?: string)
|
||||
return { data: { types: [], total: 0 } };
|
||||
}
|
||||
|
||||
const response = await postgrestGet<DocumentType[]>(
|
||||
'/api/postgrest/proxy/document_types',
|
||||
{
|
||||
filter: {
|
||||
'id': `in.(${ids.join(',')})`
|
||||
},
|
||||
token: frontendJWT
|
||||
});
|
||||
|
||||
const response = await getDocumentTypes({ ids, page: 1, pageSize: Math.max(ids.length, 10) }, frontendJWT);
|
||||
if (response.error) {
|
||||
return { error: response.error, status: response.status };
|
||||
}
|
||||
|
||||
const extractedData = extractApiData<DocumentType[]>(response.data);
|
||||
const extractedData = response.data?.types;
|
||||
if (!extractedData) {
|
||||
return { error: '获取文档类型列表失败', status: 500 };
|
||||
}
|
||||
@@ -556,30 +654,45 @@ export async function getDocumentsListFromAPI(searchParams: {
|
||||
token
|
||||
} = searchParams;
|
||||
|
||||
// 构建查询参数
|
||||
const params: Record<string, any> = {
|
||||
page,
|
||||
page_size: pageSize
|
||||
pageSize
|
||||
};
|
||||
|
||||
// 添加可选参数
|
||||
if (name) params.name = name;
|
||||
if (documentNumber) params.document_number = documentNumber;
|
||||
if (auditStatus) params.audit_status = parseInt(auditStatus, 10);
|
||||
if (fileStatus) params.status = fileStatus;
|
||||
if (dateFrom) params.start_time = dateFrom;
|
||||
if (dateTo) params.end_time = dateTo;
|
||||
|
||||
// 处理文档类型ID数组 - 转换为逗号分隔的字符串
|
||||
if (documentTypeIds && documentTypeIds.length > 0) {
|
||||
params.type_id = documentTypeIds.join(',');
|
||||
// 新接口已落地的筛选项
|
||||
if (name) params.keyword = name;
|
||||
if (fileStatus) {
|
||||
const normalizedFileStatus = fileStatus.toLowerCase();
|
||||
if (normalizedFileStatus === 'processed') {
|
||||
params.processingStatus = 'completed';
|
||||
} else if (normalizedFileStatus === 'failed') {
|
||||
params.processingStatus = 'failed';
|
||||
} else {
|
||||
params.processingStatus = 'running';
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('📤 [getDocumentsListFromAPI] 请求参数:', params);
|
||||
if (documentTypeIds && documentTypeIds.length === 1) {
|
||||
const typeResponse = await getDocumentTypes({ ids: documentTypeIds, page: 1, pageSize: 10 }, token);
|
||||
const matchedType = typeResponse.data?.types?.[0];
|
||||
if (matchedType?.code) {
|
||||
params.typeCode = matchedType.code;
|
||||
}
|
||||
}
|
||||
|
||||
// 下面几个旧筛选项在新系统版列表接口里暂未一一对齐:
|
||||
// - documentNumber
|
||||
// - auditStatus
|
||||
// - dateFrom/dateTo
|
||||
// - 多个 documentTypeIds 的组合筛选
|
||||
// 先保留参数签名,后续再单独接新后端的类型/状态体系。
|
||||
void documentNumber;
|
||||
void auditStatus;
|
||||
void dateFrom;
|
||||
void dateTo;
|
||||
|
||||
// 调用后端API
|
||||
const axios = await import('axios').then(m => m.default);
|
||||
const response = await axios.get(`${API_BASE_URL}/admin/versions/documents-list`, {
|
||||
const response = await axios.get(`${API_BASE_URL}/api/documents/list`, {
|
||||
params,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
@@ -587,105 +700,79 @@ export async function getDocumentsListFromAPI(searchParams: {
|
||||
}
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
const backendDocuments = data.documents || [];
|
||||
const totalCount = data.total || 0;
|
||||
const totalPages = data.total_pages || 0;
|
||||
const pageData = extractApiData<LeauditListPage>(response.data);
|
||||
if (!pageData) {
|
||||
return { error: '获取文档列表失败', status: response.status };
|
||||
}
|
||||
|
||||
// console.log(`📥 [getDocumentsListFromAPI] 获取到 ${backendDocuments.length} 个文档,总数: ${totalCount}`);
|
||||
const backendDocuments = pageData.documents || [];
|
||||
const totalCount = pageData.total || 0;
|
||||
const totalPages = pageData.totalPages || Math.ceil(totalCount / pageSize) || 0;
|
||||
|
||||
// 转换后端数据为前端 DocumentUI 格式
|
||||
const convertedDocuments: DocumentUI[] = backendDocuments.map((doc: any) => {
|
||||
// 转换历史版本数据
|
||||
const historyVersions: DocumentVersionUI[] = (doc.history_versions || []).map((hv: any, index: number) => {
|
||||
// 计算与下一个版本(更早的版本)的问题数量差异
|
||||
let issuesDiff: number | undefined;
|
||||
let issuesDiffType: 'increase' | 'decrease' | 'same' | undefined;
|
||||
|
||||
if (index < doc.history_versions.length - 1) {
|
||||
const olderDoc = doc.history_versions[index + 1];
|
||||
if (hv.issue_count != null && olderDoc.issue_count != null) {
|
||||
const diff = hv.issue_count - olderDoc.issue_count;
|
||||
issuesDiff = Math.abs(diff);
|
||||
if (diff > 0) {
|
||||
issuesDiffType = 'increase';
|
||||
} else if (diff < 0) {
|
||||
issuesDiffType = 'decrease';
|
||||
} else {
|
||||
issuesDiffType = 'same';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取前一个版本的统计数据(如果存在)
|
||||
const prevVersion = index < doc.history_versions.length - 1 ? doc.history_versions[index + 1] : null;
|
||||
|
||||
return {
|
||||
id: hv.id,
|
||||
name: hv.name || doc.name,
|
||||
documentNumber: hv.document_number || doc.document_number || '',
|
||||
type: hv.type_id?.toString() || doc.type_id?.toString() || '',
|
||||
typeName: hv.type_name || doc.type_name || '未知类型',
|
||||
size: hv.file_size || 0,
|
||||
auditStatus: hv.audit_status ?? 0,
|
||||
fileStatus: hv.status || 'Processed',
|
||||
issues: hv.issue_count ?? null,
|
||||
issuesDiff,
|
||||
issuesDiffType,
|
||||
uploadTime: formatDate(hv.created_at),
|
||||
fileType: getFileExtension(hv.name || doc.name),
|
||||
path: hv.path || '',
|
||||
isTest: hv.is_test_document || false,
|
||||
updatedAt: formatDate(hv.updated_at || hv.created_at),
|
||||
pageCount: hv.ocr_result?.__meta?.page_count || 0,
|
||||
ocrResult: hv.ocr_result,
|
||||
versionNumber: hv.version_number,
|
||||
// 结果统计字段
|
||||
pass_count: hv.pass_count ?? null,
|
||||
warning_count: hv.warning_count ?? null,
|
||||
error_count: hv.error_count ?? null,
|
||||
manual_count: hv.manual_count ?? null,
|
||||
// 前一版本统计(用于差异对比)
|
||||
previous_pass_count: prevVersion?.pass_count ?? null,
|
||||
previous_warning_count: prevVersion?.warning_count ?? null,
|
||||
previous_error_count: prevVersion?.error_count ?? null,
|
||||
previous_manual_count: prevVersion?.manual_count ?? null
|
||||
};
|
||||
});
|
||||
const convertedDocuments: DocumentUI[] = backendDocuments.map((doc) => {
|
||||
const historyVersions: DocumentVersionUI[] = (doc.historyVersions || []).map((hv) => ({
|
||||
id: hv.documentId,
|
||||
name: hv.fileName || doc.fileName || doc.normalizedName || '未命名文档',
|
||||
documentNumber: buildDocumentNumber(hv),
|
||||
type: doc.typeId?.toString() || '',
|
||||
typeName: typeNameFromCode(doc.typeCode),
|
||||
size: 0,
|
||||
auditStatus: mapLeauditDocToAuditStatus({
|
||||
processingStatus: hv.processingStatus,
|
||||
runStatus: hv.runStatus,
|
||||
passedCount: null,
|
||||
failedCount: null,
|
||||
}),
|
||||
fileStatus: mapProcessingStatusToFileStatus(hv.processingStatus),
|
||||
issues: null,
|
||||
uploadTime: formatDate(hv.updatedAt || ''),
|
||||
fileType: hv.fileExt || getFileExtension(hv.fileName || doc.fileName || ''),
|
||||
path: '',
|
||||
isTest: false,
|
||||
updatedAt: formatDate(hv.updatedAt || ''),
|
||||
pageCount: 0,
|
||||
ocrResult: undefined,
|
||||
versionNumber: hv.versionNo,
|
||||
pass_count: null,
|
||||
warning_count: 0,
|
||||
error_count: null,
|
||||
manual_count: null,
|
||||
previous_pass_count: null,
|
||||
previous_warning_count: null,
|
||||
previous_error_count: null,
|
||||
previous_manual_count: null
|
||||
}));
|
||||
|
||||
return {
|
||||
id: doc.id,
|
||||
name: doc.name,
|
||||
documentNumber: doc.document_number || '',
|
||||
type: doc.type_id?.toString() || '',
|
||||
typeName: doc.type_name || '未知类型',
|
||||
size: doc.file_size || 0,
|
||||
auditStatus: doc.audit_status ?? 0,
|
||||
fileStatus: doc.status || '',
|
||||
issues: doc.issue_count ?? null,
|
||||
uploadTime: formatDate(doc.upload_time || doc.created_at),
|
||||
fileType: getFileExtension(doc.name),
|
||||
path: doc.path || '',
|
||||
isTest: doc.is_test_document || false,
|
||||
updatedAt: formatDate(doc.updated_at || doc.created_at),
|
||||
pageCount: doc.ocr_result?.__meta?.page_count || 0,
|
||||
ocrResult: doc.ocr_result,
|
||||
// 结果统计字段
|
||||
pass_count: doc.pass_count ?? null,
|
||||
warning_count: doc.warning_count ?? null,
|
||||
error_count: doc.error_count ?? null,
|
||||
manual_count: doc.manual_count ?? null,
|
||||
// 消息详情字段
|
||||
warning_messages: doc.warning_messages || [],
|
||||
error_messages: doc.error_messages || [],
|
||||
manual_messages: doc.manual_messages || [],
|
||||
// 版本管理字段
|
||||
historyCount: (doc.total_versions || 1) - 1, // 总版本数 - 1 = 历史版本数
|
||||
previousIssues: doc.history_versions?.[0]?.issue_count ?? null,
|
||||
previous_pass_count: doc.history_versions?.[0]?.pass_count ?? null,
|
||||
previous_warning_count: doc.history_versions?.[0]?.warning_count ?? null,
|
||||
previous_error_count: doc.history_versions?.[0]?.error_count ?? null,
|
||||
previous_manual_count: doc.history_versions?.[0]?.manual_count ?? null,
|
||||
id: doc.documentId,
|
||||
name: doc.fileName || doc.normalizedName || '未命名文档',
|
||||
documentNumber: buildDocumentNumber(doc),
|
||||
type: doc.typeId?.toString() || '',
|
||||
typeName: typeNameFromCode(doc.typeCode),
|
||||
size: doc.fileSize || 0,
|
||||
auditStatus: mapLeauditDocToAuditStatus(doc),
|
||||
fileStatus: mapProcessingStatusToFileStatus(doc.processingStatus),
|
||||
issues: doc.failedCount ?? null,
|
||||
uploadTime: formatDate(doc.updatedAt || ''),
|
||||
fileType: doc.fileExt || getFileExtension(doc.fileName || ''),
|
||||
path: doc.ossUrl || '',
|
||||
isTest: false,
|
||||
updatedAt: formatDate(doc.updatedAt || ''),
|
||||
pageCount: 0,
|
||||
ocrResult: undefined,
|
||||
pass_count: doc.passedCount ?? null,
|
||||
warning_count: 0,
|
||||
error_count: doc.failedCount ?? null,
|
||||
manual_count: doc.skippedCount ?? null,
|
||||
warning_messages: [],
|
||||
error_messages: [],
|
||||
manual_messages: [],
|
||||
historyCount: Math.max(0, (doc.totalVersions || 1) - 1),
|
||||
previousIssues: historyVersions[0]?.issues ?? null,
|
||||
previous_pass_count: historyVersions[0]?.pass_count ?? null,
|
||||
previous_warning_count: historyVersions[0]?.warning_count ?? null,
|
||||
previous_error_count: historyVersions[0]?.error_count ?? null,
|
||||
previous_manual_count: historyVersions[0]?.manual_count ?? null,
|
||||
historyVersions: historyVersions.length > 0 ? historyVersions : undefined
|
||||
};
|
||||
});
|
||||
@@ -694,7 +781,7 @@ export async function getDocumentsListFromAPI(searchParams: {
|
||||
data: {
|
||||
documents: convertedDocuments,
|
||||
total: totalCount,
|
||||
page: data.page || page,
|
||||
page: pageData.page || page,
|
||||
totalPages
|
||||
}
|
||||
};
|
||||
|
||||
@@ -322,12 +322,22 @@ export default function DocumentsIndex() {
|
||||
|
||||
// 获取经过过滤的文档类型列表
|
||||
const filteredTypesResponse = await getDocumentTypesByIds(typeIds, jwtToken);
|
||||
const filteredDocumentTypes = filteredTypesResponse.data?.types || [];
|
||||
const filteredOptions = filteredDocumentTypes.map(type => ({
|
||||
value: type.id,
|
||||
label: type.name
|
||||
}));
|
||||
setFilteredDocumentTypeOptions(filteredOptions);
|
||||
if (filteredTypesResponse.data?.types?.length) {
|
||||
const filteredOptions = filteredTypesResponse.data.types.map(type => ({
|
||||
value: type.id,
|
||||
label: type.name
|
||||
}));
|
||||
setFilteredDocumentTypeOptions(filteredOptions);
|
||||
} else {
|
||||
const fallbackOptions = Array.from(
|
||||
new Map(
|
||||
result.data.documents
|
||||
.filter(doc => doc.type && doc.typeName)
|
||||
.map(doc => [doc.type, { value: Number(doc.type), label: doc.typeName }])
|
||||
).values()
|
||||
);
|
||||
setFilteredDocumentTypeOptions(fallbackOptions);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ [fetchData] 获取文档列表失败:', error);
|
||||
|
||||
Reference in New Issue
Block a user