import { PrismaService } from '../prisma/prisma.service.js'; import { getRequestContext } from './context/request-context.js'; /** * 软删时需「改名回收」唯一键的模型映射:modelName → 唯一字段及其列长。 * 目的:软删只置 deletedAt 不释放 @@unique,重建同名会 P2002;删除时把唯一字段改名 * 成「原值(截断) + #id」释放唯一键,展示名字段(name/label)保持不变。 */ const RECYCLE_FIELDS: Record = { user: { field: 'username', maxLen: 64 }, role: { field: 'code', maxLen: 64 }, resource: { field: 'code', maxLen: 128 }, org: { field: 'code', maxLen: 64 }, dictType: { field: 'code', maxLen: 64 }, dictItem: { field: 'value', maxLen: 64 }, config: { field: 'key', maxLen: 128 }, }; /** * 通用 CRUD 基类:封装分页/创建/更新/软删。 * 创建时自动注入 tenantCode(Tenant 模型除外);软删由子类按需调用 softRemove。 */ export class BaseCrudService { constructor( protected readonly prisma: PrismaService, private readonly modelName: string, ) {} protected db(): any { return (this.prisma.client as any)[this.modelName]; } async paginate( page = 1, pageSize = 20, where: Record = {}, orderBy: Record = { createdAt: 'desc' }, ) { const [list, total] = await Promise.all([ this.db().findMany({ where, skip: (page - 1) * pageSize, take: pageSize, orderBy }), this.db().count({ where }), ]); return { list, total, page, pageSize }; } async list(where: Record = {}, orderBy?: Record) { return this.db().findMany({ where, orderBy }); } async findById(id: string) { return this.db().findUnique({ where: { id } }); } async create(data: Record) { const ctx = getRequestContext(); if (ctx && this.modelName !== 'Tenant') data.tenantCode = ctx.tenantCode; return this.db().create({ data }); } async update(id: string, data: Record) { return this.db().update({ where: { id }, data }); } async softRemove(id: string) { const recycle = RECYCLE_FIELDS[this.modelName]; if (!recycle) { return this.db().update({ where: { id }, data: { deletedAt: new Date() } }); } // 先读原值,改名回收唯一键,再软删 const record = await this.findById(id); const original = record?.[recycle.field]; if (original == null) { return this.db().update({ where: { id }, data: { deletedAt: new Date() } }); } const suffix = `#${id}`; const recycled = `${String(original).slice(0, recycle.maxLen - suffix.length)}${suffix}`; return this.db().update({ where: { id }, data: { [recycle.field]: recycled, deletedAt: new Date() } }); } }