318 lines
7.6 KiB
TypeScript
318 lines
7.6 KiB
TypeScript
import { postgrestGet, postgrestDelete, type PostgrestParams } from '../postgrest-client';
|
|
import dayjs from 'dayjs';
|
|
import { getDocumentTypes } from '../document-types/document-types';
|
|
|
|
/**
|
|
* 从不同格式的 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;
|
|
}
|
|
|
|
/**
|
|
* 格式化日期
|
|
* @param dateString 日期字符串
|
|
* @returns 格式化后的日期字符串
|
|
*/
|
|
function formatDate(dateString: string): string {
|
|
if (!dateString) return '';
|
|
try {
|
|
return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss');
|
|
} catch (error) {
|
|
console.error('日期格式化失败:', error);
|
|
return dateString;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 查询参数
|
|
*/
|
|
export interface DocumentSearchParams {
|
|
name?: string;
|
|
documentNumber?: string;
|
|
documentType?: string;
|
|
status?: string;
|
|
dateFrom?: string;
|
|
dateTo?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
/**
|
|
* 数据库文档结构
|
|
*/
|
|
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';
|
|
ocr_result: unknown;
|
|
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;
|
|
status: string;
|
|
issues: number | null;
|
|
uploadTime: string;
|
|
fileType: string;
|
|
path: string;
|
|
isTest: boolean;
|
|
}
|
|
|
|
/**
|
|
* 获取文件扩展名
|
|
* @param filename 文件名
|
|
* @returns 文件扩展名
|
|
*/
|
|
function getFileExtension(filename: string): string {
|
|
const parts = filename.split('.');
|
|
return parts.length > 1 ? parts.pop()?.toLowerCase() || '' : '';
|
|
}
|
|
|
|
/**
|
|
* 将API文档转换为UI文档
|
|
*/
|
|
async function convertToUIDocument(doc: Document): Promise<DocumentUI> {
|
|
// 获取文档类型信息
|
|
const typeResponse = await getDocumentTypes();
|
|
const documentTypes = typeResponse.data?.types || [];
|
|
const docType = documentTypes.find(type => type.id.toString() === doc.type_id.toString());
|
|
|
|
return {
|
|
id: doc.id,
|
|
name: doc.name,
|
|
documentNumber: doc.document_number,
|
|
type: doc.type_id.toString(),
|
|
typeName: docType?.name || '未知类型',
|
|
size: doc.file_size,
|
|
status: doc.status,
|
|
issues: 0, // 固定为0
|
|
uploadTime: formatDate(doc.updated_at),
|
|
fileType: getFileExtension(doc.name),
|
|
path: doc.path,
|
|
isTest: doc.is_test_document
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 获取文档列表
|
|
* @param searchParams 搜索参数
|
|
* @returns 文档列表和总数
|
|
*/
|
|
export async function getDocuments(searchParams: DocumentSearchParams = {}): Promise<{
|
|
data?: { documents: DocumentUI[], total: number };
|
|
error?: string;
|
|
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.status) {
|
|
filter['status'] = `eq.${searchParams.status}`;
|
|
}
|
|
|
|
// 处理日期范围
|
|
if (searchParams.dateFrom) {
|
|
filter['updated_at'] = `gte.${searchParams.dateFrom}`;
|
|
}
|
|
|
|
if (searchParams.dateTo) {
|
|
const dateToKey = searchParams.dateFrom ? 'and.updated_at.lte' : 'updated_at';
|
|
filter[dateToKey] = `lte.${searchParams.dateTo}`;
|
|
}
|
|
|
|
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 };
|
|
}
|
|
|
|
// 转换为UI格式
|
|
const documents = await Promise.all(extractedData.map(convertToUIDocument));
|
|
|
|
// 获取总数
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
data: {
|
|
documents,
|
|
total: totalCount || documents.length
|
|
}
|
|
};
|
|
} catch (error) {
|
|
console.error('获取文档列表失败:', error);
|
|
return {
|
|
error: error instanceof Error ? error.message : '获取文档列表失败',
|
|
status: 500
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除文档
|
|
* @param id 文档ID
|
|
* @returns 删除结果
|
|
*/
|
|
export async function deleteDocument(id: string): Promise<{
|
|
success?: boolean;
|
|
error?: string;
|
|
status?: number;
|
|
}> {
|
|
try {
|
|
if (!id) {
|
|
return { error: '文档ID不能为空', status: 400 };
|
|
}
|
|
|
|
const response = await postgrestDelete(
|
|
'documents',
|
|
{
|
|
filter: {
|
|
'id': `eq.${id}`
|
|
}
|
|
}
|
|
);
|
|
|
|
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): Promise<{
|
|
data?: DocumentUI;
|
|
error?: string;
|
|
status?: number;
|
|
}> {
|
|
try {
|
|
if (!id) {
|
|
return { error: '文档ID不能为空', status: 400 };
|
|
}
|
|
|
|
const response = await postgrestGet<Document[]>(
|
|
'documents',
|
|
{
|
|
filter: {
|
|
'id': `eq.${id}`
|
|
},
|
|
limit: 1
|
|
}
|
|
);
|
|
|
|
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]);
|
|
|
|
return { data: documentUI };
|
|
} catch (error) {
|
|
console.error('获取文档详情失败:', error);
|
|
return {
|
|
error: error instanceof Error ? error.message : '获取文档详情失败',
|
|
status: 500
|
|
};
|
|
}
|
|
} |