|
@@ -32,7 +32,7 @@ export class YourEntityService extends GenericCrudService<YourEntity> {
|
|
|
| 方法 | 描述 | 参数 | 返回值 |
|
|
| 方法 | 描述 | 参数 | 返回值 |
|
|
|
|------|------|------|--------|
|
|
|------|------|------|--------|
|
|
|
| `getList` | 获取分页列表 | `page`, `pageSize`, `keyword`, `searchFields`, `where`, `relations`, `order` | `[T[], number]` |
|
|
| `getList` | 获取分页列表 | `page`, `pageSize`, `keyword`, `searchFields`, `where`, `relations`, `order` | `[T[], number]` |
|
|
|
-| `getById` | 根据ID获取单个实体 | `id: number` | `T \| null` |
|
|
|
|
|
|
|
+| `getById` | 根据ID获取单个实体 | `id: number`, `relations?: string[]` | `T \| null` |
|
|
|
| `create` | 创建实体 | `data: DeepPartial<T>` | `T` |
|
|
| `create` | 创建实体 | `data: DeepPartial<T>` | `T` |
|
|
|
| `update` | 更新实体 | `id: number`, `data: Partial<T>` | `T \| null` |
|
|
| `update` | 更新实体 | `id: number`, `data: Partial<T>` | `T \| null` |
|
|
|
| `delete` | 删除实体 | `id: number` | `boolean` |
|
|
| `delete` | 删除实体 | `id: number` | `boolean` |
|
|
@@ -73,6 +73,7 @@ const yourEntityRoutes = createCrudRoutes({
|
|
|
getSchema: YourEntitySchema,
|
|
getSchema: YourEntitySchema,
|
|
|
listSchema: YourEntitySchema,
|
|
listSchema: YourEntitySchema,
|
|
|
searchFields: ['name', 'description'], // 可选,指定搜索字段
|
|
searchFields: ['name', 'description'], // 可选,指定搜索字段
|
|
|
|
|
+ relations: ['relatedEntity'], // 可选,指定关联查询关系(支持嵌套关联,如 ['relatedEntity.client'])
|
|
|
middleware: [authMiddleware] // 可选,添加中间件
|
|
middleware: [authMiddleware] // 可选,添加中间件
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -89,6 +90,7 @@ export default yourEntityRoutes;
|
|
|
| `getSchema` | `z.ZodSchema` | 获取单个实体的响应 schema | 是 |
|
|
| `getSchema` | `z.ZodSchema` | 获取单个实体的响应 schema | 是 |
|
|
|
| `listSchema` | `z.ZodSchema` | 获取列表的响应 schema | 是 |
|
|
| `listSchema` | `z.ZodSchema` | 获取列表的响应 schema | 是 |
|
|
|
| `searchFields` | `string[]` | 搜索字段数组,用于关键词搜索 | 否 |
|
|
| `searchFields` | `string[]` | 搜索字段数组,用于关键词搜索 | 否 |
|
|
|
|
|
+| `relations` | `string[]` | 关联查询配置,指定需要关联查询的关系 | 否 |
|
|
|
| `middleware` | `any[]` | 应用于所有CRUD路由的中间件数组 | 否 |
|
|
| `middleware` | `any[]` | 应用于所有CRUD路由的中间件数组 | 否 |
|
|
|
|
|
|
|
|
### 2.3 生成的路由
|
|
### 2.3 生成的路由
|
|
@@ -97,9 +99,9 @@ export default yourEntityRoutes;
|
|
|
|
|
|
|
|
| 方法 | 路径 | 描述 |
|
|
| 方法 | 路径 | 描述 |
|
|
|
|------|------|------|
|
|
|------|------|------|
|
|
|
-| GET | `/` | 获取实体列表(支持分页、搜索、排序) |
|
|
|
|
|
|
|
+| GET | `/` | 获取实体列表(支持分页、搜索、排序、关联查询) |
|
|
|
| POST | `/` | 创建新实体 |
|
|
| POST | `/` | 创建新实体 |
|
|
|
-| GET | `/{id}` | 获取单个实体详情 |
|
|
|
|
|
|
|
+| GET | `/{id}` | 获取单个实体详情(支持关联查询) |
|
|
|
| PUT | `/{id}` | 更新实体 |
|
|
| PUT | `/{id}` | 更新实体 |
|
|
|
| DELETE | `/{id}` | 删除实体 |
|
|
| DELETE | `/{id}` | 删除实体 |
|
|
|
|
|
|
|
@@ -129,8 +131,9 @@ api.route('/api/v1/your-entities', yourEntityRoutes);
|
|
|
|
|
|
|
|
```typescript
|
|
```typescript
|
|
|
// your-entity.entity.ts
|
|
// your-entity.entity.ts
|
|
|
-import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
|
|
|
|
|
|
+import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany } from 'typeorm';
|
|
|
import { z } from '@hono/zod-openapi';
|
|
import { z } from '@hono/zod-openapi';
|
|
|
|
|
+import { RelatedEntity } from './related-entity.entity';
|
|
|
|
|
|
|
|
@Entity('your_entity')
|
|
@Entity('your_entity')
|
|
|
export class YourEntity {
|
|
export class YourEntity {
|
|
@@ -140,6 +143,9 @@ export class YourEntity {
|
|
|
@Column({ name: 'name', type: 'varchar', length: 255 })
|
|
@Column({ name: 'name', type: 'varchar', length: 255 })
|
|
|
name!: string;
|
|
name!: string;
|
|
|
|
|
|
|
|
|
|
+ @ManyToOne(() => RelatedEntity, related => related.yourEntities)
|
|
|
|
|
+ relatedEntity!: RelatedEntity;
|
|
|
|
|
+
|
|
|
// 其他字段...
|
|
// 其他字段...
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -147,16 +153,19 @@ export class YourEntity {
|
|
|
export const YourEntitySchema = z.object({
|
|
export const YourEntitySchema = z.object({
|
|
|
id: z.number().int().positive().openapi({ description: '实体ID' }),
|
|
id: z.number().int().positive().openapi({ description: '实体ID' }),
|
|
|
name: z.string().max(255).openapi({ description: '名称', example: '示例名称' }),
|
|
name: z.string().max(255).openapi({ description: '名称', example: '示例名称' }),
|
|
|
|
|
+ relatedEntity: RelatedEntitySchema, // 关联实体schema
|
|
|
// 其他字段schema...
|
|
// 其他字段schema...
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
export const CreateYourEntityDto = z.object({
|
|
export const CreateYourEntityDto = z.object({
|
|
|
name: z.string().max(255).openapi({ description: '名称', example: '示例名称' }),
|
|
name: z.string().max(255).openapi({ description: '名称', example: '示例名称' }),
|
|
|
|
|
+ relatedEntityId: z.number().int().positive().openapi({ description: '关联实体ID', example: 1 }),
|
|
|
// 其他创建字段schema...
|
|
// 其他创建字段schema...
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
export const UpdateYourEntityDto = z.object({
|
|
export const UpdateYourEntityDto = z.object({
|
|
|
name: z.string().max(255).optional().openapi({ description: '名称', example: '示例名称' }),
|
|
name: z.string().max(255).optional().openapi({ description: '名称', example: '示例名称' }),
|
|
|
|
|
+ relatedEntityId: z.number().int().positive().optional().openapi({ description: '关联实体ID', example: 1 }),
|
|
|
// 其他更新字段schema...
|
|
// 其他更新字段schema...
|
|
|
});
|
|
});
|
|
|
```
|
|
```
|
|
@@ -249,4 +258,5 @@ export class YourEntityService extends GenericCrudService<YourEntity> {
|
|
|
4. **数据验证**:确保Zod schema包含完整的验证规则和OpenAPI元数据
|
|
4. **数据验证**:确保Zod schema包含完整的验证规则和OpenAPI元数据
|
|
|
5. **搜索优化**:合理设置`searchFields`,避免在大表的文本字段上进行模糊搜索
|
|
5. **搜索优化**:合理设置`searchFields`,避免在大表的文本字段上进行模糊搜索
|
|
|
6. **分页处理**:所有列表接口必须支持分页,避免返回大量数据
|
|
6. **分页处理**:所有列表接口必须支持分页,避免返回大量数据
|
|
|
-7. **事务管理**:复杂操作应使用事务确保数据一致性
|
|
|
|
|
|
|
+7. **关联查询**:使用`relations`配置时,避免过度关联导致性能问题
|
|
|
|
|
+8. **事务管理**:复杂操作应使用事务确保数据一致性
|