From 4b8653080efd796c7e610b29b4e5850d01339a72 Mon Sep 17 00:00:00 2001 From: wangdl Date: Fri, 5 Jun 2026 20:12:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20#67=20GET=20/activity/trend=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20dailySeries=20=E6=97=B6=E9=97=B4=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 返回格式新增 dailySeries 字段 [{date, value, label}],支持 iOS 折线图/柱状图渲染。 数据来源:按日聚合 LearningActivity.durationSeconds。 Co-Authored-By: Claude Opus 4.7 --- .../prompts/schemas/learning-trend.schema.ts | 8 ++++++ .../learning-activity.service.ts | 27 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/modules/ai/prompts/schemas/learning-trend.schema.ts b/src/modules/ai/prompts/schemas/learning-trend.schema.ts index 0ddc93e..6f7cabc 100644 --- a/src/modules/ai/prompts/schemas/learning-trend.schema.ts +++ b/src/modules/ai/prompts/schemas/learning-trend.schema.ts @@ -8,6 +8,12 @@ export const TrendItemSchema = z.object({ detail: z.string().max(500), }); +export const DailySeriesItemSchema = z.object({ + date: z.string(), + value: z.number(), + label: z.string(), +}); + export const LearningTrendResultSchema = z.object({ periodSummary: z.string().min(1).max(2000), overallScore: z.number().int().min(0).max(100), @@ -17,9 +23,11 @@ export const LearningTrendResultSchema = z.object({ weaknesses: z.array(z.string().max(500)).max(10).default([]), recommendations: z.array(z.string().max(500)).max(10).default([]), nextFocusAreas: z.array(z.string().max(200)).max(5).default([]), + dailySeries: z.array(DailySeriesItemSchema).default([]), }); export type LearningTrendResult = z.infer; +export type DailySeriesItem = z.infer; export const LEARNING_TREND_OUTPUT_SCHEMA_DESC = `{ "periodSummary": "过去7天,你的学习时长为320分钟,完成了45次主动回忆和120张复习卡片。整体掌握水平有所提升。", diff --git a/src/modules/learning-activity/learning-activity.service.ts b/src/modules/learning-activity/learning-activity.service.ts index 359c497..f927180 100644 --- a/src/modules/learning-activity/learning-activity.service.ts +++ b/src/modules/learning-activity/learning-activity.service.ts @@ -66,6 +66,9 @@ export class LearningActivityService { const prevTotalMinutes = Math.round(sum(previous, 'durationSeconds') / 60); + // Build daily time-series for chart rendering + const dailySeries = this.buildDailySeries(recent, periodDays); + const trendInput = { userId, periodDays, @@ -86,6 +89,28 @@ export class LearningActivityService { } : undefined, }; - return this.trendWorkflow.execute(trendInput); + const aiResult = await this.trendWorkflow.execute(trendInput); + return { ...aiResult, dailySeries }; + } + + private buildDailySeries(activities: any[], days: number) { + const series: { date: string; value: number; label: string }[] = []; + const now = new Date(); + for (let i = days - 1; i >= 0; i--) { + const d = new Date(now); + d.setDate(d.getDate() - i); + const dateStr = d.toISOString().split('T')[0]; + const dayActs = activities.filter((a) => { + const ad = a.activityDate instanceof Date ? a.activityDate : new Date(a.activityDate); + return ad.toISOString().split('T')[0] === dateStr; + }); + const minutes = Math.round(dayActs.reduce((s: number, a: any) => s + a.durationSeconds, 0) / 60); + series.push({ + date: dateStr, + value: minutes, + label: `${minutes}分钟`, + }); + } + return series; } }