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
|
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 Volo.Abp.Application.Dtos;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
||||||
|
|
||||||
public class AssignmentGetListOutputDto:EntityDto<Guid>
|
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.Dtos.AccessLog;
|
||||||
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
||||||
using Yi.Framework.Bbs.Domain.Entities;
|
using Yi.Framework.Bbs.Domain.Entities;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Services
|
namespace Yi.Framework.Bbs.Application.Services
|
||||||
@@ -11,7 +12,11 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
public class AccessLogService : ApplicationService, IAccessLogService
|
public class AccessLogService : ApplicationService, IAccessLogService
|
||||||
{
|
{
|
||||||
private readonly ISqlSugarRepository<AccessLogAggregateRoot> _repository;
|
private readonly ISqlSugarRepository<AccessLogAggregateRoot> _repository;
|
||||||
public AccessLogService(ISqlSugarRepository<AccessLogAggregateRoot> repository) { _repository = repository; }
|
|
||||||
|
public AccessLogService(ISqlSugarRepository<AccessLogAggregateRoot> repository)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
public DateTime GetWeekFirst()
|
public DateTime GetWeekFirst()
|
||||||
{
|
{
|
||||||
@@ -45,16 +50,15 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取全部访问流量(3个月)
|
/// 获取全部访问流量(3个月)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="AccessLogType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<AccessLogDto>> Get()
|
public async Task<List<AccessLogDto>> GetListAsync([FromQuery] AccessLogTypeEnum accessLogType)
|
||||||
{
|
{
|
||||||
var entities = await _repository._DbQueryable
|
var entities = await _repository._DbQueryable.Where(x => x.AccessLogType == accessLogType)
|
||||||
.Where(x=>x.CreationTime>=DateTime.Now.AddMonths(-3))
|
.Where(x => x.CreationTime >= DateTime.Now.AddMonths(-3))
|
||||||
.OrderBy(x => x.CreationTime).ToListAsync();
|
.OrderBy(x => x.CreationTime).ToListAsync();
|
||||||
var output = entities.Adapt<List<AccessLogDto>>();
|
var output = entities.Adapt<List<AccessLogDto>>();
|
||||||
output?.ForEach(x => x.CreationTime = x.CreationTime.Date);
|
output?.ForEach(x => x.CreationTime = x.CreationTime.Date);
|
||||||
@@ -62,32 +66,35 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发
|
/// 首页点击触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("access-log")]
|
[HttpPost("access-log")]
|
||||||
public async Task AccessAsync()
|
public async Task AccessAsync()
|
||||||
{
|
{
|
||||||
//可判断http重复,防止同一ip多次访问
|
//可判断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)
|
if (last is null || last.CreationTime.Date != DateTime.Today)
|
||||||
{
|
{
|
||||||
await _repository.InsertAsync(new AccessLogAggregateRoot());
|
await _repository.InsertAsync(new AccessLogAggregateRoot(){AccessLogType=AccessLogTypeEnum.HomeClick});
|
||||||
}
|
}
|
||||||
else
|
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>
|
||||||
/// 获取当前周数据
|
/// 获取当前周首页点击数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <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());
|
return WeekTimeHandler(lastSeven.ToArray());
|
||||||
}
|
}
|
||||||
@@ -99,7 +106,8 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private AccessLogDto[] WeekTimeHandler(AccessLogAggregateRoot[] data)
|
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>();
|
Dictionary<DayOfWeek, AccessLogDto> processedData = new Dictionary<DayOfWeek, AccessLogDto>();
|
||||||
|
|
||||||
@@ -117,8 +125,8 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
// 如果当天有数据,则更新字典中的值为对应的Number
|
// 如果当天有数据,则更新字典中的值为对应的Number
|
||||||
var sss = data.Adapt<AccessLogDto>();
|
var sss = data.Adapt<AccessLogDto>();
|
||||||
processedData[dayOfWeek] = item.Adapt<AccessLogDto>();
|
processedData[dayOfWeek] = item.Adapt<AccessLogDto>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = processedData.Values.ToList();
|
var result = processedData.Values.ToList();
|
||||||
|
|
||||||
//此时的时间是周日-周一-周二,需要处理
|
//此时的时间是周日-周一-周二,需要处理
|
||||||
@@ -128,8 +136,5 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
|
|
||||||
return result.ToArray();
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Mapster;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Assignment;
|
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.Managers;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Services;
|
namespace Yi.Framework.Bbs.Application.Services;
|
||||||
|
|
||||||
@@ -26,26 +28,55 @@ public class AssignmentService : ApplicationService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
[HttpPost("assignment/accept/{id}")]
|
[HttpPost("assignment/accept/{id}")]
|
||||||
public async Task AcceptAsync(Guid id)
|
public async Task AcceptAsync([FromRoute] Guid id)
|
||||||
{
|
{
|
||||||
await _assignmentManager.AcceptAsync(CurrentUser.GetId(), id);
|
await _assignmentManager.AcceptAsync(CurrentUser.GetId(), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 接收任务奖励
|
/// 领取任务奖励
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
[HttpPost("assignment/receive-rewards/{id}")]
|
[HttpPost("assignment/complete/{id}")]
|
||||||
public async Task ReceiveRewardsAsync(Guid id)
|
public async Task ReceiveRewardsAsync([FromRoute] Guid id)
|
||||||
{
|
{
|
||||||
await _assignmentManager.ReceiveRewardsAsync(id);
|
await _assignmentManager.ReceiveRewardsAsync(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询任务
|
/// 查看可接受的任务
|
||||||
/// </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>
|
||||||
/// 已过期
|
/// 已过期
|
||||||
/// </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 SqlSugar;
|
||||||
using Volo.Abp.Auditing;
|
using Volo.Abp.Auditing;
|
||||||
using Volo.Abp.Domain.Entities;
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Domain.Entities
|
namespace Yi.Framework.Bbs.Domain.Entities
|
||||||
{
|
{
|
||||||
[SugarTable("AccessLog")]
|
[SugarTable("AccessLog")]
|
||||||
public class AccessLogAggregateRoot : AggregateRoot<Guid>, IHasModificationTime, IHasCreationTime
|
public class AccessLogAggregateRoot : AggregateRoot<Guid>, IHasCreationTime,IHasModificationTime
|
||||||
{
|
{
|
||||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||||
public override Guid Id { get; protected set; }
|
public override Guid Id { get; protected set; }
|
||||||
public long Number { get; set; }
|
public long Number { get; set; }
|
||||||
public DateTime? LastModificationTime { get; set; }
|
|
||||||
|
public AccessLogTypeEnum AccessLogType { get; set; }
|
||||||
public DateTime CreationTime { get; set; }
|
public DateTime CreationTime { get; set; }
|
||||||
|
public DateTime? LastModificationTime { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,32 +44,45 @@ public class AssignmentAggregateRoot : AggregateRoot<Guid>, IHasCreationTime, IO
|
|||||||
/// 任务奖励的钱钱数量
|
/// 任务奖励的钱钱数量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal RewardsMoneyNumber { get; set; }
|
public decimal RewardsMoneyNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务过期时间
|
/// 任务过期时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? ExpireTime { get; set; }
|
public DateTime? ExpireTime { get; set; }
|
||||||
|
|
||||||
public DateTime? CompleteTime { get; set; }
|
/// <summary>
|
||||||
|
/// 任务需求类型
|
||||||
|
/// </summary>
|
||||||
|
public AssignmentRequirementTypeEnum AssignmentRequirementType { get; set; }
|
||||||
|
|
||||||
|
public DateTime? EndTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public DateTime CreationTime { get; }
|
public DateTime CreationTime { get; set; }
|
||||||
public int OrderNum { get; set; }
|
public int OrderNum { get; set; }
|
||||||
public DateTime? LastModificationTime { get; }
|
public DateTime? LastModificationTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public bool IsAllowCompleted()
|
public bool IsAllowCompleted()
|
||||||
{
|
{
|
||||||
return AssignmentState == AssignmentStateEnum.Progress && this.CurrentStepNumber == this.TotalStepNumber;
|
return AssignmentState == AssignmentStateEnum.Completed && this.CurrentStepNumber == this.TotalStepNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TrySetExpire()
|
public bool TrySetExpire()
|
||||||
{
|
{
|
||||||
if (ExpireTime<=DateTime.Now)
|
if (ExpireTime <= DateTime.Now)
|
||||||
{
|
{
|
||||||
|
//现在时间已经大于过期时间
|
||||||
AssignmentState = AssignmentStateEnum.Expired;
|
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>
|
/// </summary>
|
||||||
public AssignmentTypeEnum AssignmentType{ get; set; }
|
public AssignmentTypeEnum AssignmentType{ get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务需求类型
|
||||||
|
/// </summary>
|
||||||
|
public AssignmentRequirementTypeEnum AssignmentRequirementType{ get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 总共步骤数
|
/// 总共步骤数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -46,6 +51,6 @@ public class AssignmentDefineAggregateRoot: AggregateRoot<Guid>, IHasCreationTim
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal RewardsMoneyNumber { get; set; }
|
public decimal RewardsMoneyNumber { get; set; }
|
||||||
|
|
||||||
public DateTime CreationTime { get; }
|
public DateTime CreationTime{ get; set; }
|
||||||
public int OrderNum { 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;
|
||||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
using Yi.Framework.Rbac.Domain.Entities;
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
@@ -14,20 +15,24 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 被点赞
|
/// 被点赞
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AgreeCreatedEventHandler : ILocalEventHandler<EntityCreatedEventData<AgreeEntity>>,
|
public class AgreeChangeEventHandler : ILocalEventHandler<EntityCreatedEventData<AgreeEntity>>,
|
||||||
ITransientDependency
|
ITransientDependency
|
||||||
{
|
{
|
||||||
private ISqlSugarRepository<UserAggregateRoot> _userRepository;
|
private ISqlSugarRepository<UserAggregateRoot> _userRepository;
|
||||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userInfoRepository;
|
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userInfoRepository;
|
||||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||||
private ILocalEventBus _localEventBus;
|
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;
|
_userInfoRepository = userInfoRepository;
|
||||||
_agreeRepository = agreeRepository;
|
_agreeRepository = agreeRepository;
|
||||||
_localEventBus = localEventBus;
|
_localEventBus = localEventBus;
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleEventAsync(EntityCreatedEventData<AgreeEntity> eventData)
|
public async Task HandleEventAsync(EntityCreatedEventData<AgreeEntity> eventData)
|
||||||
{
|
{
|
||||||
var agreeEntity = eventData.Entity;
|
var agreeEntity = eventData.Entity;
|
||||||
@@ -35,55 +40,66 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
|||||||
//查询主题的信息
|
//查询主题的信息
|
||||||
var discussAndAgreeDto = await _agreeRepository._DbQueryable
|
var discussAndAgreeDto = await _agreeRepository._DbQueryable
|
||||||
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||||
.Select((agree, discuss) =>
|
.Select((agree, discuss) =>
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
DiscussId=discuss.Id,
|
DiscussId = discuss.Id,
|
||||||
DiscussTitle = discuss.Title,
|
DiscussTitle = discuss.Title,
|
||||||
DiscussCreatorId = discuss.CreatorId,
|
DiscussCreatorId = discuss.CreatorId,
|
||||||
})
|
})
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
//查询点赞者用户
|
//查询点赞者用户
|
||||||
var agreeUser = await _userRepository.GetFirstAsync(x => x.Id == agreeEntity.CreatorId);
|
var agreeUser = await _userRepository.GetFirstAsync(x => x.Id == agreeEntity.CreatorId);
|
||||||
|
|
||||||
//给创建者点赞数量+1
|
//给创建者点赞数量+1
|
||||||
await _userInfoRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
await _userInfoRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber + 1)
|
.SetColumns(it => it.AgreeNumber == it.AgreeNumber + 1)
|
||||||
.Where(it => it.UserId == discussAndAgreeDto.DiscussCreatorId)
|
.Where(it => it.UserId == discussAndAgreeDto.DiscussCreatorId)
|
||||||
.ExecuteCommandAsync();
|
.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>
|
||||||
/// 取消点赞
|
/// 取消点赞
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AgreeDeletedEventHandler : ILocalEventHandler<EntityDeletedEventData<AgreeEntity>>,
|
public class AgreeDeletedEventHandler : ILocalEventHandler<EntityDeletedEventData<AgreeEntity>>,
|
||||||
ITransientDependency
|
ITransientDependency
|
||||||
{
|
{
|
||||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
||||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||||
private ILocalEventBus _localEventBus;
|
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;
|
_userRepository = userRepository;
|
||||||
_agreeRepository = agreeRepository;
|
_agreeRepository = agreeRepository;
|
||||||
_localEventBus = localEventBus;
|
_localEventBus = localEventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleEventAsync(EntityDeletedEventData<AgreeEntity> eventData)
|
public async Task HandleEventAsync(EntityDeletedEventData<AgreeEntity> eventData)
|
||||||
{
|
{
|
||||||
var agreeEntity = eventData.Entity;
|
var agreeEntity = eventData.Entity;
|
||||||
var userId = await _agreeRepository._DbQueryable.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
var userId = await _agreeRepository._DbQueryable
|
||||||
.Select((agree, discuss) => discuss.CreatorId).FirstAsync();
|
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||||
|
.Select((agree, discuss) => discuss.CreatorId).FirstAsync();
|
||||||
|
|
||||||
//给创建者点赞数量-1
|
//给创建者点赞数量-1
|
||||||
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||||
.SetColumns(it => it.AgreeNumber == it.AgreeNumber - 1)
|
.SetColumns(it => it.AgreeNumber == it.AgreeNumber - 1)
|
||||||
.Where(it => it.UserId == userId)
|
.Where(it => it.UserId == userId)
|
||||||
.ExecuteCommandAsync();
|
.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;
|
||||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
using Yi.Framework.Rbac.Domain.Entities;
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
@@ -63,6 +64,10 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//最后发布任务触发事件
|
||||||
|
await _localEventBus.PublishAsync(
|
||||||
|
new AssignmentEventArgs(AssignmentRequirementTypeEnum.Comment, commentUser.Id),false);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
using Volo.Abp.Domain.Entities.Events;
|
using Volo.Abp.Domain.Entities.Events;
|
||||||
using Volo.Abp.EventBus;
|
using Volo.Abp.EventBus;
|
||||||
|
using Volo.Abp.EventBus.Local;
|
||||||
using Yi.Framework.Bbs.Domain.Entities;
|
using Yi.Framework.Bbs.Domain.Entities;
|
||||||
using Yi.Framework.Bbs.Domain.Entities.Forum;
|
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;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Domain.EventHandlers
|
namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||||
@@ -11,22 +14,31 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
|||||||
/// 主题创建的领域事件
|
/// 主题创建的领域事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DiscussCreatedEventHandler : ILocalEventHandler<EntityCreatedEventData<DiscussAggregateRoot>>,
|
public class DiscussCreatedEventHandler : ILocalEventHandler<EntityCreatedEventData<DiscussAggregateRoot>>,
|
||||||
ITransientDependency
|
ITransientDependency
|
||||||
{
|
{
|
||||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userRepository;
|
||||||
public DiscussCreatedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository)
|
private ILocalEventBus _localEventBus;
|
||||||
|
|
||||||
|
public DiscussCreatedEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userRepository,
|
||||||
|
ILocalEventBus localEventBus)
|
||||||
{
|
{
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
|
_localEventBus = localEventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleEventAsync(EntityCreatedEventData<DiscussAggregateRoot> eventData)
|
public async Task HandleEventAsync(EntityCreatedEventData<DiscussAggregateRoot> eventData)
|
||||||
{
|
{
|
||||||
var disucussEntity = eventData.Entity;
|
var disucussEntity = eventData.Entity;
|
||||||
|
|
||||||
//给创建者发布数量+1
|
//给创建者发布数量+1
|
||||||
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
await _userRepository._Db.Updateable<BbsUserExtraInfoEntity>()
|
||||||
.SetColumns(it => it.DiscussNumber == it.DiscussNumber + 1)
|
.SetColumns(it => it.DiscussNumber == it.DiscussNumber + 1)
|
||||||
.Where(it => it.UserId == disucussEntity.CreatorId)
|
.Where(it => it.UserId == disucussEntity.CreatorId)
|
||||||
.ExecuteCommandAsync();
|
.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
|
public class AssignmentManager : DomainService
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<IAssignmentProvider> _assignmentProviders;
|
private readonly IEnumerable<IAssignmentProvider> _assignmentProviders;
|
||||||
private readonly ISqlSugarRepository<AssignmentAggregateRoot> _assignmentRepository;
|
public readonly ISqlSugarRepository<AssignmentAggregateRoot> _assignmentRepository;
|
||||||
private readonly ISqlSugarRepository<AssignmentDefineAggregateRoot> _assignmentDefineRepository;
|
public readonly ISqlSugarRepository<AssignmentDefineAggregateRoot> _assignmentDefineRepository;
|
||||||
private readonly ILocalEventBus _localEventBus;
|
private readonly ILocalEventBus _localEventBus;
|
||||||
|
|
||||||
public AssignmentManager(IEnumerable<IAssignmentProvider> assignmentProviders,
|
public AssignmentManager(IEnumerable<IAssignmentProvider> assignmentProviders,
|
||||||
@@ -52,6 +52,7 @@ public class AssignmentManager : DomainService
|
|||||||
entity.CurrentStepNumber = 0;
|
entity.CurrentStepNumber = 0;
|
||||||
entity.TotalStepNumber = assignmentDefine.TotalStepNumber;
|
entity.TotalStepNumber = assignmentDefine.TotalStepNumber;
|
||||||
entity.RewardsMoneyNumber = assignmentDefine.RewardsMoneyNumber;
|
entity.RewardsMoneyNumber = assignmentDefine.RewardsMoneyNumber;
|
||||||
|
entity.AssignmentRequirementType = assignmentDefine.AssignmentRequirementType;
|
||||||
entity.ExpireTime = assignmentDefine.AssignmentType.GetExpireTime();
|
entity.ExpireTime = assignmentDefine.AssignmentType.GetExpireTime();
|
||||||
await _assignmentRepository.InsertAsync(entity);
|
await _assignmentRepository.InsertAsync(entity);
|
||||||
}
|
}
|
||||||
@@ -68,11 +69,18 @@ public class AssignmentManager : DomainService
|
|||||||
var assignment = await _assignmentRepository.GetByIdAsync(asignmentId);
|
var assignment = await _assignmentRepository.GetByIdAsync(asignmentId);
|
||||||
if (assignment.IsAllowCompleted())
|
if (assignment.IsAllowCompleted())
|
||||||
{
|
{
|
||||||
//设置已完成,并领取奖励,钱钱
|
|
||||||
assignment.AssignmentState = AssignmentStateEnum.Completed;
|
|
||||||
//加钱加钱
|
//加钱加钱
|
||||||
await _localEventBus.PublishAsync(
|
await _localEventBus.PublishAsync(
|
||||||
new MoneyChangeEventArgs { UserId = assignment.UserId, Number = assignment.RewardsMoneyNumber }, false);
|
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.AddRange(await assignmentProvider.GetCanReceiveListAsync(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
output.DistinctBy(x => x.Id);
|
output = output.DistinctBy(x => x.Id).OrderBy(x => x.OrderNum).ToList();
|
||||||
throw new NotImplementedException();
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -134,6 +142,5 @@ public class AssignmentManager : DomainService
|
|||||||
{
|
{
|
||||||
await _assignmentRepository._Db.Updateable(needUpdateEntities).ExecuteCommandAsync();
|
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;
|
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 每日任务提供者
|
/// 每日任务提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ExposeServices(typeof(IAssignmentProvider))]
|
||||||
public class DailyProvider : TimerProvider
|
public class DailyProvider : TimerProvider
|
||||||
{
|
{
|
||||||
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Daily;
|
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Daily;
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 新手任务提供者
|
/// 新手任务提供者
|
||||||
/// </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;
|
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 每周任务提供者
|
/// 每周任务提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ExposeServices(typeof(IAssignmentProvider))]
|
||||||
public class WeeklyProvider : TimerProvider
|
public class WeeklyProvider : TimerProvider
|
||||||
{
|
{
|
||||||
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Weekly;
|
protected override AssignmentTypeEnum AssignmentType => AssignmentTypeEnum.Weekly;
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ public abstract class TimerProvider : IAssignmentProvider
|
|||||||
//2: 存在已完成,但是完成时间是过期的
|
//2: 存在已完成,但是完成时间是过期的
|
||||||
var assignmentFilterIds = context.CurrentUserAssignments
|
var assignmentFilterIds = context.CurrentUserAssignments
|
||||||
.Where(x =>
|
.Where(x =>
|
||||||
//正在进行的,要去掉
|
//正在进行的,已经完成,要去掉
|
||||||
x.AssignmentState == AssignmentStateEnum.Progress||
|
x.AssignmentState == AssignmentStateEnum.Progress||
|
||||||
//已完成,但是还没过期,要去掉
|
x.AssignmentState==AssignmentStateEnum.Completed||
|
||||||
(x.AssignmentState == AssignmentStateEnum.Completed&&!AssignmentType.IsExpire(x.CompleteTime!.Value)))
|
//已结束,但是还没过期,要去掉
|
||||||
|
(x.AssignmentState == AssignmentStateEnum.End&&!AssignmentType.IsExpire(x.EndTime!.Value)))
|
||||||
.Select(x => x.AssignmentDefineId)
|
.Select(x => x.AssignmentDefineId)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class BankManager : DomainService
|
public class BankManager : DomainService
|
||||||
{
|
{
|
||||||
private const decimal DefalutRate = 1.3m;
|
private const decimal DefalutRate = 1.2m;
|
||||||
private ISqlSugarRepository<BankCardAggregateRoot> _repository;
|
private ISqlSugarRepository<BankCardAggregateRoot> _repository;
|
||||||
private ILocalEventBus _localEventBus;
|
private ILocalEventBus _localEventBus;
|
||||||
private ISqlSugarRepository<InterestRecordsAggregateRoot> _interestRepository;
|
private ISqlSugarRepository<InterestRecordsAggregateRoot> _interestRepository;
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
|||||||
private IDistributedCache<List<LevelCacheItem>> _levelCache;
|
private IDistributedCache<List<LevelCacheItem>> _levelCache;
|
||||||
private IRepository<LevelAggregateRoot> _repository;
|
private IRepository<LevelAggregateRoot> _repository;
|
||||||
private ISqlSugarRepository<BbsUserExtraInfoEntity> _bbsUserRepository;
|
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;
|
_localEventBus = localEventBus;
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
@@ -35,14 +37,14 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<Dictionary<int, LevelCacheItem>> GetCacheMapAsync()
|
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()
|
.OrderByDescending(x => x.CurrentLevel).ToList()
|
||||||
.Adapt<List<LevelCacheItem>>();
|
.Adapt<List<LevelCacheItem>>();
|
||||||
return cacheItem;
|
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)
|
public async Task ChangeLevelByMoneyAsync(Guid userId, int moneyNumber)
|
||||||
{
|
{
|
||||||
//通过用户id获取用户信息的经验和等级
|
//通过用户id获取用户信息的经验和等级
|
||||||
var userInfo = await _bbsUserRepository.GetAsync(x=>x.UserId==userId);
|
var userInfo = await _bbsUserRepository.GetAsync(x => x.UserId == userId);
|
||||||
|
|
||||||
//钱钱和经验的比例为1:1
|
//钱钱和经验的比例为1:1
|
||||||
//根据钱钱修改经验
|
//根据钱钱修改经验
|
||||||
@@ -63,7 +65,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
//更改最终的经验再变化等级
|
//更改最终的经验再变化等级
|
||||||
var levelList = (await GetCacheMapAsync()).Values;
|
var levelList = (await GetCacheMapAsync()).Values.OrderByDescending(x => x.CurrentLevel);
|
||||||
var currentNewLevel = 1;
|
var currentNewLevel = 1;
|
||||||
foreach (var level in levelList)
|
foreach (var level in levelList)
|
||||||
{
|
{
|
||||||
@@ -78,7 +80,7 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
|||||||
userInfo.Level = currentNewLevel;
|
userInfo.Level = currentNewLevel;
|
||||||
userInfo.Experience = currentNewExperience;
|
userInfo.Experience = currentNewExperience;
|
||||||
await _bbsUserRepository._Db.Updateable(userInfo)
|
await _bbsUserRepository._Db.Updateable(userInfo)
|
||||||
.UpdateColumns(it => new { it.Level,it.Experience })
|
.UpdateColumns(it => new { it.Level, it.Experience })
|
||||||
.ExecuteCommandAsync();
|
.ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
|
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Volo.Abp.AspNetCore.ExceptionHandling;
|
||||||
using Volo.Abp.AspNetCore.MultiTenancy;
|
using Volo.Abp.AspNetCore.MultiTenancy;
|
||||||
using Volo.Abp.AspNetCore.Mvc;
|
using Volo.Abp.AspNetCore.Mvc;
|
||||||
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
|
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.AspNetCore.Builder;
|
||||||
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
|
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
|
||||||
using Yi.Framework.Bbs.Application;
|
using Yi.Framework.Bbs.Application;
|
||||||
|
using Yi.Framework.Bbs.Application.Extensions;
|
||||||
using Yi.Framework.ChatHub.Application;
|
using Yi.Framework.ChatHub.Application;
|
||||||
using Yi.Framework.CodeGen.Application;
|
using Yi.Framework.CodeGen.Application;
|
||||||
using Yi.Framework.Rbac.Application;
|
using Yi.Framework.Rbac.Application;
|
||||||
@@ -38,8 +40,6 @@ namespace Yi.Abp.Web
|
|||||||
[DependsOn(
|
[DependsOn(
|
||||||
typeof(YiAbpSqlSugarCoreModule),
|
typeof(YiAbpSqlSugarCoreModule),
|
||||||
typeof(YiAbpApplicationModule),
|
typeof(YiAbpApplicationModule),
|
||||||
|
|
||||||
|
|
||||||
typeof(AbpAspNetCoreMultiTenancyModule),
|
typeof(AbpAspNetCoreMultiTenancyModule),
|
||||||
typeof(AbpAspNetCoreMvcModule),
|
typeof(AbpAspNetCoreMvcModule),
|
||||||
typeof(AbpAutofacModule),
|
typeof(AbpAutofacModule),
|
||||||
@@ -49,11 +49,11 @@ namespace Yi.Abp.Web
|
|||||||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
|
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
|
||||||
typeof(YiFrameworkAspNetCoreModule),
|
typeof(YiFrameworkAspNetCoreModule),
|
||||||
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
|
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
|
||||||
|
)]
|
||||||
)]
|
|
||||||
public class YiAbpWebModule : AbpModule
|
public class YiAbpWebModule : AbpModule
|
||||||
{
|
{
|
||||||
private const string DefaultCorsPolicyName = "Default";
|
private const string DefaultCorsPolicyName = "Default";
|
||||||
|
|
||||||
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
|
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
|
||||||
{
|
{
|
||||||
var configuration = context.Services.GetConfiguration();
|
var configuration = context.Services.GetConfiguration();
|
||||||
@@ -68,15 +68,24 @@ namespace Yi.Abp.Web
|
|||||||
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
|
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//配置错误处理显示详情
|
||||||
|
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
|
||||||
|
|
||||||
//动态Api
|
//动态Api
|
||||||
Configure<AbpAspNetCoreMvcOptions>(options =>
|
Configure<AbpAspNetCoreMvcOptions>(options =>
|
||||||
{
|
{
|
||||||
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly, options => options.RemoteServiceName = "default");
|
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly,
|
||||||
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly, options => options.RemoteServiceName = "rbac");
|
options => options.RemoteServiceName = "default");
|
||||||
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly, options => options.RemoteServiceName = "bbs");
|
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly,
|
||||||
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly, options => options.RemoteServiceName = "chat-hub");
|
options => options.RemoteServiceName = "rbac");
|
||||||
options.ConventionalControllers.Create(typeof(YiFrameworkTenantManagementApplicationModule).Assembly, options => options.RemoteServiceName = "tenant-management");
|
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly,
|
||||||
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly, options => options.RemoteServiceName = "code-gen");
|
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");
|
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
|
||||||
@@ -91,22 +100,20 @@ namespace Yi.Abp.Web
|
|||||||
|
|
||||||
//设置缓存不要过期,默认滑动20分钟
|
//设置缓存不要过期,默认滑动20分钟
|
||||||
Configure<AbpDistributedCacheOptions>(cacheOptions =>
|
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
|
//Swagger
|
||||||
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
|
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 = "集大成者" });
|
||||||
});
|
});
|
||||||
|
|
||||||
//跨域
|
//跨域
|
||||||
@@ -153,6 +160,7 @@ namespace Yi.Abp.Web
|
|||||||
context.HttpContext.Response.Headers.RetryAfter =
|
context.HttpContext.Response.Headers.RetryAfter =
|
||||||
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
|
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
||||||
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
|
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
|
||||||
|
|
||||||
@@ -161,20 +169,20 @@ namespace Yi.Abp.Web
|
|||||||
|
|
||||||
//全局使用,链式表达式
|
//全局使用,链式表达式
|
||||||
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
|
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
|
||||||
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
||||||
{
|
{
|
||||||
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
||||||
|
|
||||||
return RateLimitPartition.GetSlidingWindowLimiter
|
return RateLimitPartition.GetSlidingWindowLimiter
|
||||||
(userAgent, _ =>
|
(userAgent, _ =>
|
||||||
new SlidingWindowRateLimiterOptions
|
new SlidingWindowRateLimiterOptions
|
||||||
{
|
{
|
||||||
PermitLimit = 1000,
|
PermitLimit = 1000,
|
||||||
Window = TimeSpan.FromSeconds(60),
|
Window = TimeSpan.FromSeconds(60),
|
||||||
SegmentsPerWindow = 6,
|
SegmentsPerWindow = 6,
|
||||||
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
|
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -196,14 +204,15 @@ namespace Yi.Abp.Web
|
|||||||
options.Events = new JwtBearerEvents
|
options.Events = new JwtBearerEvents
|
||||||
{
|
{
|
||||||
OnMessageReceived = context =>
|
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 =>
|
.AddJwtBearer(TokenTypeConst.Refresh, options =>
|
||||||
@@ -214,37 +223,32 @@ namespace Yi.Abp.Web
|
|||||||
ValidateIssuerSigningKey = true,
|
ValidateIssuerSigningKey = true,
|
||||||
ValidIssuer = refreshJwtOptions.Issuer,
|
ValidIssuer = refreshJwtOptions.Issuer,
|
||||||
ValidAudience = refreshJwtOptions.Audience,
|
ValidAudience = refreshJwtOptions.Audience,
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
IssuerSigningKey =
|
||||||
|
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
||||||
};
|
};
|
||||||
options.Events = new JwtBearerEvents
|
options.Events = new JwtBearerEvents
|
||||||
{
|
{
|
||||||
OnMessageReceived = context =>
|
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;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
var refreshToken = context.Request.Query["refresh_token"];
|
|
||||||
if (!string.IsNullOrEmpty(refreshToken))
|
|
||||||
{
|
|
||||||
context.Token = refreshToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})
|
})
|
||||||
.AddQQ(options =>
|
.AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
|
||||||
{
|
.AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
|
||||||
configuration.GetSection("OAuth:QQ").Bind(options);
|
|
||||||
})
|
|
||||||
.AddGitee(options =>
|
|
||||||
{
|
|
||||||
configuration.GetSection("OAuth:Gitee").Bind(options);
|
|
||||||
});
|
|
||||||
|
|
||||||
//授权
|
//授权
|
||||||
context.Services.AddAuthorization();
|
context.Services.AddAuthorization();
|
||||||
@@ -284,6 +288,9 @@ namespace Yi.Abp.Web
|
|||||||
//swagger
|
//swagger
|
||||||
app.UseYiSwagger();
|
app.UseYiSwagger();
|
||||||
|
|
||||||
|
//流量访问统计,需redis支持,否则不生效
|
||||||
|
app.UseAccessLog();
|
||||||
|
|
||||||
//请求处理
|
//请求处理
|
||||||
app.UseYiApiHandlinge();
|
app.UseYiApiHandlinge();
|
||||||
|
|
||||||
|
|||||||
@@ -9,16 +9,18 @@ export function access() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取本周数据
|
// 获取本周数据
|
||||||
export function getWeek() {
|
export function getWeek(data) {
|
||||||
return request({
|
return request({
|
||||||
url: "/access-log/week",
|
url: "/access-log/week",
|
||||||
method: "get",
|
method: "get",
|
||||||
|
params :data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 获取全部数据
|
// 获取全部数据
|
||||||
export function getAccessList() {
|
export function getAccessList(data) {
|
||||||
return request({
|
return request({
|
||||||
url: "/access-log",
|
url: "/access-log",
|
||||||
method: "get",
|
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 {
|
.el-divider {
|
||||||
margin: 0.2rem 0;
|
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 {
|
.card-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -52,9 +59,4 @@ const onClickText=()=>{
|
|||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-card {
|
|
||||||
width: 100%;
|
|
||||||
height: v-bind(height);
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
<el-icon>
|
<el-icon>
|
||||||
<Memo />
|
<Memo />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>任务列表(暂未开放)</span>
|
<span>任务列表</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item index="4" :route="{ path: '/activity/lucky' }">
|
<el-menu-item index="4" :route="{ path: '/activity/assignment' }">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<HelpFilled />
|
<HelpFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
|
|||||||
@@ -156,6 +156,14 @@ const router = createRouter({
|
|||||||
title: "银行",
|
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-row :gutter="20" class="top-div">
|
||||||
<el-col :span="17">
|
<el-col :span="17">
|
||||||
<div class="chat-hub">
|
<div class="chat-hub">
|
||||||
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家</p>
|
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar">
|
<div class="scrollbar">
|
||||||
<ScrollbarInfo />
|
<ScrollbarInfo/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-row class="left-div">
|
<el-row class="left-div">
|
||||||
@@ -14,23 +15,23 @@
|
|||||||
'padding-left': i % 3 == 1 ? 0 : 0.2 + 'rem',
|
'padding-left': i % 3 == 1 ? 0 : 0.2 + 'rem',
|
||||||
'padding-right': i % 3 == 0 ? 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>
|
</el-col>
|
||||||
<template v-if="isDiscussFinished">
|
<template v-if="isDiscussFinished">
|
||||||
<el-col :span="24" v-for="i in discussList" :key="i.id">
|
<el-col :span="24" v-for="i in discussList" :key="i.id">
|
||||||
<DisscussCard :discuss="i" />
|
<DisscussCard :discuss="i"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Skeleton :isBorder="true" />
|
<Skeleton :isBorder="true"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="isAllDiscussFinished">
|
<template v-if="isAllDiscussFinished">
|
||||||
<el-col :span="24" v-for="i in allDiscussList" :key="i.id">
|
<el-col :span="24" v-for="i in allDiscussList" :key="i.id">
|
||||||
<DisscussCard :discuss="i" />
|
<DisscussCard :discuss="i"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Skeleton :isBorder="true" />
|
<Skeleton :isBorder="true"/>
|
||||||
</template>
|
</template>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
<div class="carousel-font" :style="{ color: item.color }">
|
<div class="carousel-font" :style="{ color: item.color }">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</div>
|
</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-item>
|
||||||
</el-carousel>
|
</el-carousel>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -97,23 +98,26 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<InfoCard header="访问统计" class="VisitsLineChart" text="全站历史统计" @onClickText="onClickAccessLog">
|
<InfoCard header="访问统计" class="VisitsLineChart" text="全站历史统计" @onClickText="onClickAccessLog">
|
||||||
<template #content>
|
<template #content>
|
||||||
<VisitsLineChart :option="statisOptions" class="statisChart" />
|
<p class="switch-span" @click="onClickWeekSwitch">切换</p>
|
||||||
|
<VisitsLineChart :option="statisOptions" class="statisChart"/>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
|
|
||||||
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
||||||
<el-tabs v-model="accessLogTab">
|
<el-tabs v-model="accessLogTab">
|
||||||
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart" style="display: flex;justify-content: center;">
|
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart"
|
||||||
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;" />
|
style="display: flex;justify-content: center;">
|
||||||
|
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="注册统计(近3月)" name="RegisterChart" style="display: flex;justify-content: center;">
|
<el-tab-pane label="注册统计(近3月)" name="RegisterChart"
|
||||||
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;" />
|
style="display: flex;justify-content: center;">
|
||||||
|
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
@@ -129,16 +133,17 @@
|
|||||||
|
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<template v-if="isPointFinished">
|
<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">
|
<template #item="temp">
|
||||||
<PointsRanking :pointsData="temp" />
|
<PointsRanking :pointsData="temp"/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<InfoCard header="本月排行" text="更多">
|
<InfoCard header="本月排行" text="更多">
|
||||||
<template #content>
|
<template #content>
|
||||||
<Skeleton />
|
<Skeleton/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
@@ -148,14 +153,14 @@
|
|||||||
<template v-if="isFriendFinished">
|
<template v-if="isFriendFinished">
|
||||||
<InfoCard :items="friendList" header="推荐好友" text="更多" height="400">
|
<InfoCard :items="friendList" header="推荐好友" text="更多" height="400">
|
||||||
<template #item="temp">
|
<template #item="temp">
|
||||||
<RecommendFriend :friendData="temp" />
|
<RecommendFriend :friendData="temp"/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<InfoCard header="推荐好友" text="更多">
|
<InfoCard header="推荐好友" text="更多">
|
||||||
<template #content>
|
<template #content>
|
||||||
<Skeleton />
|
<Skeleton/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
@@ -164,21 +169,21 @@
|
|||||||
<template v-if="isThemeFinished">
|
<template v-if="isThemeFinished">
|
||||||
<InfoCard :items="themeList" header="推荐主题" text="更多" height="400">
|
<InfoCard :items="themeList" header="推荐主题" text="更多" height="400">
|
||||||
<template #item="temp">
|
<template #item="temp">
|
||||||
<ThemeData :themeData="temp" />
|
<ThemeData :themeData="temp"/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<InfoCard header="推荐主题" text="更多">
|
<InfoCard header="推荐主题" text="更多">
|
||||||
<template #content>
|
<template #content>
|
||||||
<Skeleton />
|
<Skeleton/>
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
</template>
|
</template>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="24" style="background: transparent">
|
<el-col :span="24" style="background: transparent">
|
||||||
<BottomInfo />
|
<BottomInfo/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -187,8 +192,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
|
import {onMounted, ref, reactive, computed, nextTick, watch} from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import DisscussCard from "@/components/DisscussCard.vue";
|
import DisscussCard from "@/components/DisscussCard.vue";
|
||||||
import InfoCard from "@/components/InfoCard.vue";
|
import InfoCard from "@/components/InfoCard.vue";
|
||||||
import PlateCard from "@/components/PlateCard.vue";
|
import PlateCard from "@/components/PlateCard.vue";
|
||||||
@@ -196,11 +201,11 @@ import ScrollbarInfo from "@/components/ScrollbarInfo.vue";
|
|||||||
import BottomInfo from "@/components/BottomInfo.vue";
|
import BottomInfo from "@/components/BottomInfo.vue";
|
||||||
import VisitsLineChart from "./components/VisitsLineChart/index.vue";
|
import VisitsLineChart from "./components/VisitsLineChart/index.vue";
|
||||||
import AccessLogChart from "./components/AccessLogChart/Index.vue"
|
import AccessLogChart from "./components/AccessLogChart/Index.vue"
|
||||||
import { access, getAccessList } from "@/apis/accessApi.js";
|
import {access, getAccessList} from "@/apis/accessApi.js";
|
||||||
import { getList } from "@/apis/plateApi.js";
|
import {getList} from "@/apis/plateApi.js";
|
||||||
import { getList as bannerGetList } from "@/apis/bannerApi.js";
|
import {getList as bannerGetList} from "@/apis/bannerApi.js";
|
||||||
import { getHomeDiscuss } from "@/apis/discussApi.js";
|
import {getHomeDiscuss} from "@/apis/discussApi.js";
|
||||||
import { getWeek } from "@/apis/accessApi.js";
|
import {getWeek} from "@/apis/accessApi.js";
|
||||||
import {
|
import {
|
||||||
getRecommendedTopic,
|
getRecommendedTopic,
|
||||||
getRecommendedFriend,
|
getRecommendedFriend,
|
||||||
@@ -208,7 +213,7 @@ import {
|
|||||||
getUserAnalyse,
|
getUserAnalyse,
|
||||||
getRegisterAnalyse
|
getRegisterAnalyse
|
||||||
} from "@/apis/analyseApi.js";
|
} 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 PointsRanking from "./components/PointsRanking/index.vue";
|
||||||
import RecommendFriend from "./components/RecommendFriend/index.vue";
|
import RecommendFriend from "./components/RecommendFriend/index.vue";
|
||||||
import ThemeData from "./components/RecommendTheme/index.vue";
|
import ThemeData from "./components/RecommendTheme/index.vue";
|
||||||
@@ -238,15 +243,15 @@ const userAnalyseInfo = ref({});
|
|||||||
const onlineNumber = ref(0);
|
const onlineNumber = ref(0);
|
||||||
const accessLogTab = ref()
|
const accessLogTab = ref()
|
||||||
const activeList = [
|
const activeList = [
|
||||||
{ name: "签到", path: "/activity/sign", icon: "Present" },
|
{name: "签到", path: "/activity/sign", icon: "Present"},
|
||||||
{ name: "等级", path: "/activity/level", icon: "Ticket" },
|
{name: "等级", path: "/activity/level", icon: "Ticket"},
|
||||||
{ name: "大转盘", path: "/activity/lucky", icon: "Sunny" },
|
{name: "大转盘", path: "/activity/lucky", icon: "Sunny"},
|
||||||
{ name: "银行", path: "/activity/bank", icon: "CreditCard" },
|
{name: "银行", path: "/activity/bank", icon: "CreditCard"},
|
||||||
|
|
||||||
{ name: "任务", path: "/activity/sign", icon: "Memo" },
|
{name: "任务", path: "/activity/assignment", icon: "Memo"},
|
||||||
{ name: "排行榜", path: "/money", icon: "Money" },
|
{name: "排行榜", path: "/money", icon: "Money"},
|
||||||
{ name: "开始", path: "/start", icon: "Position" },
|
{name: "开始", path: "/start", icon: "Position"},
|
||||||
{ name: "聊天室", path: "/chat", icon: "ChatRound" },
|
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
||||||
];
|
];
|
||||||
|
|
||||||
//主题查询参数
|
//主题查询参数
|
||||||
@@ -256,37 +261,38 @@ const query = reactive({
|
|||||||
isTop: true,
|
isTop: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const weekQuery = reactive({accessLogType: "Request"});
|
||||||
//初始化
|
//初始化
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
access();
|
access();
|
||||||
const { data: plateData } = await getList();
|
const {data: plateData} = await getList();
|
||||||
plateList.value = plateData.items;
|
plateList.value = plateData.items;
|
||||||
const { data: discussData, config: discussConfig } = await getHomeDiscuss();
|
const {data: discussData, config: discussConfig} = await getHomeDiscuss();
|
||||||
discussList.value = discussData;
|
discussList.value = discussData;
|
||||||
isDiscussFinished.value = discussConfig.isFinish;
|
isDiscussFinished.value = discussConfig.isFinish;
|
||||||
const { data: bannerData } = await bannerGetList();
|
const {data: bannerData} = await bannerGetList();
|
||||||
bannerList.value = bannerData.items;
|
bannerList.value = bannerData.items;
|
||||||
const { data: weekData } = await getWeek();
|
const {data: weekData} = await getWeek(weekQuery);
|
||||||
weekList.value = weekData;
|
weekList.value = weekData;
|
||||||
const { data: pointData, config: pointConfig } = await getRankingPoints();
|
const {data: pointData, config: pointConfig} = await getRankingPoints();
|
||||||
pointList.value = pointData.items;
|
pointList.value = pointData.items;
|
||||||
isPointFinished.value = pointConfig.isFinish;
|
isPointFinished.value = pointConfig.isFinish;
|
||||||
const { data: friendData, config: friendConfig } =
|
const {data: friendData, config: friendConfig} =
|
||||||
await getRecommendedFriend();
|
await getRecommendedFriend();
|
||||||
friendList.value = friendData;
|
friendList.value = friendData;
|
||||||
isFriendFinished.value = friendConfig.isFinish;
|
isFriendFinished.value = friendConfig.isFinish;
|
||||||
const { data: themeData, config: themeConfig } = await getRecommendedTopic();
|
const {data: themeData, config: themeConfig} = await getRecommendedTopic();
|
||||||
themeList.value = themeData;
|
themeList.value = themeData;
|
||||||
isThemeFinished.value = themeConfig.isFinish;
|
isThemeFinished.value = themeConfig.isFinish;
|
||||||
const { data: allDiscussData, config: allDiscussConfig } =
|
const {data: allDiscussData, config: allDiscussConfig} =
|
||||||
await getAllDiscussList({
|
await getAllDiscussList({
|
||||||
Type: 0,
|
Type: 0,
|
||||||
skipCount: 1,
|
skipCount: 1,
|
||||||
maxResultCount: 30,
|
maxResultCount: 30,
|
||||||
});
|
});
|
||||||
isAllDiscussFinished.value = allDiscussConfig.isFinish;
|
isAllDiscussFinished.value = allDiscussConfig.isFinish;
|
||||||
allDiscussList.value = allDiscussData.items;
|
allDiscussList.value = allDiscussData.items;
|
||||||
const { data: userAnalyseInfoData } = await getUserAnalyse();
|
const {data: userAnalyseInfoData} = await getUserAnalyse();
|
||||||
onlineNumber.value = userAnalyseInfoData.onlineNumber;
|
onlineNumber.value = userAnalyseInfoData.onlineNumber;
|
||||||
userAnalyseInfo.value = userAnalyseInfoData;
|
userAnalyseInfo.value = userAnalyseInfoData;
|
||||||
});
|
});
|
||||||
@@ -361,29 +367,28 @@ const handleToRouter = (path) => {
|
|||||||
// 推送的实时人数获取
|
// 推送的实时人数获取
|
||||||
const currentOnlineNum = computed(() => useSocketStore().getOnlineNum());
|
const currentOnlineNum = computed(() => useSocketStore().getOnlineNum());
|
||||||
watch(
|
watch(
|
||||||
() => currentOnlineNum.value,
|
() => currentOnlineNum.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
onlineNumber.value = val;
|
onlineNumber.value = val;
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{deep: true}
|
||||||
);
|
);
|
||||||
watch(
|
watch(
|
||||||
() => accessLogTab.value,
|
() => accessLogTab.value,
|
||||||
async (value) => {
|
async (value) => {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case "AccessLogChart":
|
case "AccessLogChart":
|
||||||
const { data } = await getAccessList();
|
const {data} = await getAccessList(weekQuery);
|
||||||
accessAllList.value = data;
|
accessAllList.value = data;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "RegisterChart":
|
case "RegisterChart":
|
||||||
const { data: registerUserListData } = await getRegisterAnalyse();
|
const {data: registerUserListData} = await getRegisterAnalyse();
|
||||||
registerAllList.value = registerUserListData;
|
registerAllList.value = registerUserListData;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
)
|
)
|
||||||
const onClickAccessLog = async () => {
|
const onClickAccessLog = async () => {
|
||||||
accessLogDialogVisible.value = true;
|
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>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.home-box {
|
.home-box {
|
||||||
@@ -535,10 +551,17 @@ const onClickAccessLog = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.VisitsLineChart>>>.el-card__body {
|
.VisitsLineChart > > > .el-card__body {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.VisitsLineChart p{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
.statisChart {
|
.statisChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
@@ -550,6 +573,7 @@ const onClickAccessLog = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//走马灯,聊天室链接
|
//走马灯,聊天室链接
|
||||||
.chat-hub {
|
.chat-hub {
|
||||||
background-color: #E6A23C;
|
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