2026-04-10 22:39:32 +08:00
|
|
|
|
using Furion.FriendlyException;
|
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
2026-01-17 12:52:58 +08:00
|
|
|
|
using YD_Event.Application.Points.Dtos;
|
|
|
|
|
|
using YD_Event.Core.Entities;
|
|
|
|
|
|
|
|
|
|
|
|
namespace YD_Event.Application.Points;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 积分规则管理
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class PointsRuleService : BaseService<PointsRule>, ITransient
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly ISqlSugarRepository<PointsRule> _repository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<PointsRuleDetail> _detailRepository;
|
2026-04-10 22:39:32 +08:00
|
|
|
|
private readonly ISqlSugarRepository<PointsRecord> _pointsRecordRepository;
|
2026-01-17 12:52:58 +08:00
|
|
|
|
private readonly IIdGenerator _idGenerator;
|
2026-04-10 22:39:32 +08:00
|
|
|
|
private readonly Microsoft.Extensions.Logging.ILogger<PointsRuleService> _logger;
|
2026-01-17 12:52:58 +08:00
|
|
|
|
|
|
|
|
|
|
public PointsRuleService(ISqlSugarRepository<PointsRule> repository,
|
|
|
|
|
|
ISqlSugarRepository<PointsRuleDetail> detailRepository,
|
2026-04-10 22:39:32 +08:00
|
|
|
|
ISqlSugarRepository<PointsRecord> pointsRecordRepository,
|
|
|
|
|
|
IIdGenerator idGenerator,
|
|
|
|
|
|
Microsoft.Extensions.Logging.ILogger<PointsRuleService> logger) : base(repository)
|
2026-01-17 12:52:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
_repository = repository;
|
|
|
|
|
|
_detailRepository = detailRepository;
|
2026-04-10 22:39:32 +08:00
|
|
|
|
_pointsRecordRepository = pointsRecordRepository;
|
2026-01-17 12:52:58 +08:00
|
|
|
|
_idGenerator = idGenerator;
|
2026-04-10 22:39:32 +08:00
|
|
|
|
_logger = logger;
|
2026-01-17 12:52:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 积分规则分页查询
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[DisplayName("积分规则分页查询")]
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
|
public async Task<PageResult<PointsRule>> Page([FromQuery] PointsRuleQueryInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
return await _repository.AsQueryable()
|
|
|
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(input.RuleName), x => x.RuleName.Contains(input.RuleName))
|
|
|
|
|
|
.OrderByDescending(x => x.CreatedTime)
|
|
|
|
|
|
.ToPagedListAsync(input);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加积分规则
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[DisplayName("添加积分规则")]
|
|
|
|
|
|
[HttpPost("add")]
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
public async Task Add(AddPointsRuleInput input)
|
|
|
|
|
|
{
|
2026-04-12 13:14:20 +08:00
|
|
|
|
ValidateRankDetails(input.Details);
|
|
|
|
|
|
|
2026-01-17 12:52:58 +08:00
|
|
|
|
var entity = input.Adapt<PointsRule>();
|
|
|
|
|
|
entity.Id = _idGenerator.NextId();
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.InsertAsync(entity);
|
|
|
|
|
|
|
|
|
|
|
|
if (input.Details != null && input.Details.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
var details = input.Details.Adapt<List<PointsRuleDetail>>();
|
|
|
|
|
|
details.ForEach(x =>
|
|
|
|
|
|
{
|
|
|
|
|
|
x.PointsRuleId = entity.Id;
|
|
|
|
|
|
x.Id = _idGenerator.NextId();
|
|
|
|
|
|
});
|
|
|
|
|
|
await _detailRepository.InsertRangeAsync(details);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新积分规则
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[DisplayName("更新积分规则")]
|
|
|
|
|
|
[HttpPut("edit")]
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
public async Task Update(UpdatePointsRuleInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var entity = await _repository.GetByIdAsync(input.Id);
|
|
|
|
|
|
if (entity == null) throw Oops.Bah("规则不存在");
|
|
|
|
|
|
|
2026-04-12 13:14:20 +08:00
|
|
|
|
ValidateRankDetails(input.Details);
|
|
|
|
|
|
|
2026-01-17 12:52:58 +08:00
|
|
|
|
input.Adapt(entity);
|
|
|
|
|
|
await _repository.UpdateAsync(entity);
|
|
|
|
|
|
|
|
|
|
|
|
// Update details: Delete old, Insert new
|
|
|
|
|
|
await _detailRepository.DeleteAsync(x => x.PointsRuleId == entity.Id);
|
|
|
|
|
|
|
|
|
|
|
|
if (input.Details != null && input.Details.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
var details = input.Details.Adapt<List<PointsRuleDetail>>();
|
|
|
|
|
|
details.ForEach(x =>
|
|
|
|
|
|
{
|
|
|
|
|
|
x.PointsRuleId = entity.Id;
|
|
|
|
|
|
x.Id = _idGenerator.NextId();
|
|
|
|
|
|
});
|
|
|
|
|
|
await _detailRepository.InsertRangeAsync(details);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-12 13:14:20 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 验证名次积分详情是否有重叠
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ValidateRankDetails(List<PointsRuleDetailInput>? details)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (details == null || details.Count <= 1)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < details.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var item1 = details[i];
|
|
|
|
|
|
|
|
|
|
|
|
for (int j = i + 1; j < details.Count; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var item2 = details[j];
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否重叠:两个区间 [s1, e1] 和 [s2, e2] 不重叠的条件是 e1 < s2 或 e2 < s1
|
|
|
|
|
|
bool isOverlap = !(item1.EndRank < item2.StartRank || item2.EndRank < item1.StartRank);
|
|
|
|
|
|
if (isOverlap)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw Oops.Bah($"名次范围 {item1.StartRank}-{item1.EndRank} 与 {item2.StartRank}-{item2.EndRank} 存在重叠,请调整!");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-17 12:52:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 删除积分规则
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[DisplayName("删除积分规则")]
|
|
|
|
|
|
[HttpPost("delete")]
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
public async Task Delete([FromBody] List<long> ids)
|
|
|
|
|
|
{
|
2026-04-10 22:39:32 +08:00
|
|
|
|
_logger.LogInformation("开始删除积分规则:规则ID列表={Ids}", string.Join(",", ids ?? new List<long>()));
|
|
|
|
|
|
|
|
|
|
|
|
if (ids == null || !ids.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogWarning("删除积分规则失败:未选择积分规则");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 执行删除
|
2026-01-17 12:52:58 +08:00
|
|
|
|
await _repository.DeleteAsync(x => ids.Contains(x.Id));
|
|
|
|
|
|
await _detailRepository.DeleteAsync(x => ids.Contains(x.PointsRuleId));
|
2026-04-10 22:39:32 +08:00
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation("删除积分规则成功:规则ID列表={Ids}", string.Join(",", ids));
|
2026-01-17 12:52:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取积分规则详情
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[DisplayName("获取积分规则详情")]
|
|
|
|
|
|
[HttpGet("detail")]
|
|
|
|
|
|
public async Task<PointsRule> Detail([FromQuery] long id)
|
|
|
|
|
|
{
|
|
|
|
|
|
var entity = await _repository.GetByIdAsync(id);
|
|
|
|
|
|
if (entity == null) throw Oops.Bah("规则不存在");
|
|
|
|
|
|
|
|
|
|
|
|
entity.Details = await _detailRepository.AsQueryable().Where(x => x.PointsRuleId == id).ToListAsync();
|
|
|
|
|
|
return entity;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|