import { Injectable } from '@nestjs/common'; import { BaseService } from '../base/base.service'; import { UserProfile, db, ObjectType, Prisma, VisitType } from '@nice/common'; import EventBus from '@server/utils/event-bus'; @Injectable() export class VisitService extends BaseService { constructor() { super(db, ObjectType.VISIT); } async create(args: Prisma.VisitCreateArgs, staff?: UserProfile) { const { postId, messageId } = args.data; const clientIp = (args.data.meta as any)?.ip; const visitorId = args.data.visitorId || staff?.id; let result; const existingVisit = await db.visit.findFirst({ where: { type: args.data.type, OR: [ { AND: [ { OR: [{ postId }, { messageId }] }, { visitorId: visitorId || null }, ], }, { AND: [ { OR: [{ postId }, { messageId }] }, { visitorId: null }, { meta: { path: ['ip'], equals: clientIp } }, ], }, ], }, }); if (!existingVisit) { result = await super.create(args); } else if (args.data.type === VisitType.READED) { result = await super.update({ where: { id: existingVisit.id }, data: { ...args.data, views: existingVisit.views + 1, }, }); } else if (args.data.type === VisitType.LIKE) { if (!visitorId && existingVisit) { const thirtyMinutesAgo = new Date(Date.now() - 30 * 60 * 1000); if (existingVisit.updatedAt < thirtyMinutesAgo) { // 如果上次更新时间超过30分钟,增加view计数 result = await super.update({ where: { id: existingVisit.id }, data: { ...args.data, views: existingVisit.views + 1, }, }); } } } if (postId) { if (visitorId) { EventBus.emit('updatePostState', { id: postId, }); } if (args.data.type === VisitType.READED) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: postId, visitType: VisitType.READED, }); } if (args.data.type === VisitType.LIKE) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: postId, visitType: VisitType.LIKE, }); } if (args.data.type === VisitType.HATE) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: postId, visitType: VisitType.HATE, }); } } return result; } async createMany(args: Prisma.VisitCreateManyArgs, staff?: UserProfile) { const data = Array.isArray(args.data) ? args.data : [args.data]; const updatePromises: any[] = []; const createData: Prisma.VisitCreateManyInput[] = []; await Promise.all( data.map(async (item) => { if (staff && !item.visitorId) item.visitorId = staff.id; const { postId, messageId, visitorId } = item; const existingVisit = await db.visit.findFirst({ where: { visitorId, OR: [{ postId }, { messageId }], }, }); if (existingVisit) { updatePromises.push( super.update({ where: { id: existingVisit.id }, data: { ...item, views: existingVisit.views + 1, }, }), ); } else { createData.push(item); } }), ); // Execute all updates in parallel await Promise.all(updatePromises); // Create new visits for those not existing if (createData.length > 0) { return super.createMany({ ...args, data: createData, }); } return { count: updatePromises.length }; // Return the number of updates if no new creates } async deleteMany(args: Prisma.VisitDeleteManyArgs, staff?: UserProfile) { // const where = Array.isArray(args.where) ? args.where : [args.where]; // const updatePromises: any[] = []; // const createData: Prisma.VisitCreateManyInput[] = []; // super // await Promise.all( // data.map(async (item) => { // if (staff && !item.visitorId) item.visitorId = staff.id; // const { postId, messageId, visitorId } = item; // const existingVisit = await db.visit.findFirst({ // where: { // visitorId, // OR: [{ postId }, { messageId }], // }, // }); // if (existingVisit) { // updatePromises.push( // super.update({ // where: { id: existingVisit.id }, // data: { // ...item, // views: existingVisit.views + 1, // }, // }), // ); // } else { // createData.push(item); // } // }), // ); // // Execute all updates in parallel // await Promise.all(updatePromises); // // Create new visits for those not existing // if (createData.length > 0) { // return super.createMany({ // ...args, // data: createData, // }); // } // return { count: updatePromises.length }; // Return the number of updates if no new creates const superDetele = super.deleteMany(args, staff); if (args?.where?.postId) { if (args.where.type === VisitType.READED) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: args?.where?.postId as string, visitType: VisitType.READED, }); } if (args.where.type === VisitType.LIKE) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: args?.where?.postId as string, visitType: VisitType.LIKE, }); } if (args.where.type === VisitType.HATE) { EventBus.emit('updateVisitCount', { objectType: ObjectType.POST, id: args?.where?.postId as string, visitType: VisitType.HATE, }); } } return superDetele; } }