Merge branch 'refs/heads/abp-dev' into abp
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
||||
|
||||
public class AssignmentDefineGetListOutputDto : EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务类型
|
||||
/// </summary>
|
||||
public AssignmentTypeEnum AssignmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务需求类型
|
||||
/// </summary>
|
||||
public AssignmentRequirementTypeEnum AssignmentRequirementType{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总共步骤数
|
||||
/// </summary>
|
||||
public int TotalStepNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 前置任务id
|
||||
/// </summary>
|
||||
public Guid? PreAssignmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务奖励的钱钱数量
|
||||
/// </summary>
|
||||
public decimal RewardsMoneyNumber { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
@@ -4,5 +4,21 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
||||
|
||||
public class AssignmentGetListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务查询条件
|
||||
/// </summary>
|
||||
public AssignmentQueryStateEnum AssignmentQueryState { get; set; } = AssignmentQueryStateEnum.Progress;
|
||||
}
|
||||
|
||||
public enum AssignmentQueryStateEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 正在进行
|
||||
/// </summary>
|
||||
Progress,
|
||||
|
||||
/// <summary>
|
||||
/// 已结束
|
||||
/// </summary>
|
||||
End
|
||||
}
|
||||
@@ -1,8 +1,54 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
||||
|
||||
public class AssignmentGetListOutputDto:EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; }
|
||||
/// <summary>
|
||||
/// 当前步骤数
|
||||
/// </summary>
|
||||
public int CurrentStepNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总共步骤数
|
||||
/// </summary>
|
||||
public int TotalStepNumber { get; set; }
|
||||
/// <summary>
|
||||
/// 任务类型
|
||||
/// </summary>
|
||||
public AssignmentTypeEnum AssignmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务需求类型
|
||||
/// </summary>
|
||||
public AssignmentRequirementTypeEnum AssignmentRequirementType{ get; set; }
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public AssignmentStateEnum AssignmentState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务奖励的钱钱数量
|
||||
/// </summary>
|
||||
public decimal RewardsMoneyNumber { get; set; }
|
||||
/// <summary>
|
||||
/// 任务过期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpireTime { get; set; }
|
||||
|
||||
public DateTime? CompleteTime { get; set; }
|
||||
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Extensions;
|
||||
|
||||
public static class AccessLogExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseAccessLog(this IApplicationBuilder app)
|
||||
{
|
||||
app.UseMiddleware<AccessLogMiddleware>();
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using FreeRedis;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// 访问日志中间件
|
||||
/// 并发最高,采用缓存,默认10分钟才会真正操作一次数据库
|
||||
/// 需考虑一致性问题,又不能上锁影响性能
|
||||
/// </summary>
|
||||
public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存前缀
|
||||
/// </summary>
|
||||
private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDistributedCacheOptions>>()
|
||||
.Value.KeyPrefix;
|
||||
|
||||
/// <summary>
|
||||
/// 使用懒加载防止报错
|
||||
/// </summary>
|
||||
private IRedisClient RedisClient => LazyServiceProvider.LazyGetRequiredService<IRedisClient>();
|
||||
|
||||
/// <summary>
|
||||
/// 属性注入
|
||||
/// </summary>
|
||||
public IAbpLazyServiceProvider LazyServiceProvider { get; set; }
|
||||
|
||||
private bool EnableRedisCache
|
||||
{
|
||||
get
|
||||
{
|
||||
var redisEnabled = LazyServiceProvider.LazyGetRequiredService<IConfiguration>()["Redis:IsEnabled"];
|
||||
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
await next(context);
|
||||
if (EnableRedisCache)
|
||||
{
|
||||
await RedisClient.IncrByAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date}", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using FreeRedis;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Quartz;
|
||||
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Jobs;
|
||||
|
||||
public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
||||
{
|
||||
private readonly ISqlSugarRepository<AccessLogAggregateRoot> _repository;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存前缀
|
||||
/// </summary>
|
||||
private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDistributedCacheOptions>>()
|
||||
.Value.KeyPrefix;
|
||||
|
||||
/// <summary>
|
||||
/// 使用懒加载防止报错
|
||||
/// </summary>
|
||||
private IRedisClient RedisClient => LazyServiceProvider.LazyGetRequiredService<IRedisClient>();
|
||||
|
||||
/// <summary>
|
||||
/// 属性注入
|
||||
/// </summary>
|
||||
public IAbpLazyServiceProvider LazyServiceProvider { get; set; }
|
||||
|
||||
private bool EnableRedisCache
|
||||
{
|
||||
get
|
||||
{
|
||||
var redisEnabled = LazyServiceProvider.LazyGetRequiredService<IConfiguration>()["Redis:IsEnabled"];
|
||||
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
public AccessLogStoreJob(ISqlSugarRepository<AccessLogAggregateRoot> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
JobDetail = JobBuilder.Create<AccessLogStoreJob>().WithIdentity(nameof(AccessLogStoreJob))
|
||||
.Build();
|
||||
|
||||
//每分钟执行一次
|
||||
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
|
||||
.WithCronSchedule("0 * * * * ?")
|
||||
.Build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
if (EnableRedisCache)
|
||||
{
|
||||
//当天的访问量
|
||||
var number =
|
||||
await RedisClient.GetAsync<long>($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date}");
|
||||
|
||||
|
||||
var entity = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogTypeEnum.Request)
|
||||
.Where(x => x.CreationTime.Date == DateTime.Today)
|
||||
.FirstAsync();
|
||||
|
||||
|
||||
if (entity is not null)
|
||||
{
|
||||
entity.Number = number+1;
|
||||
await _repository.UpdateAsync(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _repository.InsertAsync((new AccessLogAggregateRoot() { Number = number,AccessLogType = AccessLogTypeEnum.Request}));
|
||||
}
|
||||
|
||||
//删除前一天的缓存
|
||||
await RedisClient.DelAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.AccessLog;
|
||||
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Services
|
||||
@@ -11,7 +12,11 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
public class AccessLogService : ApplicationService, IAccessLogService
|
||||
{
|
||||
private readonly ISqlSugarRepository<AccessLogAggregateRoot> _repository;
|
||||
public AccessLogService(ISqlSugarRepository<AccessLogAggregateRoot> repository) { _repository = repository; }
|
||||
|
||||
public AccessLogService(ISqlSugarRepository<AccessLogAggregateRoot> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public DateTime GetWeekFirst()
|
||||
{
|
||||
@@ -45,16 +50,15 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取全部访问流量(3个月)
|
||||
/// </summary>
|
||||
/// <param name="AccessLogType"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AccessLogDto>> Get()
|
||||
public async Task<List<AccessLogDto>> GetListAsync([FromQuery] AccessLogTypeEnum accessLogType)
|
||||
{
|
||||
var entities = await _repository._DbQueryable
|
||||
.Where(x=>x.CreationTime>=DateTime.Now.AddMonths(-3))
|
||||
var entities = await _repository._DbQueryable.Where(x => x.AccessLogType == accessLogType)
|
||||
.Where(x => x.CreationTime >= DateTime.Now.AddMonths(-3))
|
||||
.OrderBy(x => x.CreationTime).ToListAsync();
|
||||
var output = entities.Adapt<List<AccessLogDto>>();
|
||||
output?.ForEach(x => x.CreationTime = x.CreationTime.Date);
|
||||
@@ -62,32 +66,35 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发
|
||||
/// 首页点击触发
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("access-log")]
|
||||
public async Task AccessAsync()
|
||||
{
|
||||
//可判断http重复,防止同一ip多次访问
|
||||
var last = await _repository._DbQueryable.OrderByDescending(x => x.CreationTime).FirstAsync();
|
||||
var last = await _repository._DbQueryable.Where(x=>x.AccessLogType==AccessLogTypeEnum.HomeClick).OrderByDescending(x => x.CreationTime).FirstAsync();
|
||||
|
||||
if (last is null || last.CreationTime.Date != DateTime.Today)
|
||||
{
|
||||
await _repository.InsertAsync(new AccessLogAggregateRoot());
|
||||
await _repository.InsertAsync(new AccessLogAggregateRoot(){AccessLogType=AccessLogTypeEnum.HomeClick});
|
||||
}
|
||||
else
|
||||
{
|
||||
await _repository._Db.Updateable<AccessLogAggregateRoot>().SetColumns(it => it.Number == it.Number + 1).Where(it => it.Id == last.Id).ExecuteCommandAsync();
|
||||
await _repository._Db.Updateable<AccessLogAggregateRoot>().SetColumns(it => it.Number == it.Number + 1)
|
||||
.Where(it => it.Id == last.Id).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前周数据
|
||||
/// 获取当前周首页点击数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<AccessLogDto[]> GetWeekAsync()
|
||||
public async Task<AccessLogDto[]> GetWeekAsync([FromQuery] AccessLogTypeEnum accessLogType)
|
||||
{
|
||||
var lastSeven = await _repository._DbQueryable.OrderByDescending(x => x.CreationTime).ToPageListAsync(1, 7);
|
||||
var lastSeven = await _repository._DbQueryable
|
||||
.Where(x => x.AccessLogType == accessLogType)
|
||||
.OrderByDescending(x => x.CreationTime).ToPageListAsync(1, 7);
|
||||
|
||||
return WeekTimeHandler(lastSeven.ToArray());
|
||||
}
|
||||
@@ -99,7 +106,8 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
/// <returns></returns>
|
||||
private AccessLogDto[] WeekTimeHandler(AccessLogAggregateRoot[] data)
|
||||
{
|
||||
data = data.Where(x => x.CreationTime >= GetWeekFirst()).OrderByDescending(x => x.CreationTime).DistinctBy(x => x.CreationTime.DayOfWeek).ToArray();
|
||||
data = data.Where(x => x.CreationTime >= GetWeekFirst()).OrderByDescending(x => x.CreationTime)
|
||||
.DistinctBy(x => x.CreationTime.DayOfWeek).ToArray();
|
||||
|
||||
Dictionary<DayOfWeek, AccessLogDto> processedData = new Dictionary<DayOfWeek, AccessLogDto>();
|
||||
|
||||
@@ -117,8 +125,8 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
// 如果当天有数据,则更新字典中的值为对应的Number
|
||||
var sss = data.Adapt<AccessLogDto>();
|
||||
processedData[dayOfWeek] = item.Adapt<AccessLogDto>();
|
||||
|
||||
}
|
||||
|
||||
var result = processedData.Values.ToList();
|
||||
|
||||
//此时的时间是周日-周一-周二,需要处理
|
||||
@@ -128,8 +136,5 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||
using Yi.Framework.Bbs.Domain.Managers;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Services;
|
||||
|
||||
@@ -26,26 +28,55 @@ public class AssignmentService : ApplicationService
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
[HttpPost("assignment/accept/{id}")]
|
||||
public async Task AcceptAsync(Guid id)
|
||||
public async Task AcceptAsync([FromRoute] Guid id)
|
||||
{
|
||||
await _assignmentManager.AcceptAsync(CurrentUser.GetId(), id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收任务奖励
|
||||
/// 领取任务奖励
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
[HttpPost("assignment/receive-rewards/{id}")]
|
||||
public async Task ReceiveRewardsAsync(Guid id)
|
||||
[HttpPost("assignment/complete/{id}")]
|
||||
public async Task ReceiveRewardsAsync([FromRoute] Guid id)
|
||||
{
|
||||
await _assignmentManager.ReceiveRewardsAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询任务
|
||||
/// 查看可接受的任务
|
||||
/// </summary>
|
||||
public async Task<PagedResultDto<AssignmentGetListOutputDto>> GetListAsync(AssignmentGetListInput input)
|
||||
/// <returns></returns>
|
||||
[HttpGet("assignment/receive")]
|
||||
public async Task<List<AssignmentDefineGetListOutputDto>> GetCanReceiveListAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var entities = await _assignmentManager.GetCanReceiveListAsync(CurrentUser.GetId());
|
||||
var output = entities.Adapt<List<AssignmentDefineGetListOutputDto>>();
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询接受的任务
|
||||
/// </summary>
|
||||
[HttpGet("assignment")]
|
||||
public async Task<List<AssignmentGetListOutputDto>> GetListAsync([FromQuery] AssignmentGetListInput input)
|
||||
{
|
||||
var output = await _assignmentManager._assignmentRepository._DbQueryable
|
||||
.Where(x => x.UserId == CurrentUser.GetId())
|
||||
.WhereIF(input.AssignmentQueryState == AssignmentQueryStateEnum.Progress,
|
||||
x => x.AssignmentState == AssignmentStateEnum.Progress||
|
||||
x.AssignmentState == AssignmentStateEnum.Completed)
|
||||
.WhereIF(input.AssignmentQueryState == AssignmentQueryStateEnum.End,
|
||||
x => x.AssignmentState == AssignmentStateEnum.End ||
|
||||
x.AssignmentState == AssignmentStateEnum.Expired)
|
||||
.OrderBy(x=>x.CreationTime)
|
||||
.LeftJoin<AssignmentDefineAggregateRoot>((x, define) => x.AssignmentDefineId==define.Id)
|
||||
.Select((x, define) => new AssignmentGetListOutputDto
|
||||
{
|
||||
Id = x.Id
|
||||
},true)
|
||||
.ToListAsync();
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||
|
||||
public class AccessLogCacheItem
|
||||
{
|
||||
public AccessLogCacheItem(long number)
|
||||
{
|
||||
Number = number;
|
||||
}
|
||||
|
||||
public long Number { get; set; }
|
||||
public DateTime LastModificationTime { get; set; }=DateTime.Now;
|
||||
|
||||
public DateTime LastInsertTime { get; set; }=DateTime.Now;
|
||||
}
|
||||
|
||||
public class AccessLogCacheConst
|
||||
{
|
||||
|
||||
public const string Key = "AccessLog";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
public enum AccessLogTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 首页点击量
|
||||
/// </summary>
|
||||
HomeClick,
|
||||
|
||||
/// <summary>
|
||||
/// 接口请求量
|
||||
/// </summary>
|
||||
Request
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
public enum AssignmentRequirementTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 主题
|
||||
/// </summary>
|
||||
Discuss=2,
|
||||
|
||||
/// <summary>
|
||||
/// 评论
|
||||
/// </summary>
|
||||
Comment=4,
|
||||
|
||||
/// <summary>
|
||||
/// 点赞
|
||||
/// </summary>
|
||||
Agree=8,
|
||||
|
||||
/// <summary>
|
||||
/// 更新个人中心
|
||||
/// </summary>
|
||||
UpdateProfile=16
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -15,5 +15,10 @@ public enum AssignmentStateEnum
|
||||
/// <summary>
|
||||
/// 已过期
|
||||
/// </summary>
|
||||
Expired
|
||||
Expired,
|
||||
|
||||
/// <summary>
|
||||
/// 已结束
|
||||
/// </summary>
|
||||
End
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
|
||||
public class AssignmentEventArgs
|
||||
{
|
||||
public AssignmentEventArgs(AssignmentRequirementTypeEnum requirementType, Guid currentUserId,object? args=null)
|
||||
{
|
||||
RequirementType = requirementType;
|
||||
Args = args;
|
||||
CurrentUserId = currentUserId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务需求类型
|
||||
/// </summary>
|
||||
public AssignmentRequirementTypeEnum RequirementType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 任务参数,可空,只需要一个触发点即可
|
||||
/// </summary>
|
||||
public object? Args { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 当前用户id
|
||||
/// </summary>
|
||||
public Guid CurrentUserId { get; set; }
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Entities
|
||||
{
|
||||
[SugarTable("AccessLog")]
|
||||
public class AccessLogAggregateRoot : AggregateRoot<Guid>, IHasModificationTime, IHasCreationTime
|
||||
public class AccessLogAggregateRoot : AggregateRoot<Guid>, IHasCreationTime,IHasModificationTime
|
||||
{
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
public long Number { get; set; }
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
|
||||
public AccessLogTypeEnum AccessLogType { get; set; }
|
||||
public DateTime CreationTime { get; set; }
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,32 +44,45 @@ public class AssignmentAggregateRoot : AggregateRoot<Guid>, IHasCreationTime, IO
|
||||
/// 任务奖励的钱钱数量
|
||||
/// </summary>
|
||||
public decimal RewardsMoneyNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务过期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpireTime { get; set; }
|
||||
|
||||
public DateTime? CompleteTime { get; set; }
|
||||
|
||||
|
||||
public DateTime CreationTime { get; }
|
||||
/// <summary>
|
||||
/// 任务需求类型
|
||||
/// </summary>
|
||||
public AssignmentRequirementTypeEnum AssignmentRequirementType { get; set; }
|
||||
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
public int OrderNum { get; set; }
|
||||
public DateTime? LastModificationTime { get; }
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
|
||||
|
||||
public bool IsAllowCompleted()
|
||||
{
|
||||
return AssignmentState == AssignmentStateEnum.Progress && this.CurrentStepNumber == this.TotalStepNumber;
|
||||
return AssignmentState == AssignmentStateEnum.Completed && this.CurrentStepNumber == this.TotalStepNumber;
|
||||
}
|
||||
|
||||
public bool TrySetExpire()
|
||||
{
|
||||
if (ExpireTime<=DateTime.Now)
|
||||
if (ExpireTime <= DateTime.Now)
|
||||
{
|
||||
//现在时间已经大于过期时间
|
||||
AssignmentState = AssignmentStateEnum.Expired;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetEnd()
|
||||
{
|
||||
this.AssignmentState = AssignmentStateEnum.End;
|
||||
this.EndTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,11 @@ public class AssignmentDefineAggregateRoot: AggregateRoot<Guid>, IHasCreationTim
|
||||
/// </summary>
|
||||
public AssignmentTypeEnum AssignmentType{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务需求类型
|
||||
/// </summary>
|
||||
public AssignmentRequirementTypeEnum AssignmentRequirementType{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总共步骤数
|
||||
/// </summary>
|
||||
@@ -46,6 +51,6 @@ public class AssignmentDefineAggregateRoot: AggregateRoot<Guid>, IHasCreationTim
|
||||
/// </summary>
|
||||
public decimal RewardsMoneyNumber { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; }
|
||||
public DateTime CreationTime{ get; set; }
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Volo.Abp.EventBus.Local;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
@@ -14,20 +15,24 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
/// <summary>
|
||||
/// 被点赞
|
||||
/// </summary>
|
||||
public class AgreeCreatedEventHandler : ILocalEventHandler<EntityCreatedEventData<AgreeEntity>>,
|
||||
ITransientDependency
|
||||
public class AgreeChangeEventHandler : ILocalEventHandler<EntityCreatedEventData<AgreeEntity>>,
|
||||
ITransientDependency
|
||||
{
|
||||
private ISqlSugarRepository<UserAggregateRoot> _userRepository;
|
||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userInfoRepository;
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
private ILocalEventBus _localEventBus;
|
||||
public AgreeCreatedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userInfoRepository, ISqlSugarRepository<AgreeEntity> agreeRepository, ILocalEventBus localEventBus, ISqlSugarRepository<UserAggregateRoot> userRepository)
|
||||
|
||||
public AgreeChangeEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userInfoRepository,
|
||||
ISqlSugarRepository<AgreeEntity> agreeRepository, ILocalEventBus localEventBus,
|
||||
ISqlSugarRepository<UserAggregateRoot> userRepository)
|
||||
{
|
||||
_userInfoRepository = userInfoRepository;
|
||||
_agreeRepository = agreeRepository;
|
||||
_localEventBus = localEventBus;
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityCreatedEventData<AgreeEntity> eventData)
|
||||
{
|
||||
var agreeEntity = eventData.Entity;
|
||||
@@ -35,55 +40,66 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
//查询主题的信息
|
||||
var discussAndAgreeDto = await _agreeRepository._DbQueryable
|
||||
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||
.Select((agree, discuss) =>
|
||||
new
|
||||
{
|
||||
DiscussId=discuss.Id,
|
||||
DiscussTitle = discuss.Title,
|
||||
DiscussCreatorId = discuss.CreatorId,
|
||||
})
|
||||
.FirstAsync();
|
||||
.Select((agree, discuss) =>
|
||||
new
|
||||
{
|
||||
DiscussId = discuss.Id,
|
||||
DiscussTitle = discuss.Title,
|
||||
DiscussCreatorId = discuss.CreatorId,
|
||||
})
|
||||
.FirstAsync();
|
||||
|
||||
//查询点赞者用户
|
||||
var agreeUser = await _userRepository.GetFirstAsync(x => x.Id == agreeEntity.CreatorId);
|
||||
|
||||
//给创建者点赞数量+1
|
||||
await _userInfoRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber + 1)
|
||||
.Where(it => it.UserId == discussAndAgreeDto.DiscussCreatorId)
|
||||
.ExecuteCommandAsync();
|
||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber + 1)
|
||||
.Where(it => it.UserId == discussAndAgreeDto.DiscussCreatorId)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
//通知主题作者,有人点赞
|
||||
await _localEventBus.PublishAsync(new BbsNoticeEventArgs(discussAndAgreeDto.DiscussCreatorId!.Value, string.Format(DiscussConst.AgreeNotice, discussAndAgreeDto.DiscussTitle, agreeUser.UserName,discussAndAgreeDto.DiscussId)), false);
|
||||
await _localEventBus.PublishAsync(
|
||||
new BbsNoticeEventArgs(discussAndAgreeDto.DiscussCreatorId!.Value,
|
||||
string.Format(DiscussConst.AgreeNotice, discussAndAgreeDto.DiscussTitle, agreeUser.UserName,
|
||||
discussAndAgreeDto.DiscussId)), false);
|
||||
|
||||
//最后发布任务触发事件
|
||||
await _localEventBus.PublishAsync(
|
||||
new AssignmentEventArgs(AssignmentRequirementTypeEnum.Agree, agreeUser.Id),false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消点赞
|
||||
/// </summary>
|
||||
public class AgreeDeletedEventHandler : ILocalEventHandler<EntityDeletedEventData<AgreeEntity>>,
|
||||
ITransientDependency
|
||||
ITransientDependency
|
||||
{
|
||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
private ILocalEventBus _localEventBus;
|
||||
public AgreeDeletedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository, ISqlSugarRepository<AgreeEntity> agreeRepository, ILocalEventBus localEventBus)
|
||||
|
||||
public AgreeDeletedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository,
|
||||
ISqlSugarRepository<AgreeEntity> agreeRepository, ILocalEventBus localEventBus)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_agreeRepository = agreeRepository;
|
||||
_localEventBus = localEventBus;
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityDeletedEventData<AgreeEntity> eventData)
|
||||
{
|
||||
var agreeEntity = eventData.Entity;
|
||||
var userId = await _agreeRepository._DbQueryable.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||
.Select((agree, discuss) => discuss.CreatorId).FirstAsync();
|
||||
var userId = await _agreeRepository._DbQueryable
|
||||
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||
.Select((agree, discuss) => discuss.CreatorId).FirstAsync();
|
||||
|
||||
//给创建者点赞数量-1
|
||||
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber - 1)
|
||||
.Where(it => it.UserId == userId)
|
||||
.ExecuteCommandAsync();
|
||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber - 1)
|
||||
.Where(it => it.UserId == userId)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.EventBus;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.EventHandlers;
|
||||
|
||||
/// <summary>
|
||||
/// 任务系统的领域事件,处理不同任务触发变化
|
||||
/// </summary>
|
||||
public class AssignmentEventHandler : ILocalEventHandler<AssignmentEventArgs>, ITransientDependency
|
||||
{
|
||||
private readonly ISqlSugarRepository<AssignmentAggregateRoot> _repository;
|
||||
|
||||
public AssignmentEventHandler(ISqlSugarRepository<AssignmentAggregateRoot> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(AssignmentEventArgs eventData)
|
||||
{
|
||||
var currentAssignmentList = await _repository.GetListAsync(x =>
|
||||
x.AssignmentState == AssignmentStateEnum.Progress && x.UserId == eventData.CurrentUserId);
|
||||
|
||||
//如果有接收的任务
|
||||
if (currentAssignmentList.Count > 0)
|
||||
{
|
||||
switch (eventData.RequirementType)
|
||||
{
|
||||
//发表主题
|
||||
case AssignmentRequirementTypeEnum.Discuss:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Discuss, currentAssignmentList);
|
||||
break;
|
||||
|
||||
//发表评论
|
||||
case AssignmentRequirementTypeEnum.Comment:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Comment, currentAssignmentList);
|
||||
break;
|
||||
|
||||
//点赞
|
||||
case AssignmentRequirementTypeEnum.Agree:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Agree, currentAssignmentList);
|
||||
break;
|
||||
|
||||
//更新个人信息
|
||||
case AssignmentRequirementTypeEnum.UpdateProfile:
|
||||
//这里还需判断是否更新了
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
|
||||
//更新
|
||||
await _repository.UpdateRangeAsync(currentAssignmentList);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置当前进度
|
||||
/// </summary>
|
||||
/// <param name="requirementType"></param>
|
||||
/// <param name="currentAssignmentList"></param>
|
||||
private void SetCurrentStepNumber(AssignmentRequirementTypeEnum requirementType,
|
||||
List<AssignmentAggregateRoot> currentAssignmentList)
|
||||
{
|
||||
currentAssignmentList.ForEach(x =>
|
||||
{
|
||||
if (x.AssignmentRequirementType == requirementType &&
|
||||
x.CurrentStepNumber < x.TotalStepNumber)
|
||||
{
|
||||
x.CurrentStepNumber += 1;
|
||||
if (x.CurrentStepNumber==x.TotalStepNumber)
|
||||
{
|
||||
x.AssignmentState = AssignmentStateEnum.Completed;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Volo.Abp.EventBus.Local;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
@@ -62,6 +63,10 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
await _localEventBus.PublishAsync(new BbsNoticeEventArgs(commentEntity.ParentId, string.Format(DiscussConst.CommentNoticeToReply, disucssDto.DiscussTitle, commentUser.UserName, content,commentEntity.DiscussId)), false);
|
||||
|
||||
}
|
||||
|
||||
//最后发布任务触发事件
|
||||
await _localEventBus.PublishAsync(
|
||||
new AssignmentEventArgs(AssignmentRequirementTypeEnum.Comment, commentUser.Id),false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities.Events;
|
||||
using Volo.Abp.EventBus;
|
||||
using Volo.Abp.EventBus.Local;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
@@ -11,22 +14,31 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
/// 主题创建的领域事件
|
||||
/// </summary>
|
||||
public class DiscussCreatedEventHandler : ILocalEventHandler<EntityCreatedEventData<DiscussAggregateRoot>>,
|
||||
ITransientDependency
|
||||
ITransientDependency
|
||||
{
|
||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
||||
public DiscussCreatedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository)
|
||||
private ILocalEventBus _localEventBus;
|
||||
|
||||
public DiscussCreatedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository,
|
||||
ILocalEventBus localEventBus)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_localEventBus = localEventBus;
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityCreatedEventData<DiscussAggregateRoot> eventData)
|
||||
{
|
||||
var disucussEntity = eventData.Entity;
|
||||
|
||||
//给创建者发布数量+1
|
||||
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||
.SetColumns(it => it.DiscussNumber == it.DiscussNumber + 1)
|
||||
.Where(it => it.UserId == disucussEntity.CreatorId)
|
||||
.ExecuteCommandAsync();
|
||||
.SetColumns(it => it.DiscussNumber == it.DiscussNumber + 1)
|
||||
.Where(it => it.UserId == disucussEntity.CreatorId)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
//最后发布任务触发事件
|
||||
await _localEventBus.PublishAsync(
|
||||
new AssignmentEventArgs(AssignmentRequirementTypeEnum.Discuss, disucussEntity.CreatorId!.Value), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@ namespace Yi.Framework.Bbs.Domain.Managers;
|
||||
public class AssignmentManager : DomainService
|
||||
{
|
||||
private readonly IEnumerable<IAssignmentProvider> _assignmentProviders;
|
||||
private readonly ISqlSugarRepository<AssignmentAggregateRoot> _assignmentRepository;
|
||||
private readonly ISqlSugarRepository<AssignmentDefineAggregateRoot> _assignmentDefineRepository;
|
||||
public readonly ISqlSugarRepository<AssignmentAggregateRoot> _assignmentRepository;
|
||||
public readonly ISqlSugarRepository<AssignmentDefineAggregateRoot> _assignmentDefineRepository;
|
||||
private readonly ILocalEventBus _localEventBus;
|
||||
|
||||
public AssignmentManager(IEnumerable<IAssignmentProvider> assignmentProviders,
|
||||
@@ -52,6 +52,7 @@ public class AssignmentManager : DomainService
|
||||
entity.CurrentStepNumber = 0;
|
||||
entity.TotalStepNumber = assignmentDefine.TotalStepNumber;
|
||||
entity.RewardsMoneyNumber = assignmentDefine.RewardsMoneyNumber;
|
||||
entity.AssignmentRequirementType = assignmentDefine.AssignmentRequirementType;
|
||||
entity.ExpireTime = assignmentDefine.AssignmentType.GetExpireTime();
|
||||
await _assignmentRepository.InsertAsync(entity);
|
||||
}
|
||||
@@ -68,11 +69,18 @@ public class AssignmentManager : DomainService
|
||||
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);
|
||||
|
||||
//设置已完成,并领取奖励,钱钱
|
||||
assignment.SetEnd();
|
||||
await _assignmentRepository.UpdateAsync(assignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
//不能领取
|
||||
throw new UserFriendlyException("该任务没有满足领取条件,请检查任务详情");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +99,8 @@ public class AssignmentManager : DomainService
|
||||
output.AddRange(await assignmentProvider.GetCanReceiveListAsync(context));
|
||||
}
|
||||
|
||||
output.DistinctBy(x => x.Id);
|
||||
throw new NotImplementedException();
|
||||
output = output.DistinctBy(x => x.Id).OrderBy(x => x.OrderNum).ToList();
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +142,5 @@ public class AssignmentManager : DomainService
|
||||
{
|
||||
await _assignmentRepository._Db.Updateable(needUpdateEntities).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||
|
||||
/// <summary>
|
||||
/// 每日任务提供者
|
||||
/// </summary>
|
||||
[ExposeServices(typeof(IAssignmentProvider))]
|
||||
public class DailyProvider : TimerProvider
|
||||
{
|
||||
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Daily;
|
||||
|
||||
@@ -5,11 +5,12 @@ namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||
/// <summary>
|
||||
/// 新手任务提供者
|
||||
/// </summary>
|
||||
public class NoviceProvider : IAssignmentProvider
|
||||
public class NoviceProvider : IAssignmentProvider
|
||||
{
|
||||
public Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
||||
public async Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
||||
{
|
||||
//新手任务是要有前置依赖关系的,链表类型依赖
|
||||
throw new NotImplementedException();
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||
|
||||
/// <summary>
|
||||
/// 每周任务提供者
|
||||
/// </summary>
|
||||
[ExposeServices(typeof(IAssignmentProvider))]
|
||||
public class WeeklyProvider : TimerProvider
|
||||
{
|
||||
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Weekly;
|
||||
|
||||
@@ -24,10 +24,11 @@ public abstract class TimerProvider : IAssignmentProvider
|
||||
//2: 存在已完成,但是完成时间是过期的
|
||||
var assignmentFilterIds = context.CurrentUserAssignments
|
||||
.Where(x =>
|
||||
//正在进行的,要去掉
|
||||
//正在进行的,已经完成,要去掉
|
||||
x.AssignmentState == AssignmentStateEnum.Progress||
|
||||
//已完成,但是还没过期,要去掉
|
||||
(x.AssignmentState == AssignmentStateEnum.Completed&&!AssignmentType.IsExpire(x.CompleteTime!.Value)))
|
||||
x.AssignmentState==AssignmentStateEnum.Completed||
|
||||
//已结束,但是还没过期,要去掉
|
||||
(x.AssignmentState == AssignmentStateEnum.End&&!AssignmentType.IsExpire(x.EndTime!.Value)))
|
||||
.Select(x => x.AssignmentDefineId)
|
||||
.ToList();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
/// </summary>
|
||||
public class BankManager : DomainService
|
||||
{
|
||||
private const decimal DefalutRate = 1.3m;
|
||||
private const decimal DefalutRate = 1.2m;
|
||||
private ISqlSugarRepository<BankCardAggregateRoot> _repository;
|
||||
private ILocalEventBus _localEventBus;
|
||||
private ISqlSugarRepository<InterestRecordsAggregateRoot> _interestRepository;
|
||||
|
||||
@@ -19,8 +19,10 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
private IDistributedCache<List<LevelCacheItem>> _levelCache;
|
||||
private IRepository<LevelAggregateRoot> _repository;
|
||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _bbsUserRepository;
|
||||
public LevelManager( ILocalEventBus localEventBus,
|
||||
IDistributedCache<List<LevelCacheItem>> levelCache, IRepository<LevelAggregateRoot> repository, ISqlSugarRepository<BbsUserExtraInfoEntity> bbsUserRepository)
|
||||
|
||||
public LevelManager(ILocalEventBus localEventBus,
|
||||
IDistributedCache<List<LevelCacheItem>> levelCache, IRepository<LevelAggregateRoot> repository,
|
||||
ISqlSugarRepository<BbsUserExtraInfoEntity> bbsUserRepository)
|
||||
{
|
||||
_localEventBus = localEventBus;
|
||||
_repository = repository;
|
||||
@@ -35,16 +37,16 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
/// <returns></returns>
|
||||
public async Task<Dictionary<int, LevelCacheItem>> GetCacheMapAsync()
|
||||
{
|
||||
var items = _levelCache.GetOrAdd(LevelConst.LevelCacheKey, () =>
|
||||
var items = _levelCache.GetOrAdd(LevelConst.LevelCacheKey, () =>
|
||||
{
|
||||
var cacheItem = ( _repository.GetListAsync().Result)
|
||||
var cacheItem = (_repository.GetListAsync().Result)
|
||||
.OrderByDescending(x => x.CurrentLevel).ToList()
|
||||
.Adapt<List<LevelCacheItem>>();
|
||||
return cacheItem;
|
||||
});
|
||||
return items.ToDictionary(x=>x.CurrentLevel);
|
||||
return items.ToDictionary(x => x.CurrentLevel);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 使用钱钱投喂等级
|
||||
/// </summary>
|
||||
@@ -52,7 +54,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
public async Task ChangeLevelByMoneyAsync(Guid userId, int moneyNumber)
|
||||
{
|
||||
//通过用户id获取用户信息的经验和等级
|
||||
var userInfo = await _bbsUserRepository.GetAsync(x=>x.UserId==userId);
|
||||
var userInfo = await _bbsUserRepository.GetAsync(x => x.UserId == userId);
|
||||
|
||||
//钱钱和经验的比例为1:1
|
||||
//根据钱钱修改经验
|
||||
@@ -63,7 +65,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
false);
|
||||
|
||||
//更改最终的经验再变化等级
|
||||
var levelList = (await GetCacheMapAsync()).Values;
|
||||
var levelList = (await GetCacheMapAsync()).Values.OrderByDescending(x => x.CurrentLevel);
|
||||
var currentNewLevel = 1;
|
||||
foreach (var level in levelList)
|
||||
{
|
||||
@@ -73,12 +75,12 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//这里注意,只更新等级
|
||||
userInfo.Level = currentNewLevel;
|
||||
userInfo.Experience = currentNewExperience;
|
||||
await _bbsUserRepository._Db.Updateable(userInfo)
|
||||
.UpdateColumns(it => new { it.Level,it.Experience })
|
||||
.UpdateColumns(it => new { it.Level, it.Experience })
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
|
||||
using Volo.Abp.AspNetCore.ExceptionHandling;
|
||||
using Volo.Abp.AspNetCore.MultiTenancy;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
|
||||
@@ -25,6 +26,7 @@ using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
|
||||
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
|
||||
using Yi.Framework.Bbs.Application;
|
||||
using Yi.Framework.Bbs.Application.Extensions;
|
||||
using Yi.Framework.ChatHub.Application;
|
||||
using Yi.Framework.CodeGen.Application;
|
||||
using Yi.Framework.Rbac.Application;
|
||||
@@ -38,8 +40,6 @@ namespace Yi.Abp.Web
|
||||
[DependsOn(
|
||||
typeof(YiAbpSqlSugarCoreModule),
|
||||
typeof(YiAbpApplicationModule),
|
||||
|
||||
|
||||
typeof(AbpAspNetCoreMultiTenancyModule),
|
||||
typeof(AbpAspNetCoreMvcModule),
|
||||
typeof(AbpAutofacModule),
|
||||
@@ -49,11 +49,11 @@ namespace Yi.Abp.Web
|
||||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
|
||||
typeof(YiFrameworkAspNetCoreModule),
|
||||
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
|
||||
|
||||
)]
|
||||
)]
|
||||
public class YiAbpWebModule : AbpModule
|
||||
{
|
||||
private const string DefaultCorsPolicyName = "Default";
|
||||
|
||||
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
|
||||
{
|
||||
var configuration = context.Services.GetConfiguration();
|
||||
@@ -68,15 +68,24 @@ namespace Yi.Abp.Web
|
||||
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
|
||||
});
|
||||
|
||||
//配置错误处理显示详情
|
||||
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
|
||||
|
||||
//动态Api
|
||||
Configure<AbpAspNetCoreMvcOptions>(options =>
|
||||
{
|
||||
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly, options => options.RemoteServiceName = "default");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly, options => options.RemoteServiceName = "rbac");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly, options => options.RemoteServiceName = "bbs");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly, options => options.RemoteServiceName = "chat-hub");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkTenantManagementApplicationModule).Assembly, options => options.RemoteServiceName = "tenant-management");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly, options => options.RemoteServiceName = "code-gen");
|
||||
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "default");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "rbac");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "bbs");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "chat-hub");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkTenantManagementApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "tenant-management");
|
||||
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly,
|
||||
options => options.RemoteServiceName = "code-gen");
|
||||
|
||||
//统一前缀
|
||||
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
|
||||
@@ -91,22 +100,20 @@ namespace Yi.Abp.Web
|
||||
|
||||
//设置缓存不要过期,默认滑动20分钟
|
||||
Configure<AbpDistributedCacheOptions>(cacheOptions =>
|
||||
{
|
||||
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
|
||||
//缓存key前缀
|
||||
cacheOptions.KeyPrefix = "Yi:";
|
||||
});
|
||||
|
||||
|
||||
Configure<AbpAntiForgeryOptions>(options =>
|
||||
{
|
||||
options.AutoValidate = false;
|
||||
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
|
||||
//缓存key前缀
|
||||
cacheOptions.KeyPrefix = "Yi:";
|
||||
});
|
||||
|
||||
|
||||
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; });
|
||||
|
||||
//Swagger
|
||||
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
|
||||
{
|
||||
options.SwaggerDoc("default", new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
|
||||
options.SwaggerDoc("default",
|
||||
new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
|
||||
});
|
||||
|
||||
//跨域
|
||||
@@ -145,7 +152,7 @@ namespace Yi.Abp.Web
|
||||
//每60秒限制100个请求,滑块添加,分6段
|
||||
service.AddRateLimiter(_ =>
|
||||
{
|
||||
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
_.OnRejected = (context, _) =>
|
||||
{
|
||||
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
|
||||
@@ -153,6 +160,7 @@ namespace Yi.Abp.Web
|
||||
context.HttpContext.Response.Headers.RetryAfter =
|
||||
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
|
||||
}
|
||||
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
||||
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
|
||||
|
||||
@@ -161,20 +169,20 @@ namespace Yi.Abp.Web
|
||||
|
||||
//全局使用,链式表达式
|
||||
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
|
||||
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
||||
{
|
||||
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
||||
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
||||
{
|
||||
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
||||
|
||||
return RateLimitPartition.GetSlidingWindowLimiter
|
||||
(userAgent, _ =>
|
||||
new SlidingWindowRateLimiterOptions
|
||||
{
|
||||
PermitLimit = 1000,
|
||||
Window = TimeSpan.FromSeconds(60),
|
||||
SegmentsPerWindow = 6,
|
||||
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
|
||||
});
|
||||
}));
|
||||
return RateLimitPartition.GetSlidingWindowLimiter
|
||||
(userAgent, _ =>
|
||||
new SlidingWindowRateLimiterOptions
|
||||
{
|
||||
PermitLimit = 1000,
|
||||
Window = TimeSpan.FromSeconds(60),
|
||||
SegmentsPerWindow = 6,
|
||||
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
@@ -196,14 +204,15 @@ namespace Yi.Abp.Web
|
||||
options.Events = new JwtBearerEvents
|
||||
{
|
||||
OnMessageReceived = context =>
|
||||
{
|
||||
var accessToken = context.Request.Query["access_token"];
|
||||
if (!string.IsNullOrEmpty(accessToken))
|
||||
{
|
||||
context.Token = accessToken;
|
||||
var accessToken = context.Request.Query["access_token"];
|
||||
if (!string.IsNullOrEmpty(accessToken))
|
||||
{
|
||||
context.Token = accessToken;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
})
|
||||
.AddJwtBearer(TokenTypeConst.Refresh, options =>
|
||||
@@ -214,37 +223,32 @@ namespace Yi.Abp.Web
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = refreshJwtOptions.Issuer,
|
||||
ValidAudience = refreshJwtOptions.Audience,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
||||
IssuerSigningKey =
|
||||
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
||||
};
|
||||
options.Events = new JwtBearerEvents
|
||||
{
|
||||
OnMessageReceived = context =>
|
||||
{
|
||||
var refresh_token = context.Request.Headers["refresh_token"];
|
||||
if (!string.IsNullOrEmpty(refresh_token))
|
||||
{
|
||||
context.Token = refresh_token;
|
||||
var refresh_token = context.Request.Headers["refresh_token"];
|
||||
if (!string.IsNullOrEmpty(refresh_token))
|
||||
{
|
||||
context.Token = refresh_token;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var refreshToken = context.Request.Query["refresh_token"];
|
||||
if (!string.IsNullOrEmpty(refreshToken))
|
||||
{
|
||||
context.Token = refreshToken;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
var refreshToken = context.Request.Query["refresh_token"];
|
||||
if (!string.IsNullOrEmpty(refreshToken))
|
||||
{
|
||||
context.Token = refreshToken;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
|
||||
})
|
||||
.AddQQ(options =>
|
||||
{
|
||||
configuration.GetSection("OAuth:QQ").Bind(options);
|
||||
})
|
||||
.AddGitee(options =>
|
||||
{
|
||||
configuration.GetSection("OAuth:Gitee").Bind(options);
|
||||
});
|
||||
.AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
|
||||
.AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
|
||||
|
||||
//授权
|
||||
context.Services.AddAuthorization();
|
||||
@@ -284,6 +288,9 @@ namespace Yi.Abp.Web
|
||||
//swagger
|
||||
app.UseYiSwagger();
|
||||
|
||||
//流量访问统计,需redis支持,否则不生效
|
||||
app.UseAccessLog();
|
||||
|
||||
//请求处理
|
||||
app.UseYiApiHandlinge();
|
||||
|
||||
@@ -310,4 +317,4 @@ namespace Yi.Abp.Web
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,18 @@ export function access() {
|
||||
}
|
||||
|
||||
// 获取本周数据
|
||||
export function getWeek() {
|
||||
export function getWeek(data) {
|
||||
return request({
|
||||
url: "/access-log/week",
|
||||
method: "get",
|
||||
params :data
|
||||
});
|
||||
}
|
||||
// 获取全部数据
|
||||
export function getAccessList() {
|
||||
export function getAccessList(data) {
|
||||
return request({
|
||||
url: "/access-log",
|
||||
method: "get",
|
||||
params :data
|
||||
});
|
||||
}
|
||||
|
||||
33
Yi.Bbs.Vue3/src/apis/assignmentApi.js
Normal file
33
Yi.Bbs.Vue3/src/apis/assignmentApi.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import request from "@/config/axios/service";
|
||||
|
||||
//接受任务
|
||||
export function acceptAssignment(id) {
|
||||
return request({
|
||||
url: `/assignment/accept/${id}`,
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
//领取奖励
|
||||
export function receiveAssignment(id) {
|
||||
return request({
|
||||
url: `/assignment/complete/${id}`,
|
||||
method: "post",
|
||||
});
|
||||
}
|
||||
|
||||
//查询能够领取的任务
|
||||
export function getCanReceiveAssignment() {
|
||||
return request({
|
||||
url: `/assignment/receive`,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
//查询已领取的任务
|
||||
export function getAssignmentList(data) {
|
||||
return request({
|
||||
url: `/assignment`,
|
||||
method: "get",
|
||||
params:data
|
||||
});
|
||||
}
|
||||
@@ -37,7 +37,14 @@ const onClickText=()=>{
|
||||
.el-divider {
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
.VisitsLineChart /deep/ .el-card__body{
|
||||
padding: 0 20px;
|
||||
}
|
||||
.box-card-info {
|
||||
width: 100%;
|
||||
height: v-bind(height);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -52,9 +59,4 @@ const onClickText=()=>{
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.box-card {
|
||||
width: 100%;
|
||||
height: v-bind(height);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
<el-icon>
|
||||
<Memo />
|
||||
</el-icon>
|
||||
<span>任务列表(暂未开放)</span>
|
||||
<span>任务列表</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="4" :route="{ path: '/activity/lucky' }">
|
||||
<el-menu-item index="4" :route="{ path: '/activity/assignment' }">
|
||||
<el-icon>
|
||||
<HelpFilled />
|
||||
</el-icon>
|
||||
|
||||
@@ -156,6 +156,14 @@ const router = createRouter({
|
||||
title: "银行",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "assignment",
|
||||
path: "assignment",
|
||||
component: () => import("../views/assignment/Index.vue"),
|
||||
meta: {
|
||||
title: "任务",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
115
Yi.Bbs.Vue3/src/views/assignment/Index.vue
Normal file
115
Yi.Bbs.Vue3/src/views/assignment/Index.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<script setup>
|
||||
import {getAssignmentList, getCanReceiveAssignment, acceptAssignment, receiveAssignment} from '@/apis/assignmentApi'
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import AssignmentCard from "./components/AssignmentCard.vue"
|
||||
|
||||
const canReceiveAssignmentList = ref([]);
|
||||
|
||||
const assignmentList = ref([]);
|
||||
const queryForm = reactive({
|
||||
assignmentQueryState: "Progress"
|
||||
});
|
||||
|
||||
//当前选择table页
|
||||
const currentTableSelect = ref("canAccept");
|
||||
|
||||
//切换tab
|
||||
const changeClickTable = async (tabName) => {
|
||||
switch (tabName) {
|
||||
case "canAccept":
|
||||
const {data: canReceiveAssignmentListData} = await getCanReceiveAssignment();
|
||||
canReceiveAssignmentList.value = canReceiveAssignmentListData;
|
||||
return;
|
||||
case "progress":
|
||||
queryForm.assignmentQueryState = "Progress";
|
||||
break;
|
||||
case "end":
|
||||
queryForm.assignmentQueryState = "End";
|
||||
break;
|
||||
}
|
||||
const {data} = await getAssignmentList(queryForm);
|
||||
assignmentList.value = data;
|
||||
}
|
||||
onMounted(async () => {
|
||||
const {data: canReceiveAssignmentListData} = await getCanReceiveAssignment();
|
||||
canReceiveAssignmentList.value = canReceiveAssignmentListData;
|
||||
});
|
||||
//刷新数据
|
||||
const refreshData = async () => {
|
||||
|
||||
const {data: canReceiveAssignmentListData} = await getCanReceiveAssignment();
|
||||
canReceiveAssignmentList.value = canReceiveAssignmentListData;
|
||||
|
||||
const {data} = await getAssignmentList(queryForm);
|
||||
assignmentList.value = data;
|
||||
}
|
||||
|
||||
//接收任务
|
||||
const onClickAcceptAssignment = async (item) => {
|
||||
await acceptAssignment(item.id);
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '接受任务成功',
|
||||
});
|
||||
await refreshData();
|
||||
}
|
||||
|
||||
//领取奖励
|
||||
const onClickReceiveAssignment = async (item) => {
|
||||
await receiveAssignment(item.id);
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '任务奖励领取成功',
|
||||
});
|
||||
await refreshData();
|
||||
}
|
||||
|
||||
//切换tab
|
||||
const changeTab = async (state) => {
|
||||
queryForm.assignmentQueryState = state;
|
||||
await refreshData();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="content-body">
|
||||
<el-tabs
|
||||
v-model="currentTableSelect"
|
||||
type="border-card"
|
||||
@tab-change="changeClickTable"
|
||||
>
|
||||
<el-tab-pane label="可接受" name="canAccept"/>
|
||||
<el-tab-pane label="已接受" name="progress"/>
|
||||
<el-tab-pane label="已结束" name="end"/>
|
||||
|
||||
<div v-if="currentTableSelect==='canAccept'">
|
||||
<div v-for="item in canReceiveAssignmentList" class="assign-box" v-if="canReceiveAssignmentList.length>0">
|
||||
<AssignmentCard :isDefind="true" :data="item" @onClick="onClickAcceptAssignment"/>
|
||||
</div>
|
||||
<el-empty v-else description="暂时没有可领取的任务" />
|
||||
|
||||
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-for="item in assignmentList" class="assign-box" v-if="assignmentList.length>0">
|
||||
<AssignmentCard :isDefind="false" :data="item" @onClick="onClickReceiveAssignment"/>
|
||||
</div>
|
||||
<el-empty v-else description="暂时没有任务" />
|
||||
</div>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.content-body {
|
||||
|
||||
padding: 30px;
|
||||
|
||||
.assign-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
152
Yi.Bbs.Vue3/src/views/assignment/components/AssignmentCard.vue
Normal file
152
Yi.Bbs.Vue3/src/views/assignment/components/AssignmentCard.vue
Normal file
@@ -0,0 +1,152 @@
|
||||
<script setup>
|
||||
import {computed, ref, watch} from "vue";
|
||||
import { dayjs } from 'element-plus'
|
||||
const props = defineProps(['data', 'isDefind'])
|
||||
const cardData = ref(props.data);
|
||||
|
||||
const emit = defineEmits(['onClick'])
|
||||
const onClick = () => {
|
||||
emit('onClick', cardData.value)
|
||||
}
|
||||
//监视组件传值变化
|
||||
watch(() => props.data, (n, o) => {
|
||||
cardData.value = n;
|
||||
})
|
||||
|
||||
//任务类型
|
||||
const assignmentTypeEnum = {
|
||||
"Daily": {name:"每日任务",backgroundColor:"#fff"},
|
||||
"Weekly":{name:"每周任务",backgroundColor:"#fff"} ,
|
||||
"Novice": {name:"新手任务",backgroundColor:"#fff"}
|
||||
}
|
||||
const computedAssignmentState = computed(() => {
|
||||
|
||||
if (props.isDefind) {
|
||||
return btnAssignmentStateEnum["CanReceive"];
|
||||
} else {
|
||||
return btnAssignmentStateEnum[cardData.value.assignmentState];
|
||||
}
|
||||
});
|
||||
const btnAssignmentStateEnum = {
|
||||
"CanReceive": {name: "接受任务", backgroundColor: "primary",isDisabled:false},
|
||||
"End": {name: "已完成", backgroundColor: "info",isDisabled:true},
|
||||
"Progress": {name: "正在进行", backgroundColor: "Default",isDisabled:true},
|
||||
"Completed": {name: "领取奖励", backgroundColor: "success",isDisabled:false},
|
||||
"Expired": {name: "已过期", backgroundColor: "info",isDisabled:true}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card-box">
|
||||
<div class="left">
|
||||
<div class="left-type" :style="{backgroundColor:assignmentTypeEnum[cardData.assignmentType].backgroundColor}">{{ assignmentTypeEnum[cardData.assignmentType].name }}</div>
|
||||
<div class="content">
|
||||
<div class="content-title">
|
||||
<h2>{{ cardData.name }}</h2>
|
||||
<h4>{{ cardData.remarks }}</h4>
|
||||
</div>
|
||||
<div class="progress" v-if="props.isDefind===false">
|
||||
<el-progress
|
||||
:text-inside="true"
|
||||
:stroke-width="20"
|
||||
:percentage=" Math.round((cardData.currentStepNumber/cardData.totalStepNumber)*100)"
|
||||
|
||||
status="success"
|
||||
/>
|
||||
<span>{{cardData.currentStepNumber}}/{{cardData.totalStepNumber}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="right">
|
||||
<div class="right-btn">
|
||||
|
||||
<h5> {{cardData.expireTime ==null?"":"过期时间:"+dayjs(cardData.expireTime).format('YYYY年M月D日')}}</h5>
|
||||
<h5>奖励:<span style="color: #FF0000;font-weight: bolder ">{{cardData.rewardsMoneyNumber}}</span> 钱钱</h5>
|
||||
<el-button @click="onClick()" :disabled="computedAssignmentState.isDisabled" :type="computedAssignmentState.backgroundColor">
|
||||
{{ computedAssignmentState.name }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.el-progress{
|
||||
width: 450px;
|
||||
}
|
||||
.el-button {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 0 0 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
h5 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.card-box {
|
||||
padding: 10px;
|
||||
border: 2px solid #dcdfe6;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.right-btn {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
.content {
|
||||
margin-left: 30px;
|
||||
.content-title{
|
||||
display: flex;
|
||||
}
|
||||
.progress{
|
||||
display: flex;
|
||||
}
|
||||
span{
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.left-type {
|
||||
border: 1px solid #dcdfe6;
|
||||
height: 60px;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -3,10 +3,11 @@
|
||||
<el-row :gutter="20" class="top-div">
|
||||
<el-col :span="17">
|
||||
<div class="chat-hub">
|
||||
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家</p>
|
||||
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家
|
||||
</p>
|
||||
</div>
|
||||
<div class="scrollbar">
|
||||
<ScrollbarInfo />
|
||||
<ScrollbarInfo/>
|
||||
</div>
|
||||
|
||||
<el-row class="left-div">
|
||||
@@ -14,23 +15,23 @@
|
||||
'padding-left': i % 3 == 1 ? 0 : 0.2 + 'rem',
|
||||
'padding-right': i % 3 == 0 ? 0 : 0.2 + 'rem',
|
||||
}">
|
||||
<PlateCard :name="i.name" :introduction="i.introduction" :id="i.id" :isPublish="i.isDisableCreateDiscuss" />
|
||||
<PlateCard :name="i.name" :introduction="i.introduction" :id="i.id" :isPublish="i.isDisableCreateDiscuss"/>
|
||||
</el-col>
|
||||
<template v-if="isDiscussFinished">
|
||||
<el-col :span="24" v-for="i in discussList" :key="i.id">
|
||||
<DisscussCard :discuss="i" />
|
||||
<DisscussCard :discuss="i"/>
|
||||
</el-col>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Skeleton :isBorder="true" />
|
||||
<Skeleton :isBorder="true"/>
|
||||
</template>
|
||||
<template v-if="isAllDiscussFinished">
|
||||
<el-col :span="24" v-for="i in allDiscussList" :key="i.id">
|
||||
<DisscussCard :discuss="i" />
|
||||
<DisscussCard :discuss="i"/>
|
||||
</el-col>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Skeleton :isBorder="true" />
|
||||
<Skeleton :isBorder="true"/>
|
||||
</template>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@@ -42,7 +43,7 @@
|
||||
<div class="carousel-font" :style="{ color: item.color }">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<el-image style="width: 100%; height: 100%" :src="item.logo" fit="cover" />
|
||||
<el-image style="width: 100%; height: 100%" :src="item.logo" fit="cover"/>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</el-col>
|
||||
@@ -97,23 +98,26 @@
|
||||
<el-col :span="24">
|
||||
<InfoCard header="访问统计" class="VisitsLineChart" text="全站历史统计" @onClickText="onClickAccessLog">
|
||||
<template #content>
|
||||
<VisitsLineChart :option="statisOptions" class="statisChart" />
|
||||
<p class="switch-span" @click="onClickWeekSwitch">切换</p>
|
||||
<VisitsLineChart :option="statisOptions" class="statisChart"/>
|
||||
|
||||
</template>
|
||||
</InfoCard>
|
||||
|
||||
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
||||
<el-tabs v-model="accessLogTab">
|
||||
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart" style="display: flex;justify-content: center;">
|
||||
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;" />
|
||||
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart"
|
||||
style="display: flex;justify-content: center;">
|
||||
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="注册统计(近3月)" name="RegisterChart" style="display: flex;justify-content: center;">
|
||||
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;" />
|
||||
<el-tab-pane label="注册统计(近3月)" name="RegisterChart"
|
||||
style="display: flex;justify-content: center;">
|
||||
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;"/>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
||||
|
||||
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
|
||||
@@ -129,16 +133,17 @@
|
||||
|
||||
<el-col :span="24">
|
||||
<template v-if="isPointFinished">
|
||||
<InfoCard :items="pointList" header="财富排行榜" text="查看我的位置" height="400" @onClickText="onClickMoneyTop">
|
||||
<InfoCard :items="pointList" header="财富排行榜" text="查看我的位置" height="400"
|
||||
@onClickText="onClickMoneyTop">
|
||||
<template #item="temp">
|
||||
<PointsRanking :pointsData="temp" />
|
||||
<PointsRanking :pointsData="temp"/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
<template v-else>
|
||||
<InfoCard header="本月排行" text="更多">
|
||||
<template #content>
|
||||
<Skeleton />
|
||||
<Skeleton/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
@@ -148,14 +153,14 @@
|
||||
<template v-if="isFriendFinished">
|
||||
<InfoCard :items="friendList" header="推荐好友" text="更多" height="400">
|
||||
<template #item="temp">
|
||||
<RecommendFriend :friendData="temp" />
|
||||
<RecommendFriend :friendData="temp"/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
<template v-else>
|
||||
<InfoCard header="推荐好友" text="更多">
|
||||
<template #content>
|
||||
<Skeleton />
|
||||
<Skeleton/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
@@ -164,21 +169,21 @@
|
||||
<template v-if="isThemeFinished">
|
||||
<InfoCard :items="themeList" header="推荐主题" text="更多" height="400">
|
||||
<template #item="temp">
|
||||
<ThemeData :themeData="temp" />
|
||||
<ThemeData :themeData="temp"/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
<template v-else>
|
||||
<InfoCard header="推荐主题" text="更多">
|
||||
<template #content>
|
||||
<Skeleton />
|
||||
<Skeleton/>
|
||||
</template>
|
||||
</InfoCard>
|
||||
</template>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" style="background: transparent">
|
||||
<BottomInfo />
|
||||
<BottomInfo/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@@ -187,8 +192,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import {onMounted, ref, reactive, computed, nextTick, watch} from "vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import DisscussCard from "@/components/DisscussCard.vue";
|
||||
import InfoCard from "@/components/InfoCard.vue";
|
||||
import PlateCard from "@/components/PlateCard.vue";
|
||||
@@ -196,11 +201,11 @@ import ScrollbarInfo from "@/components/ScrollbarInfo.vue";
|
||||
import BottomInfo from "@/components/BottomInfo.vue";
|
||||
import VisitsLineChart from "./components/VisitsLineChart/index.vue";
|
||||
import AccessLogChart from "./components/AccessLogChart/Index.vue"
|
||||
import { access, getAccessList } from "@/apis/accessApi.js";
|
||||
import { getList } from "@/apis/plateApi.js";
|
||||
import { getList as bannerGetList } from "@/apis/bannerApi.js";
|
||||
import { getHomeDiscuss } from "@/apis/discussApi.js";
|
||||
import { getWeek } from "@/apis/accessApi.js";
|
||||
import {access, getAccessList} from "@/apis/accessApi.js";
|
||||
import {getList} from "@/apis/plateApi.js";
|
||||
import {getList as bannerGetList} from "@/apis/bannerApi.js";
|
||||
import {getHomeDiscuss} from "@/apis/discussApi.js";
|
||||
import {getWeek} from "@/apis/accessApi.js";
|
||||
import {
|
||||
getRecommendedTopic,
|
||||
getRecommendedFriend,
|
||||
@@ -208,7 +213,7 @@ import {
|
||||
getUserAnalyse,
|
||||
getRegisterAnalyse
|
||||
} from "@/apis/analyseApi.js";
|
||||
import { getList as getAllDiscussList } from "@/apis/discussApi.js";
|
||||
import {getList as getAllDiscussList} from "@/apis/discussApi.js";
|
||||
import PointsRanking from "./components/PointsRanking/index.vue";
|
||||
import RecommendFriend from "./components/RecommendFriend/index.vue";
|
||||
import ThemeData from "./components/RecommendTheme/index.vue";
|
||||
@@ -238,15 +243,15 @@ const userAnalyseInfo = ref({});
|
||||
const onlineNumber = ref(0);
|
||||
const accessLogTab = ref()
|
||||
const activeList = [
|
||||
{ name: "签到", path: "/activity/sign", icon: "Present" },
|
||||
{ name: "等级", path: "/activity/level", icon: "Ticket" },
|
||||
{ name: "大转盘", path: "/activity/lucky", icon: "Sunny" },
|
||||
{ name: "银行", path: "/activity/bank", icon: "CreditCard" },
|
||||
{name: "签到", path: "/activity/sign", icon: "Present"},
|
||||
{name: "等级", path: "/activity/level", icon: "Ticket"},
|
||||
{name: "大转盘", path: "/activity/lucky", icon: "Sunny"},
|
||||
{name: "银行", path: "/activity/bank", icon: "CreditCard"},
|
||||
|
||||
{ name: "任务", path: "/activity/sign", icon: "Memo" },
|
||||
{ name: "排行榜", path: "/money", icon: "Money" },
|
||||
{ name: "开始", path: "/start", icon: "Position" },
|
||||
{ name: "聊天室", path: "/chat", icon: "ChatRound" },
|
||||
{name: "任务", path: "/activity/assignment", icon: "Memo"},
|
||||
{name: "排行榜", path: "/money", icon: "Money"},
|
||||
{name: "开始", path: "/start", icon: "Position"},
|
||||
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
||||
];
|
||||
|
||||
//主题查询参数
|
||||
@@ -256,37 +261,38 @@ const query = reactive({
|
||||
isTop: true,
|
||||
});
|
||||
|
||||
const weekQuery = reactive({accessLogType: "Request"});
|
||||
//初始化
|
||||
onMounted(async () => {
|
||||
access();
|
||||
const { data: plateData } = await getList();
|
||||
const {data: plateData} = await getList();
|
||||
plateList.value = plateData.items;
|
||||
const { data: discussData, config: discussConfig } = await getHomeDiscuss();
|
||||
const {data: discussData, config: discussConfig} = await getHomeDiscuss();
|
||||
discussList.value = discussData;
|
||||
isDiscussFinished.value = discussConfig.isFinish;
|
||||
const { data: bannerData } = await bannerGetList();
|
||||
const {data: bannerData} = await bannerGetList();
|
||||
bannerList.value = bannerData.items;
|
||||
const { data: weekData } = await getWeek();
|
||||
const {data: weekData} = await getWeek(weekQuery);
|
||||
weekList.value = weekData;
|
||||
const { data: pointData, config: pointConfig } = await getRankingPoints();
|
||||
const {data: pointData, config: pointConfig} = await getRankingPoints();
|
||||
pointList.value = pointData.items;
|
||||
isPointFinished.value = pointConfig.isFinish;
|
||||
const { data: friendData, config: friendConfig } =
|
||||
await getRecommendedFriend();
|
||||
const {data: friendData, config: friendConfig} =
|
||||
await getRecommendedFriend();
|
||||
friendList.value = friendData;
|
||||
isFriendFinished.value = friendConfig.isFinish;
|
||||
const { data: themeData, config: themeConfig } = await getRecommendedTopic();
|
||||
const {data: themeData, config: themeConfig} = await getRecommendedTopic();
|
||||
themeList.value = themeData;
|
||||
isThemeFinished.value = themeConfig.isFinish;
|
||||
const { data: allDiscussData, config: allDiscussConfig } =
|
||||
await getAllDiscussList({
|
||||
Type: 0,
|
||||
skipCount: 1,
|
||||
maxResultCount: 30,
|
||||
});
|
||||
const {data: allDiscussData, config: allDiscussConfig} =
|
||||
await getAllDiscussList({
|
||||
Type: 0,
|
||||
skipCount: 1,
|
||||
maxResultCount: 30,
|
||||
});
|
||||
isAllDiscussFinished.value = allDiscussConfig.isFinish;
|
||||
allDiscussList.value = allDiscussData.items;
|
||||
const { data: userAnalyseInfoData } = await getUserAnalyse();
|
||||
const {data: userAnalyseInfoData} = await getUserAnalyse();
|
||||
onlineNumber.value = userAnalyseInfoData.onlineNumber;
|
||||
userAnalyseInfo.value = userAnalyseInfoData;
|
||||
});
|
||||
@@ -361,29 +367,28 @@ const handleToRouter = (path) => {
|
||||
// 推送的实时人数获取
|
||||
const currentOnlineNum = computed(() => useSocketStore().getOnlineNum());
|
||||
watch(
|
||||
() => currentOnlineNum.value,
|
||||
(val) => {
|
||||
onlineNumber.value = val;
|
||||
},
|
||||
{ deep: true }
|
||||
() => currentOnlineNum.value,
|
||||
(val) => {
|
||||
onlineNumber.value = val;
|
||||
},
|
||||
{deep: true}
|
||||
);
|
||||
watch(
|
||||
() => accessLogTab.value,
|
||||
async (value) => {
|
||||
switch (value) {
|
||||
case "AccessLogChart":
|
||||
const { data } = await getAccessList();
|
||||
accessAllList.value = data;
|
||||
() => accessLogTab.value,
|
||||
async (value) => {
|
||||
switch (value) {
|
||||
case "AccessLogChart":
|
||||
const {data} = await getAccessList(weekQuery);
|
||||
accessAllList.value = data;
|
||||
|
||||
break;
|
||||
case "RegisterChart":
|
||||
const { data: registerUserListData } = await getRegisterAnalyse();
|
||||
registerAllList.value = registerUserListData;
|
||||
break;
|
||||
case "RegisterChart":
|
||||
const {data: registerUserListData} = await getRegisterAnalyse();
|
||||
registerAllList.value = registerUserListData;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
const onClickAccessLog = async () => {
|
||||
accessLogDialogVisible.value = true;
|
||||
@@ -391,6 +396,17 @@ const onClickAccessLog = async () => {
|
||||
|
||||
}
|
||||
|
||||
//切换统计开关
|
||||
const onClickWeekSwitch = async () => {
|
||||
if (weekQuery.accessLogType === "HomeClick") {
|
||||
weekQuery.accessLogType= "Request";
|
||||
} else if (weekQuery.accessLogType === "Request") {
|
||||
weekQuery.accessLogType = "HomeClick";
|
||||
}
|
||||
|
||||
const {data: weekData} = await getWeek(weekQuery);
|
||||
weekList.value = weekData;
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.home-box {
|
||||
@@ -535,10 +551,17 @@ const onClickAccessLog = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
.VisitsLineChart>>>.el-card__body {
|
||||
.VisitsLineChart > > > .el-card__body {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
.VisitsLineChart p{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.statisChart {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
@@ -550,6 +573,7 @@ const onClickAccessLog = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//走马灯,聊天室链接
|
||||
.chat-hub {
|
||||
background-color: #E6A23C;
|
||||
|
||||
113
Yi.Bbs.Vue3/src/views/money/Index.vue
Normal file
113
Yi.Bbs.Vue3/src/views/money/Index.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<script setup>
|
||||
import AwardPedestal from "./components/AwardPedestal.vue";
|
||||
import AvatarInfo from "@/components/AvatarInfo.vue";
|
||||
import { onMounted, reactive, ref, computed } from "vue";
|
||||
import {
|
||||
getRankingPoints,
|
||||
} from "@/apis/analyseApi.js";
|
||||
const pointList = ref([]);
|
||||
const total = ref(0);
|
||||
const moneyQuery = reactive({ skipCount: 1, maxResultCount: 30 });
|
||||
|
||||
const isFirstPage = computed(() => {
|
||||
return moneyQuery.skipCount == 1;
|
||||
})
|
||||
|
||||
const pointListFilter=computed(() => {
|
||||
//如果是第一页,去掉前3个
|
||||
if(moneyQuery.skipCount == 1)
|
||||
{
|
||||
return pointList.value.slice(3);
|
||||
}
|
||||
return pointList.value;
|
||||
})
|
||||
|
||||
|
||||
//初始化
|
||||
onMounted(async () => {
|
||||
await initData();
|
||||
});
|
||||
|
||||
const initData = async () => {
|
||||
const { data: pointData } = await getRankingPoints(moneyQuery);
|
||||
pointList.value = pointData.items;;
|
||||
total.value = pointData.totalCount
|
||||
}
|
||||
//分页事件
|
||||
const changePage = async (currentPage) => {
|
||||
await initData();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="content-body">
|
||||
<AwardPedestal v-show="isFirstPage" :goldUserInfo="pointList[0]" :silverUserInfo="pointList[1]"
|
||||
:bronzeUserInfo="pointList[2]" />
|
||||
<div v-for="item in pointListFilter" :key="item.id" class="list-div">
|
||||
<div class="list-left">
|
||||
<span> {{ item.order }}</span>
|
||||
<AvatarInfo :userInfo="item" :isSelf="false" />
|
||||
<span class="money">
|
||||
{{ item.money }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="list-right">
|
||||
关注
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
|
||||
:page-sizes="[10, 30, 50, 100]" v-model:current-page="moneyQuery.skipCount"
|
||||
v-model:page-size="moneyQuery.maxResultCount" @current-change="changePage" @size-change="changePage" />
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.el-pagination {
|
||||
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content-body {
|
||||
margin-bottom: 40px;
|
||||
margin-top: 20px;
|
||||
padding: 20px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.list-div {
|
||||
justify-content: space-between;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
height: 80px;
|
||||
width: 850px;
|
||||
cursor: pointer;
|
||||
padding: 16px 12px;
|
||||
|
||||
.list-left {
|
||||
display: flex;
|
||||
|
||||
span {
|
||||
margin-right: 20px;
|
||||
color: #515767;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
line-height: 2rem;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.money {
|
||||
font-size: 1.0rem;
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-div:hover {
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
</style>
|
||||
92
Yi.Bbs.Vue3/src/views/money/components/AwardPedestal.vue
Normal file
92
Yi.Bbs.Vue3/src/views/money/components/AwardPedestal.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<script setup>
|
||||
import AvatarInfo from "@/components/AvatarInfo.vue";
|
||||
const props = defineProps([
|
||||
"goldUserInfo",
|
||||
"silverUserInfo",
|
||||
"bronzeUserInfo",
|
||||
]);
|
||||
</script>
|
||||
<template>
|
||||
<div class="podium">
|
||||
<div class="avatar">
|
||||
<AvatarInfo :userInfo="silverUserInfo" :isSelf="true" />
|
||||
<div class="tier silver">
|
||||
<h2>第二</h2>
|
||||
<h3>{{ silverUserInfo?.money }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="avatar">
|
||||
<AvatarInfo :userInfo="goldUserInfo" :isSelf="true" :size="50" />
|
||||
<div class="tier gold">
|
||||
<h2>第一</h2>
|
||||
<h3>{{ goldUserInfo?.money }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="avatar">
|
||||
<AvatarInfo :userInfo="bronzeUserInfo" :isSelf="true" />
|
||||
<div class="tier bronze">
|
||||
<h2>第三</h2>
|
||||
<h3>{{ bronzeUserInfo?.money }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
h2{
|
||||
margin: 10px;
|
||||
}
|
||||
h3{
|
||||
margin: 10px;
|
||||
}
|
||||
.avatar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.podium {
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tier {
|
||||
flex-direction: column;
|
||||
width: 150px;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 5px 40px 40px 40px;
|
||||
border-radius: 20px;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gold:hover {
|
||||
box-shadow: 0 0 20px 10px rgba(255, 215, 0, 0.7); /* 金色光辉效果 */
|
||||
}
|
||||
|
||||
.gold {
|
||||
background: linear-gradient(to bottom, #ffd700 0%, #ffcc00 100%);
|
||||
height: 250px;
|
||||
box-shadow: 0 8px 20px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
.silver {
|
||||
background: linear-gradient(to bottom, #c0c0c0 0%, #d3d3d3 100%);
|
||||
height: 200px;
|
||||
box-shadow: 0 6px 18px rgba(192, 192, 192, 0.5);
|
||||
}
|
||||
|
||||
.bronze {
|
||||
background: linear-gradient(to bottom, #cd7f32 0%, #a0522d 100%);
|
||||
height: 170px;
|
||||
box-shadow: 0 4px 16px rgba(205, 127, 50, 0.5);
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user