|
|
@@ -13,13 +13,13 @@ export function createCrudRoutes<
|
|
|
GetSchema extends z.ZodSchema = z.ZodSchema,
|
|
|
ListSchema extends z.ZodSchema = z.ZodSchema
|
|
|
>(options: CrudOptions<T, CreateSchema, UpdateSchema, GetSchema, ListSchema>) {
|
|
|
- const { entity, createSchema, updateSchema, getSchema, listSchema, searchFields, middleware = [] } = options;
|
|
|
+ const { entity, createSchema, updateSchema, getSchema, listSchema, searchFields, relations, middleware = [], userTracking } = options;
|
|
|
|
|
|
// 创建CRUD服务实例
|
|
|
// 抽象类不能直接实例化,需要创建具体实现类
|
|
|
class ConcreteCrudService extends GenericCrudService<T> {
|
|
|
constructor() {
|
|
|
- super(AppDataSource, entity);
|
|
|
+ super(AppDataSource, entity, { userTracking });
|
|
|
}
|
|
|
}
|
|
|
const crudService = new ConcreteCrudService();
|
|
|
@@ -53,6 +53,11 @@ export function createCrudRoutes<
|
|
|
sortOrder: z.enum(['ASC', 'DESC']).optional().default('DESC').openapi({
|
|
|
example: 'DESC',
|
|
|
description: '排序方向'
|
|
|
+ }),
|
|
|
+ // 增强的筛选参数
|
|
|
+ filters: z.string().optional().openapi({
|
|
|
+ example: '{"status": 1, "createdAt": {"gte": "2024-01-01", "lte": "2024-12-31"}}',
|
|
|
+ description: '筛选条件(JSON字符串),支持精确匹配、范围查询、IN查询等'
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
@@ -215,16 +220,25 @@ export function createCrudRoutes<
|
|
|
const routes = app
|
|
|
.openapi(listRoute, async (c) => {
|
|
|
try {
|
|
|
- const { page, pageSize, keyword, sortBy, sortOrder } = c.req.valid('query');
|
|
|
+ const query = c.req.valid('query') as any;
|
|
|
+ const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;
|
|
|
|
|
|
// 构建排序对象
|
|
|
- // 使用Record和类型断言解决泛型索引写入问题
|
|
|
- const order: Partial<Record<keyof T, 'ASC' | 'DESC'>> = {};
|
|
|
+ const order: any = {};
|
|
|
if (sortBy) {
|
|
|
- (order as Record<string, 'ASC' | 'DESC'>)[sortBy] = sortOrder || 'DESC';
|
|
|
+ order[sortBy] = sortOrder || 'DESC';
|
|
|
} else {
|
|
|
- // 默认按id降序排序
|
|
|
- (order as Record<string, 'ASC' | 'DESC'>)['id'] = 'DESC';
|
|
|
+ order['id'] = 'DESC';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析筛选条件
|
|
|
+ let parsedFilters: any = undefined;
|
|
|
+ if (filters) {
|
|
|
+ try {
|
|
|
+ parsedFilters = JSON.parse(filters);
|
|
|
+ } catch (e) {
|
|
|
+ return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const [data, total] = await crudService.getList(
|
|
|
@@ -232,13 +246,14 @@ export function createCrudRoutes<
|
|
|
pageSize,
|
|
|
keyword,
|
|
|
searchFields,
|
|
|
- undefined, // where条件
|
|
|
- [], // relations
|
|
|
- order
|
|
|
+ undefined,
|
|
|
+ relations || [],
|
|
|
+ order,
|
|
|
+ parsedFilters
|
|
|
);
|
|
|
|
|
|
return c.json({
|
|
|
- data: data as any[],
|
|
|
+ data,
|
|
|
pagination: { total, current: page, pageSize }
|
|
|
}, 200);
|
|
|
} catch (error) {
|
|
|
@@ -251,10 +266,11 @@ export function createCrudRoutes<
|
|
|
}, 500);
|
|
|
}
|
|
|
})
|
|
|
- .openapi(createRouteDef, async (c) => {
|
|
|
+ .openapi(createRouteDef, async (c: any) => {
|
|
|
try {
|
|
|
const data = c.req.valid('json');
|
|
|
- const result = await crudService.create(data);
|
|
|
+ const user = c.get('user');
|
|
|
+ const result = await crudService.create(data, user?.id);
|
|
|
return c.json(result, 201);
|
|
|
} catch (error) {
|
|
|
if (error instanceof z.ZodError) {
|
|
|
@@ -266,10 +282,10 @@ export function createCrudRoutes<
|
|
|
}, 500);
|
|
|
}
|
|
|
})
|
|
|
- .openapi(getRouteDef, async (c) => {
|
|
|
+ .openapi(getRouteDef, async (c: any) => {
|
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
|
- const result = await crudService.getById(id);
|
|
|
+ const result = await crudService.getById(id, relations || []);
|
|
|
|
|
|
if (!result) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
@@ -286,11 +302,12 @@ export function createCrudRoutes<
|
|
|
}, 500);
|
|
|
}
|
|
|
})
|
|
|
- .openapi(updateRouteDef, async (c) => {
|
|
|
+ .openapi(updateRouteDef, async (c: any) => {
|
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
|
const data = c.req.valid('json');
|
|
|
- const result = await crudService.update(id, data);
|
|
|
+ const user = c.get('user');
|
|
|
+ const result = await crudService.update(id, data, user?.id);
|
|
|
|
|
|
if (!result) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
@@ -298,9 +315,6 @@ export function createCrudRoutes<
|
|
|
|
|
|
return c.json(result, 200);
|
|
|
} catch (error) {
|
|
|
- if (error instanceof z.ZodError) {
|
|
|
- return c.json({ code: 400, message: '参数验证失败', errors: error.errors }, 400);
|
|
|
- }
|
|
|
if (error instanceof z.ZodError) {
|
|
|
return c.json({ code: 400, message: '参数验证失败', errors: error.errors }, 400);
|
|
|
}
|
|
|
@@ -310,7 +324,7 @@ export function createCrudRoutes<
|
|
|
}, 500);
|
|
|
}
|
|
|
})
|
|
|
- .openapi(deleteRouteDef, async (c) => {
|
|
|
+ .openapi(deleteRouteDef, async (c: any) => {
|
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
|
const success = await crudService.delete(id);
|
|
|
@@ -319,11 +333,8 @@ export function createCrudRoutes<
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
}
|
|
|
|
|
|
- return c.body(null, 204) as unknown as Response;
|
|
|
+ return c.body(null, 204);
|
|
|
} catch (error) {
|
|
|
- if (error instanceof z.ZodError) {
|
|
|
- return c.json({ code: 400, message: '参数验证失败', errors: error.errors }, 400);
|
|
|
- }
|
|
|
if (error instanceof z.ZodError) {
|
|
|
return c.json({ code: 400, message: '参数验证失败', errors: error.errors }, 400);
|
|
|
}
|