import { DataSource, Repository, ObjectLiteral, DeepPartial } from 'typeorm'; import { z } from '@hono/zod-openapi'; export abstract class GenericCrudService { protected repository: Repository; constructor( protected dataSource: DataSource, protected entity: new () => T ) { this.repository = this.dataSource.getRepository(entity); } /** * 获取分页列表 */ /** * 获取分页列表,支持高级查询 */ async getList( page: number = 1, pageSize: number = 10, keyword?: string, searchFields?: string[], where?: Partial, relations: string[] = [], order: { [P in keyof T]?: 'ASC' | 'DESC' } = {} ): Promise<[T[], number]> { const skip = (page - 1) * pageSize; const query = this.repository.createQueryBuilder('entity'); // 关联查询 if (relations.length > 0) { relations.forEach(relation => { query.leftJoinAndSelect(`entity.${relation}`, relation); }); } // 关键词搜索 if (keyword && searchFields && searchFields.length > 0) { query.andWhere(searchFields.map(field => `entity.${field} LIKE :keyword`).join(' OR '), { keyword: `%${keyword}%` }); } // 条件查询 if (where) { Object.entries(where).forEach(([key, value]) => { if (value !== undefined && value !== null) { query.andWhere(`entity.${key} = :${key}`, { [key]: value }); } }); } // 排序 Object.entries(order).forEach(([key, direction]) => { query.orderBy(`entity.${key}`, direction); }); return query.skip(skip).take(pageSize).getManyAndCount(); } /** * 高级查询方法 */ createQueryBuilder(alias: string = 'entity') { return this.repository.createQueryBuilder(alias); } /** * 根据ID获取单个实体 */ async getById(id: number): Promise { return this.repository.findOneBy({ id } as any); } /** * 创建实体 */ async create(data: DeepPartial): Promise { const entity = this.repository.create(data as DeepPartial); return this.repository.save(entity); } /** * 更新实体 */ async update(id: number, data: Partial): Promise { await this.repository.update(id, data); return this.getById(id); } /** * 删除实体 */ async delete(id: number): Promise { const result = await this.repository.delete(id); return result.affected === 1; } } export type CrudOptions = { entity: new () => T; createSchema: z.ZodSchema; updateSchema: z.ZodSchema; getSchema: z.ZodSchema; listSchema: z.ZodSchema; searchFields?: string[]; middleware?: any[]; };