feat(diet-records): 新增营养成分分析免费使用次数限制

在营养成分分析功能中添加免费使用次数检查和扣减机制,非VIP用户免费次数用尽时将无法使用该功能。分析成功后自动扣减用户免费次数,确保资源合理使用。
This commit is contained in:
richarjiang
2025-10-16 17:17:38 +08:00
parent 66a9e65d9b
commit d89adaf19a

View File

@@ -23,6 +23,7 @@ import { NutritionAnalysisRecordsResponseDto, GetNutritionAnalysisRecordsQueryDt
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
import { CurrentUser } from '../common/decorators/current-user.decorator'; import { CurrentUser } from '../common/decorators/current-user.decorator';
import { AccessTokenPayload } from '../users/services/apple-auth.service'; import { AccessTokenPayload } from '../users/services/apple-auth.service';
import { UsersService } from '../users/users.service';
@ApiTags('diet-records') @ApiTags('diet-records')
@Controller('diet-records') @Controller('diet-records')
@@ -32,6 +33,7 @@ export class DietRecordsController {
constructor( constructor(
private readonly dietRecordsService: DietRecordsService, private readonly dietRecordsService: DietRecordsService,
private readonly nutritionAnalysisService: NutritionAnalysisService, private readonly nutritionAnalysisService: NutritionAnalysisService,
private readonly usersService: UsersService,
) { } ) { }
/** /**
@@ -190,13 +192,30 @@ export class DietRecordsController {
} }
try { try {
// 检查用户免费使用次数
const userUsageCount = await this.usersService.getUserUsageCount(user.sub);
// 如果用户不是VIP且免费次数不足返回错误
if (userUsageCount <= 0) {
this.logger.warn(`营养成分表分析失败 - 用户ID: ${user.sub}, 免费次数不足`);
return NutritionAnalysisResponseDto.createError('免费使用次数已用完,请开通会员获取更多使用次数');
}
// 传递用户ID以便保存分析记录 // 传递用户ID以便保存分析记录
const result = await this.nutritionAnalysisService.analyzeNutritionImage(requestDto.imageUrl, user.sub); const result = await this.nutritionAnalysisService.analyzeNutritionImage(requestDto.imageUrl, user.sub);
this.logger.log(`营养成分表分析完成 - 用户ID: ${user.sub}, 成功: ${result.success}, 营养素数量: ${result.data.length}`); this.logger.log(`营养成分表分析完成 - 用户ID: ${user.sub}, 成功: ${result.success}, 营养素数量: ${result.data.length}`);
// 转换旧的响应格式到新的通用格式 // 如果分析成功,扣减用户免费使用次数
if (result.success) { if (result.success) {
try {
await this.usersService.deductUserUsageCount(user.sub, 1);
this.logger.log(`营养成分表分析成功,已扣减用户免费次数 - 用户ID: ${user.sub}, 剩余次数: ${userUsageCount - 1}`);
} catch (deductError) {
this.logger.error(`扣减用户免费次数失败 - 用户ID: ${user.sub}, 错误: ${deductError instanceof Error ? deductError.message : String(deductError)}`);
// 不影响主流程,继续返回成功结果
}
return NutritionAnalysisResponseDto.createSuccess(result.data, result.message || '分析成功'); return NutritionAnalysisResponseDto.createSuccess(result.data, result.message || '分析成功');
} else { } else {
return NutritionAnalysisResponseDto.createError(result.message || '分析失败'); return NutritionAnalysisResponseDto.createError(result.message || '分析失败');