# 自定义复杂CRUD开发流程规范

## 适用场景

适用于包含复杂业务逻辑的实体，需要手动实现服务方法和路由处理的场景，如：
- 复杂业务规则
- 多表关联操作
- 特殊权限控制
- 非标准数据处理

## 开发流程

### 1. **创建实体**
   - 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
   - 定义实体类
   - 示例:
     ```typescript
     import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
     
     @Entity('your_entity')
     export class YourEntity {
       @PrimaryGeneratedColumn({ unsigned: true })
       id!: number;
       
       @Column({ name: 'name', type: 'varchar', length: 255 })
       name!: string;
       
       // 其他业务字段...
     }
     ```


   - 位置: `src/server/modules/[模块名]/[实体名].schema.ts`
   - 定义实体Zod Schema
   - 示例:
     ```typescript
     import { z } from '@hono/zod-openapi';
     
     // Zod Schema定义
     export const YourEntitySchema = z.object({
       id: z.number().int().positive().openapi({ description: '实体ID' }),
       name: z.string().max(255).openapi({ description: '名称', example: '示例名称' })
       // 其他字段Schema...
     });
     
     export const CreateYourEntityDto = z.object({
       name: z.string().max(255).openapi({ description: '名称', example: '示例名称' })
       // 其他创建字段...
     });
     
     export const UpdateYourEntityDto = z.object({
       name: z.string().max(255).optional().openapi({ description: '名称', example: '示例名称' })
       // 其他更新字段...
     });
     ```


### 2. **注册实体到数据源**
   - 在`src/server/data-source.ts`中添加实体导入和注册:
     ```typescript
     // 实体类导入
     import { YourEntity } from "./modules/[模块名]/[实体名].entity"
     
     export const AppDataSource = new DataSource({
       // ...其他配置
       entities: [
         User, Role, YourEntity // 添加新实体到数组
       ],
       // ...其他配置
     });
     ```

### 3. **创建自定义Service**
   - 位置: `src/server/modules/[模块名]/[实体名].service.ts`
   - 实现自定义业务逻辑和数据访问
   - 示例:
     ```typescript
     import { DataSource, Repository } from 'typeorm';
     import { YourEntity } from './your-entity.entity';
     import { CreateYourEntityDto, UpdateYourEntityDto } from './your-entity.entity';
     
     export class YourEntityService {
       private repository: Repository<YourEntity>;
       
       constructor(dataSource: DataSource) {
         this.repository = dataSource.getRepository(YourEntity);
       }
       
       /**
        * 获取实体列表（带复杂过滤条件）
        */
       async findAll(filters: any): Promise<[YourEntity[], number]> {
         const query = this.repository.createQueryBuilder('entity');
         
         // 添加复杂业务过滤逻辑
         if (filters.status) {
           query.andWhere('entity.status = :status', { status: filters.status });
         }
         
         // 多表关联查询示例
         if (filters.includeRelated) {
           query.leftJoinAndSelect('entity.relatedEntity', 'related');
         }
         
         const [items, total] = await query.getManyAndCount();
         return [items, total];
       }
       
       /**
        * 根据ID获取单个实体
        */
       async findById(id: number): Promise<YourEntity> {
         const entity = await this.repository.findOneBy({ id });
         if (!entity) {
           throw new Error('实体不存在');
         }
         return entity;
       }
       
       /**
        * 创建实体（带业务规则验证）
        */
       async create(data: CreateYourEntityDto): Promise<YourEntity> {
         // 业务规则验证示例
         const existing = await this.repository.findOneBy({ name: data.name });
         if (existing) {
           throw new Error('名称已存在');
         }
         
         const entity = this.repository.create(data);
         return this.repository.save(entity);
       }
       
       /**
        * 更新实体（带业务逻辑处理）
        */
       async update(id: number, data: UpdateYourEntityDto): Promise<YourEntity> {
         const entity = await this.findById(id);
         
         // 业务逻辑处理示例
         if (data.name && data.name !== entity.name) {
           // 记录名称变更日志等业务操作
         }
         
         Object.assign(entity, data);
         return this.repository.save(entity);
       }
       
       /**
        * 删除实体（带权限检查）
        */
       async delete(id: number, userId: number): Promise<boolean> {
         const entity = await this.findById(id);
         
         // 权限检查示例
         if (entity.createdBy !== userId) {
           throw new Error('没有删除权限');
         }
         
         await this.repository.remove(entity);
         return true;
       }
       
       /**
        * 自定义业务方法示例
        */
       async customBusinessOperation(params: any): Promise<any> {
         // 实现复杂业务逻辑
         // 可能包含事务、多表操作等
       }
     }
     ```

