This commit is contained in:
马梓彭 2026-03-10 16:33:19 +08:00
parent 8a94c46eed
commit db15e4c68b
2 changed files with 197 additions and 1 deletions

View File

@ -0,0 +1,92 @@
using System.ComponentModel.DataAnnotations;
using YD_Event.Core.Enum;
namespace YD_Event.Application.Points.Dtos;
/// <summary>
/// 用户积分查询输入
/// </summary>
public class UserPointsQueryInput : Pagination
{
/// <summary>
/// 积分类型(1-获取 2-消耗,不传为全部)
/// </summary>
public PointsOperationType? Type { get; set; }
/// <summary>
/// 动作关键字(赛事名称/商品名称)
/// </summary>
public string? ActionKeyword { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
}
/// <summary>
/// 积分明细列表项
/// </summary>
public class UserPointsLogDto
{
/// <summary>
/// 记录ID
/// </summary>
public long Id { get; set; }
/// <summary>
/// 积分类型(1-获取 2-消耗)
/// </summary>
public PointsOperationType Type { get; set; }
/// <summary>
/// 动作(赛事名称/消费内容)
/// </summary>
public string Action { get; set; }
/// <summary>
/// 项目名称
/// </summary>
public string? ProjectName { get; set; }
/// <summary>
/// 组别名称
/// </summary>
public string? GroupName { get; set; }
/// <summary>
/// 参赛人(仅单位账号有效)
/// </summary>
public string? ParticipantName { get; set; }
/// <summary>
/// 名次
/// </summary>
public int? Rank { get; set; }
/// <summary>
/// 积分变动
/// </summary>
public decimal Points { get; set; }
/// <summary>
/// 生成时间
/// </summary>
public DateTime CreatedTime { get; set; }
}
/// <summary>
/// 用户积分概览
/// </summary>
public class UserPointsOverviewDto
{
/// <summary>
/// 当前总积分
/// </summary>
public decimal CurrentBalance { get; set; }
}

View File

@ -1,4 +1,5 @@
using SqlSugar;
using YD_Event.Application.Auth;
using YD_Event.Application.Points.Dtos;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
@ -13,15 +14,118 @@ public class PointsRecordService : BaseService<PointsRecord>, ITransient
private readonly ISqlSugarRepository<PointsRecord> _repository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Merchant> _merchantRepository;
private readonly ISqlSugarRepository<PointsRule> _pointsRuleRepository;
private readonly AuthManager _authManager;
public PointsRecordService(
ISqlSugarRepository<PointsRecord> repository,
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
ISqlSugarRepository<YD_Event.Core.Entities.Merchant> merchantRepository) : base(repository)
ISqlSugarRepository<YD_Event.Core.Entities.Merchant> merchantRepository,
ISqlSugarRepository<PointsRule> pointsRuleRepository,
AuthManager authManager) : base(repository)
{
_repository = repository;
_appUserRepository = appUserRepository;
_merchantRepository = merchantRepository;
_pointsRuleRepository = pointsRuleRepository;
_authManager = authManager;
}
/// <summary>
/// 获取用户当前积分余额 (PC端)
/// </summary>
/// <returns></returns>
[DisplayName("获取用户当前积分余额")]
[HttpGet("balance")]
public async Task<UserPointsOverviewDto> GetBalance()
{
var userId = _authManager.UserId;
var merchant = await _merchantRepository.GetFirstAsync(m => m.CreatedUserId == userId);
// 如果是商户/团队账号,查询商户积分;否则查询个人积分
decimal balance;
if (merchant != null)
{
balance = await _repository.AsQueryable()
.Where(x => x.MerchantId == merchant.Id)
.SumAsync(x => x.Points);
}
else
{
balance = await _repository.AsQueryable()
.Where(x => x.UserId == userId && x.MerchantId == null) // 个人积分需排除作为商户成员的记录(如果有)
.SumAsync(x => x.Points);
}
return new UserPointsOverviewDto { CurrentBalance = balance };
}
/// <summary>
/// 查询积分明细列表 (PC端)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("查询积分明细列表")]
[HttpGet("logs")]
public async Task<PageResult<UserPointsLogDto>> GetLogs([FromQuery] UserPointsQueryInput input)
{
var userId = _authManager.UserId;
var merchant = await _merchantRepository.GetFirstAsync(m => m.CreatedUserId == userId);
var query = _repository.AsQueryable()
.LeftJoin<EventInfo>((pr, e) => pr.EventId == e.Id)
.LeftJoin<YD_Event.Core.Entities.Project>((pr, e, p) => pr.ProjectId == p.Id)
.LeftJoin<ProjectGroup>((pr, e, p, pg) => pr.ProjectGroupId == pg.Id)
.LeftJoin<YD_Event.Core.Entities.AppUser>((pr, e, p, pg, u) => pr.UserId == u.Id)
.WhereIF(input.Type.HasValue, pr => pr.Type == input.Type)
.WhereIF(!string.IsNullOrWhiteSpace(input.ActionKeyword), (pr, e) => e.EventName.Contains(input.ActionKeyword) || pr.Remark.Contains(input.ActionKeyword))
.WhereIF(input.StartTime.HasValue, pr => pr.CreatedTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, pr => pr.CreatedTime <= input.EndTime)
.OrderByDescending(pr => pr.CreatedTime);
if (merchant != null)
{
// 商户查询:按 MerchantId 过滤
query = query.Where(pr => pr.MerchantId == merchant.Id);
}
else
{
// 个人查询:按 UserId 过滤,且排除商户记录
query = query.Where(pr => pr.UserId == userId && pr.MerchantId == null);
}
var result = await query.Select((pr, e, p, pg, u) => new UserPointsLogDto
{
Id = pr.Id,
Type = pr.Type,
Action = e.EventName ?? pr.Remark ?? "未知动作",
ProjectName = p.Name,
GroupName = pg.GroupName,
ParticipantName = u.Name, // 显示关联用户的姓名
Rank = 0, // 暂无法直接关联到名次,需业务侧在写入PointsRecord时记录
Points = pr.Points,
CreatedTime = pr.CreatedTime
})
.ToPagedListAsync(input);
return result;
}
/// <summary>
/// 积分规则说明接口 (PC端)
/// </summary>
/// <returns></returns>
[DisplayName("积分规则说明接口")]
[HttpGet("rules")]
[AllowAnonymous]
public async Task<List<PointsRule>> GetRules()
{
// 返回所有启用的积分规则
return await _pointsRuleRepository.AsQueryable()
.Where(x => x.Status == AvailabilityStatus.Enable)
.Includes(x => x.Details) // 包含明细
.OrderBy(x => x.CreatedTime)
.ToListAsync();
}
/// <summary>