Explorar el Código

📝 docs(frontend): 优化前端开发文档结构和内容

- 重构admin前端开发流程文档,简化页面组件创建说明
- 统一规范各CRUD文档中的前端调用示例格式
- 补充home前端路由配置说明
- 调整标准CRUD开发流程中的实体创建说明顺序
- 移除重复的代码示例,保留关键指导信息
yourname hace 4 meses
padre
commit
b7604d9050

+ 1 - 427
.roo/rules/11-admin-frontend.md

@@ -7,438 +7,12 @@
 ## 开发流程
 
 ### 1. **创建页面组件**
-   - 位置: `src/client/admin/pages/[EntityName]List.tsx` 和 `src/client/admin/pages/[EntityName]Detail.tsx`
-   - 列表页组件示例:
-     ```tsx
-     import React, { useEffect, useState } from 'react';
-     import { Table, Button, Space, Tag, message } from 'antd';
-     import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
-     import { useNavigate } from 'react-router-dom';
-     import type { InferResponseType } from 'hono/client';
-     import { yourEntityClient } from '@/client/api';
-
-     // 类型定义
-     type EntityItem = InferResponseType<typeof yourEntityClient[':id']['$get'], 200>;
-     type EntityListResponse = InferResponseType<typeof yourEntityClient.$get, 200>;
-
-     const YourEntityList: React.FC = () => {
-       const navigate = useNavigate();
-       const [data, setData] = useState<EntityItem[]>([]);
-       const [loading, setLoading] = useState<boolean>(true);
-       const [pagination, setPagination] = useState({
-         current: 1,
-         pageSize: 10,
-         total: 0
-       });
-
-       // 获取数据列表
-       const fetchData = async () => {
-         try {
-           setLoading(true);
-           const res = await yourEntityClient.$get({
-             query: {
-               page: pagination.current,
-               pageSize: pagination.pageSize
-             }
-           });
-           
-           if (!res.ok) throw new Error('获取数据失败');
-           
-           const result: EntityListResponse = await res.json();
-           setData(result.data);
-           setPagination({
-             ...pagination,
-             total: result.pagination.total
-           });
-         } catch (error) {
-           message.error(error instanceof Error ? error.message : '获取数据失败');
-         } finally {
-           setLoading(false);
-         }
-       };
-
-       useEffect(() => {
-         fetchData();
-       }, [pagination.current, pagination.pageSize]);
-
-       // 分页变化处理
-       const handleTableChange = (pagination: any) => {
-         setPagination({
-           ...pagination,
-           current: pagination.current,
-           pageSize: pagination.pageSize
-         });
-       };
-
-       // 操作按钮处理
-       const handleAdd = () => {
-         navigate('/your-entities/new');
-       };
-
-       const handleEdit = (id: number) => {
-         navigate(`/your-entities/${id}`);
-       };
-
-       const handleDelete = async (id: number) => {
-         try {
-           const res = await yourEntityClient[':id'].$delete({
-             param: { id }
-           });
-           
-           if (!res.ok) throw new Error('删除失败');
-           
-           message.success('删除成功');
-           fetchData();
-         } catch (error) {
-           message.error(error instanceof Error ? error.message : '删除失败');
-         }
-       };
-
-       // 表格列定义
-       const columns = [
-         {
-           title: 'ID',
-           dataIndex: 'id',
-           key: 'id',
-           width: 80
-         },
-         {
-           title: '名称',
-           dataIndex: 'name',
-           key: 'name'
-         },
-         {
-           title: '状态',
-           dataIndex: 'status',
-           key: 'status',
-           render: (status: number) => (
-             <Tag color={status === 1 ? 'green' : 'red'}>
-               {status === 1 ? '启用' : '禁用'}
-             </Tag>
-           )
-         },
-         {
-           title: '操作',
-           key: 'action',
-           render: (_: any, record: EntityItem) => (
-             <Space size="middle">
-               <Button 
-                 type="text" 
-                 icon={<EditOutlined />} 
-                 onClick={() => handleEdit(record.id)}
-               >
-                 编辑
-               </Button>
-               <Button 
-                 type="text" 
-                 danger 
-                 icon={<DeleteOutlined />} 
-                 onClick={() => handleDelete(record.id)}
-               >
-                 删除
-               </Button>
-             </Space>
-           )
-         }
-       ];
-
-       return (
-         <div className="page-container">
-           <div className="page-header">
-             <h2>实体管理</h2>
-             <Button 
-               type="primary" 
-               icon={<PlusOutlined />} 
-               onClick={handleAdd}
-             >
-               添加实体
-             </Button>
-           </div>
-           
-           <Table
-             columns={columns}
-             dataSource={data.map(item => ({ ...item, key: item.id }))}
-             loading={loading}
-             pagination={{
-               current: pagination.current,
-               pageSize: pagination.pageSize,
-               total: pagination.total,
-               showSizeChanger: true,
-               showQuickJumper: true,
-               showTotal: (total) => `共 ${total} 条记录`
-             }}
-             onChange={handleTableChange}
-             bordered
-           />
-         </div>
-       );
-     };
-
-     export default YourEntityList;
-     ```
+   - 位置: `src/client/admin/pages/[EntityName].tsx`
 
 ### 2. **注册路由配置**
    - 位置: `src/client/admin/routes.tsx`
