feat: 完成任务系统的领域服务
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
using Quartz;
|
||||||
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
|
using Yi.Framework.Bbs.Domain.Managers;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Bbs.Application.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每日任务job
|
||||||
|
/// </summary>
|
||||||
|
public class AssignmentExpireTimeOutJob : QuartzBackgroundWorkerBase
|
||||||
|
{
|
||||||
|
private readonly AssignmentManager _assignmentManager;
|
||||||
|
|
||||||
|
public AssignmentExpireTimeOutJob(AssignmentManager assignmentManager)
|
||||||
|
{
|
||||||
|
_assignmentManager = assignmentManager;
|
||||||
|
JobDetail = JobBuilder.Create<AssignmentExpireTimeOutJob>().WithIdentity(nameof(AssignmentExpireTimeOutJob)).Build();
|
||||||
|
//每个小时整点执行一次
|
||||||
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).WithCronSchedule("0 0 * * * ?")
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
await _assignmentManager.ExpireTimeoutAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,3 +17,49 @@ public enum AssignmentTypeEnum
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Weekly
|
Weekly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class AssignmentTypeExtension
|
||||||
|
{
|
||||||
|
public static DateTime? GetExpireTime(this AssignmentTypeEnum assignmentType)
|
||||||
|
{
|
||||||
|
switch (assignmentType)
|
||||||
|
{
|
||||||
|
case AssignmentTypeEnum.Novice:
|
||||||
|
return null;
|
||||||
|
case AssignmentTypeEnum.Daily:
|
||||||
|
return DateTime.Now.Date.AddDays(1);
|
||||||
|
case AssignmentTypeEnum.Weekly:
|
||||||
|
DateTime today = DateTime.Now; // 获取当前日期和时间
|
||||||
|
int daysUntilNextMonday = ((int)DayOfWeek.Monday - (int)today.DayOfWeek + 7) % 7 + 7;
|
||||||
|
DateTime nextMonday = today.AddDays(daysUntilNextMonday).Date; // 添加天数并将时间设为 0 点
|
||||||
|
return nextMonday;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(assignmentType), assignmentType, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsExpire(this AssignmentTypeEnum assignmentType,DateTime time)
|
||||||
|
{
|
||||||
|
switch (assignmentType)
|
||||||
|
{
|
||||||
|
case AssignmentTypeEnum.Novice:
|
||||||
|
return false;
|
||||||
|
case AssignmentTypeEnum.Daily:
|
||||||
|
//昨天之前发的,算过期
|
||||||
|
return time.Date < DateTime.Now.Date;
|
||||||
|
case AssignmentTypeEnum.Weekly:
|
||||||
|
// 获取当前日期
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
// 计算本周一的日期
|
||||||
|
int daysToSubtract = (int)now.DayOfWeek - (int)DayOfWeek.Monday;
|
||||||
|
if (daysToSubtract < 0) daysToSubtract += 7; // 如果今天是周日,则需要调整
|
||||||
|
DateTime startOfWeek = now.AddDays(-daysToSubtract).Date;
|
||||||
|
// 获取本周一的凌晨 00:00
|
||||||
|
DateTime mondayMidnight = startOfWeek; // .Date 默认为 00:00
|
||||||
|
//本周一之前发的
|
||||||
|
return time<mondayMidnight ;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(assignmentType), assignmentType, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,29 +25,51 @@ public class AssignmentAggregateRoot : AggregateRoot<Guid>, IHasCreationTime, IO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid UserId { get; set; }
|
public Guid UserId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 总共步骤数
|
|
||||||
/// </summary>
|
|
||||||
public int TotalStepNumber { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前步骤数
|
/// 当前步骤数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int CurrentStepNumber { get; set; }
|
public int CurrentStepNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总共步骤数
|
||||||
|
/// </summary>
|
||||||
|
public int TotalStepNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务状态
|
/// 任务状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AssignmentStateEnum AssignmentState { get; set; }
|
public AssignmentStateEnum AssignmentState { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务奖励的钱钱数量
|
||||||
|
/// </summary>
|
||||||
|
public decimal RewardsMoneyNumber { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务过期时间
|
/// 任务过期时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? ExpireTime { get; set; }
|
public DateTime? ExpireTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? CompleteTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public DateTime CreationTime { get; }
|
public DateTime CreationTime { get; }
|
||||||
public int OrderNum { get; set; }
|
public int OrderNum { get; set; }
|
||||||
public DateTime? LastModificationTime { get; }
|
public DateTime? LastModificationTime { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsAllowCompleted()
|
||||||
|
{
|
||||||
|
return AssignmentState == AssignmentStateEnum.Progress && this.CurrentStepNumber == this.TotalStepNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TrySetExpire()
|
||||||
|
{
|
||||||
|
if (ExpireTime<=DateTime.Now)
|
||||||
|
{
|
||||||
|
AssignmentState = AssignmentStateEnum.Expired;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -31,6 +31,10 @@ public class AssignmentDefineAggregateRoot: AggregateRoot<Guid>, IHasCreationTim
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AssignmentTypeEnum AssignmentType{ get; set; }
|
public AssignmentTypeEnum AssignmentType{ get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总共步骤数
|
||||||
|
/// </summary>
|
||||||
|
public int TotalStepNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 前置任务id
|
/// 前置任务id
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
using Volo.Abp.Domain.Services;
|
using SqlSugar;
|
||||||
|
using Volo.Abp.Domain.Services;
|
||||||
|
using Volo.Abp.EventBus.Local;
|
||||||
|
using Volo.Abp.Users;
|
||||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||||
|
using Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Domain.Managers;
|
namespace Yi.Framework.Bbs.Domain.Managers;
|
||||||
|
|
||||||
@@ -8,15 +15,46 @@ namespace Yi.Framework.Bbs.Domain.Managers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class AssignmentManager : DomainService
|
public class AssignmentManager : DomainService
|
||||||
{
|
{
|
||||||
|
private readonly IEnumerable<IAssignmentProvider> _assignmentProviders;
|
||||||
|
private readonly ISqlSugarRepository<AssignmentAggregateRoot> _assignmentRepository;
|
||||||
|
private readonly ISqlSugarRepository<AssignmentDefineAggregateRoot> _assignmentDefineRepository;
|
||||||
|
private readonly ILocalEventBus _localEventBus;
|
||||||
|
|
||||||
|
public AssignmentManager(IEnumerable<IAssignmentProvider> assignmentProviders,
|
||||||
|
ISqlSugarRepository<AssignmentAggregateRoot> assignmentRepository,
|
||||||
|
ISqlSugarRepository<AssignmentDefineAggregateRoot> assignmentDefineRepository, ILocalEventBus localEventBus)
|
||||||
|
{
|
||||||
|
this._assignmentProviders = assignmentProviders;
|
||||||
|
_assignmentRepository = assignmentRepository;
|
||||||
|
_assignmentDefineRepository = assignmentDefineRepository;
|
||||||
|
_localEventBus = localEventBus;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 接受任务
|
/// 接受任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">领取用户</param>
|
/// <param name="userId">领取用户</param>
|
||||||
/// <param name="asignmentDefineId">任务定义id</param>
|
/// <param name="asignmentDefineId">任务定义id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task AcceptAsync(Guid userId, Guid asignmentDefineId)
|
public async Task AcceptAsync(Guid userId, Guid asignmentDefineId)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var canReceiveList = await GetCanReceiveListAsync(userId);
|
||||||
|
|
||||||
|
//如果要接收的任务id在可领取的任务列表中,就可以接收任务
|
||||||
|
if (canReceiveList.Select(x => x.Id).Contains(asignmentDefineId))
|
||||||
|
{
|
||||||
|
var assignmentDefine = await _assignmentDefineRepository.GetByIdAsync(asignmentDefineId);
|
||||||
|
|
||||||
|
var entity = new AssignmentAggregateRoot();
|
||||||
|
entity.AssignmentDefineId = asignmentDefineId;
|
||||||
|
entity.UserId = userId;
|
||||||
|
entity.AssignmentState = AssignmentStateEnum.Progress;
|
||||||
|
entity.CurrentStepNumber = 0;
|
||||||
|
entity.TotalStepNumber = assignmentDefine.TotalStepNumber;
|
||||||
|
entity.RewardsMoneyNumber = assignmentDefine.RewardsMoneyNumber;
|
||||||
|
entity.ExpireTime = assignmentDefine.AssignmentType.GetExpireTime();
|
||||||
|
await _assignmentRepository.InsertAsync(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,9 +63,17 @@ public class AssignmentManager : DomainService
|
|||||||
/// <param name="asignmentId">任务id</param>
|
/// <param name="asignmentId">任务id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
public Task ReceiveRewardsAsync(Guid asignmentId)
|
public async Task ReceiveRewardsAsync(Guid asignmentId)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var assignment = await _assignmentRepository.GetByIdAsync(asignmentId);
|
||||||
|
if (assignment.IsAllowCompleted())
|
||||||
|
{
|
||||||
|
//设置已完成,并领取奖励,钱钱
|
||||||
|
assignment.AssignmentState = AssignmentStateEnum.Completed;
|
||||||
|
//加钱加钱
|
||||||
|
await _localEventBus.PublishAsync(
|
||||||
|
new MoneyChangeEventArgs { UserId = assignment.UserId, Number = assignment.RewardsMoneyNumber }, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -36,8 +82,58 @@ public class AssignmentManager : DomainService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">用户id</param>
|
/// <param name="userId">用户id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(Guid userId)
|
public async Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(Guid userId)
|
||||||
{
|
{
|
||||||
|
var context = await GetAssignmentContext(userId);
|
||||||
|
var output = new List<AssignmentDefineAggregateRoot>();
|
||||||
|
foreach (var assignmentProvider in _assignmentProviders)
|
||||||
|
{
|
||||||
|
output.AddRange(await assignmentProvider.GetCanReceiveListAsync(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
output.DistinctBy(x => x.Id);
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取任务的上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<AssignmentContext> GetAssignmentContext(Guid userId)
|
||||||
|
{
|
||||||
|
var allAssignmentDefine = await _assignmentDefineRepository.GetListAsync();
|
||||||
|
|
||||||
|
var currentUserAssignment = await _assignmentRepository.GetListAsync(x => x.UserId == userId);
|
||||||
|
|
||||||
|
var context = new AssignmentContext(userId, allAssignmentDefine, currentUserAssignment);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 过期超时的任务,定时任务去处理即可
|
||||||
|
/// </summary>
|
||||||
|
public async Task ExpireTimeoutAsync()
|
||||||
|
{
|
||||||
|
var progressEntities = await _assignmentRepository._DbQueryable
|
||||||
|
.Where(x => x.AssignmentState == AssignmentStateEnum.Progress)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var needUpdateEntities = new List<AssignmentAggregateRoot>();
|
||||||
|
foreach (var progressEntity in progressEntities)
|
||||||
|
{
|
||||||
|
if (progressEntity.TrySetExpire())
|
||||||
|
{
|
||||||
|
needUpdateEntities.Add(progressEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needUpdateEntities.Any())
|
||||||
|
{
|
||||||
|
await _assignmentRepository._Db.Updateable(needUpdateEntities).ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,13 @@ namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
|||||||
|
|
||||||
public class AssignmentContext
|
public class AssignmentContext
|
||||||
{
|
{
|
||||||
|
public AssignmentContext( Guid currentUserId,List<AssignmentDefineAggregateRoot> allAssignmentDefine, List<AssignmentAggregateRoot> currentUserAssignments)
|
||||||
|
{
|
||||||
|
AllAssignmentDefine = allAssignmentDefine;
|
||||||
|
CurrentUserAssignments = currentUserAssignments;
|
||||||
|
CurrentUserId = currentUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全部的任务定义
|
/// 全部的任务定义
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -17,5 +24,5 @@ public class AssignmentContext
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前用户id
|
/// 当前用户id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid CurrentUserId { get; set; }
|
public Guid CurrentUserId { get; }
|
||||||
}
|
}
|
||||||
@@ -14,11 +14,4 @@ public interface IAssignmentProvider : ITransientDependency
|
|||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context);
|
Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 校验是否能够被领取,该方法还需工厂进行代理执行一次
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task VerifyCanAcceptAsync(AssignmentContext context);
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 每日任务提供者
|
/// 每日任务提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DailyProvider : TimerProvider
|
public class DailyProvider : TimerProvider
|
||||||
{
|
{
|
||||||
protected override TimeSpan TimeCycle => TimeSpan.FromDays(1);
|
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Daily;
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,7 @@ public class NoviceProvider : IAssignmentProvider
|
|||||||
{
|
{
|
||||||
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
//新手任务是要有前置依赖关系的,链表类型依赖
|
||||||
}
|
|
||||||
|
|
||||||
public Task VerifyCanAcceptAsync(AssignmentContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 每周任务提供者
|
/// 每周任务提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WeeklyProvider : TimerProvider
|
public class WeeklyProvider : TimerProvider
|
||||||
{
|
{
|
||||||
protected override TimeSpan TimeCycle => TimeSpan.FromDays(7);
|
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Weekly;
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,41 @@
|
|||||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
using SqlSugar;
|
||||||
|
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定时任务提供者
|
/// 循环任务提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class TimerProvider : IAssignmentProvider
|
public abstract class TimerProvider : IAssignmentProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 时间周期
|
/// 任务类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract TimeSpan TimeCycle { get; }
|
protected abstract AssignmentTypeEnum AssignmentType { get; }
|
||||||
|
|
||||||
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
//先获取到对应任务定义列表
|
||||||
|
var assignmentDefines = context.AllAssignmentDefine.Where(x => x.AssignmentType == AssignmentType).ToList();
|
||||||
|
|
||||||
|
//满足以下1个条件
|
||||||
|
//1:没有正在运行的
|
||||||
|
//2: 存在已完成,但是完成时间是过期的
|
||||||
|
var assignmentFilterIds = context.CurrentUserAssignments
|
||||||
|
.Where(x =>
|
||||||
|
//正在进行的,要去掉
|
||||||
|
x.AssignmentState == AssignmentStateEnum.Progress||
|
||||||
|
//已完成,但是还没过期,要去掉
|
||||||
|
(x.AssignmentState == AssignmentStateEnum.Completed&&!AssignmentType.IsExpire(x.CompleteTime!.Value)))
|
||||||
|
.Select(x => x.AssignmentDefineId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//出去不可接收的任务,就是可接收任务
|
||||||
|
var output = assignmentDefines.Where(x => !assignmentFilterIds.Contains(x.Id)).ToList();
|
||||||
|
return Task.FromResult(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task VerifyCanAcceptAsync(AssignmentContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user