mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-03-16 06:26:38 +08:00
185 lines
6.9 KiB
C#
185 lines
6.9 KiB
C#
|
|
using Microsoft.AspNetCore.Authorization;
|
|||
|
|
using Microsoft.Extensions.Logging;
|
|||
|
|
using SqlSugar;
|
|||
|
|
using Volo.Abp.Application.Services;
|
|||
|
|
using Volo.Abp.Users;
|
|||
|
|
using Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
|||
|
|
using Yi.Framework.AiHub.Domain.Entities;
|
|||
|
|
using Yi.Framework.AiHub.Domain.Entities.Chat;
|
|||
|
|
using Yi.Framework.AiHub.Domain.Extensions;
|
|||
|
|
using Yi.Framework.AiHub.Domain.Managers;
|
|||
|
|
using Yi.Framework.AiHub.Domain.Shared.Consts;
|
|||
|
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
|||
|
|
|
|||
|
|
namespace Yi.Framework.AiHub.Application.Services;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 每日任务服务
|
|||
|
|
/// </summary>
|
|||
|
|
[Authorize]
|
|||
|
|
public class DailyTaskService : ApplicationService
|
|||
|
|
{
|
|||
|
|
private readonly ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> _dailyTaskRepository;
|
|||
|
|
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
|||
|
|
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
|||
|
|
private readonly ILogger<DailyTaskService> _logger;
|
|||
|
|
|
|||
|
|
// 任务配置
|
|||
|
|
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
|||
|
|
_taskConfigs = new()
|
|||
|
|
{
|
|||
|
|
{ 1, (10000000, 2000000, "尊享包1000w token任务", "累积使用尊享包 1000w token") }, // 1000w消耗 -> 200w奖励
|
|||
|
|
{ 2, (30000000, 4000000, "尊享包3000w token任务", "累积使用尊享包 3000w token") } // 3000w消耗 -> 600w奖励
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
public DailyTaskService(
|
|||
|
|
ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> dailyTaskRepository,
|
|||
|
|
ISqlSugarRepository<MessageAggregateRoot> messageRepository,
|
|||
|
|
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
|
|||
|
|
ILogger<DailyTaskService> logger)
|
|||
|
|
{
|
|||
|
|
_dailyTaskRepository = dailyTaskRepository;
|
|||
|
|
_messageRepository = messageRepository;
|
|||
|
|
_premiumPackageRepository = premiumPackageRepository;
|
|||
|
|
_logger = logger;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取今日任务状态
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public async Task<DailyTaskStatusOutput> GetTodayTaskStatusAsync()
|
|||
|
|
{
|
|||
|
|
var userId = CurrentUser.GetId();
|
|||
|
|
var today = DateTime.Today;
|
|||
|
|
|
|||
|
|
// 1. 统计今日尊享包Token消耗量
|
|||
|
|
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
|||
|
|
|
|||
|
|
// 2. 查询今日已领取的任务
|
|||
|
|
var claimedTasks = await _dailyTaskRepository._DbQueryable
|
|||
|
|
.Where(x => x.UserId == userId && x.TaskDate == today)
|
|||
|
|
.Select(x => new { x.TaskLevel, x.IsRewarded })
|
|||
|
|
.ToListAsync();
|
|||
|
|
|
|||
|
|
// 3. 构建任务列表
|
|||
|
|
var tasks = new List<DailyTaskItem>();
|
|||
|
|
foreach (var (level, config) in _taskConfigs)
|
|||
|
|
{
|
|||
|
|
var claimed = claimedTasks.FirstOrDefault(x => x.TaskLevel == level);
|
|||
|
|
int status;
|
|||
|
|
|
|||
|
|
if (claimed != null && claimed.IsRewarded)
|
|||
|
|
{
|
|||
|
|
status = 2; // 已领取
|
|||
|
|
}
|
|||
|
|
else if (todayConsumed >= config.RequiredTokens)
|
|||
|
|
{
|
|||
|
|
status = 1; // 可领取
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
status = 0; // 未完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var progress = todayConsumed >= config.RequiredTokens
|
|||
|
|
? 100
|
|||
|
|
: Math.Round((decimal)todayConsumed / config.RequiredTokens * 100, 2);
|
|||
|
|
|
|||
|
|
tasks.Add(new DailyTaskItem
|
|||
|
|
{
|
|||
|
|
Level = level,
|
|||
|
|
Name = config.Name,
|
|||
|
|
Description = config.Description,
|
|||
|
|
RequiredTokens = config.RequiredTokens,
|
|||
|
|
RewardTokens = config.RewardTokens,
|
|||
|
|
Status = status,
|
|||
|
|
Progress = progress
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return new DailyTaskStatusOutput
|
|||
|
|
{
|
|||
|
|
TodayConsumedTokens = todayConsumed,
|
|||
|
|
Tasks = tasks
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 领取任务奖励
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="input"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public async Task ClaimTaskRewardAsync(ClaimTaskRewardInput input)
|
|||
|
|
{
|
|||
|
|
var userId = CurrentUser.GetId();
|
|||
|
|
var today = DateTime.Today;
|
|||
|
|
|
|||
|
|
// 1. 验证任务等级
|
|||
|
|
if (!_taskConfigs.TryGetValue(input.TaskLevel, out var taskConfig))
|
|||
|
|
{
|
|||
|
|
throw new UserFriendlyException($"无效的任务等级: {input.TaskLevel}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 检查是否已领取
|
|||
|
|
var existingRecord = await _dailyTaskRepository._DbQueryable
|
|||
|
|
.Where(x => x.UserId == userId && x.TaskDate == today && x.TaskLevel == input.TaskLevel)
|
|||
|
|
.FirstAsync();
|
|||
|
|
|
|||
|
|
if (existingRecord != null)
|
|||
|
|
{
|
|||
|
|
throw new UserFriendlyException("今日该任务奖励已领取,请明天再来!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 验证今日Token消耗是否达标
|
|||
|
|
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
|||
|
|
if (todayConsumed < taskConfig.RequiredTokens)
|
|||
|
|
{
|
|||
|
|
throw new UserFriendlyException(
|
|||
|
|
$"Token消耗未达标!需要 {taskConfig.RequiredTokens / 10000}w,当前 {todayConsumed / 10000}w");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 创建奖励包(使用 PremiumPackageManager)
|
|||
|
|
|
|||
|
|
var premiumPackage =
|
|||
|
|
new PremiumPackageAggregateRoot(userId, taskConfig.RewardTokens, $"每日任务:{taskConfig.Name}")
|
|||
|
|
{
|
|||
|
|
PurchaseAmount = 0, // 奖励不需要付费
|
|||
|
|
Remark = $"{today:yyyy-MM-dd} 每日任务奖励"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
await _premiumPackageRepository.InsertAsync(premiumPackage);
|
|||
|
|
|
|||
|
|
// 5. 记录领取记录
|
|||
|
|
var record = new DailyTaskRewardRecordAggregateRoot(userId, input.TaskLevel, today, taskConfig.RewardTokens)
|
|||
|
|
{
|
|||
|
|
Remark = $"完成任务{input.TaskLevel},名称:{taskConfig.Name},消耗 {todayConsumed / 10000}w token"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
await _dailyTaskRepository.InsertAsync(record);
|
|||
|
|
|
|||
|
|
_logger.LogInformation(
|
|||
|
|
$"用户 {userId} 领取每日任务 {input.TaskLevel} 奖励成功,获得 {taskConfig.RewardTokens / 10000}w tokens");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取今日尊享包Token消耗量
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="userId">用户ID</param>
|
|||
|
|
/// <param name="today">今日日期</param>
|
|||
|
|
/// <returns>消耗的Token总数</returns>
|
|||
|
|
private async Task<long> GetTodayPremiumTokenConsumptionAsync(Guid userId, DateTime today)
|
|||
|
|
{
|
|||
|
|
var tomorrow = today.AddDays(1);
|
|||
|
|
|
|||
|
|
// 查询今日所有使用尊享包模型的消息(role=system 表示消耗)
|
|||
|
|
var totalTokens = await _messageRepository._DbQueryable
|
|||
|
|
.Where(x => x.UserId == userId)
|
|||
|
|
.Where(x => x.Role == "system") // system角色表示实际消耗
|
|||
|
|
.Where(x => PremiumPackageConst.ModeIds.Contains(x.ModelId)) // 尊享包模型
|
|||
|
|
.Where(x => x.CreationTime >= today && x.CreationTime < tomorrow)
|
|||
|
|
.SumAsync(x => x.TokenUsage.TotalTokenCount);
|
|||
|
|
|
|||
|
|
return totalTokens;
|
|||
|
|
}
|
|||
|
|
}
|