-   - 添加路由配置示例:
-     ```typescript
-     import YourEntityList from './pages/YourEntityList';
-     import YourEntityDetail from './pages/YourEntityDetail';
-     
-     export const routes = [
-       // ...其他路由
-       {
-         path: '/your-entities',
-         element: <YourEntityList />
-       },
-       {
-         path: '/your-entities/:id',
-         element: <YourEntityDetail />
-       },
-       {
-         path: '/your-entities/new',
-         element: <YourEntityDetail isNew={true} />
-       }
-     ];
      ```
 
 ### 3. **添加菜单配置**
    - 位置: `src/client/admin/menu.tsx`
-   - 添加菜单配置示例:
-     ```typescript
-     import { TableOutlined } from '@ant-design/icons';
-     
-     export const menuItems = [
-       // ...其他菜单项
-       {
-         key: 'your-entities',
-         icon: <TableOutlined />,
-         label: '实体管理',
-         path: '/your-entities'
-       }
-     ];
-     ```
-
-### 4. **创建表单组件**
-   - 位置: `src/client/admin/components/[EntityName]Form.tsx`
-   - 表单组件示例:
-     ```tsx
-     import React from 'react';
-     import { Form, Input, Select, message } from 'antd';
-     import type { CreateRequest, UpdateRequest } from '@/client/api/your-entity';
-
-     interface YourEntityFormProps {
-       initialValues?: Partial<CreateRequest>;
-       onFinish: (values: CreateRequest | UpdateRequest) => Promise<void>;
-       loading: boolean;
-     }
-
-     const { Option } = Select;
-
-     const YourEntityForm: React.FC<YourEntityFormProps> = ({
-       initialValues,
-       onFinish,
-       loading
-     }) => {
-       const [form] = Form.useForm();
-
-       // 初始化表单值
-       React.useEffect(() => {
-         if (initialValues) {
-           form.setFieldsValue(initialValues);
-         } else {
-           form.resetFields();
-         }
-       }, [form, initialValues]);
-
-       // 表单提交处理
-       const handleSubmit = async () => {
-         try {
-           const values = await form.validateFields();
-           await onFinish(values);
-         } catch (error) {
-           message.error('表单验证失败,请检查输入内容');
-         }
-       };
-
-       return (
-         <Form
-           form={form}
-           layout="vertical"
-           onFinish={handleSubmit}
-           initialValues={initialValues}
-         >
-           <Form.Item
-             name="name"
-             label="名称"
-             rules={[
-               { required: true, message: '请输入名称' },
-               { max: 20, message: '名称不能超过20个字符' }
-             ]}
-           >
-             <Input placeholder="请输入名称" />
-           </Form.Item>
-
-           <Form.Item
-             name="status"
-             label="状态"
-             rules={[{ required: true, message: '请选择状态' }]}
-           >
-             <Select placeholder="请选择状态">
-               <Option value={1}>启用</Option>
-               <Option value={0}>禁用</Option>
-             </Select>
-           </Form.Item>
-
-           <Form.Item>
-             <button 
-               type="submit" 
-               className="ant-btn ant-btn-primary"
-               disabled={loading}
-             >
-               {loading ? '提交中...' : '提交'}
-             </button>
-           </Form.Item>
-         </Form>
-       );
-     };
-
-     export default YourEntityForm;
-     ```
-
-### 5. **实现详情页**
-   - 位置: `src/client/admin/pages/[EntityName]Detail.tsx`
-   - 详情页组件示例:
-     ```tsx
-     import React, { useEffect, useState } from 'react';
-     import { useParams, useNavigate } from 'react-router-dom';
-     import { Card, Spin, message } from 'antd';
-     import type { InferResponseType, InferRequestType } from 'hono/client';
-     import { yourEntityClient } from '@/client/api';
-     import YourEntityForm from '../components/YourEntityForm';
-
-     // 类型定义
-     type EntityDetail = InferResponseType<typeof yourEntityClient[':id']['$get'], 200>;
-     type CreateRequest = InferRequestType<typeof yourEntityClient.$post>['json'];
-     type UpdateRequest = InferRequestType<typeof yourEntityClient[':id']['$put']>['json'];
-
-     interface YourEntityDetailProps {
-       isNew?: boolean;
-     }
-
-     const YourEntityDetail: React.FC<YourEntityDetailProps> = ({ isNew = false }) => {
-       const { id } = useParams<{ id: string }>();
-       const navigate = useNavigate();
-       const [loading, setLoading] = useState<boolean>(!isNew);
-       const [initialValues, setInitialValues] = useState<Partial<CreateRequest>>({});
-
-       // 获取详情数据
-       const fetchDetail = async () => {
-         if (!id || isNew) return;
-         
-         try {
-           setLoading(true);
-           const res = await yourEntityClient[':id'].$get({
-             param: { id: Number(id) }
-           });
-           
-           if (!res.ok) throw new Error('获取详情失败');
-           
-           const data: EntityDetail = await res.json();
-           setInitialValues(data);
-         } catch (error) {
-           message.error(error instanceof Error ? error.message : '获取详情失败');
-         } finally {
-           setLoading(false);
-         }
-       };
-
-       useEffect(() => {
-         fetchDetail();
-       }, [id, isNew]);
-
-       // 表单提交处理
-       const handleFinish = async (values: CreateRequest | UpdateRequest) => {
-         try {
-           setLoading(true);
-           
-           if (isNew) {
-             // 创建新实体
-             const res = await yourEntityClient.$post({
-               json: values as CreateRequest
-             });
-             
-             if (!res.ok) throw new Error('创建失败');
-             message.success('创建成功');
-           } else if (id) {
-             // 更新实体
-             const res = await yourEntityClient[':id'].$put({
-               param: { id: Number(id) },
-               json: values as UpdateRequest
-             });
-             
-             if (!res.ok) throw new Error('更新失败');
-             message.success('更新成功');
-           }
-           
-           navigate('/your-entities');
-         } catch (error) {
-           message.error(error instanceof Error ? error.message : '操作失败');
-         } finally {
-           setLoading(false);
-         }
-       };
-
-       return (
-         <div className="page-container">
-           <div className="page-header">
-             <h2>{isNew ? '添加实体' : '编辑实体'}</h2>
-           </div>
-           
-           <Card>
-             <Spin spinning={loading}>
-               <YourEntityForm
-                 initialValues={initialValues}
-                 onFinish={handleFinish}
-                 loading={loading}
-               />
-             </Spin>
-           </Card>
-         </div>
-       );
-     };
-
-     export default YourEntityDetail;
-     ```
-
-### 6. **样式规范**
-   - 使用CSS Modules或Styled Components进行样式隔离
-   - 页面容器样式:
-     ```css
-     .page-container {
-       padding: 24px;
-     }
-     
-     .page-header {
-       display: flex;
-       justify-content: space-between;
-       align-items: center;
-       margin-bottom: 24px;
-     }
-     ```
 
