diff --git a/src/rpc/router/persona.router.ts b/src/rpc/router/persona.router.ts
index a4c5a9c..8baf7c5 100644
--- a/src/rpc/router/persona.router.ts
+++ b/src/rpc/router/persona.router.ts
@@ -3,9 +3,12 @@ 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'
@@ -17,7 +20,9 @@ export const personaRouter = router({
return entityToUserReadingPersona(entity)
}),
- // 手动强制重新刷新画像
+ /**
+ * 刷新用户画像
+ * */
forceRefreshUserPersona: t.procedure.mutation(async ({ ctx }) => {
const items = await ctx.db
.getRepository(ReadingReflectionTaskItem)
@@ -26,5 +31,41 @@ export const personaRouter = router({
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()
+ })
})
diff --git a/src/shared/types/IUserReadingPersona.ts b/src/shared/types/IUserReadingPersona.ts
index 84cb67e..6a4a4d9 100644
--- a/src/shared/types/IUserReadingPersona.ts
+++ b/src/shared/types/IUserReadingPersona.ts
@@ -34,3 +34,12 @@ export interface IUserReadingPersona {
mostUsedOccupation: string // 最常使用的阅读者身份
}
}
+
+/**
+ * 每日阅读贡献统计模型
+ * */
+export interface IContributionDay {
+ date: string
+ count: number
+ level: number
+}