import { ReadingPersona } from '@main/db/entities/ReadingPersona' import { router, t } from '@rpc/index' import { entityToUserReadingPersona, PersonaService } from '@main/services/persona.service' import { ReadingReflectionTaskBatch } from '@main/db/entities/ReadingReflectionTaskBatch' import { ReadingReflectionTaskItem } from '@main/db/entities/ReadingReflectionTaskItem' import { z } from 'zod' export const personaRouter = router({ /** * 获取用户画像:直接从数据库读取缓存结果,极快 * */ getUserPersona: t.procedure.query(async ({ ctx }) => { const entity = await ctx.db.getRepository(ReadingPersona).findOneBy({ id: 'current_user_persona' }) if (!entity) return null // 将数据库扁平实体映射为前端需要的结构化 IUserReadingPersona return entityToUserReadingPersona(entity) }), /** * 刷新用户画像 * */ forceRefreshUserPersona: t.procedure.mutation(async ({ ctx }) => { const items = await ctx.db .getRepository(ReadingReflectionTaskItem) .find({ where: { status: 'COMPLETED' } }) const batches = await ctx.db.getRepository(ReadingReflectionTaskBatch).find() const personaService = new PersonaService(ctx.db.getRepository(ReadingPersona)) return await personaService.refreshPersona(items, batches) }), /** * 聚合统计:从数据库中聚合数据并计算画像分值 * */ getContributionData: t.procedure.query(async ({ ctx }) => { const itemRepo = ctx.db.getRepository(ReadingReflectionTaskItem) // 关键:关联 batch 获取时间,并强制格式化为 YYYY-MM-DD const rawData = await itemRepo .createQueryBuilder('item') .leftJoin('reading_reflection_task_batches', 'batch', 'item.batchId = batch.id') .select("strftime('%Y-%m-%d', batch.createdAt)", 'date') .addSelect('COUNT(item.id)', 'count') .where("item.status = 'COMPLETED'") .groupBy('date') .getRawMany() return rawData as { date: string; count: number }[] }), /** * 获取指定日期的心得 * */ getReflectionsByDate: t.procedure .input(z.object({ date: z.string() })) .query(async ({ ctx, input }) => { const repo = ctx.db.getRepository(ReadingReflectionTaskItem) // 关键修正:必须在 batch 表上进行日期过滤 return await repo .createQueryBuilder('item') // 这里的 'batchId' 必须是你数据库中 item 表关联 batch 的实际外键列名 .leftJoinAndSelect('reading_reflection_task_batches', 'batch', 'item.batchId = batch.id') .where('date(batch.createdAt) = :date', { date: input.date }) .andWhere("item.status = 'COMPLETED'") .getMany() }) })