feat:新增活动日志模块,包括控制器、服务、模型及数据传输对象,更新应用模块以引入新模块,并在打卡和训练计划模块中集成活动日志记录功能。

This commit is contained in:
richarjiang
2025-08-14 15:43:29 +08:00
parent 24924e5d81
commit bc8a52852d
15 changed files with 373 additions and 20 deletions

View File

@@ -31,6 +31,8 @@ import { RestorePurchaseDto, RestorePurchaseResponseDto, RestoredPurchaseInfo, A
import { PurchaseRestoreLog, RestoreStatus, RestoreSource } from './models/purchase-restore-log.model';
import { BlockedTransaction, BlockReason } from './models/blocked-transaction.model';
import { UserWeightHistory, WeightUpdateSource } from './models/user-weight-history.model';
import { ActivityLogsService } from '../activity-logs/activity-logs.service';
import { ActivityActionType, ActivityEntityType } from '../activity-logs/models/activity-log.model';
const DEFAULT_FREE_USAGE_COUNT = 10;
@@ -57,6 +59,7 @@ export class UsersService {
private userWeightHistoryModel: typeof UserWeightHistory,
@InjectConnection()
private sequelize: Sequelize,
private readonly activityLogsService: ActivityLogsService,
) { }
async getProfile(user: AccessTokenPayload): Promise<UserResponseDto> {
@@ -134,17 +137,23 @@ export class UsersService {
throw new NotFoundException(`ID为${userId}的用户不存在`);
}
const profileChanges: Record<string, any> = {};
const userChanges: Record<string, any> = {};
if (name) {
user.name = name;
userChanges.name = name;
}
if (avatar) {
user.avatar = avatar;
userChanges.avatar = avatar;
}
if (gender) {
user.gender = gender;
userChanges.gender = gender;
}
if (birthDate) {
user.birthDate = dayjs(birthDate * 1000).startOf('day').toDate();
userChanges.birthDate = birthDate;
}
this.logger.log(`updateUser user: ${JSON.stringify(user, null, 2)}`);
@@ -157,9 +166,9 @@ export class UsersService {
where: { userId },
defaults: { userId },
});
if (dailyStepsGoal !== undefined) profile.dailyStepsGoal = dailyStepsGoal as any;
if (dailyCaloriesGoal !== undefined) profile.dailyCaloriesGoal = dailyCaloriesGoal as any;
if (pilatesPurposes !== undefined) profile.pilatesPurposes = pilatesPurposes as any;
if (dailyStepsGoal !== undefined) { profile.dailyStepsGoal = dailyStepsGoal as any; profileChanges.dailyStepsGoal = dailyStepsGoal; }
if (dailyCaloriesGoal !== undefined) { profile.dailyCaloriesGoal = dailyCaloriesGoal as any; profileChanges.dailyCaloriesGoal = dailyCaloriesGoal; }
if (pilatesPurposes !== undefined) { profile.pilatesPurposes = pilatesPurposes as any; profileChanges.pilatesPurposes = pilatesPurposes; }
if (weight !== undefined) {
profile.weight = weight as any;
try {
@@ -167,11 +176,32 @@ export class UsersService {
} catch (e) {
this.logger.error(`记录体重历史失败: ${e instanceof Error ? e.message : String(e)}`);
}
profileChanges.weight = weight;
}
if (height !== undefined) profile.height = height as any;
if (height !== undefined) { profile.height = height as any; profileChanges.height = height; }
await profile.save();
}
// 记录用户基础与扩展信息更新
if (Object.keys(userChanges).length > 0) {
await this.activityLogsService.record({
userId,
entityType: ActivityEntityType.USER,
action: ActivityActionType.UPDATE,
entityId: userId,
changes: userChanges,
});
}
if (Object.keys(profileChanges).length > 0) {
await this.activityLogsService.record({
userId,
entityType: ActivityEntityType.USER_PROFILE,
action: ActivityActionType.UPDATE,
entityId: userId,
changes: profileChanges,
});
}
return {
code: ResponseCode.SUCCESS,
message: 'success',
@@ -190,6 +220,14 @@ export class UsersService {
await profile.save({ transaction: t });
await this.userWeightHistoryModel.create({ userId, weight, source: WeightUpdateSource.Vision }, { transaction: t });
await t.commit();
await this.activityLogsService.record({
userId,
entityType: ActivityEntityType.USER_PROFILE,
action: ActivityActionType.UPDATE,
entityId: userId,
changes: { weight },
metadata: { source: 'vision' },
});
} catch (e) {
await t.rollback();
this.logger.error(`addWeightByVision error: ${e instanceof Error ? e.message : String(e)}`);
@@ -285,6 +323,16 @@ export class UsersService {
} : undefined,
};
// 登录行为也可视为活动(可选,记录创建或登录行为)
await this.activityLogsService.record({
userId,
entityType: ActivityEntityType.USER,
action: ActivityActionType.UPDATE,
entityId: userId,
changes: { lastLogin: user.lastLogin },
metadata: { source: 'appleLogin' },
});
return {
code: ResponseCode.SUCCESS,
message: 'success',
@@ -387,6 +435,16 @@ export class UsersService {
this.logger.log(`用户账号删除成功: ${userId}`);
// 记录删除账户行为
await this.activityLogsService.record({
userId,
entityType: ActivityEntityType.USER,
action: ActivityActionType.DELETE,
entityId: userId,
changes: null,
metadata: { reason: 'deleteAccount' },
});
return {
code: ResponseCode.SUCCESS,
message: '账号删除成功',
@@ -476,6 +534,15 @@ export class UsersService {
} : undefined,
};
await this.activityLogsService.record({
userId: guestUserId,
entityType: ActivityEntityType.USER,
action: ActivityActionType.UPDATE,
entityId: guestUserId,
changes: { lastLogin: user.lastLogin },
metadata: { source: 'guestLogin' },
});
return {
code: ResponseCode.SUCCESS,
message: 'success',