-### 7. **权限控制**
-   - 使用ProtectedRoute组件包装需要权限控制的页面:
-     ```tsx
-     import { ProtectedRoute } from '@/client/admin/components/ProtectedRoute';
-     
-     export const routes = [
-       // ...其他路由
-       {
-         path: '/your-entities',
-         element: (
-           <ProtectedRoute requiredPermissions={['your_entity:read']}>
-             <YourEntityList />
-           </ProtectedRoute>
-         )
-       }
-     ];

+ 13 - 4
.roo/rules/11-custom-crud.md

@@ -360,7 +360,16 @@
      ```
 
 ### 7. **前端调用**
-   - 在页面组件中使用类型推断:
-     ```typescript
-     type EntityResponse = InferResponseType<typeof entityClient.$get, 200>;
-     type CreateRequest = InferRequestType<typeof entityClient.$post>['json'];
+    - 在页面组件(如`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`中添加菜单配置

+ 0 - 517
.roo/rules/11-entity-creation.md

@@ -16,525 +16,8 @@
 
 ## 标准通用CRUD开发流程
 
-### 1. **创建实体**
-   - 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
-   - 参考已有实体文件如`user.entity.ts`
-   - 注意: 必须包含Zod Schema定义
-
-### 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`
-   - 继承`GenericCrudService`
-   - 通过构造函数注入DataSource
-   ```typescript
-   import { GenericCrudService } from '@/server/utils/generic-crud.service';
-   import { DataSource } from 'typeorm';
-   import { YourEntity } from './your-entity.entity';
-   
-   export class YourEntityService extends GenericCrudService<YourEntity> {
-     constructor(dataSource: DataSource) {
-       super(dataSource, YourEntity);
-     }
-   }
-   ```
-
-### 4. **创建API路由**
-   - 使用`createCrudRoutes`快速生成CRUD路由:
-     ```typescript
-     import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
-     import { YourEntity } from '@/server/modules/your-module/your-entity.entity';
-     import { YourEntitySchema, CreateYourEntityDto, UpdateYourEntityDto } from '@/server/modules/your-module/your-entity.entity';
-     import { authMiddleware } from '@/server/middleware/auth.middleware';
-     
-     const yourEntityRoutes = createCrudRoutes({
-       entity: YourEntity,
-       createSchema: CreateYourEntityDto,
-       updateSchema: UpdateYourEntityDto,
-       getSchema: YourEntitySchema,
-       listSchema: YourEntitySchema,
-       searchFields: ['name', 'description'], // 可选,指定搜索字段
-       middleware: [authMiddleware] // 可选,添加中间件
-     });
-     
-     export default yourEntityRoutes;
-     ```
-
-### 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. **前端调用**
-   - 在页面组件(如`pages_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`中添加路由配置:
-      ```typescript
-      import YourEntityList from './pages/YourEntityList';
-      import YourEntityDetail from './pages/YourEntityDetail';
-      
-      export const routes = [
-        // ...其他路由
-        {
-          path: '/your-entities',
-          element: <YourEntityList />
-        },
-        {
-          path: '/your-entities/:id',
-          element: <YourEntityDetail />
-        }
-      ];
-      ```
-      
-    - **注册菜单**:在`src/client/admin/menu.tsx`中添加菜单配置:
-      ```typescript
-      import { TableOutlined } from '@ant-design/icons';
-      
-      export const menuItems = [
-        // ...其他菜单项
-        {
-          key: 'your-entities',
-          icon: <TableOutlined />,
-          label: '实体管理',
-          path: '/your-entities'
-        }
-      ];
-      ```
-
-
 ## 自定义复杂CRUD开发流程
 
-当实体需要复杂业务逻辑或非标准CRUD操作时,采用以下完整流程:
-
-### 1. **创建实体**
-   - 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
-   - 定义实体类和Zod Schema
-   - 示例:
-     ```typescript
-     import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
-     import { z } from '@hono/zod-openapi';
-     
-     @Entity('your_entity')
-     export class YourEntity {
-       @PrimaryGeneratedColumn({ unsigned: true })
-       id!: number;
-       
-       @Column({ name: 'name', type: 'varchar', length: 255 })
-       name!: string;
-       
-       // 其他业务字段...
-     }
-     
-     // 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';
-     import { AppError } from '@/server/utils/errorHandler';
-     
-     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 AppError('实体不存在', 404);
-         }
-         return entity;
-       }
-       
-       /**
-        * 创建实体(带业务规则验证)
-        */
-       async create(data: CreateYourEntityDto): Promise<YourEntity> {
-         // 业务规则验证示例
-         const existing = await this.repository.findOneBy({ name: data.name });
-         if (existing) {
-           throw new AppError('名称已存在', 400);
-         }
-         
-         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 AppError('没有删除权限', 403);
-         }
-         
-         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. **前端调用**
-    - 在页面组件(如`pages_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`中添加路由配置:
-      ```typescript
-      import YourEntityList from './pages/YourEntityList';
-      import YourEntityDetail from './pages/YourEntityDetail';
-      
-      export const routes = [
-        // ...其他路由
-        {
-          path: '/your-entities',
-          element: <YourEntityList />
-        },
-        {
-          path: '/your-entities/:id',
-          element: <YourEntityDetail />
-        }
-      ];
-      ```
-      
-    - **注册菜单**:在`src/client/admin/menu.tsx`中添加菜单配置:
-      ```typescript
-      import { TableOutlined } from '@ant-design/icons';
-      
-      export const menuItems = [
-        // ...其他菜单项
-        {
-          key: 'your-entities',
-          icon: <TableOutlined />,
-          label: '实体管理',
-          path: '/your-entities'
-        }
-      ];
-      ```
-
 ## 注意事项
 
 1. 实体Schema必须在实体文件中定义,路由中直接引用,不要重复定义

+ 7 - 0
.roo/rules/11-home-frontend.md

@@ -24,3 +24,10 @@ src/client/home/
     ├── RegisterPage.tsx # 注册页
     └── MemberPage.tsx  # 会员中心
 ```
+
+### 1. **创建页面组件**
+   - 位置: `src/client/home/pages/[PageName].tsx`
+
+### 2. **注册路由配置**
+   - 位置: `src/client/home/routes.tsx`
+     ```

+ 15 - 5
.roo/rules/11-standard-crud.md

@@ -8,8 +8,8 @@
 
 ### 1. **创建实体**
    - 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
-   - 必须包含Zod Schema定义
    - 参考已有实体文件如`user.entity.ts`
+   - 注意: 必须包含Zod Schema定义
 
 ### 2. **注册实体到数据源**
    - 在`src/server/data-source.ts`中添加实体导入和注册:
@@ -84,7 +84,17 @@
      ```
 
 ### 7. **前端调用**
-   - 在页面组件中使用类型推断:
-     ```typescript
-     type EntityResponse = InferResponseType<typeof entityClient.$get, 200>;
-     type CreateRequest = InferRequestType<typeof entityClient.$post>['json'];
+   - 在页面组件(如`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`中添加菜单配置
+