完成文档类型增删改查
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user