d4000cd292
2. 文档的基本信息修改改用接口。 3. 重新完善角色权限管理的页面逻辑。 4.将评查点列表中的返回逻辑改用浏览器的记忆返回。
719 lines
22 KiB
TypeScript
719 lines
22 KiB
TypeScript
import { postgrestGet, postgrestDelete, postgrestPut, postgrestPost } from '../postgrest-client';
|
||
import { getDocumentTypes } from '../document-types/document-types';
|
||
import { formatDate } from '../../utils';
|
||
import { API_BASE_URL } from '~/config/api-config';
|
||
import type { DocumentType } from './files-upload';
|
||
|
||
/**
|
||
* 从不同格式的 API 响应中提取数据
|
||
* @param responseData API 响应数据
|
||
* @returns 提取后的数据或 null
|
||
*/
|
||
function extractApiData<T>(responseData: unknown): T | null {
|
||
if (!responseData) return null;
|
||
|
||
// 格式1: { code: number, msg: string, data: T }
|
||
if (typeof responseData === 'object' && responseData !== null &&
|
||
'code' in responseData &&
|
||
'data' in responseData &&
|
||
(responseData as { data: unknown }).data) {
|
||
return (responseData as { data: T }).data;
|
||
}
|
||
|
||
// 格式2: 直接是数据对象
|
||
return responseData as T;
|
||
}
|
||
|
||
|
||
/**
|
||
* 数据库文档结构
|
||
*/
|
||
export interface Document {
|
||
id: number;
|
||
user_id: number | null;
|
||
type_id: number;
|
||
name: string;
|
||
document_number: string;
|
||
path: string;
|
||
storage_type: string;
|
||
file_size: number;
|
||
upload_time: string;
|
||
is_test_document: boolean;
|
||
evaluation_level: string;
|
||
status: 'pass' | 'warning' | 'waiting' | 'processing' | 'fail';
|
||
file_status: 'Waiting' | 'Cutting' | 'Extractioning' | 'Evaluationing' | 'Processed';
|
||
audit_status: number; // -1: 不通过, 0: 待审核, 1: 通过, 2: 警告, 3: 审核中
|
||
ocr_result?: {
|
||
__meta?: {
|
||
page_count?: number;
|
||
}
|
||
};
|
||
extracted_results?: unknown;
|
||
summary?: unknown;
|
||
remark?: string;
|
||
created_at: string;
|
||
updated_at: string;
|
||
}
|
||
|
||
/**
|
||
* 前端UI文档结构
|
||
*/
|
||
export interface DocumentUI {
|
||
id: number;
|
||
name: string;
|
||
documentNumber: string;
|
||
type: string;
|
||
typeName: string;
|
||
size: number;
|
||
auditStatus: number; // -1: 不通过, 0: 待审核, 1: 通过, 2: 警告, 3: 审核中
|
||
fileStatus: string; // Waiting, Cutting, Extractioning, Failed, Evaluationing, Processed
|
||
issues: number | null;
|
||
uploadTime: string;
|
||
fileType: string;
|
||
path: string;
|
||
isTest: boolean;
|
||
remark?: string;
|
||
updatedAt?: string;
|
||
pageCount?: number;
|
||
ocrResult?: unknown;
|
||
// 结果统计字段
|
||
pass_count?: number | null; // 通过数量
|
||
warning_count?: number | null; // 警告数量
|
||
error_count?: number | null; // 错误数量
|
||
manual_count?: number | null; // 人工审核数量
|
||
// 消息详情字段
|
||
warning_messages?: string[]; // 警告消息列表
|
||
error_messages?: string[]; // 错误消息列表
|
||
manual_messages?: string[]; // 人工审核消息列表
|
||
// 版本管理相关字段
|
||
historyCount?: number; // 历史版本数量(不含当前版本)
|
||
previousIssues?: number | null; // 上一个版本的问题数量
|
||
previous_pass_count?: number | null; // 上一版本通过数量
|
||
previous_warning_count?: number | null; // 上一版本警告数量
|
||
previous_error_count?: number | null; // 上一版本错误数量
|
||
previous_manual_count?: number | null; // 上一版本人工数量
|
||
isExpanded?: boolean; // 是否展开历史版本(前端状态)
|
||
historyVersions?: DocumentVersionUI[]; // 历史版本列表
|
||
}
|
||
|
||
/**
|
||
* 文档历史版本结构
|
||
*/
|
||
export interface DocumentVersionUI {
|
||
id: number;
|
||
name: string;
|
||
documentNumber: string;
|
||
type: string;
|
||
typeName: string;
|
||
size: number;
|
||
auditStatus: number;
|
||
fileStatus: string;
|
||
issues: number | null;
|
||
issuesDiff?: number; // 与上一个版本的问题数量差异(绝对值)
|
||
issuesDiffType?: 'increase' | 'decrease' | 'same'; // 差异类型
|
||
uploadTime: string;
|
||
fileType: string;
|
||
path: string;
|
||
isTest: boolean;
|
||
updatedAt?: string;
|
||
pageCount?: number;
|
||
ocrResult?: unknown;
|
||
versionNumber?: number; // 版本号(v2, v3, v4...)
|
||
// 结果统计字段
|
||
pass_count: number | null; // 通过数量
|
||
warning_count: number | null; // 警告数量
|
||
error_count: number | null; // 错误数量
|
||
manual_count: number | null; // 人工审核数量
|
||
previous_pass_count?: number | null; // 上一版本通过数量
|
||
previous_warning_count?: number | null; // 上一版本警告数量
|
||
previous_error_count?: number | null; // 上一版本错误数量
|
||
previous_manual_count?: number | null; // 上一版本人工数量
|
||
}
|
||
|
||
/**
|
||
* 获取文件扩展名
|
||
* @param filename 文件名
|
||
* @returns 文件扩展名
|
||
*/
|
||
function getFileExtension(filename: string): string {
|
||
const parts = filename.split('.');
|
||
return parts.length > 1 ? parts.pop()?.toLowerCase() || '' : '';
|
||
}
|
||
|
||
/**
|
||
* 获取评查结果
|
||
* @param id 评查结果ID
|
||
* @returns 评查结果
|
||
*/
|
||
async function getEvaluationResults(id: number, frontendJWT?: string) {
|
||
const response = await postgrestGet<[]>('/api/postgrest/proxy/evaluation_results', {
|
||
filter: {
|
||
'document_id': `eq.${id}`
|
||
},
|
||
token: frontendJWT
|
||
});
|
||
if (response.error) {
|
||
return { error: response.error, status: response.status };
|
||
}
|
||
const evaluationResult = extractApiData<[]>(response.data);
|
||
return evaluationResult;
|
||
}
|
||
|
||
|
||
/**
|
||
* 将API文档转换为UI文档
|
||
*/
|
||
async function convertToUIDocument(doc: Document, frontendJWT?: string): Promise<DocumentUI> {
|
||
// 获取文档类型信息
|
||
const typeResponse = await getDocumentTypes(undefined, frontendJWT);
|
||
const documentTypes = typeResponse.data?.types || [];
|
||
const docType = documentTypes.find(type => type.id.toString() === doc.type_id.toString());
|
||
const evaluationResult = await getEvaluationResults(doc.id, frontendJWT);
|
||
let issues = 0;
|
||
|
||
interface EvaluationResultItem {
|
||
evaluated_results?: {
|
||
result?: string;
|
||
[key: string]: unknown;
|
||
};
|
||
[key: string]: unknown;
|
||
}
|
||
|
||
if (evaluationResult && Array.isArray(evaluationResult)) {
|
||
evaluationResult.forEach((result: EvaluationResultItem) => {
|
||
if(result && result.evaluated_results && !result.evaluated_results.result){
|
||
issues++;
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
return {
|
||
id: doc.id,
|
||
name: doc.name,
|
||
documentNumber: doc.document_number,
|
||
type: doc.type_id.toString(),
|
||
typeName: docType?.name || '未知类型',
|
||
size: doc.file_size,
|
||
auditStatus: doc.audit_status || 0,
|
||
fileStatus: doc.status || '', // 默认为''
|
||
issues: issues, // 使用计算得到的issues
|
||
uploadTime: formatDate(doc.updated_at),
|
||
fileType: getFileExtension(doc.name),
|
||
path: doc.path,
|
||
isTest: doc.is_test_document,
|
||
remark: doc.remark,
|
||
updatedAt: formatDate(doc.updated_at),
|
||
pageCount: doc.ocr_result?.__meta?.page_count || 0,
|
||
ocrResult: doc.ocr_result
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 后端SQL函数返回的文档结构
|
||
*/
|
||
interface DocumentFromSQL {
|
||
id: number;
|
||
name: string;
|
||
document_number: string;
|
||
type_id: number;
|
||
type_name: string;
|
||
file_size: number;
|
||
audit_status: number;
|
||
status: string;
|
||
false_count: number;
|
||
updated_at: string;
|
||
path: string;
|
||
is_test_document: boolean;
|
||
ocr_result: {
|
||
__meta?: {
|
||
page_count?: number;
|
||
}
|
||
};
|
||
}
|
||
|
||
|
||
/**
|
||
* 删除文档
|
||
* @param id 文档ID
|
||
* @param userId 用户ID
|
||
* @param token JWT token (可选)
|
||
* @returns 删除结果
|
||
*/
|
||
export async function deleteDocument(id: string, userId: string, token?: string): Promise<{
|
||
success?: boolean;
|
||
error?: string;
|
||
status?: number;
|
||
}> {
|
||
try {
|
||
if (!id) {
|
||
return { error: '文档ID不能为空', status: 400 };
|
||
}
|
||
|
||
if (!userId) {
|
||
return { error: '用户身份验证失败', status: 401 };
|
||
}
|
||
|
||
const response = await postgrestDelete(
|
||
'/api/postgrest/proxy/documents',
|
||
{
|
||
filter: {
|
||
'id': `eq.${id}`,
|
||
'user_id': `eq.${userId}` // 确保只能删除自己的文档
|
||
},
|
||
token
|
||
}
|
||
);
|
||
|
||
if (response.error) {
|
||
return { error: response.error, status: response.status };
|
||
}
|
||
|
||
return { success: true };
|
||
} catch (error) {
|
||
console.error('删除文档失败:', error);
|
||
return {
|
||
error: error instanceof Error ? error.message : '删除文档失败',
|
||
status: 500
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取单个文档详情
|
||
* @param id 文档ID
|
||
* @returns 文档详情
|
||
*/
|
||
export async function getDocument(id: string, userId: string, frontendJWT?: string): Promise<{
|
||
data?: DocumentUI;
|
||
error?: string;
|
||
status?: number;
|
||
}> {
|
||
try {
|
||
if (!id) {
|
||
return { error: '文档ID不能为空', status: 400 };
|
||
}
|
||
|
||
if (!userId) {
|
||
return { error: '用户身份验证失败', status: 401 };
|
||
}
|
||
|
||
const response = await postgrestGet<Document[]>(
|
||
'/api/postgrest/proxy/documents',
|
||
{
|
||
filter: {
|
||
'id': `eq.${id}`,
|
||
'user_id': `eq.${userId}`
|
||
},
|
||
limit: 1,
|
||
token: frontendJWT
|
||
}
|
||
);
|
||
|
||
if (response.error) {
|
||
return { error: response.error, status: response.status };
|
||
}
|
||
|
||
const extractedData = extractApiData<Document[]>(response.data);
|
||
if (!extractedData || extractedData.length === 0) {
|
||
return { error: '文档不存在', status: 404 };
|
||
}
|
||
|
||
const documentUI = await convertToUIDocument(extractedData[0], frontendJWT);
|
||
|
||
return { data: documentUI };
|
||
} catch (error) {
|
||
console.error('获取文档详情失败:', error);
|
||
return {
|
||
error: error instanceof Error ? error.message : '获取文档详情失败',
|
||
status: 500
|
||
};
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取单个文档详情
|
||
* @param id 文档ID
|
||
* @returns 文档详情
|
||
*/
|
||
// export async function getDocumentWithNoUserId(id: string, frontendJWT?: string): Promise<{
|
||
// data?: DocumentUI;
|
||
// error?: string;
|
||
// status?: number;
|
||
// }> {
|
||
// try {
|
||
// if (!id) {
|
||
// return { error: '文档ID不能为空', status: 400 };
|
||
// }
|
||
|
||
// // console.log("get单个文档id", id)
|
||
|
||
// const response = await postgrestGet<Document[]>(
|
||
// '/api/postgrest/proxy/documents',
|
||
// {
|
||
// filter: {
|
||
// 'id': `eq.${id}`,
|
||
// },
|
||
// limit: 1,
|
||
// token: frontendJWT
|
||
// }
|
||
// );
|
||
|
||
// if (response.error) {
|
||
// return { error: response.error, status: response.status };
|
||
// }
|
||
|
||
// // console.log("respose", response)
|
||
// const extractedData = extractApiData<Document[]>(response.data);
|
||
// if (!extractedData || extractedData.length === 0) {
|
||
// return { error: '文档不存在', status: 404 };
|
||
// }
|
||
|
||
// // console.log('extractedData', extractedData);
|
||
// const documentUI = await convertToUIDocument(extractedData[0], frontendJWT);
|
||
|
||
// return { data: documentUI };
|
||
// } catch (error) {
|
||
// console.error('获取文档详情失败:', error);
|
||
// return {
|
||
// error: error instanceof Error ? error.message : '获取文档详情失败',
|
||
// status: 500
|
||
// };
|
||
// }
|
||
// }
|
||
|
||
|
||
|
||
/**
|
||
* 获取文档类型列表(按IDs过滤版本)
|
||
* @param ids 文档类型ID数组(必填)
|
||
* @param frontendJWT JWT token(可选)
|
||
* @returns 文档类型列表
|
||
*/
|
||
export async function getDocumentTypesByIds(ids: number[], frontendJWT?: string): Promise<{
|
||
data?: { types: DocumentType[], total: number };
|
||
error?: string;
|
||
status?: number;
|
||
}> {
|
||
try {
|
||
if (!ids || ids.length === 0) {
|
||
return { data: { types: [], total: 0 } };
|
||
}
|
||
|
||
const response = await postgrestGet<DocumentType[]>(
|
||
'/api/postgrest/proxy/document_types',
|
||
{
|
||
filter: {
|
||
'id': `in.(${ids.join(',')})`
|
||
},
|
||
token: frontendJWT
|
||
});
|
||
|
||
if (response.error) {
|
||
return { error: response.error, status: response.status };
|
||
}
|
||
|
||
const extractedData = extractApiData<DocumentType[]>(response.data);
|
||
if (!extractedData) {
|
||
return { error: '获取文档类型列表失败', status: 500 };
|
||
}
|
||
|
||
return { data: { types: extractedData, total: extractedData.length } };
|
||
} catch (error) {
|
||
console.error('获取文档类型列表失败:', error);
|
||
return {
|
||
error: error instanceof Error ? error.message : '获取文档类型列表失败',
|
||
status: 500
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新文档信息
|
||
*
|
||
* 使用 PATCH 方法调用 /api/postgrest/proxy/documents 接口
|
||
* 后端会自动注入 user_id 过滤条件,确保用户只能更新自己的文档
|
||
*
|
||
* @param id 文档ID
|
||
* @param document 部分文档数据(可更新字段:document_number, audit_status, is_test_document, remark)
|
||
* @param userId 用户ID(用于权限验证)
|
||
* @param frontendJWT JWT Token(可选,如不传则使用 localStorage 中的 access_token)
|
||
* @returns 更新结果
|
||
*
|
||
* @see auth_doc/document_update_api.md 接口文档
|
||
*/
|
||
export async function updateDocument(id: string, document: Partial<DocumentUI> & { remark?: string }, userId: string, frontendJWT?: string): Promise<{
|
||
data?: DocumentUI;
|
||
error?: string;
|
||
status?: number;
|
||
}> {
|
||
try {
|
||
if (!id) {
|
||
return { error: '文档ID不能为空', status: 400 };
|
||
}
|
||
|
||
if (!userId) {
|
||
return { error: '用户身份验证失败', status: 401 };
|
||
}
|
||
|
||
// 准备API数据 - 将UI数据转换为API格式
|
||
// 根据文档,可更新字段:document_number, audit_status, is_test_document, remark
|
||
const apiDocument: Partial<Document> = {};
|
||
|
||
if (document.documentNumber !== undefined) {
|
||
apiDocument.document_number = document.documentNumber;
|
||
}
|
||
|
||
if (document.auditStatus !== undefined) {
|
||
apiDocument.audit_status = document.auditStatus;
|
||
}
|
||
|
||
if (document.isTest !== undefined) {
|
||
apiDocument.is_test_document = document.isTest;
|
||
}
|
||
|
||
if (document.remark !== undefined) {
|
||
apiDocument.remark = document.remark;
|
||
}
|
||
|
||
// console.log('📤 [updateDocument] 更新文档API数据:', apiDocument);
|
||
|
||
// 使用 axios-client 的 apiRequest 方法(支持自定义 headers)
|
||
// 接口路径: /api/postgrest/proxy/documents?id=eq.{id}
|
||
// 后端会自动注入 user_id 过滤条件(根据JWT中的用户信息)
|
||
const { apiRequest } = await import('../axios-client');
|
||
const response = await apiRequest<Document[]>(
|
||
`/api/postgrest/proxy/documents?id=eq.${id}`,
|
||
{
|
||
method: 'PATCH',
|
||
data: apiDocument,
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
...(frontendJWT ? { 'Authorization': `Bearer ${frontendJWT}` } : {})
|
||
}
|
||
}
|
||
);
|
||
|
||
if (response.error) {
|
||
console.error('❌ [updateDocument] 更新文档API错误:', response.error);
|
||
return { error: response.error, status: response.status };
|
||
}
|
||
|
||
// 检查返回数据
|
||
// 成功时返回更新后的文档数组,空数组表示文档不存在或无权访问
|
||
const responseData = response.data;
|
||
if (!responseData || (Array.isArray(responseData) && responseData.length === 0)) {
|
||
return { error: '文档不存在或无权访问', status: 404 };
|
||
}
|
||
|
||
// 获取更新后的完整文档数据(包含关联的文档类型信息)
|
||
const updatedResponse = await getDocument(id, userId, frontendJWT);
|
||
|
||
return updatedResponse;
|
||
} catch (error) {
|
||
console.error('❌ [updateDocument] 更新文档信息失败:', error);
|
||
return {
|
||
error: error instanceof Error ? error.message : '更新文档信息失败',
|
||
status: 500
|
||
};
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取文档列表(使用新的后端API)
|
||
* @param searchParams 搜索参数
|
||
* @returns 文档列表和总数
|
||
*/
|
||
export async function getDocumentsListFromAPI(searchParams: {
|
||
page?: number;
|
||
pageSize?: number;
|
||
name?: string;
|
||
documentNumber?: string;
|
||
documentTypeIds?: number[]; // 文档类型ID数组
|
||
auditStatus?: string;
|
||
fileStatus?: string;
|
||
dateFrom?: string;
|
||
dateTo?: string;
|
||
token: string; // JWT token (必填)
|
||
}): Promise<{
|
||
data?: { documents: DocumentUI[], total: number, page: number, totalPages: number };
|
||
error?: string;
|
||
status?: number;
|
||
}> {
|
||
try {
|
||
const {
|
||
page = 1,
|
||
pageSize = 10,
|
||
name,
|
||
documentNumber,
|
||
documentTypeIds,
|
||
auditStatus,
|
||
fileStatus,
|
||
dateFrom,
|
||
dateTo,
|
||
token
|
||
} = searchParams;
|
||
|
||
// 构建查询参数
|
||
const params: Record<string, any> = {
|
||
page,
|
||
page_size: 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(',');
|
||
}
|
||
|
||
// console.log('📤 [getDocumentsListFromAPI] 请求参数:', params);
|
||
|
||
// 调用后端API
|
||
const axios = await import('axios').then(m => m.default);
|
||
const response = await axios.get(`${API_BASE_URL}/admin/versions/documents-list`, {
|
||
params,
|
||
headers: {
|
||
'Authorization': `Bearer ${token}`,
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
const data = response.data;
|
||
const backendDocuments = data.documents || [];
|
||
const totalCount = data.total || 0;
|
||
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 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
|
||
};
|
||
});
|
||
|
||
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
|
||
};
|
||
});
|
||
|
||
return {
|
||
data: {
|
||
documents: convertedDocuments,
|
||
total: totalCount,
|
||
page: data.page || page,
|
||
totalPages
|
||
}
|
||
};
|
||
} catch (error) {
|
||
console.error('❌ [getDocumentsListFromAPI] 获取文档列表失败:', error);
|
||
|
||
// 处理axios错误
|
||
if (error && typeof error === 'object' && 'response' in error) {
|
||
const axiosError = error as { response?: { data?: any; status?: number; statusText?: string } };
|
||
return {
|
||
error: axiosError.response?.data?.message || axiosError.response?.statusText || '获取文档列表失败',
|
||
status: axiosError.response?.status || 500
|
||
};
|
||
}
|
||
|
||
return {
|
||
error: error instanceof Error ? error.message : '获取文档列表失败',
|
||
status: 500
|
||
};
|
||
}
|
||
}
|