完成文档列表页面ui,封装部分上传文件的公共组件,封装请求接口
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
// app/api/client.ts
|
||||
export type ApiResponse<T> = {
|
||||
data?: T;
|
||||
error?: string;
|
||||
status: number;
|
||||
};
|
||||
|
||||
export type QueryParams = Record<string, string | number | boolean | undefined>;
|
||||
|
||||
// 基本数据类型
|
||||
interface BaseItem {
|
||||
id: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
// 为模拟数据预定义类型定义(导出以允许其他文件引用)
|
||||
// 这些类型被用在模拟数据中,虽然没有直接引用
|
||||
export interface Document extends BaseItem {
|
||||
name: string;
|
||||
type: string;
|
||||
size: number;
|
||||
status: string;
|
||||
uploadDate: string;
|
||||
lastModified: string;
|
||||
}
|
||||
|
||||
export interface Rule extends BaseItem {
|
||||
code: string;
|
||||
name: string;
|
||||
ruleType: string;
|
||||
groupId: string;
|
||||
groupName: string;
|
||||
priority: string;
|
||||
description: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface RuleGroup extends BaseItem {
|
||||
name: string;
|
||||
description: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface CountItem extends BaseItem {
|
||||
count: number;
|
||||
}
|
||||
|
||||
// 获取 API 基础 URL,支持服务器端和客户端环境
|
||||
const API_BASE_URL = typeof process !== 'undefined' && process.env.API_BASE_URL
|
||||
? process.env.API_BASE_URL
|
||||
: 'http://nas.7bm.co:54302/api/docauditai'; // 如果服务器不可用,会自动使用模拟数据
|
||||
|
||||
// 获取 API 访问令牌
|
||||
const API_TOKEN = typeof process !== 'undefined' && process.env.API_TOKEN
|
||||
? process.env.API_TOKEN
|
||||
: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXBpX3VzZXIifQ.KVLm7rZOF0MuX3MR9LqiYA14gba-MaDK_EQXrJ9u5_Y';
|
||||
|
||||
// 是否使用模拟数据(开发环境使用)
|
||||
const USE_MOCK_DATA = true; // 设置为 true 可启用模拟数据
|
||||
|
||||
/**
|
||||
* 构建完整的 API URL,支持服务器端和客户端环境
|
||||
*/
|
||||
function buildUrl(endpoint: string, params?: QueryParams): string {
|
||||
// 创建 URL 字符串
|
||||
const url = new URL(
|
||||
endpoint.startsWith('http') ? endpoint : API_BASE_URL + endpoint,
|
||||
// 服务器端使用绝对 URL,客户端使用相对 URL
|
||||
typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'
|
||||
);
|
||||
|
||||
// 添加查询参数
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value !== undefined) {
|
||||
url.searchParams.append(key, String(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
// 超时控制
|
||||
const fetchWithTimeout = async (url: string, options: RequestInit, timeout = 5000) => {
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), timeout);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
signal: controller.signal
|
||||
});
|
||||
clearTimeout(id);
|
||||
return response;
|
||||
} catch (error) {
|
||||
clearTimeout(id);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 模拟数据库响应的类型
|
||||
type MockData = {
|
||||
[key: string]: BaseItem[];
|
||||
};
|
||||
|
||||
// 模拟数据库响应
|
||||
const mockDataResponses: MockData = {
|
||||
// 文档列表模拟数据
|
||||
'/documents': [
|
||||
{
|
||||
id: '1',
|
||||
name: '合同.pdf',
|
||||
type: 'contract',
|
||||
size: 1024000,
|
||||
status: 'approved',
|
||||
uploadDate: new Date().toISOString(),
|
||||
lastModified: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '报告.docx',
|
||||
type: 'report',
|
||||
size: 512000,
|
||||
status: 'pending',
|
||||
uploadDate: new Date().toISOString(),
|
||||
lastModified: new Date().toISOString()
|
||||
}
|
||||
],
|
||||
// 规则列表模拟数据
|
||||
'/evaluation_points': [
|
||||
{
|
||||
id: '1',
|
||||
code: 'R001',
|
||||
name: '合同名称',
|
||||
ruleType: 'essential',
|
||||
groupId: '1',
|
||||
groupName: '合同基本要素类检查',
|
||||
priority: 'high',
|
||||
description: '文档必须包含合同名称',
|
||||
isActive: true,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
code: 'R002',
|
||||
name: '合同编号',
|
||||
ruleType: 'legal',
|
||||
groupId: '2',
|
||||
groupName: '销售合同专项检查',
|
||||
priority: 'medium',
|
||||
description: '文档必须包含合同编号',
|
||||
isActive: true,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
],
|
||||
// 评查点组列表模拟数据
|
||||
'/evaluation_point_groups': [
|
||||
{ id: '1', name: '合同基本要素类检查', description: '合同基本要素类检查', isActive: true },
|
||||
{ id: '2', name: '销售合同专项检查', description: '销售合同专项检查', isActive: true },
|
||||
{ id: '3', name: '采购合同专项检查', description: '采购合同专项检查', isActive: true },
|
||||
{ id: '4', name: '专卖许可证审核规则', description: '专卖许可证审核规则', isActive: true },
|
||||
{ id: '5', name: '行政处罚规范性检查', description: '行政处罚规范性检查', isActive: true }
|
||||
],
|
||||
// 计数查询 - 为了满足 BaseItem 类型,添加 id 字段
|
||||
'/evaluation_points/count': [{ id: 'count', count: 2 }],
|
||||
'/documents/count': [{ id: 'count', count: 2 }]
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取模拟响应数据
|
||||
* @param endpoint API端点
|
||||
* @param params 查询参数
|
||||
* @returns 模拟的响应数据
|
||||
*/
|
||||
function getMockResponse<T>(endpoint: string, params?: QueryParams): ApiResponse<T> {
|
||||
console.log(`[开发模式] 使用模拟数据: ${endpoint}`);
|
||||
|
||||
// 移除开头的斜杠以便于匹配
|
||||
const path = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
||||
|
||||
// 检查是否有匹配的路径
|
||||
for (const [mockPath, mockData] of Object.entries(mockDataResponses)) {
|
||||
const normalizedMockPath = mockPath.startsWith('/') ? mockPath.substring(1) : mockPath;
|
||||
if (path === normalizedMockPath || path.startsWith(normalizedMockPath + '/') || path.startsWith(normalizedMockPath + '?')) {
|
||||
// 如果 ID 路径参数 (如 /rules/1),返回单个项目
|
||||
const pathParts = path.split('/');
|
||||
const mockPathParts = normalizedMockPath.split('/');
|
||||
|
||||
if (pathParts.length > mockPathParts.length && !isNaN(Number(pathParts[mockPathParts.length]))) {
|
||||
const id = pathParts[mockPathParts.length];
|
||||
const item = mockData.find(i => i.id === id);
|
||||
return item
|
||||
? { data: item as unknown as T, status: 200 }
|
||||
: { error: '未找到', status: 404 };
|
||||
}
|
||||
|
||||
// 处理分页
|
||||
if (params?.limit && params?.offset) {
|
||||
const limit = Number(params.limit);
|
||||
const offset = Number(params.offset);
|
||||
const paginatedData = mockData.slice(offset, offset + limit);
|
||||
return { data: paginatedData as unknown as T, status: 200 };
|
||||
}
|
||||
|
||||
// 返回完整数据
|
||||
return { data: mockData as unknown as T, status: 200 };
|
||||
}
|
||||
}
|
||||
|
||||
// 没有匹配的模拟数据
|
||||
return { error: '没有匹配的模拟数据', status: 404 };
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用 API 请求函数
|
||||
*/
|
||||
export async function apiRequest<T>(
|
||||
endpoint: string,
|
||||
options: RequestInit = {},
|
||||
params?: QueryParams
|
||||
): Promise<ApiResponse<T>> {
|
||||
// 如果使用模拟数据,直接返回模拟响应
|
||||
if (USE_MOCK_DATA) {
|
||||
return getMockResponse<T>(endpoint, params);
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建 URL
|
||||
const url = buildUrl(endpoint, params);
|
||||
|
||||
// 设置默认请求头
|
||||
const headers = new Headers(options.headers || {});
|
||||
if (!headers.has('Content-Type') && options.method !== 'GET') {
|
||||
headers.set('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
// 数据库连接授权信息
|
||||
if (!headers.has('Authorization')) {
|
||||
headers.set('Authorization', `Bearer ${API_TOKEN}`);
|
||||
}
|
||||
|
||||
// 发送请求,5秒超时
|
||||
const response = await fetchWithTimeout(url, {
|
||||
...options,
|
||||
headers
|
||||
}, 5000);
|
||||
|
||||
// 解析响应
|
||||
let data = null;
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (contentType && contentType.includes('application/json') && response.status !== 204) {
|
||||
data = await response.json();
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(`API请求失败: ${response.status} - ${url}`);
|
||||
return {
|
||||
error: data?.message || `请求失败: ${response.status}`,
|
||||
status: response.status
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
status: response.status
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('API请求失败:', error);
|
||||
|
||||
// 如果超时或网络错误,使用模拟数据(仅开发环境)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.warn('自动使用模拟数据作为回退');
|
||||
return getMockResponse<T>(endpoint, params);
|
||||
}
|
||||
|
||||
return {
|
||||
error: error instanceof Error ? error.message : '未知错误',
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* API 错误类,用于封装 API 请求错误
|
||||
*/
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
|
||||
constructor(message: string, status: number = 500) {
|
||||
super(message);
|
||||
this.name = 'ApiError';
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 API 错误
|
||||
* @param error 捕获的错误对象
|
||||
* @returns 统一的 ApiError 对象
|
||||
*/
|
||||
export function handleApiError(error: unknown): ApiError {
|
||||
if (error instanceof ApiError) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return new ApiError(error.message);
|
||||
}
|
||||
|
||||
return new ApiError('未知错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个标准的错误响应
|
||||
* @param message 错误消息
|
||||
* @param status HTTP 状态码
|
||||
*/
|
||||
export function createErrorResponse(message: string, status: number = 400): Response {
|
||||
return new Response(
|
||||
JSON.stringify({ error: message }),
|
||||
{
|
||||
status,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import { postgrestGet, postgrestPost, postgrestPut, postgrestDelete } from '../postgrest-client';
|
||||
|
||||
/**
|
||||
* 评查点列表查询参数
|
||||
*/
|
||||
export interface RulesQueryParams {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
ruleType?: string;
|
||||
groupId?: string;
|
||||
isActive?: boolean;
|
||||
keyword?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 评查点列表响应数据
|
||||
*/
|
||||
export interface RulesListResponse {
|
||||
rules: Rule[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 评查点详情
|
||||
*/
|
||||
export interface Rule {
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
ruleType: string;
|
||||
groupId: string;
|
||||
groupName: string;
|
||||
priority: string;
|
||||
description: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 评查点分组
|
||||
*/
|
||||
export interface RuleGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评查点列表
|
||||
* @param params 查询参数
|
||||
* @returns 评查点列表、总数和评查点组
|
||||
*/
|
||||
export async function getRulesList(params: RulesQueryParams): Promise<{data: RulesListResponse; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// 构建 PostgREST 查询参数
|
||||
const { page = 1, pageSize = 10, ...filters } = params;
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
// 构建过滤条件
|
||||
const filterArray: Record<string, unknown> = {};
|
||||
|
||||
if (filters.ruleType) {
|
||||
filterArray['rule_type'] = `eq.${filters.ruleType}`;
|
||||
}
|
||||
|
||||
if (filters.groupId) {
|
||||
filterArray['group_id'] = `eq.${filters.groupId}`;
|
||||
}
|
||||
|
||||
if (filters.isActive !== undefined) {
|
||||
filterArray['is_active'] = `eq.${filters.isActive}`;
|
||||
}
|
||||
|
||||
if (filters.keyword) {
|
||||
// 关键字搜索
|
||||
filterArray['or'] = `name.ilike.*${filters.keyword}*,code.ilike.*${filters.keyword}*`;
|
||||
}
|
||||
|
||||
// 执行多个 API 调用(获取评查点列表、总数和评查点组)
|
||||
const [rulesResponse, countResponse] = await Promise.all([
|
||||
postgrestGet<Rule[]>('/evaluation_points', {
|
||||
select: '*',
|
||||
order: 'created_at.desc',
|
||||
limit: pageSize,
|
||||
offset,
|
||||
filter: filterArray
|
||||
}),
|
||||
|
||||
postgrestGet<[{count: number}]>('/evaluation_points/count', {
|
||||
filter: filterArray
|
||||
}),
|
||||
|
||||
]);
|
||||
|
||||
// 处理错误情况
|
||||
if (rulesResponse.error) {
|
||||
return { error: `获取评查点列表失败: ${rulesResponse.error}`, status: 500 };
|
||||
}
|
||||
|
||||
if (countResponse.error) {
|
||||
return { error: `获取评查点总数失败: ${countResponse.error}`, status: 500 };
|
||||
}
|
||||
|
||||
|
||||
// 确保数据不为 undefined,提供默认值
|
||||
const rules = rulesResponse.data || [];
|
||||
const totalCount = countResponse.data && countResponse.data[0] ? countResponse.data[0].count : 0;
|
||||
|
||||
// 成功返回数据
|
||||
return {
|
||||
data: {
|
||||
rules,
|
||||
totalCount,
|
||||
}
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取评查点列表出错:', error);
|
||||
return {
|
||||
error: error instanceof Error ? error.message : '获取评查点列表失败',
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个评查点详情
|
||||
* @param id 评查点ID
|
||||
* @returns 评查点详情
|
||||
*/
|
||||
export async function getRule(id: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
return postgrestGet<Rule>(`/evaluation_points/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新评查点
|
||||
* @param ruleData 评查点数据
|
||||
* @returns 创建的评查点
|
||||
*/
|
||||
export async function createRule(ruleData: Omit<Rule, 'id' | 'createdAt' | 'updatedAt'>): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
return postgrestPost<Rule, Omit<Rule, 'id' | 'createdAt' | 'updatedAt'>>('/evaluation_points', ruleData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新评查点
|
||||
* @param id 评查点ID
|
||||
* @param ruleData 评查点数据
|
||||
* @returns 更新后的评查点
|
||||
*/
|
||||
export async function updateRule(id: string, ruleData: Partial<Omit<Rule, 'id' | 'createdAt' | 'updatedAt'>>): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
return postgrestPut<Rule, Partial<Omit<Rule, 'id' | 'createdAt' | 'updatedAt'>>>(`/evaluation_points/${id}`, ruleData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除评查点
|
||||
* @param id 评查点ID
|
||||
* @returns 删除结果
|
||||
*/
|
||||
export async function deleteRule(id: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
return postgrestDelete<Rule>(`/evaluation_points/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制评查点
|
||||
* @param id 评查点ID
|
||||
* @returns 新创建的评查点
|
||||
*/
|
||||
export async function duplicateRule(id: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// 1. 获取原评查点详情
|
||||
const ruleResponse = await getRule(id);
|
||||
|
||||
if (ruleResponse.error || !ruleResponse.data) {
|
||||
return { error: ruleResponse.error || '获取评查点详情失败', status: 500 };
|
||||
}
|
||||
|
||||
// 2. 准备新评查点数据
|
||||
const rule = ruleResponse.data;
|
||||
|
||||
// 创建新评查点对象
|
||||
const newRuleData = {
|
||||
code: `${rule.code}-COPY`,
|
||||
name: `${rule.name} (复制)`,
|
||||
ruleType: rule.ruleType,
|
||||
groupId: rule.groupId,
|
||||
groupName: rule.groupName,
|
||||
priority: rule.priority,
|
||||
description: rule.description,
|
||||
isActive: rule.isActive
|
||||
};
|
||||
|
||||
// 3. 创建新评查点
|
||||
return createRule(newRuleData);
|
||||
|
||||
} catch (error) {
|
||||
console.error('复制评查点出错:', error);
|
||||
return {
|
||||
error: error instanceof Error ? error.message : '复制评查点失败',
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// app/api/postgrest-client.ts
|
||||
import { apiRequest, type QueryParams } from './client';
|
||||
import { handleApiError } from './error-handler';
|
||||
|
||||
/**
|
||||
* PostgresREST 特定的查询参数接口
|
||||
*/
|
||||
export interface PostgrestParams {
|
||||
select?: string;
|
||||
order?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
filter?: Record<string, unknown>;
|
||||
schema?: string; // 指定 PostgreSQL schema
|
||||
[key: string]: unknown; // 允许添加其他参数
|
||||
}
|
||||
|
||||
/**
|
||||
* 将通用查询参数转换为 PostgresREST 支持的格式
|
||||
* @param params 查询参数
|
||||
* @returns 转换后的 PostgresREST 参数
|
||||
*/
|
||||
export function transformParams(params: PostgrestParams): QueryParams {
|
||||
const result: QueryParams = {};
|
||||
|
||||
// 处理 select 参数
|
||||
if (params.select) {
|
||||
result.select = params.select;
|
||||
}
|
||||
|
||||
// 处理 order 参数
|
||||
if (params.order) {
|
||||
result.order = params.order;
|
||||
}
|
||||
|
||||
// 处理 limit 和 offset 参数
|
||||
if (params.limit !== undefined) {
|
||||
result.limit = params.limit;
|
||||
}
|
||||
|
||||
if (params.offset !== undefined) {
|
||||
result.offset = params.offset;
|
||||
}
|
||||
|
||||
// 处理 schema 参数
|
||||
if (params.schema) {
|
||||
result.schema = params.schema;
|
||||
}
|
||||
|
||||
// 处理过滤条件 - PostgresREST 格式
|
||||
if (params.filter) {
|
||||
Object.entries(params.filter).forEach(([key, value]) => {
|
||||
// 如果值不为 undefined,则添加到查询参数中
|
||||
if (value !== undefined) {
|
||||
// 支持 PostgreSQL 的比较操作符 (eq, gt, lt, gte, lte, like, ilike 等)
|
||||
result[key] = value as string | number | boolean;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 处理其他额外参数
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
// 跳过已处理的特殊参数
|
||||
if (!['select', 'order', 'limit', 'offset', 'filter', 'schema'].includes(key) && value !== undefined) {
|
||||
result[key] = value as string | number | boolean;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 GET 请求到 PostgresREST 接口
|
||||
* @param endpoint 端点
|
||||
* @param params 查询参数
|
||||
* @returns 响应数据
|
||||
*/
|
||||
export async function postgrestGet<T>(endpoint: string, params?: PostgrestParams): Promise<{data: T; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
const queryParams = params ? transformParams(params) : {};
|
||||
// 添加前缀表示使用 docauditai 数据库
|
||||
const apiEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
|
||||
const response = await apiRequest<T>(
|
||||
apiEndpoint,
|
||||
{ method: 'GET' },
|
||||
queryParams
|
||||
);
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
return { data: response.data as T };
|
||||
} catch (error) {
|
||||
const apiError = handleApiError(error);
|
||||
return { error: apiError.message, status: apiError.status };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 POST 请求到 PostgresREST 接口
|
||||
* @param endpoint 端点
|
||||
* @param data 请求体数据
|
||||
* @returns 响应数据
|
||||
*/
|
||||
export async function postgrestPost<T, D = Record<string, unknown>>(endpoint: string, data: D): Promise<{data: T; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// 添加前缀表示使用 docauditai 数据库
|
||||
const apiEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
|
||||
const response = await apiRequest<T>(
|
||||
apiEndpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Prefer': 'return=representation'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
return { data: response.data as T };
|
||||
} catch (error) {
|
||||
const apiError = handleApiError(error);
|
||||
return { error: apiError.message, status: apiError.status };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 PUT 请求到 PostgresREST 接口
|
||||
* @param endpoint 端点
|
||||
* @param data 请求体数据
|
||||
* @returns 响应数据
|
||||
*/
|
||||
export async function postgrestPut<T, D = Record<string, unknown>>(endpoint: string, data: D): Promise<{data: T; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// 添加前缀表示使用 docauditai 数据库
|
||||
const apiEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
|
||||
const response = await apiRequest<T>(
|
||||
apiEndpoint,
|
||||
{
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Prefer': 'return=representation'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
return { data: response.data as T };
|
||||
} catch (error) {
|
||||
const apiError = handleApiError(error);
|
||||
return { error: apiError.message, status: apiError.status };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 DELETE 请求到 PostgresREST 接口
|
||||
* @param endpoint 端点
|
||||
* @returns 响应数据
|
||||
*/
|
||||
export async function postgrestDelete<T>(endpoint: string): Promise<{data: T; error?: never} | {data?: never; error: string; status?: number}> {
|
||||
try {
|
||||
// 添加前缀表示使用 docauditai 数据库
|
||||
const apiEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
|
||||
const response = await apiRequest<T>(
|
||||
apiEndpoint,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Prefer': 'return=representation'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
return { data: response.data as T };
|
||||
} catch (error) {
|
||||
const apiError = handleApiError(error);
|
||||
return { error: apiError.message, status: apiError.status };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user