fix: sessionsCount 修复 + 手动会话结束更新 DailyLearningActivity
- upsertFromReadingEvent 加 isNewSession 参数,material_opened 时 increment sessionsCount - LearningSessionService.end() 调用 incrementDailySessions 更新日活会话计数 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c97b58fc5f
commit
d23b9953ec
@ -27,9 +27,10 @@ export class LearningActivityRepository {
|
||||
activeSecondsDelta: number;
|
||||
isNewMaterial?: boolean;
|
||||
isMarkedRead?: boolean;
|
||||
isNewSession?: boolean;
|
||||
}) {
|
||||
const activityDate = this.computeActivityDate(data.clientTimestampMs, data.clientTimezoneOffsetMinutes);
|
||||
const { userId, activeSecondsDelta, isNewMaterial, isMarkedRead } = data;
|
||||
const { userId, activeSecondsDelta, isNewMaterial, isMarkedRead, isNewSession } = data;
|
||||
|
||||
return tx.dailyLearningActivity.upsert({
|
||||
where: { userId_activityDate: { userId, activityDate } },
|
||||
@ -40,16 +41,28 @@ export class LearningActivityRepository {
|
||||
readingSeconds: activeSecondsDelta,
|
||||
materialsReadCount: isNewMaterial ? 1 : 0,
|
||||
markedReadCount: isMarkedRead ? 1 : 0,
|
||||
sessionsCount: isNewSession ? 1 : 0,
|
||||
},
|
||||
update: {
|
||||
durationSeconds: { increment: activeSecondsDelta },
|
||||
readingSeconds: { increment: activeSecondsDelta },
|
||||
materialsReadCount: isNewMaterial ? { increment: 1 } : undefined,
|
||||
markedReadCount: isMarkedRead ? { increment: 1 } : undefined,
|
||||
sessionsCount: isNewSession ? { increment: 1 } : undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Increment sessionsCount for a given day (called from manual session end). */
|
||||
async incrementDailySessions(userId: string, activityDate: Date) {
|
||||
const date = new Date(Date.UTC(activityDate.getUTCFullYear(), activityDate.getUTCMonth(), activityDate.getUTCDate()));
|
||||
return this.prisma.dailyLearningActivity.upsert({
|
||||
where: { userId_activityDate: { userId, activityDate: date } },
|
||||
create: { userId, activityDate: date, sessionsCount: 1 },
|
||||
update: { sessionsCount: { increment: 1 } },
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
/** Compute local date from timestamp and timezone offset. */
|
||||
private computeActivityDate(timestampMs: bigint, offsetMinutes: number | null): Date {
|
||||
const offsetMs = (offsetMinutes ?? 0) * 60 * 1000;
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { LearningSessionRepository } from './learning-session.repository';
|
||||
import { LearningActivityRepository } from '../learning-activity/learning-activity.repository';
|
||||
|
||||
@Injectable()
|
||||
export class LearningSessionService {
|
||||
constructor(private readonly repository: LearningSessionRepository) {}
|
||||
constructor(
|
||||
private readonly repository: LearningSessionRepository,
|
||||
private readonly activityRepo: LearningActivityRepository,
|
||||
) {}
|
||||
|
||||
async start(userId: string, dto: any) {
|
||||
return this.repository.create(userId, dto);
|
||||
@ -12,6 +16,10 @@ export class LearningSessionService {
|
||||
async end(id: string) {
|
||||
const session = await this.repository.end(id);
|
||||
if (!session) throw new NotFoundException('会话不存在');
|
||||
// 更新 DailyLearningActivity 的会话计数
|
||||
if (session.userId) {
|
||||
this.activityRepo.incrementDailySessions(session.userId, session.startedAt ?? new Date());
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
@ -148,6 +148,7 @@ export class ReadingEventProcessorService {
|
||||
activeSecondsDelta: validated.activeSecondsDelta,
|
||||
isNewMaterial: validated.eventType === 'material_opened',
|
||||
isMarkedRead: validated.eventType === 'marked_as_read',
|
||||
isNewSession: validated.eventType === 'material_opened',
|
||||
});
|
||||
|
||||
// 5d. Write LearningRecord (first open / closed / marked read)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user