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 }