### 4. **创建自定义API路由**
   - 目录结构:
     ```
     src/server/api/[实体名]/
     ├── get.ts       # 列表查询
     ├── post.ts      # 创建实体
     ├── [id]/
     │   ├── get.ts   # 获取单个实体
     │   ├── put.ts   # 更新实体
     │   └── delete.ts # 删除实体
     └── index.ts     # 路由聚合
     ```
   
   - **列表查询路由示例** (get.ts):
     ```typescript
     import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
     import { z } from 'zod';
     import { YourEntitySchema } from '@/server/modules/your-module/your-entity.entity';
     import { ErrorSchema } from '@/server/utils/errorHandler';
     import { AppDataSource } from '@/server/data-source';
     import { YourEntityService } from '@/server/modules/your-module/your-entity.service';
     import { AuthContext } from '@/server/types/context';
     import { authMiddleware } from '@/server/middleware/auth.middleware';
     
     // 查询参数Schema
     const ListQuery = z.object({
       page: z.coerce.number().int().positive().default(1).openapi({
         description: '页码',
         example: 1
       }),
       pageSize: z.coerce.number().int().positive().default(10).openapi({
         description: '每页条数',
         example: 10
       }),
       status: z.coerce.number().optional().openapi({
         description: '状态过滤',
         example: 1
       })
     });
     
     // 响应Schema
     const ListResponse = z.object({
       data: z.array(YourEntitySchema),
       pagination: z.object({
         total: z.number().openapi({ example: 100, description: '总记录数' }),
         current: z.number().openapi({ example: 1, description: '当前页码' }),
         pageSize: z.number().openapi({ example: 10, description: '每页数量' })
       })
     });
     
     // 路由定义
     const routeDef = createRoute({
       method: 'get',
       path: '/',
       middleware: [authMiddleware],
       request: {
         query: ListQuery
       },
       responses: {
         200: {
           description: '成功获取实体列表',
           content: { 'application/json': { schema: ListResponse } }
         },
         400: {
           description: '请求参数错误',
           content: { 'application/json': { schema: ErrorSchema } }
         },
         500: {
           description: '服务器错误',
           content: { 'application/json': { schema: ErrorSchema } }
         }
       }
     });
     
     // 路由实现
     const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
       try {
         const query = c.req.valid('query');
         const service = new YourEntityService(AppDataSource);
         
         const [data, total] = await service.findAll({
           status: query.status,
           // 其他过滤条件
         });
         
         return c.json({
           data,
           pagination: {
             total,
             current: query.page,
             pageSize: query.pageSize
           }
         }, 200);
       } catch (error) {
         const { code = 500, message = '获取列表失败' } = error as Error & { code?: number };
         return c.json({ code, message }, code);
       }
     });
     
     export default app;
     ```
     
   - **创建实体路由示例** (post.ts):
     ```typescript
     import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
     import { CreateYourEntityDto, YourEntitySchema } from '@/server/modules/your-module/your-entity.entity';
     import { ErrorSchema } from '@/server/utils/errorHandler';
     import { AppDataSource } from '@/server/data-source';
     import { YourEntityService } from '@/server/modules/your-module/your-entity.service';
     import { AuthContext } from '@/server/types/context';
     import { authMiddleware } from '@/server/middleware/auth.middleware';
     
     // 路由定义
     const routeDef = createRoute({
       method: 'post',
       path: '/',
       middleware: [authMiddleware],
       request: {
         body: {
           content: {
             'application/json': { schema: CreateYourEntityDto }
           }
         }
       },
       responses: {
         200: {
           description: '成功创建实体',
           content: { 'application/json': { schema: YourEntitySchema } }
         },
         400: {
           description: '请求参数错误',
           content: { 'application/json': { schema: ErrorSchema } }
         },
         500: {
           description: '服务器错误',
           content: { 'application/json': { schema: ErrorSchema } }
         }
       }
     });
     
     // 路由实现
     const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
       try {
         const data = await c.req.json();
         const service = new YourEntityService(AppDataSource);
         const result = await service.create(data);
         return c.json(result, 200);
       } catch (error) {
         const { code = 500, message = '创建实体失败' } = error as Error & { code?: number };
         return c.json({ code, message }, code);
       }
     });
     
     export default app;
     ```
     
   - **路由聚合示例** (index.ts):
     ```typescript
     import { OpenAPIHono } from '@hono/zod-openapi';
     import listRoute from './get';
     import createRoute from './post';
     import getByIdRoute from './[id]/get';
     import updateRoute from './[id]/put';
     import deleteRoute from './[id]/delete';
     
     const app = new OpenAPIHono()
       .route('/', listRoute)
       .route('/', createRoute)
       .route('/', getByIdRoute)
       .route('/', updateRoute)
       .route('/', deleteRoute);
     
     export default app;
     ```

### 5. **注册路由**
   - 在`src/server/api.ts`中添加路由注册:
     ```typescript
     import yourEntityRoutes from '@/server/api/your-entity/index';
     
     // 注册路由
     api.route('/api/v1/your-entities', yourEntityRoutes);
     ```

### 6. **创建客户端API**
   - 在`src/client/api.ts`中添加客户端定义:
     ```typescript
     import { hc } from 'hono/client';
     import { YourEntityRoutes } from '@/server/api';
     
     export const yourEntityClient = hc<YourEntityRoutes>('/api/v1', {
       fetch: axiosFetch,
     }).api.v1['your-entities'];
     ```

### 7. **前端调用**
    - 在页面组件(如`Users.tsx`)中:
      - 使用`InferResponseType`提取响应类型
      - 使用`InferRequestType`提取请求类型
      - 示例:
        ```typescript
        type EntityResponse = InferResponseType<typeof entityClient.$get, 200>;
        type CreateRequest = InferRequestType<typeof entityClient.$post>['json'];
        ```

### 8. **注册管理后台路由和菜单**
    - **注册路由**：在`src/client/admin/routes.tsx`中添加路由配置
      
    - **注册菜单**：在`src/client/admin/menu.tsx`中添加菜单配置
