using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;
namespace QYZH.InteractiveMagazine.Service;
///
/// 勋章服务实现
///
public class MedalService(BaseRepository medalRepository, ILogger logger) : BaseRepository, IMedalService
{
///
/// 创建勋章(含规则,事务)
///
public async Task CreateAsync(MedalInput input)
{
logger.LogInformation("正在创建勋章,勋章名称: {Name}", input.Name);
if (string.IsNullOrWhiteSpace(input.Name))
{
throw new BusinessException("勋章名称不能为空", 400);
}
if (string.IsNullOrWhiteSpace(input.Type))
{
throw new BusinessException("勋章类型不能为空", 400);
}
var medal = new Medal
{
Name = input.Name.Trim(),
Description = input.Description,
ImageUrl = input.ImageUrl,
SortOrder = input.SortOrder,
Type = input.Type,
JournalId = input.JournalId,
CreatedBy = "System",
UpdatedBy = "System",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
IsDeleted = false
};
try
{
await UseTranAsync(async () =>
{
var result = await medalRepository.InsertAsync(medal);
if (!result)
{
throw new BusinessException("创建勋章失败", 500);
}
if (input.Rules != null && input.Rules.Count > 0)
{
await InsertRulesAsync(medal.Id, input.Rules);
}
});
}
catch (BusinessException)
{
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "勋章创建事务失败,勋章名称: {Name}", input.Name);
throw new BusinessException("创建勋章失败", 500);
}
logger.LogInformation("勋章创建成功,勋章名称: {Name}, ID: {Id}", input.Name, medal.Id);
var rules = await GetRulesByMedalIdAsync(medal.Id);
return BuildMedalOutput(medal, rules);
}
///
/// 更新勋章(含规则,事务)
///
public async Task UpdateAsync(long id, MedalInput input)
{
logger.LogInformation("正在更新勋章,ID: {Id}", id);
var medal = await medalRepository.GetByIdAsync(id);
if (medal == null)
{
logger.LogWarning("未找到要更新的勋章,ID: {Id}", id);
throw new BusinessException("勋章不存在", 404);
}
if (string.IsNullOrWhiteSpace(input.Name))
{
throw new BusinessException("勋章名称不能为空", 400);
}
if (string.IsNullOrWhiteSpace(input.Type))
{
throw new BusinessException("勋章类型不能为空", 400);
}
medal.Name = input.Name.Trim();
medal.Description = input.Description;
medal.ImageUrl = input.ImageUrl;
medal.SortOrder = input.SortOrder;
medal.Type = input.Type;
medal.JournalId = input.JournalId;
medal.UpdatedBy = "System";
medal.UpdatedAt = DateTime.Now;
try
{
await UseTranAsync(async () =>
{
var result = await medalRepository.UpdateAsync(medal);
if (!result)
{
throw new BusinessException("更新勋章失败", 500);
}
// 删除旧规则,重新插入新规则
await Context.Updateable()
.SetColumns(r => new MedalRule { IsDeleted = true, UpdatedBy = "System", UpdatedAt = DateTime.Now })
.Where(r => r.MedalId == medal.Id)
.ExecuteCommandAsync();
if (input.Rules != null && input.Rules.Count > 0)
{
await InsertRulesAsync(medal.Id, input.Rules);
}
});
}
catch (BusinessException)
{
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "勋章更新事务失败,ID: {Id}", id);
throw new BusinessException("更新勋章失败", 500);
}
logger.LogInformation("勋章更新成功,ID: {Id}", id);
var rules = await GetRulesByMedalIdAsync(medal.Id);
return BuildMedalOutput(medal, rules);
}
///
/// 删除勋章(软删除,含规则)
///
public async Task DeleteAsync(long id)
{
logger.LogInformation("正在删除勋章,ID: {Id}", id);
var medal = await medalRepository.GetByIdAsync(id);
if (medal == null)
{
logger.LogWarning("未找到要删除的勋章,ID: {Id}", id);
throw new BusinessException("勋章不存在", 404);
}
try
{
await UseTranAsync(async () =>
{
var result = await medalRepository.DeleteByIdAsync(id);
if (!result)
{
throw new BusinessException("删除勋章失败", 500);
}
// 同时软删除关联规则
await Context.Updateable()
.SetColumns(r => new MedalRule { IsDeleted = true, UpdatedBy = "System", UpdatedAt = DateTime.Now })
.Where(r => r.MedalId == id)
.ExecuteCommandAsync();
});
}
catch (BusinessException)
{
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "勋章删除事务失败,ID: {Id}", id);
throw new BusinessException("删除勋章失败", 500);
}
logger.LogInformation("勋章删除成功,ID: {Id}", id);
}
///
/// 根据ID获取勋章(含规则)
///
public async Task GetByIdAsync(long id)
{
logger.LogInformation("正在获取勋章信息,ID: {Id}", id);
var medal = await medalRepository.GetByIdAsync(id);
if (medal == null)
{
logger.LogWarning("未找到勋章,ID: {Id}", id);
throw new BusinessException("勋章不存在", 404);
}
var rules = await GetRulesByMedalIdAsync(medal.Id);
return BuildMedalOutput(medal, rules);
}
///
/// 分页查询勋章列表(含规则)
///
public async Task> GetListAsync(MedalQueryInput input)
{
logger.LogInformation("正在查询勋章列表,页码: {PageIndex}, 每页条数: {PageSize}", input.PageIndex, input.PageSize);
if (input.PageIndex <= 0)
{
throw new BusinessException("页码必须大于0", 400);
}
if (input.PageSize <= 0 || input.PageSize > 100)
{
throw new BusinessException("每页条数必须在1-100之间", 400);
}
RefAsync totalNumber = 0;
var medals = await medalRepository.Queryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), m => m.Name.Contains(input.Name))
.WhereIF(!string.IsNullOrWhiteSpace(input.Type), m => m.Type == input.Type)
.OrderBy(m => m.SortOrder)
.OrderByDescending(m => m.CreatedAt)
.ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);
// 批量查询所有勋章的规则
var medalIds = medals.Select(m => m.Id).ToList();
var allRules = await Context.Queryable()
.Where(r => medalIds.Contains(r.MedalId) && !r.IsDeleted)
.ToListAsync();
var rulesDict = allRules.GroupBy(r => r.MedalId)
.ToDictionary(g => g.Key, g => g.OrderBy(r => r.RuleOrder).Select(r => MapRuleOutput(r)).ToList());
var pageResult = medals.Select(m => BuildMedalOutput(m, rulesDict.GetValueOrDefault(m.Id))).ToList();
var result = new PageListModel(new List(), input.PageIndex, input.PageSize, totalNumber);
result.Result = pageResult;
return result;
}
///
/// 更新勋章启用/禁用状态
///
public async Task UpdateStatusAsync(long id, int status)
{
logger.LogInformation("正在更新勋章状态,ID: {Id}, Status: {Status}", id, status);
if (status != 0 && status != 1)
{
throw new BusinessException("状态值无效,只能为0(禁用)或1(启用)", 400);
}
var medal = await medalRepository.GetByIdAsync(id);
if (medal == null)
{
logger.LogWarning("未找到要更新状态的勋章,ID: {Id}", id);
throw new BusinessException("勋章不存在", 404);
}
medal.Status = status;
medal.UpdatedBy = "System";
medal.UpdatedAt = DateTime.Now;
var result = await medalRepository.UpdateAsync(medal);
if (!result)
{
logger.LogError("勋章状态更新失败,ID: {Id}", id);
throw new BusinessException("更新勋章状态失败", 500);
}
logger.LogInformation("勋章状态更新成功,ID: {Id}, Status: {Status}", id, status);
}
///
/// 获取勋章的规则列表
///
public async Task> GetRulesByMedalIdAsync(long medalId)
{
var rules = await Context.Queryable()
.Where(r => r.MedalId == medalId && !r.IsDeleted)
.OrderBy(r => r.RuleOrder)
.ToListAsync();
return rules.Select(r => MapRuleOutput(r)).ToList();
}
///
/// 获取所有启用勋章列表(含当前用户拥有状态)
///
public async Task> GetAllMedalsAsync(long userId)
{
logger.LogInformation("正在获取所有勋章列表,用户ID: {UserId}", userId);
var medals = await medalRepository.Queryable()
.Where(m => m.Status == 1)
.OrderBy(m => m.SortOrder)
.OrderByDescending(m => m.CreatedAt)
.ToListAsync();
var userMedals = await Context.Queryable()
.Where(um => um.UserId == userId && um.Status == "Awarded")
.ToListAsync();
var userMedalDict = userMedals.ToDictionary(um => um.MedalId, um => um.AwardedAt);
return medals.Select(m => new WxMedalListOutput
{
Id = m.Id,
Name = m.Name,
Description = m.Description,
ImageUrl = m.ImageUrl,
SortOrder = m.SortOrder,
Type = m.Type,
IsOwned = userMedalDict.ContainsKey((int)m.Id),
AwardedAt = userMedalDict.TryGetValue((int)m.Id, out var awardedAt) ? awardedAt : null
}).ToList();
}
///
/// 获取用户已拥有的勋章列表
///
public async Task> GetUserMedalsAsync(long userId)
{
logger.LogInformation("正在获取用户勋章列表,用户ID: {UserId}", userId);
var result = await Context.Queryable()
.InnerJoin((um, m) => um.MedalId == m.Id)
.Where((um, m) => um.UserId == userId && um.Status == "Awarded")
.OrderByDescending((um, m) => um.AwardedAt)
.Select((um, m) => new WxUserMedalOutput
{
MedalId = m.Id,
Name = m.Name,
Description = m.Description,
ImageUrl = m.ImageUrl,
Type = m.Type,
AwardedAt = um.AwardedAt,
Status = um.Status
})
.ToListAsync();
return result;
}
///
/// 激活/获得勋章
///
public async Task ActivateMedalAsync(long userId, WxMedalActivateInput input)
{
logger.LogInformation("用户正在激活勋章,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
if (input.MedalId <= 0)
{
throw new BusinessException("勋章ID无效", 400);
}
var medal = await medalRepository.GetByIdAsync(input.MedalId);
if (medal == null)
{
logger.LogWarning("未找到要激活的勋章,勋章ID: {MedalId}", input.MedalId);
throw new BusinessException("勋章不存在", 404);
}
if (medal.Status != 1)
{
throw new BusinessException("该勋章当前不可获得", 400);
}
var existingUserMedal = await Context.Queryable()
.Where(um => um.UserId == userId && um.MedalId == (int)input.MedalId && um.Status == "Awarded")
.FirstAsync();
if (existingUserMedal != null)
{
throw new BusinessException("您已拥有该勋章", 400);
}
var userMedal = new UserMedal
{
UserId = userId,
MedalId = (int)input.MedalId,
AwardedAt = DateTime.Now,
Type = medal.Type,
Status = "Awarded",
CreatedBy = "System",
UpdatedBy = "System",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
IsDeleted = false
};
var insertResult = await Context.Insertable(userMedal).ExecuteCommandAsync();
if (insertResult <= 0)
{
logger.LogError("勋章激活失败,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
throw new BusinessException("激活勋章失败", 500);
}
logger.LogInformation("勋章激活成功,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
}
#region 私有辅助方法
///
/// 批量插入规则
///
private async Task InsertRulesAsync(long medalId, List ruleInputs)
{
var rules = ruleInputs.Select(r => new MedalRule
{
MedalId = medalId,
TargetTable = r.TargetTable,
TargetField = r.TargetField,
Operator = r.Operator,
ThresholdValue = r.ThresholdValue,
FilterCondition = r.FilterCondition,
DateRangeType = r.DateRangeType,
DateRangeStart = r.DateRangeStart,
DateRangeEnd = r.DateRangeEnd,
LogicOperator = r.LogicOperator,
RuleOrder = r.RuleOrder,
Description = r.Description,
CreatedBy = "System",
UpdatedBy = "System",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
IsDeleted = false
}).ToList();
var count = await Context.Insertable(rules).ExecuteCommandAsync();
if (count <= 0)
{
logger.LogError("勋章规则插入失败,MedalId: {MedalId}", medalId);
throw new BusinessException("创建勋章规则失败", 500);
}
logger.LogInformation("勋章规则创建成功,MedalId: {MedalId}, 规则数: {Count}", medalId, rules.Count);
}
///
/// 构建MedalOutput
///
private static MedalOutput BuildMedalOutput(Medal medal, List? rules)
{
return new MedalOutput
{
Id = medal.Id,
Name = medal.Name,
Description = medal.Description,
ImageUrl = medal.ImageUrl,
SortOrder = medal.SortOrder,
Type = medal.Type,
JournalId = medal.JournalId,
Rules = rules,
CreatedBy = medal.CreatedBy,
CreatedAt = medal.CreatedAt,
UpdatedBy = medal.UpdatedBy,
UpdatedAt = medal.UpdatedAt
};
}
///
/// 映射规则实体到输出DTO
///
private static MedalRuleOutput MapRuleOutput(MedalRule r)
{
return new MedalRuleOutput
{
Id = r.Id,
MedalId = r.MedalId,
TargetTable = r.TargetTable,
TargetField = r.TargetField,
Operator = r.Operator,
ThresholdValue = r.ThresholdValue,
FilterCondition = r.FilterCondition,
DateRangeType = r.DateRangeType,
DateRangeStart = r.DateRangeStart,
DateRangeEnd = r.DateRangeEnd,
LogicOperator = r.LogicOperator,
RuleOrder = r.RuleOrder,
Description = r.Description,
CreatedAt = r.CreatedAt,
UpdatedAt = r.UpdatedAt
};
}
#endregion
}