import { Injectable } from '@nestjs/common'; import { db, Prisma, UserProfile, Post, RolePerms, ResPerm, ObjectType, PostType, } from '@nice/common'; import { MessageService } from '../message/message.service'; import { BaseService } from '../base/base.service'; import { DepartmentService } from '../department/department.service'; import { setPostRelation, updatePostState } from './utils'; import EventBus, { CrudOperation } from '@server/utils/event-bus'; import { DefaultArgs } from '@prisma/client/runtime/library'; @Injectable() export class PostService extends BaseService { constructor( private readonly messageService: MessageService, private readonly departmentService: DepartmentService, ) { super(db, ObjectType.POST); } onModuleInit() { EventBus.on('updatePostState', ({ id }) => { console.log('updatePostState'); updatePostState(id); }); } async create( args: Prisma.PostCreateArgs, params: { staff?: UserProfile; tx?: Prisma.PostDelegate }, ) { console.log('params?.staff?.id', params?.staff?.id); args.data.authorId = params?.staff?.id; args.data.updatedAt = new Date(); // args.data.resources const result = await super.create(args); await this.updateParentTimestamp(result?.parentId); EventBus.emit('dataChanged', { type: ObjectType.POST, operation: CrudOperation.CREATED, data: result, }); if (args.data.authorId && args?.data?.type === PostType.POST_COMMENT) { EventBus.emit('updatePostState', { id: result?.id, }); } return result; } async update(args: Prisma.PostUpdateArgs, staff?: UserProfile) { args.data.authorId = staff?.id; args.data.updatedAt = new Date(); const result = await super.update(args); EventBus.emit('dataChanged', { type: ObjectType.POST, operation: CrudOperation.UPDATED, data: result, }); return result; } async findFirst( args?: Prisma.PostFindFirstArgs, staff?: UserProfile, clientIp?: string, ) { const transDto = await this.wrapResult( super.findFirst(args), async (result) => { if (result) { await setPostRelation({ data: result, staff, clientIp }); await this.setPerms(result, staff); } return result; }, ); return transDto; } async findManyWithCursor( args: Prisma.PostFindManyArgs, staff?: UserProfile, clientIp?: string, ) { if (!args.where) args.where = {}; args.where.OR = await this.preFilter(args.where.OR, staff); return this.wrapResult(super.findManyWithCursor(args), async (result) => { const { items } = result; await Promise.all( items.map(async (item) => { await setPostRelation({ data: item, staff, clientIp }); await this.setPerms(item, staff); }), ); return { ...result, items }; }); } async findManyWithPagination( args: { page?: number; pageSize?: number; where?: Prisma.PostWhereInput; select?: Prisma.PostSelect; orderBy?: Prisma.PostOrderByWithRelationInput; }, staff?: UserProfile, clientIp?: string, ) { if (!args.where) args.where = {}; args.where.OR = await this.preFilter(args.where.OR, staff); return this.wrapResult( super.findManyWithPagination(args as any), async (result) => { const { items } = result; await Promise.all( items.map(async (item) => { await setPostRelation({ data: item, staff, clientIp }); await this.setPerms(item, staff); }), ); return { ...result, items }; }, ); } protected async setPerms(data: Post, staff?: UserProfile) { if (!staff) return; const perms: ResPerm = { delete: false, }; const isMySelf = data?.authorId === staff?.id; // const isDomain = staff.domainId === data.domainId; const setManagePermissions = (perms: ResPerm) => { Object.assign(perms, { delete: true, // edit: true, }); }; if (isMySelf) { perms.delete = true; // perms.edit = true; } staff.permissions.forEach((permission) => { switch (permission) { case RolePerms.MANAGE_ANY_POST: setManagePermissions(perms); break; // case RolePerms.MANAGE_DOM_POST: // if (isDomain) { // setManagePermissions(perms); // } // break; } }); Object.assign(data, { perms }); } async preFilter(OR?: Prisma.PostWhereInput[], staff?: UserProfile) { const preFilter = (await this.getPostPreFilter(staff)) || []; const outOR = OR ? [...OR, ...preFilter].filter(Boolean) : preFilter; return outOR?.length > 0 ? outOR : undefined; } async getPostPreFilter(staff?: UserProfile) { if (!staff) return; // const { deptId, domainId } = staff; if ( staff.permissions.includes(RolePerms.READ_ANY_POST) || staff.permissions.includes(RolePerms.MANAGE_ANY_POST) ) { return undefined; } const orCondition: Prisma.PostWhereInput[] = [ staff?.id && { authorId: staff.id, }, { isPublic: true, }, staff?.id && { receivers: { some: { id: staff.id, }, }, }, ].filter(Boolean); if (orCondition?.length > 0) return orCondition; return undefined; } /** * 更新父帖子的时间戳 * 当子帖子被创建时,自动更新父帖子的更新时间 * @param parentId 父帖子的ID */ async updateParentTimestamp(parentId: string | undefined) { if (!parentId) { return; } await this.update({ where: { id: parentId, }, data: {}, // 空对象会自动更新 updatedAt 时间戳 }); } }