| 版本 | 日期 | 描述 | 作者 |
|---|---|---|---|
| 1.0 | 2025-10-15 | 创建通用 CRUD 规范文档 | Winston |
通用 CRUD(Create, Read, Update, Delete)系统是本项目的核心基础设施,提供类型安全、可扩展的数据操作服务。基于 TypeORM 和 Hono 框架构建,支持自动生成 OpenAPI 文档、关联查询、用户跟踪等高级功能。
GenericCrudService 提供核心 CRUD 操作createCrudRoutes 自动生成 RESTful API 路由位置: packages/server/src/utils/generic-crud.service.ts
核心功能:
主要方法:
// 分页查询
async getList(
page: number = 1,
pageSize: number = 10,
keyword?: string,
searchFields?: string[],
where?: Partial<T>,
relations: string[] = [],
order: { [P in keyof T]?: 'ASC' | 'DESC' } = {},
filters?: { [key: string]: any }
): Promise<[T[], number]>
// 根据ID查询
async getById(id: number, relations: string[] = []): Promise<T | null>
// 创建实体
async create(data: DeepPartial<T>, userId?: string | number): Promise<T>
// 更新实体
async update(id: number, data: Partial<T>, userId?: string | number): Promise<T | null>
// 删除实体
async delete(id: number): Promise<boolean>
位置: packages/server/src/utils/concrete-crud.service.ts
用途: 简化 GenericCrudService 的实例化,自动注入数据源。
使用示例:
const userService = new ConcreteCrudService(User, {
userTracking: { createdByField: 'createdBy', updatedByField: 'updatedBy' }
});
位置: packages/server/src/utils/generic-crud.routes.ts
功能: 自动生成完整的 CRUD 路由,包括:
GET / - 分页列表GET /{id} - 单个实体详情POST / - 创建实体PUT /{id} - 更新实体DELETE /{id} - 删除实体支持特性:
// user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity()
export class User {
/** 用户ID */
@PrimaryGeneratedColumn()
id: number;
/** 用户名,唯一标识 */
@Column({ unique: true, comment: '用户名,唯一标识' })
username: string;
/** 邮箱地址 */
@Column({ nullable: true, comment: '邮箱地址' })
email: string | null;
/** 创建时间 */
@CreateDateColumn({ comment: '创建时间' })
createdAt: Date;
/** 更新时间 */
@UpdateDateColumn({ comment: '更新时间' })
updatedAt: Date;
}
// packages/server/src/share/user.types.ts
export enum UserStatus {
ACTIVE = 'active',
INACTIVE = 'inactive',
SUSPENDED = 'suspended'
}
export enum UserRole {
ADMIN = 'admin',
USER = 'user',
GUEST = 'guest'
}
// 其他共享类型定义...
// user.schema.ts
import { z } from '@hono/zod-openapi';
import { UserStatus, UserRole } from '../../share/user.types';
export const UserCreateSchema = z.object({
username: z.string().min(3).max(50),
email: z.string().email().optional().nullable(),
status: z.nativeEnum(UserStatus).default(UserStatus.ACTIVE),
role: z.nativeEnum(UserRole).default(UserRole.USER)
});
export const UserUpdateSchema = UserCreateSchema.partial();
export const UserGetSchema = z.object({
id: z.number(),
username: z.string(),
email: z.string().email().nullable(),
status: z.nativeEnum(UserStatus),
role: z.nativeEnum(UserRole),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});
export const UserListSchema = UserGetSchema;
// api/users/index.ts
import { createCrudRoutes } from '../../utils/generic-crud.routes';
import { User } from './user.entity';
import {
UserCreateSchema,
UserUpdateSchema,
UserGetSchema,
UserListSchema
} from './user.schema';
export const userRoutes = createCrudRoutes({
entity: User,
createSchema: UserCreateSchema,
updateSchema: UserUpdateSchema,
getSchema: UserGetSchema,
listSchema: UserListSchema,
searchFields: ['username', 'email'],
relations: ['roles'],
middleware: [authMiddleware],
userTracking: {
createdByField: 'createdBy',
updatedByField: 'updatedBy'
}
});
// api/index.ts
import { userRoutes } from './users';
const app = new OpenAPIHono();
app.route('/users', userRoutes);
支持多对多、一对多等关联关系的自动处理:
const roleRoutes = createCrudRoutes({
entity: Role,
// ... schemas
relationFields: {
permissions: {
relationName: 'permissions',
targetEntity: Permission
}
}
});
支持多种筛选方式:
// 精确匹配
filters: '{"status": 1}'
// 范围查询
filters: '{"createdAt": {"gte": "2024-01-01", "lte": "2024-12-31"}}'
// IN 查询
filters: '{"status": [1, 2, 3]}'
// 模糊匹配
filters: '{"name": "%keyword%"}'
支持嵌套关联字段的搜索:
// 搜索用户关联的角色名称
searchFields: ['username', 'roles.name']
// 搜索嵌套关联
searchFields: ['contract.client.name']
comment 配置,说明字段用途createdAt 和 updatedAt 时间戳.optional() 和 .nullable() 明确字段可选性packages/server/src/share/*.types.ts),避免在实体文件中定义,以确保前端可以安全导入class CustomUserService extends ConcreteCrudService<User> {
async createWithValidation(data: UserCreateDto): Promise<User> {
// 自定义验证逻辑
await this.validateUniqueUsername(data.username);
// 调用父类方法
return super.create(data);
}
private async validateUniqueUsername(username: string): Promise<void> {
const existing = await this.repository.findOne({ where: { username } });
if (existing) {
throw new Error('用户名已存在');
}
}
}
const customRoutes = new OpenAPIHono();
// 使用通用 CRUD 路由
customRoutes.route('/', createCrudRoutes(crudOptions));
// 添加自定义路由
customRoutes.post('/bulk-create', async (c) => {
// 自定义批量创建逻辑
});
A: 继承 ConcreteCrudService 并添加自定义方法,或创建独立的业务服务类。
A: 在实体中添加 deletedAt 字段,重写 delete 方法实现软删除逻辑。
A: 使用 relations 参数指定需要的关联关系,避免不必要的关联加载。
A: 创建独立的文件管理服务,或扩展 CRUD 服务添加文件处理逻辑。
文档状态: 正式版 下次评审: 2025-11-15