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; // 上一版本人工数量
|
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 文件名
|
* @param filename 文件名
|
||||||
@@ -140,6 +191,61 @@ function getFileExtension(filename: string): string {
|
|||||||
return parts.length > 1 ? parts.pop()?.toLowerCase() || '' : '';
|
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
|
* @param id 评查结果ID
|
||||||
@@ -401,20 +507,12 @@ export async function getDocumentTypesByIds(ids: number[], frontendJWT?: string)
|
|||||||
return { data: { types: [], total: 0 } };
|
return { data: { types: [], total: 0 } };
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await postgrestGet<DocumentType[]>(
|
const response = await getDocumentTypes({ ids, page: 1, pageSize: Math.max(ids.length, 10) }, frontendJWT);
|
||||||
'/api/postgrest/proxy/document_types',
|
|
||||||
{
|
|
||||||
filter: {
|
|
||||||
'id': `in.(${ids.join(',')})`
|
|
||||||
},
|
|
||||||
token: frontendJWT
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
return { error: response.error, status: response.status };
|
return { error: response.error, status: response.status };
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractedData = extractApiData<DocumentType[]>(response.data);
|
const extractedData = response.data?.types;
|
||||||
if (!extractedData) {
|
if (!extractedData) {
|
||||||
return { error: '获取文档类型列表失败', status: 500 };
|
return { error: '获取文档类型列表失败', status: 500 };
|
||||||
}
|
}
|
||||||
@@ -556,30 +654,45 @@ export async function getDocumentsListFromAPI(searchParams: {
|
|||||||
token
|
token
|
||||||
} = searchParams;
|
} = searchParams;
|
||||||
|
|
||||||
// 构建查询参数
|
|
||||||
const params: Record<string, any> = {
|
const params: Record<string, any> = {
|
||||||
page,
|
page,
|
||||||
page_size: pageSize
|
pageSize
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加可选参数
|
// 新接口已落地的筛选项
|
||||||
if (name) params.name = name;
|
if (name) params.keyword = name;
|
||||||
if (documentNumber) params.document_number = documentNumber;
|
if (fileStatus) {
|
||||||
if (auditStatus) params.audit_status = parseInt(auditStatus, 10);
|
const normalizedFileStatus = fileStatus.toLowerCase();
|
||||||
if (fileStatus) params.status = fileStatus;
|
if (normalizedFileStatus === 'processed') {
|
||||||
if (dateFrom) params.start_time = dateFrom;
|
params.processingStatus = 'completed';
|
||||||
if (dateTo) params.end_time = dateTo;
|
} else if (normalizedFileStatus === 'failed') {
|
||||||
|
params.processingStatus = 'failed';
|
||||||
// 处理文档类型ID数组 - 转换为逗号分隔的字符串
|
} else {
|
||||||
if (documentTypeIds && documentTypeIds.length > 0) {
|
params.processingStatus = 'running';
|
||||||
params.type_id = documentTypeIds.join(',');
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 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,
|
params,
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`,
|
'Authorization': `Bearer ${token}`,
|
||||||
@@ -587,105 +700,79 @@ export async function getDocumentsListFromAPI(searchParams: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = response.data;
|
const pageData = extractApiData<LeauditListPage>(response.data);
|
||||||
const backendDocuments = data.documents || [];
|
if (!pageData) {
|
||||||
const totalCount = data.total || 0;
|
return { error: '获取文档列表失败', status: response.status };
|
||||||
const totalPages = data.total_pages || 0;
|
|
||||||
|
|
||||||
// console.log(`📥 [getDocumentsListFromAPI] 获取到 ${backendDocuments.length} 个文档,总数: ${totalCount}`);
|
|
||||||
|
|
||||||
// 转换后端数据为前端 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 backendDocuments = pageData.documents || [];
|
||||||
const prevVersion = index < doc.history_versions.length - 1 ? doc.history_versions[index + 1] : null;
|
const totalCount = pageData.total || 0;
|
||||||
|
const totalPages = pageData.totalPages || Math.ceil(totalCount / pageSize) || 0;
|
||||||
|
|
||||||
|
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 {
|
return {
|
||||||
id: hv.id,
|
id: doc.documentId,
|
||||||
name: hv.name || doc.name,
|
name: doc.fileName || doc.normalizedName || '未命名文档',
|
||||||
documentNumber: hv.document_number || doc.document_number || '',
|
documentNumber: buildDocumentNumber(doc),
|
||||||
type: hv.type_id?.toString() || doc.type_id?.toString() || '',
|
type: doc.typeId?.toString() || '',
|
||||||
typeName: hv.type_name || doc.type_name || '未知类型',
|
typeName: typeNameFromCode(doc.typeCode),
|
||||||
size: hv.file_size || 0,
|
size: doc.fileSize || 0,
|
||||||
auditStatus: hv.audit_status ?? 0,
|
auditStatus: mapLeauditDocToAuditStatus(doc),
|
||||||
fileStatus: hv.status || 'Processed',
|
fileStatus: mapProcessingStatusToFileStatus(doc.processingStatus),
|
||||||
issues: hv.issue_count ?? null,
|
issues: doc.failedCount ?? null,
|
||||||
issuesDiff,
|
uploadTime: formatDate(doc.updatedAt || ''),
|
||||||
issuesDiffType,
|
fileType: doc.fileExt || getFileExtension(doc.fileName || ''),
|
||||||
uploadTime: formatDate(hv.created_at),
|
path: doc.ossUrl || '',
|
||||||
fileType: getFileExtension(hv.name || doc.name),
|
isTest: false,
|
||||||
path: hv.path || '',
|
updatedAt: formatDate(doc.updatedAt || ''),
|
||||||
isTest: hv.is_test_document || false,
|
pageCount: 0,
|
||||||
updatedAt: formatDate(hv.updated_at || hv.created_at),
|
ocrResult: undefined,
|
||||||
pageCount: hv.ocr_result?.__meta?.page_count || 0,
|
pass_count: doc.passedCount ?? null,
|
||||||
ocrResult: hv.ocr_result,
|
warning_count: 0,
|
||||||
versionNumber: hv.version_number,
|
error_count: doc.failedCount ?? null,
|
||||||
// 结果统计字段
|
manual_count: doc.skippedCount ?? null,
|
||||||
pass_count: hv.pass_count ?? null,
|
warning_messages: [],
|
||||||
warning_count: hv.warning_count ?? null,
|
error_messages: [],
|
||||||
error_count: hv.error_count ?? null,
|
manual_messages: [],
|
||||||
manual_count: hv.manual_count ?? null,
|
historyCount: Math.max(0, (doc.totalVersions || 1) - 1),
|
||||||
// 前一版本统计(用于差异对比)
|
previousIssues: historyVersions[0]?.issues ?? null,
|
||||||
previous_pass_count: prevVersion?.pass_count ?? null,
|
previous_pass_count: historyVersions[0]?.pass_count ?? null,
|
||||||
previous_warning_count: prevVersion?.warning_count ?? null,
|
previous_warning_count: historyVersions[0]?.warning_count ?? null,
|
||||||
previous_error_count: prevVersion?.error_count ?? null,
|
previous_error_count: historyVersions[0]?.error_count ?? null,
|
||||||
previous_manual_count: prevVersion?.manual_count ?? null
|
previous_manual_count: historyVersions[0]?.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,
|
|
||||||
historyVersions: historyVersions.length > 0 ? historyVersions : undefined
|
historyVersions: historyVersions.length > 0 ? historyVersions : undefined
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -694,7 +781,7 @@ export async function getDocumentsListFromAPI(searchParams: {
|
|||||||
data: {
|
data: {
|
||||||
documents: convertedDocuments,
|
documents: convertedDocuments,
|
||||||
total: totalCount,
|
total: totalCount,
|
||||||
page: data.page || page,
|
page: pageData.page || page,
|
||||||
totalPages
|
totalPages
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -322,12 +322,22 @@ export default function DocumentsIndex() {
|
|||||||
|
|
||||||
// 获取经过过滤的文档类型列表
|
// 获取经过过滤的文档类型列表
|
||||||
const filteredTypesResponse = await getDocumentTypesByIds(typeIds, jwtToken);
|
const filteredTypesResponse = await getDocumentTypesByIds(typeIds, jwtToken);
|
||||||
const filteredDocumentTypes = filteredTypesResponse.data?.types || [];
|
if (filteredTypesResponse.data?.types?.length) {
|
||||||
const filteredOptions = filteredDocumentTypes.map(type => ({
|
const filteredOptions = filteredTypesResponse.data.types.map(type => ({
|
||||||
value: type.id,
|
value: type.id,
|
||||||
label: type.name
|
label: type.name
|
||||||
}));
|
}));
|
||||||
setFilteredDocumentTypeOptions(filteredOptions);
|
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) {
|
} catch (error) {
|
||||||
console.error('❌ [fetchData] 获取文档列表失败:', error);
|
console.error('❌ [fetchData] 获取文档列表失败:', error);
|
||||||
|
|||||||
Reference in New Issue
Block a user