using Microsoft.AspNetCore.Authorization; using SqlSugar; using Volo.Abp.Application.Services; using Volo.Abp.Users; using Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics; using Yi.Framework.AiHub.Application.Contracts.IServices; using Yi.Framework.AiHub.Domain.Entities; using Yi.Framework.AiHub.Domain.Entities.Chat; using Yi.Framework.SqlSugarCore.Abstractions; namespace Yi.Framework.AiHub.Application.Services; /// /// 使用量统计服务 /// [Authorize] public class UsageStatisticsService : ApplicationService, IUsageStatisticsService { private readonly ISqlSugarRepository _messageRepository; private readonly ISqlSugarRepository _usageStatisticsRepository; public UsageStatisticsService( ISqlSugarRepository messageRepository, ISqlSugarRepository usageStatisticsRepository) { _messageRepository = messageRepository; _usageStatisticsRepository = usageStatisticsRepository; } /// /// 获取当前用户近7天的Token消耗统计 /// /// 每日Token使用量列表 public async Task> GetLast7DaysTokenUsageAsync() { var userId = CurrentUser.GetId(); var endDate = DateTime.Today; var startDate = endDate.AddDays(-6); // 近7天 // 从Message表统计近7天的token消耗 var dailyUsage = await _messageRepository._DbQueryable .Where(x => x.UserId == userId) .Where(x => x.CreationTime >= startDate && x.CreationTime < endDate.AddDays(1)) .GroupBy(x => x.CreationTime.Date) .Select(g => new { Date = g.CreationTime.Date, Tokens = SqlFunc.AggregateSum(g.TokenUsage.TotalTokenCount) }) .ToListAsync(); // 生成完整的7天数据,包括没有使用记录的日期 var result = new List(); for (int i = 0; i < 7; i++) { var date = startDate.AddDays(i); var usage = dailyUsage.FirstOrDefault(x => x.Date == date); result.Add(new DailyTokenUsageDto { Date = date, Tokens = usage?.Tokens ?? 0 }); } return result.OrderBy(x => x.Date).ToList(); } /// /// 获取当前用户各个模型的Token消耗量及占比 /// /// 模型Token使用量列表 public async Task> GetModelTokenUsageAsync() { var userId = CurrentUser.GetId(); // 从UsageStatistics表获取各模型的token消耗统计 var modelUsages = await _usageStatisticsRepository._DbQueryable .Where(x => x.UserId == userId) .Select(x => new { x.ModelId, x.TotalTokenCount }) .ToListAsync(); if (!modelUsages.Any()) { return new List(); } // 计算总token数 var totalTokens = modelUsages.Sum(x => x.TotalTokenCount); // 计算各模型占比 var result = modelUsages.Select(x => new ModelTokenUsageDto { Model = x.ModelId, Tokens = x.TotalTokenCount, Percentage = totalTokens > 0 ? Math.Round((decimal)x.TotalTokenCount / totalTokens * 100, 2) : 0 }).OrderByDescending(x => x.Tokens).ToList(); return result; } }