添加登录内容,尚未完善,先创建分支
This commit is contained in:
+96
-112
@@ -1,4 +1,4 @@
|
||||
import { postgrestGet, postgrestDelete, postgrestPut, type PostgrestParams } from '../postgrest-client';
|
||||
import { postgrestGet, postgrestDelete, postgrestPut, postgrestPost } from '../postgrest-client';
|
||||
import { getDocumentTypes } from '../document-types/document-types';
|
||||
import { formatDate } from '../../utils';
|
||||
|
||||
@@ -169,6 +169,29 @@ async function convertToUIDocument(doc: Document): Promise<DocumentUI> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 后端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 searchParams 搜索参数
|
||||
@@ -180,124 +203,85 @@ export async function getDocuments(searchParams: DocumentSearchParams = {}): Pro
|
||||
status?: number;
|
||||
}> {
|
||||
try {
|
||||
const page = searchParams.page || 1;
|
||||
const pageSize = searchParams.pageSize || 10;
|
||||
|
||||
// 构建查询参数
|
||||
const params: PostgrestParams = {
|
||||
select: '*',
|
||||
order: 'updated_at.desc',
|
||||
headers: {
|
||||
'Prefer': 'count=exact'
|
||||
},
|
||||
limit: pageSize,
|
||||
offset: (page - 1) * pageSize,
|
||||
filter: {} as Record<string, string>
|
||||
};
|
||||
|
||||
// 添加筛选条件
|
||||
const filter: Record<string, string> = {};
|
||||
|
||||
if (searchParams.name) {
|
||||
filter['name'] = `ilike.%${searchParams.name}%`;
|
||||
}
|
||||
|
||||
if (searchParams.documentNumber) {
|
||||
filter['document_number'] = `ilike.%${searchParams.documentNumber}%`;
|
||||
}
|
||||
|
||||
if (searchParams.documentType) {
|
||||
filter['type_id'] = `eq.${searchParams.documentType}`;
|
||||
}
|
||||
|
||||
if (searchParams.auditStatus) {
|
||||
// 处理"待审核"状态 - 特殊处理 audit_status = 0 的情况,同时包含 null 值
|
||||
if (searchParams.auditStatus === '0') {
|
||||
filter['or'] = `(audit_status.eq.0,audit_status.is.null)`;
|
||||
} else {
|
||||
filter['audit_status'] = `eq.${searchParams.auditStatus}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (searchParams.fileStatus) {
|
||||
filter['status'] = `eq.${searchParams.fileStatus}`;
|
||||
}
|
||||
|
||||
// 处理日期范围
|
||||
if (searchParams.dateFrom) {
|
||||
// 添加当天开始时间 00:00:00
|
||||
filter['updated_at'] = `gte.${searchParams.dateFrom + ' 00:00:00'}`;
|
||||
}
|
||||
|
||||
if (searchParams.dateTo) {
|
||||
// 如果有开始日期,使用and条件;否则直接设置结束日期
|
||||
const dateToKey = searchParams.dateFrom ? 'and' : 'updated_at';
|
||||
// 添加当天结束时间 23:59:59
|
||||
if (dateToKey === 'and') {
|
||||
delete filter['updated_at'];
|
||||
// 使用OR操作符连接两个条件
|
||||
filter[dateToKey] = `(updated_at.gte.${searchParams.dateFrom+' 00:00:00'},updated_at.lte.${searchParams.dateTo+' 23:59:59'})`;
|
||||
} else {
|
||||
filter['updated_at'] = `lte.${searchParams.dateTo+' 23:59:59'}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据 reviewType 添加过滤条件
|
||||
if (searchParams.reviewType) {
|
||||
// 如果已经有文档类型过滤,则不再添加 reviewType 的过滤
|
||||
if (!searchParams.documentType) {
|
||||
if (searchParams.reviewType === 'contract') {
|
||||
// 如果是合同类型,只显示 type_id=1 的文档
|
||||
filter['type_id'] = 'eq.1';
|
||||
} else if (searchParams.reviewType === 'record') {
|
||||
// 如果是卷宗类型,只显示 type_id=2 或 type_id=3 的文档
|
||||
filter['type_id'] = 'in.(2,3)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('filter-----', filter);
|
||||
params.filter = filter;
|
||||
|
||||
// 发送请求
|
||||
const response = await postgrestGet<Document[]>('documents', params);
|
||||
|
||||
if (response.error) {
|
||||
return { error: response.error, status: response.status };
|
||||
}
|
||||
|
||||
// 提取数据
|
||||
const extractedData = extractApiData<Document[]>(response.data);
|
||||
if (!extractedData) {
|
||||
return { error: '获取文档数据失败', status: 500 };
|
||||
}
|
||||
|
||||
// console.log('extractedData---1--',extractedData[0]);
|
||||
// 准备RPC调用参数
|
||||
const {
|
||||
page = 1,
|
||||
pageSize = 10,
|
||||
name,
|
||||
documentNumber,
|
||||
documentType,
|
||||
auditStatus,
|
||||
fileStatus,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
reviewType
|
||||
} = searchParams;
|
||||
|
||||
// 转换为UI格式
|
||||
const documents = await Promise.all(extractedData.map(convertToUIDocument));
|
||||
// console.log('documentsItem',documents)
|
||||
// 获取总数
|
||||
let totalCount = 0;
|
||||
const responseWithHeaders = response as {
|
||||
data: unknown;
|
||||
headers?: Record<string, string>
|
||||
};
|
||||
|
||||
if (responseWithHeaders.headers) {
|
||||
const rangeHeader = responseWithHeaders.headers['content-range'];
|
||||
if (rangeHeader) {
|
||||
const total = rangeHeader.split('/')[1];
|
||||
if (total !== '*') {
|
||||
totalCount = parseInt(total, 10);
|
||||
}
|
||||
let documentTypes: number[] | undefined;
|
||||
if (documentType) {
|
||||
documentTypes = [parseInt(documentType, 10)];
|
||||
} else if (reviewType) {
|
||||
if (reviewType === 'contract') {
|
||||
documentTypes = [1];
|
||||
} else if (reviewType === 'record') {
|
||||
documentTypes = [2, 3];
|
||||
}
|
||||
}
|
||||
|
||||
const rpcParams = {
|
||||
search_name: name,
|
||||
search_document_number: documentNumber,
|
||||
search_document_types: documentTypes,
|
||||
search_audit_status: auditStatus !== undefined ? parseInt(auditStatus, 10) : undefined,
|
||||
search_file_status: fileStatus,
|
||||
search_date_from: dateFrom,
|
||||
search_date_to: dateTo,
|
||||
};
|
||||
|
||||
// 并行执行获取数据和获取总数的请求
|
||||
const [documentsResponse, countResponse] = await Promise.all([
|
||||
postgrestPost<DocumentFromSQL[], unknown>('rpc/get_documents_with_filters', { ...rpcParams, page, page_size: pageSize }),
|
||||
postgrestPost<number, unknown>('rpc/count_documents_with_filters', rpcParams)
|
||||
]);
|
||||
|
||||
// 处理获取文档列表的错误
|
||||
if (documentsResponse.error || !documentsResponse.data) {
|
||||
return { error: documentsResponse.error || '获取文档数据失败', status: documentsResponse.status || 500 };
|
||||
}
|
||||
|
||||
// 处理获取总数的错误
|
||||
if (countResponse.error || typeof countResponse.data !== 'number') {
|
||||
// 如果计数失败,可以继续返回数据,但总数可能不准
|
||||
console.error('获取文档总数失败:', countResponse.error);
|
||||
}
|
||||
// console.log('countResponse.data', countResponse.data);
|
||||
|
||||
const totalCount = typeof countResponse.data === 'number' ? countResponse.data : 0;
|
||||
|
||||
// 将SQL返回的数据转换为UI格式
|
||||
const documents: DocumentUI[] = documentsResponse.data.map((doc: DocumentFromSQL) => ({
|
||||
id: doc.id,
|
||||
name: doc.name,
|
||||
documentNumber: doc.document_number,
|
||||
type: doc.type_id.toString(),
|
||||
typeName: doc.type_name || '未知类型',
|
||||
size: doc.file_size,
|
||||
auditStatus: doc.audit_status ?? 0,
|
||||
fileStatus: doc.status || '',
|
||||
issues: doc.false_count ?? null,
|
||||
uploadTime: formatDate(doc.updated_at),
|
||||
fileType: getFileExtension(doc.name),
|
||||
path: doc.path,
|
||||
isTest: doc.is_test_document,
|
||||
updatedAt: formatDate(doc.updated_at),
|
||||
pageCount: doc.ocr_result?.__meta?.page_count || 0,
|
||||
ocrResult: doc.ocr_result
|
||||
}));
|
||||
|
||||
return {
|
||||
data: {
|
||||
documents,
|
||||
total: totalCount || documents.length
|
||||
total: totalCount
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
+205
-30
@@ -70,6 +70,19 @@ export interface Document {
|
||||
audit_status?: number;
|
||||
}
|
||||
|
||||
// 合同结构比较表接口
|
||||
export interface ContractStructureComparison {
|
||||
id: number;
|
||||
template_contract_name: string;
|
||||
file_size: number;
|
||||
status: DocumentStatus;
|
||||
created_at: string;
|
||||
document_id?: number;
|
||||
template_contract_path?: string;
|
||||
ocr_results?: Record<string, unknown>;
|
||||
comparison_results?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// 文件上传响应接口
|
||||
export interface FileUploadResponse {
|
||||
success: boolean;
|
||||
@@ -118,6 +131,7 @@ export async function uploadFileToBinary(file: File): Promise<ArrayBuffer> {
|
||||
* @param documentNumber 文档编号(可选)
|
||||
* @param remark 备注信息(可选)
|
||||
* @param isTestDocument 是否为测试文档
|
||||
* @param documentId 关联的文档ID(用于合同附件上传)
|
||||
* @returns 上传结果
|
||||
*/
|
||||
export async function uploadDocumentToServer(
|
||||
@@ -128,7 +142,9 @@ export async function uploadDocumentToServer(
|
||||
priority: string,
|
||||
documentNumber?: string | null,
|
||||
remark?: string | null,
|
||||
isTestDocument: boolean = false
|
||||
isTestDocument: boolean = false,
|
||||
documentId?: number | null,
|
||||
isReupload: boolean = false
|
||||
): Promise<{data: FileUploadResponse; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// console.log('【调试】开始上传文档:', { fileName, fileSize: binaryData.byteLength });
|
||||
@@ -147,22 +163,25 @@ export async function uploadDocumentToServer(
|
||||
evaluation_level: priority,
|
||||
document_number: documentNumber || null,
|
||||
remark: remark || null,
|
||||
is_test_document: isTestDocument
|
||||
is_test_document: isTestDocument,
|
||||
document_id: documentId || null,
|
||||
is_reupload: isReupload
|
||||
};
|
||||
|
||||
// 添加JSON字符串到FormData
|
||||
formData.append('upload_info', JSON.stringify(uploadInfo));
|
||||
// console.log('【调试】FormData准备完成:', JSON.stringify(uploadInfo));
|
||||
|
||||
// console.log('【调试】准备发送请求到服务器:', UPLOAD_URL);
|
||||
// 根据是否有documentId决定使用哪个接口
|
||||
const uploadEndpoint = documentId ? '/upload_contract_template' : '/upload';
|
||||
const uploadUrl = UPLOAD_URL + uploadEndpoint;
|
||||
// console.log('【调试】准备发送请求到服务器:', uploadUrl);
|
||||
|
||||
// 发送请求
|
||||
// const response = await fetch(`${API_BASE_URL}/admin/documents/upload`, {
|
||||
try {
|
||||
// console.log('【调试】开始fetch请求...');
|
||||
const response = await fetch(UPLOAD_URL, {
|
||||
// const response = await fetch('http://172.16.0.55:8000/admin/documents/upload', {
|
||||
// const response = await fetch('http://172.16.0.119:8000/admin/documents/upload', {
|
||||
const response = await fetch(uploadUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-File-Name': encodeURIComponent(fileName)
|
||||
@@ -230,6 +249,126 @@ export async function getTodayDocuments(reviewType?: string): Promise<{data: Doc
|
||||
const today = dayjs().startOf('day').format('YYYY-MM-DD');
|
||||
// console.log('查询当天文档,日期范围:', today);
|
||||
|
||||
// 如果是合同类型,需要合并查询documents表和contract_structure_comparison表
|
||||
if (reviewType === 'contract') {
|
||||
try {
|
||||
// 查询documents表中的合同数据
|
||||
const documentsParams: PostgrestParams = {
|
||||
select: `
|
||||
id,
|
||||
name,
|
||||
type_id,
|
||||
file_size,
|
||||
status,
|
||||
created_at,
|
||||
document_number,
|
||||
path,
|
||||
storage_type,
|
||||
is_test_document,
|
||||
evaluation_level,
|
||||
ocr_result,
|
||||
extracted_results,
|
||||
sumary,
|
||||
remark,
|
||||
audit_status
|
||||
`,
|
||||
order: 'created_at.desc',
|
||||
filter: {
|
||||
'created_at': `gte.${today}`,
|
||||
'type_id': 'eq.1'
|
||||
}
|
||||
};
|
||||
|
||||
// 查询contract_structure_comparison表中的数据
|
||||
// const comparisonParams: PostgrestParams = {
|
||||
// select: `
|
||||
// id,
|
||||
// template_contract_name,
|
||||
// file_size,
|
||||
// status,
|
||||
// created_at,
|
||||
// document_id,
|
||||
// template_contract_path,
|
||||
// ocr_results,
|
||||
// comparison_results
|
||||
// `,
|
||||
// order: 'created_at.desc',
|
||||
// filter: {
|
||||
// 'created_at': `gte.${today}`
|
||||
// }
|
||||
// };
|
||||
|
||||
// 并行查询两个表
|
||||
// const [documentsResponse, comparisonResponse] = await Promise.all([
|
||||
// postgrestGet<Document[]>('documents', documentsParams),
|
||||
// postgrestGet<ContractStructureComparison[]>('contract_structure_comparison', comparisonParams)
|
||||
// ]);
|
||||
|
||||
const documentsResponse = await postgrestGet<Document[]>('documents', documentsParams);
|
||||
|
||||
// console.log('documents表响应:', documentsResponse);
|
||||
// console.log('contract_structure_comparison表响应:', comparisonResponse);
|
||||
|
||||
// if (documentsResponse.error && comparisonResponse.error) {
|
||||
// console.error('两个表查询都失败:', documentsResponse.error, comparisonResponse.error);
|
||||
// return { error: documentsResponse.error || comparisonResponse.error, status: documentsResponse.status || comparisonResponse.status };
|
||||
// }
|
||||
if (documentsResponse.error) {
|
||||
console.error('documents表查询失败:', documentsResponse.error);
|
||||
return { error: documentsResponse.error, status: documentsResponse.status };
|
||||
}
|
||||
|
||||
// 提取documents表数据
|
||||
let documentsData: Document[] = [];
|
||||
if (!documentsResponse.error && documentsResponse.data) {
|
||||
const extractedDocuments = extractApiData<Document[]>(documentsResponse.data);
|
||||
if (extractedDocuments) {
|
||||
documentsData = extractedDocuments;
|
||||
}
|
||||
}
|
||||
|
||||
// 提取contract_structure_comparison表数据并转换为Document格式
|
||||
// let comparisonData: Document[] = [];
|
||||
// if (!comparisonResponse.error && comparisonResponse.data) {
|
||||
// const extractedComparison = extractApiData<ContractStructureComparison[]>(comparisonResponse.data);
|
||||
// if (extractedComparison) {
|
||||
// // 将ContractStructureComparison转换为Document格式
|
||||
// console.log('extractedComparison:', extractedComparison);
|
||||
// comparisonData = extractedComparison.map(item => ({
|
||||
// id: item.id,
|
||||
// name: item.template_contract_name || `合同结构比较记录_${item.id}`,
|
||||
// type_id: 1, // 合同结构比较默认为合同类型
|
||||
// file_size: item.file_size || 0,
|
||||
// status: item.status,
|
||||
// created_at: item.created_at,
|
||||
// document_id: item.document_id,
|
||||
// template_contract_path: item.template_contract_path,
|
||||
// ocr_results: item.ocr_results,
|
||||
// comparison_results: item.comparison_results
|
||||
// }));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 合并两个数据源
|
||||
// const allData = [...documentsData, ...comparisonData];
|
||||
const allData = [...documentsData];
|
||||
|
||||
// 按created_at降序排序
|
||||
allData.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
||||
|
||||
// console.log('合并后的数据:', allData);
|
||||
return { data: allData };
|
||||
|
||||
} catch (contractError) {
|
||||
console.error('合同类型查询失败:', contractError);
|
||||
return {
|
||||
error: contractError instanceof Error ? contractError.message : '合同类型查询失败',
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 非合同类型的原有逻辑
|
||||
const params: PostgrestParams = {
|
||||
select: `
|
||||
id,
|
||||
@@ -256,14 +395,7 @@ export async function getTodayDocuments(reviewType?: string): Promise<{data: Doc
|
||||
};
|
||||
|
||||
// 根据reviewType添加过滤条件
|
||||
if (reviewType === 'contract') {
|
||||
// 如果是合同类型,只显示type_id=1的文档
|
||||
if (params.filter) {
|
||||
params.filter['type_id'] = 'eq.1';
|
||||
} else {
|
||||
params.filter = { 'type_id': 'eq.1' };
|
||||
}
|
||||
} else if (reviewType === 'record') {
|
||||
if (reviewType === 'record') {
|
||||
// 如果是卷宗类型,只显示type_id=2或type_id=3的文档
|
||||
if (params.filter) {
|
||||
params.filter['type_id'] = 'in.(2,3)';
|
||||
@@ -352,33 +484,76 @@ export async function getDocumentTypes(reviewType?: string): Promise<{data: Docu
|
||||
/**
|
||||
* 获取指定文档的状态
|
||||
* @param documentIds 文档ID列表
|
||||
* @param attachmentIds 合同附件ID列表(可选)
|
||||
* @returns 文档状态列表
|
||||
*/
|
||||
export async function getDocumentsStatus(documentIds: number[]): Promise<{data: Document[]; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
export async function getDocumentsStatus(
|
||||
documentIds: number[],
|
||||
attachmentIds?: number[]
|
||||
): Promise<{data: Document[]; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
if (!documentIds || documentIds.length === 0) {
|
||||
if ((!documentIds || documentIds.length === 0) && (!attachmentIds || attachmentIds.length === 0)) {
|
||||
return { data: [] };
|
||||
}
|
||||
|
||||
const params: PostgrestParams = {
|
||||
select: 'id, status',
|
||||
filter: {
|
||||
'id': `in.(${documentIds.join(',')})`
|
||||
// 查询主文档状态
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let documentsResponse: any = { data: [], error: undefined, status: undefined };
|
||||
if (documentIds && documentIds.length > 0) {
|
||||
const documentsParams: PostgrestParams = {
|
||||
select: 'id, status',
|
||||
filter: {
|
||||
'id': `in.(${documentIds.join(',')})`
|
||||
}
|
||||
};
|
||||
documentsResponse = await postgrestGet<Document[]>('documents', documentsParams);
|
||||
}
|
||||
|
||||
// 查询合同附件状态
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let attachmentResponse: any = { data: [], error: undefined, status: undefined };
|
||||
if (attachmentIds && attachmentIds.length > 0) {
|
||||
const attachmentParams: PostgrestParams = {
|
||||
select: 'id, status',
|
||||
filter: {
|
||||
'id': `in.(${attachmentIds.join(',')})`
|
||||
}
|
||||
};
|
||||
attachmentResponse = await postgrestGet<ContractStructureComparison[]>('contract_structure_comparison', attachmentParams);
|
||||
}
|
||||
|
||||
if (documentsResponse.error && attachmentResponse.error) {
|
||||
return { error: documentsResponse.error || attachmentResponse.error, status: documentsResponse.status || attachmentResponse.status };
|
||||
}
|
||||
|
||||
let allData: Document[] = [];
|
||||
|
||||
// 处理主文档数据
|
||||
if (!documentsResponse.error && documentsResponse.data) {
|
||||
const extractedDocuments = extractApiData<Document[]>(documentsResponse.data);
|
||||
if (extractedDocuments) {
|
||||
allData = [...allData, ...extractedDocuments];
|
||||
}
|
||||
};
|
||||
|
||||
const response = await postgrestGet<Document[]>('documents', params);
|
||||
|
||||
if (response.error) {
|
||||
return { error: response.error, status: response.status };
|
||||
}
|
||||
|
||||
const extractedData = extractApiData<Document[]>(response.data);
|
||||
if (!extractedData) {
|
||||
return { error: '获取数据失败', status: 500 };
|
||||
// 处理合同附件数据
|
||||
if (!attachmentResponse.error && attachmentResponse.data) {
|
||||
const extractedAttachments = extractApiData<ContractStructureComparison[]>(attachmentResponse.data);
|
||||
if (extractedAttachments) {
|
||||
// 将ContractStructureComparison转换为Document格式
|
||||
const convertedAttachments: Document[] = extractedAttachments.map(item => ({
|
||||
id: item.id,
|
||||
name: item.template_contract_name || `合同结构比较记录_${item.id}`,
|
||||
type_id: 1,
|
||||
file_size: item.file_size || 0,
|
||||
status: item.status,
|
||||
created_at: item.created_at
|
||||
}));
|
||||
allData = [...allData, ...convertedAttachments];
|
||||
}
|
||||
}
|
||||
|
||||
return { data: extractedData };
|
||||
return { data: allData };
|
||||
} catch (error) {
|
||||
console.error('获取文档状态失败:', error);
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user