|
|
@@ -1,37 +1,97 @@
|
|
|
# 新实体创建流程规范
|
|
|
|
|
|
-## 完整开发流程
|
|
|
+## 流程概述
|
|
|
|
|
|
-1. **创建实体**
|
|
|
+实体创建流程分为两种模式,根据业务复杂度选择合适的实现方式:
|
|
|
+
|
|
|
+- **标准通用CRUD**:适用于简单数据模型,使用`GenericCrudService`和`createCrudRoutes`快速生成基础CRUD接口
|
|
|
+- **自定义复杂CRUD**:适用于包含复杂业务逻辑的实体,需要手动实现服务方法和路由处理
|
|
|
+
|
|
|
+## 适用场景选择
|
|
|
+
|
|
|
+| 类型 | 适用场景 | 技术选型 |
|
|
|
+|------|----------|----------|
|
|
|
+| 标准通用CRUD | 简单数据管理、无复杂业务逻辑、基础CRUD操作 | `GenericCrudService` + `createCrudRoutes` |
|
|
|
+| 自定义复杂CRUD | 复杂业务规则、多表关联操作、特殊权限控制、非标准数据处理 | 自定义Service + 手动路由实现 |
|
|
|
+
|
|
|
+## 标准通用CRUD开发流程
|
|
|
+
|
|
|
+### 1. **创建实体**
|
|
|
- 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
|
|
|
- 参考已有实体文件如`user.entity.ts`
|
|
|
- 注意: 必须包含Zod Schema定义
|
|
|
|
|
|
-2. **创建Service**
|
|
|
+### 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
|
|
|
- - 使用实体Schema进行输入输出验证
|
|
|
+ ```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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ```
|
|
|
|
|
|
-3. **创建API路由**
|
|
|
- - 目录结构:
|
|
|
- ```
|
|
|
- src/server/api/[实体名]/
|
|
|
- ├── get.ts # 列表
|
|
|
- ├── post.ts # 创建
|
|
|
- ├── [id]/
|
|
|
- │ ├── get.ts # 详情
|
|
|
- │ ├── put.ts # 更新
|
|
|
- │ └── delete.ts # 删除
|
|
|
- └── index.ts # 路由聚合
|
|
|
+### 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;
|
|
|
```
|
|
|
- - 必须使用实体Schema作为请求/响应Schema
|
|
|
- - 参考`users`模块的实现
|
|
|
|
|
|
-4. **注册路由**
|
|
|
- - 在`src/server/api.ts`中添加路由注册
|
|
|
+### 5. **注册路由**
|
|
|
+ - 在`src/server/api.ts`中添加路由注册:
|
|
|
+ ```typescript
|
|
|
+ import yourEntityRoutes from '@/server/api/your-entity/index';
|
|
|
+
|
|
|
+ // 注册路由
|
|
|
+ api.route('/api/v1/your-entities', yourEntityRoutes);
|
|
|
+ ```
|
|
|
|
|
|
-5. **创建客户端API**
|
|
|
- - 在`src/client/api.ts`中添加客户端定义
|
|
|
+### 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,
|
|
|
+ }).your-entities;
|
|
|
+ ```
|
|
|
|
|
|
6. **前端调用**
|
|
|
- 在页面组件(如`pages_users.tsx`)中:
|
|
|
@@ -43,6 +103,421 @@
|
|
|
type CreateRequest = InferRequestType<typeof entityClient.$post>['json'];
|
|
|
```
|
|
|
|
|
|
+## 自定义复杂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';
|
|
|
+ import { axiosFetch } from '@/client/utils/fetch';
|
|
|
+
|
|
|
+ export const yourEntityClient = hc<YourEntityRoutes>('/api/v1', {
|
|
|
+ fetch: axiosFetch,
|
|
|
+ }).your_entities; // 注意: 路由路径中的连字符会转为下划线
|
|
|
+
|
|
|
+ // 类型提取
|
|
|
+ import type { InferRequestType, InferResponseType } from 'hono/client';
|
|
|
+
|
|
|
+ // 列表查询
|
|
|
+ export type YourEntityListQuery = InferRequestType<typeof yourEntityClient.$get>['query'];
|
|
|
+ export type YourEntityListResponse = InferResponseType<typeof yourEntityClient.$get, 200>;
|
|
|
+
|
|
|
+ // 创建实体
|
|
|
+ export type CreateYourEntityRequest = InferRequestType<typeof yourEntityClient.$post>['json'];
|
|
|
+ export type CreateYourEntityResponse = InferResponseType<typeof yourEntityClient.$post, 200>;
|
|
|
+
|
|
|
+ // 获取单个实体
|
|
|
+ export type GetYourEntityParams = InferRequestType<typeof yourEntityClient[':id']['$get']>['param'];
|
|
|
+ export type GetYourEntityResponse = InferResponseType<typeof yourEntityClient[':id']['$get'], 200>;
|
|
|
+
|
|
|
+ // 更新实体
|
|
|
+ export type UpdateYourEntityParams = InferRequestType<typeof yourEntityClient[':id']['$put']>['param'];
|
|
|
+ export type UpdateYourEntityRequest = InferRequestType<typeof yourEntityClient[':id']['$put']>['json'];
|
|
|
+ export type UpdateYourEntityResponse = InferResponseType<typeof yourEntityClient[':id']['$put'], 200>;
|
|
|
+
|
|
|
+ // 删除实体
|
|
|
+ export type DeleteYourEntityParams = InferRequestType<typeof yourEntityClient[':id']['$delete']>['param'];
|
|
|
+ export type DeleteYourEntityResponse = InferResponseType<typeof yourEntityClient[':id']['$delete'], 200>;
|
|
|
+ ```
|
|
|
+
|
|
|
+### 7. **前端调用示例**
|
|
|
+ - 在页面组件中使用客户端API:
|
|
|
+ ```typescript
|
|
|
+ import { yourEntityClient, type YourEntityListResponse } from '@/client/api';
|
|
|
+ import { useQuery, useMutation, useQueryClient } from 'react-query';
|
|
|
+
|
|
|
+ // 获取列表数据
|
|
|
+ const fetchEntities = async () => {
|
|
|
+ const res = await yourEntityClient.$get({
|
|
|
+ query: { page: 1, pageSize: 10, status: 1 }
|
|
|
+ });
|
|
|
+ if (!res.ok) {
|
|
|
+ const error = await res.json();
|
|
|
+ throw new Error(error.message || '获取数据失败');
|
|
|
+ }
|
|
|
+ return res.json() as Promise<YourEntityListResponse>;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 使用React Query获取数据
|
|
|
+ export function useEntitiesData() {
|
|
|
+ return useQuery(['entities'], fetchEntities);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建实体
|
|
|
+ export function useCreateEntity() {
|
|
|
+ const queryClient = useQueryClient();
|
|
|
+ return useMutation(
|
|
|
+ (data) => yourEntityClient.$post({ json: data }),
|
|
|
+ {
|
|
|
+ onSuccess: () => {
|
|
|
+ queryClient.invalidateQueries(['entities']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ ```
|
|
|
+
|
|
|
## 注意事项
|
|
|
|
|
|
1. 实体Schema必须在实体文件中定义,路由中直接引用,不要重复定义
|