using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Task;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HoneyBox.Core.Services;
///
/// 任务服务实现
///
public class TaskService : ITaskService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger _logger;
public TaskService(HoneyBoxDbContext dbContext, ILogger logger)
{
_dbContext = dbContext;
_logger = logger;
}
///
public async Task GetTaskListAsync(int userId, int type)
{
// 获取任务列表
var tasks = await _dbContext.Tasks
.Where(t => t.Type == type && t.DeletedAt == null)
.OrderByDescending(t => t.Sort)
.ThenByDescending(t => t.Id)
.ToListAsync();
var taskDtos = new List();
foreach (var task in tasks)
{
// 计算任务周期时间范围
var (startTime, endTime) = GetTaskPeriod(task.Type);
// 计算任务进度
int completedCount = await CalculateTaskProgress(userId, task.Cate, startTime);
// 判断是否已完成
int targetNumber = task.Number ?? 0;
int isComplete;
int percentage;
int ywcCount;
if (completedCount >= targetNumber)
{
isComplete = 1;
percentage = 100;
ywcCount = targetNumber;
}
else
{
isComplete = 0;
percentage = targetNumber > 0 ? (int)Math.Round((double)completedCount / targetNumber * 100) : 0;
ywcCount = completedCount;
}
// 检查是否已领取
var hasClaimed = await _dbContext.UserTasks
.AnyAsync(ut => ut.UserId == userId
&& ut.TaskId == task.Id
&& ut.CreatedAt >= startTime
&& ut.CreatedAt <= endTime
&& ut.DeletedAt == null);
if (hasClaimed)
{
isComplete = 2; // 已领取
}
taskDtos.Add(new TaskDto
{
Id = task.Id,
Type = task.Type,
Cate = task.Cate,
Title = task.Title,
Number = targetNumber,
ZNumber = task.ZNumber ?? 0,
IsComplete = isComplete,
Percentage = percentage,
YwcCount = ywcCount
});
}
return new TaskListResponse
{
TaskList = taskDtos
};
}
///
public async Task ClaimTaskRewardAsync(int userId, int taskListId)
{
// 获取任务信息
var task = await _dbContext.Tasks
.FirstOrDefaultAsync(t => t.Id == taskListId && t.DeletedAt == null);
if (task == null)
{
throw new InvalidOperationException("任务不存在");
}
// 计算任务周期时间范围
var (startTime, endTime) = GetTaskPeriod(task.Type);
// 检查任务是否已完成
int completedCount = await CalculateTaskProgress(userId, task.Cate, startTime);
int targetNumber = task.Number ?? 0;
if (completedCount < targetNumber)
{
throw new InvalidOperationException("任务未完成");
}
// 检查是否已领取
var hasClaimed = await _dbContext.UserTasks
.AnyAsync(ut => ut.UserId == userId
&& ut.TaskId == taskListId
&& ut.CreatedAt >= startTime
&& ut.CreatedAt <= endTime
&& ut.DeletedAt == null);
if (hasClaimed)
{
throw new InvalidOperationException("你已经领取过了");
}
// 开始事务
using var transaction = await _dbContext.Database.BeginTransactionAsync();
try
{
var now = DateTime.Now;
// 创建用户任务记录
var userTask = new UserTask
{
UserId = userId,
TaskId = taskListId,
Type = task.Type,
Cate = task.Cate,
IsImportant = task.IsImportant,
Number = task.Number,
ZNumber = task.ZNumber,
CreatedAt = now,
UpdatedAt = now
};
await _dbContext.UserTasks.AddAsync(userTask);
// 发放欧气值奖励
int reward = task.ZNumber ?? 0;
int currentOuQi = 0;
if (reward > 0)
{
var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
if (user != null)
{
user.OuQi = (user.OuQi ?? 0) + reward;
currentOuQi = user.OuQi ?? 0;
// 重新计算欧气等级
user.OuQiLevel = CalculateOuQiLevel(currentOuQi);
user.UpdatedAt = now;
// 记录欧气值变动
var profitOuQi = new ProfitOuQi
{
UserId = userId,
ChangeMoney = reward,
Money = currentOuQi,
Type = 1, // 完成任务
Content = "完成任务",
CreatedAt = now
};
await _dbContext.ProfitOuQis.AddAsync(profitOuQi);
}
}
await _dbContext.SaveChangesAsync();
await transaction.CommitAsync();
_logger.LogInformation("用户 {UserId} 领取任务 {TaskId} 奖励 {Reward} 欧气值", userId, taskListId, reward);
return new ClaimTaskRewardResponse
{
Reward = reward,
CurrentOuQi = currentOuQi
};
}
catch (Exception ex)
{
await transaction.RollbackAsync();
_logger.LogError(ex, "用户 {UserId} 领取任务 {TaskId} 奖励失败", userId, taskListId);
throw new InvalidOperationException("网络故障, 请稍后再试");
}
}
///
/// 获取任务周期时间范围
///
/// 任务类型: 1=每日, 2=每周
/// 开始时间和结束时间
private (DateTime startTime, DateTime endTime) GetTaskPeriod(int taskType)
{
var now = DateTime.Now;
if (taskType == 1)
{
// 每日任务: 当天 00:00:00 到 23:59:59
var startTime = now.Date;
var endTime = now.Date.AddDays(1).AddSeconds(-1);
return (startTime, endTime);
}
else
{
// 每周任务: 本周一 00:00:00 到 本周日 23:59:59
var dayOfWeek = (int)now.DayOfWeek;
// 周日是0,需要转换为7
if (dayOfWeek == 0) dayOfWeek = 7;
var startTime = now.Date.AddDays(-(dayOfWeek - 1)); // 本周一
var endTime = startTime.AddDays(7).AddSeconds(-1); // 本周日 23:59:59
return (startTime, endTime);
}
}
///
/// 计算任务进度
///
/// 用户ID
/// 任务分类: 1=邀请, 2=抽赏
/// 开始时间
/// 完成数量
private async Task CalculateTaskProgress(int userId, int taskCate, DateTime startTime)
{
if (taskCate == 1)
{
// 邀请好友注册: 统计推荐人为当前用户且注册时间在周期内的用户数
return await _dbContext.Users
.CountAsync(u => u.Pid == userId && u.CreatedAt >= startTime);
}
else if (taskCate == 2)
{
// 抽赏任务: 统计已支付订单数 (pay_type < 10 且 status = 1)
// 将DateTime转换为Unix时间戳进行比较
var startTimestamp = (int)((DateTimeOffset)startTime).ToUnixTimeSeconds();
return await _dbContext.Orders
.CountAsync(o => o.UserId == userId
&& o.PayType < 10
&& o.Status == 1
&& o.Addtime >= startTimestamp);
}
return 0;
}
///
/// 根据欧气值计算欧气等级
///
/// 当前欧气值
/// 欧气等级
private static int CalculateOuQiLevel(int ouQi)
{
// 等级阈值: 0=普通, 1=青铜(100), 2=白银(500), 3=黄金(1000),
// 4=铂金(3000), 5=钻石(6000), 6=星耀(10000), 7=王者(20000)
if (ouQi >= 20000) return 7;
if (ouQi >= 10000) return 6;
if (ouQi >= 6000) return 5;
if (ouQi >= 3000) return 4;
if (ouQi >= 1000) return 3;
if (ouQi >= 500) return 2;
if (ouQi >= 100) return 1;
return 0;
}
}