From eab84747a5b956fed1fa35ba9a9aeaf3dd45f75e Mon Sep 17 00:00:00 2001 From: glz <694770232@qq.com> Date: Fri, 5 Jun 2026 15:52:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=8B=8B?= =?UTF-8?q?=E7=AB=A0=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=8B=86=E5=88=86=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=8B=AC=E7=AB=8B=E7=AE=A1=E7=90=86=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=9C=9F=E5=88=8A=E7=BB=91=E5=AE=9A=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增MedalRule实体类,将勋章条件拆分独立为规则管理 2. 重构Medal相关服务和DTO,支持勋章规则的增删改查 3. 简化Journal绑定逻辑,移除冗余的实例化期刊校验和字段 4. 重命名部分实体类,统一命名前缀 5. 为勋章相关操作添加事务管理,优化异常处理逻辑 --- .../IMedalService.cs | 7 + .../Dto/Journal/JournalDto.cs | 9 +- .../Dto/Medal/MedalDto.cs | 181 ++++++++-- .../Entity/CommunityMessageComment.cs | 4 +- .../Entity/CommunityTemplateSentence.cs | 4 +- .../Entity/Medal.cs | 14 - .../Entity/MedalRule.cs | 101 ++++++ .../MedalService.cs | 310 ++++++++++++------ .../UserJournalService.cs | 34 +- 9 files changed, 471 insertions(+), 193 deletions(-) create mode 100644 QYZH.InteractiveMagazine.Models/Entity/MedalRule.cs diff --git a/QYZH.InteractiveMagazine.IService/IMedalService.cs b/QYZH.InteractiveMagazine.IService/IMedalService.cs index 3bede1f..8bbe9f5 100644 --- a/QYZH.InteractiveMagazine.IService/IMedalService.cs +++ b/QYZH.InteractiveMagazine.IService/IMedalService.cs @@ -50,6 +50,13 @@ public interface IMedalService : IBaseService /// 状态: 0=禁用, 1=启用 Task UpdateStatusAsync(long id, int status); + /// + /// 获取勋章的规则列表 + /// + /// 勋章ID + /// 规则列表 + Task> GetRulesByMedalIdAsync(long medalId); + /// /// 获取所有启用勋章列表(含当前用户拥有状态) /// diff --git a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalDto.cs b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalDto.cs index f7e2166..2bf0000 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalDto.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalDto.cs @@ -13,7 +13,7 @@ public class BindJournalInput /// /// 实例化期刊Id(扫码解析的具体期刊实例Id,可选) /// - public long? JournalInstanceId { get; set; } + public long Id { get; set; } /// /// 关联类型: Read(已读), Favorite(收藏), Subscribe(订阅),默认 Subscribe @@ -41,11 +41,6 @@ public class BindJournalOutput /// public long JournalId { get; set; } - /// - /// 实例化期刊Id - /// - public long? JournalInstanceId { get; set; } - /// /// 关联类型 /// @@ -75,7 +70,7 @@ public class UserJournalQueryInput : PageQueryModel /// /// 实例化期刊Id /// - public long? JournalInstanceId { get; set; } + public long Id { get; set; } /// /// 关联类型: Read, Favorite, Subscribe diff --git a/QYZH.InteractiveMagazine.Models/Dto/Medal/MedalDto.cs b/QYZH.InteractiveMagazine.Models/Dto/Medal/MedalDto.cs index 01371f9..4f4e15e 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/Medal/MedalDto.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/Medal/MedalDto.cs @@ -20,16 +20,6 @@ public class MedalInput /// public string? ImageUrl { get; set; } - /// - /// 条件类型: EvolutionCount, FeedingCount等 - /// - public string ConditionType { get; set; } = string.Empty; - - /// - /// 条件阈值 - /// - public int ConditionValue { get; set; } - /// /// 排序 /// @@ -44,6 +34,11 @@ public class MedalInput /// 书id /// public long JournalId { get; set; } + + /// + /// 勋章规则列表 + /// + public List? Rules { get; set; } } /// @@ -71,16 +66,6 @@ public class MedalOutput /// public string? ImageUrl { get; set; } - /// - /// 条件类型 - /// - public string ConditionType { get; set; } = string.Empty; - - /// - /// 条件阈值 - /// - public int ConditionValue { get; set; } - /// /// 排序 /// @@ -96,6 +81,11 @@ public class MedalOutput /// public long JournalId { get; set; } + /// + /// 勋章规则列表 + /// + public List? Rules { get; set; } + /// /// 创建人 /// @@ -131,11 +121,148 @@ public class MedalQueryInput : PageQueryModel /// 勋章的类型: Pet, Community /// public string? Type { get; set; } +} + +/// +/// 勋章规则输入 +/// +public class MedalRuleInput +{ + /// + /// 目标表名(如:JournalPageTask、UserAction等) + /// + public string TargetTable { get; set; } = string.Empty; /// - /// 条件类型 + /// 目标字段名(如:TotalScore、LoginDays等) /// - public string? ConditionType { get; set; } + public string TargetField { get; set; } = string.Empty; + + /// + /// 比较运算符: >=, >, =, <=, < + /// + public string Operator { get; set; } = ">="; + + /// + /// 阈值数量 + /// + public int ThresholdValue { get; set; } + + /// + /// 额外筛选条件(JSON格式) + /// + public string? FilterCondition { get; set; } + + /// + /// 时间范围类型: All/CurrentMonth/CurrentWeek/Last7Days/Custom + /// + public string? DateRangeType { get; set; } + + /// + /// 自定义起始时间 + /// + public DateTime? DateRangeStart { get; set; } + + /// + /// 自定义结束时间 + /// + public DateTime? DateRangeEnd { get; set; } + + /// + /// 多规则间的逻辑关系: AND/OR + /// + public string LogicOperator { get; set; } = "AND"; + + /// + /// 规则执行顺序 + /// + public int RuleOrder { get; set; } + + /// + /// 规则说明 + /// + public string? Description { get; set; } +} + +/// +/// 勋章规则输出 +/// +public class MedalRuleOutput +{ + /// + /// 规则ID + /// + public long Id { get; set; } + + /// + /// 关联的勋章ID + /// + public long MedalId { get; set; } + + /// + /// 目标表名 + /// + public string TargetTable { get; set; } = string.Empty; + + /// + /// 目标字段名 + /// + public string TargetField { get; set; } = string.Empty; + + /// + /// 比较运算符 + /// + public string Operator { get; set; } = string.Empty; + + /// + /// 阈值数量 + /// + public int ThresholdValue { get; set; } + + /// + /// 额外筛选条件 + /// + public string? FilterCondition { get; set; } + + /// + /// 时间范围类型 + /// + public string? DateRangeType { get; set; } + + /// + /// 自定义起始时间 + /// + public DateTime? DateRangeStart { get; set; } + + /// + /// 自定义结束时间 + /// + public DateTime? DateRangeEnd { get; set; } + + /// + /// 多规则间的逻辑关系 + /// + public string LogicOperator { get; set; } = string.Empty; + + /// + /// 规则执行顺序 + /// + public int RuleOrder { get; set; } + + /// + /// 规则说明 + /// + public string? Description { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 更新时间 + /// + public DateTime? UpdatedAt { get; set; } } /// @@ -163,16 +290,6 @@ public class WxMedalListOutput /// public string? ImageUrl { get; set; } - /// - /// 条件类型 - /// - public string ConditionType { get; set; } = string.Empty; - - /// - /// 条件阈值 - /// - public int ConditionValue { get; set; } - /// /// 排序 /// diff --git a/QYZH.InteractiveMagazine.Models/Entity/CommunityMessageComment.cs b/QYZH.InteractiveMagazine.Models/Entity/CommunityMessageComment.cs index a31ca90..ff87542 100644 --- a/QYZH.InteractiveMagazine.Models/Entity/CommunityMessageComment.cs +++ b/QYZH.InteractiveMagazine.Models/Entity/CommunityMessageComment.cs @@ -6,9 +6,9 @@ namespace QYZH.InteractiveMagazine.Models.Entity ///模板评论表 /// [SugarTable("MessageComment")] - public partial class MessageComment : SqlSugarBaseEntity + public partial class CommunityMessageComment : SqlSugarBaseEntity { - public MessageComment(){ + public CommunityMessageComment(){ } diff --git a/QYZH.InteractiveMagazine.Models/Entity/CommunityTemplateSentence.cs b/QYZH.InteractiveMagazine.Models/Entity/CommunityTemplateSentence.cs index 9bfd70e..1d8c8f8 100644 --- a/QYZH.InteractiveMagazine.Models/Entity/CommunityTemplateSentence.cs +++ b/QYZH.InteractiveMagazine.Models/Entity/CommunityTemplateSentence.cs @@ -6,9 +6,9 @@ namespace QYZH.InteractiveMagazine.Models.Entity ///固定模板言论表 /// [SugarTable("TemplateSentence")] - public partial class TemplateSentence : SqlSugarBaseEntity + public partial class CommunityTemplateSentence : SqlSugarBaseEntity { - public TemplateSentence(){ + public CommunityTemplateSentence(){ } diff --git a/QYZH.InteractiveMagazine.Models/Entity/Medal.cs b/QYZH.InteractiveMagazine.Models/Entity/Medal.cs index eda0567..a16c742 100644 --- a/QYZH.InteractiveMagazine.Models/Entity/Medal.cs +++ b/QYZH.InteractiveMagazine.Models/Entity/Medal.cs @@ -35,20 +35,6 @@ namespace QYZH.InteractiveMagazine.Models.Entity /// public string ImageUrl { get; set; } - /// - /// Desc:条件类型: EvolutionCount, FeedingCount等 - /// Default: - /// Nullable:False - /// - public string ConditionType { get; set; } - - /// - /// Desc:条件阈值 - /// Default: - /// Nullable:False - /// - public int ConditionValue { get; set; } - /// /// Desc:排序 /// Default:0 diff --git a/QYZH.InteractiveMagazine.Models/Entity/MedalRule.cs b/QYZH.InteractiveMagazine.Models/Entity/MedalRule.cs new file mode 100644 index 0000000..d155aa8 --- /dev/null +++ b/QYZH.InteractiveMagazine.Models/Entity/MedalRule.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + +namespace QYZH.InteractiveMagazine.Models.Entity +{ + /// + ///勋章获取规则配置表 + /// + [SugarTable("MedalRule")] + public partial class MedalRule : SqlSugarBaseEntity + { + + /// + /// Desc:关联的勋章ID + /// Default: + /// Nullable:False + /// + public long MedalId {get;set;} + + /// + /// Desc:目标表名(如:JournalPageTask、UserAction等) + /// Default: + /// Nullable:False + /// + public string TargetTable {get;set;} + + /// + /// Desc:目标字段名(如:TotalScore、LoginDays等) + /// Default: + /// Nullable:False + /// + public string TargetField {get;set;} + + /// + /// Desc:比较运算符: >=, >, =, <=, < + /// Default:>= + /// Nullable:False + /// + public string Operator {get;set;} + + /// + /// Desc:阈值数量 + /// Default: + /// Nullable:False + /// + public int ThresholdValue {get;set;} + + /// + /// Desc:额外筛选条件(JSON格式,如:{"Type": 1, "Status": 2}) + /// Default: + /// Nullable:True + /// + public string FilterCondition {get;set;} + + /// + /// Desc:时间范围类型: All/CurrentMonth/CurrentWeek/Last7Days/Custom + /// Default: + /// Nullable:True + /// + public string DateRangeType {get;set;} + + /// + /// Desc:自定义起始时间 + /// Default: + /// Nullable:True + /// + public DateTime? DateRangeStart {get;set;} + + /// + /// Desc:自定义结束时间 + /// Default: + /// Nullable:True + /// + public DateTime? DateRangeEnd {get;set;} + + /// + /// Desc:多规则间的逻辑关系: AND/OR + /// Default:AND + /// Nullable:False + /// + public string LogicOperator {get;set;} + + /// + /// Desc:规则执行顺序(多个规则时生效) + /// Default:0 + /// Nullable:False + /// + public int RuleOrder {get;set;} + + /// + /// Desc:规则说明 + /// Default: + /// Nullable:True + /// + public string Description {get;set;} + + + } +} diff --git a/QYZH.InteractiveMagazine.Service/MedalService.cs b/QYZH.InteractiveMagazine.Service/MedalService.cs index 1c0957f..f1074d6 100644 --- a/QYZH.InteractiveMagazine.Service/MedalService.cs +++ b/QYZH.InteractiveMagazine.Service/MedalService.cs @@ -15,7 +15,7 @@ public class MedalService(BaseRepository medalRepository, ILogger - /// 创建勋章 + /// 创建勋章(含规则,事务) /// public async Task CreateAsync(MedalInput input) { @@ -26,28 +26,16 @@ public class MedalService(BaseRepository medalRepository, ILogger medalRepository, ILogger + { + 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); - return new MedalOutput - { - Id = medal.Id, - Name = medal.Name, - Description = medal.Description, - ImageUrl = medal.ImageUrl, - ConditionType = medal.ConditionType, - ConditionValue = medal.ConditionValue, - SortOrder = medal.SortOrder, - Type = medal.Type, - JournalId = medal.JournalId, - CreatedBy = medal.CreatedBy, - CreatedAt = medal.CreatedAt, - UpdatedBy = medal.UpdatedBy, - UpdatedAt = medal.UpdatedAt - }; + var rules = await GetRulesByMedalIdAsync(medal.Id); + return BuildMedalOutput(medal, rules); } /// - /// 更新勋章 + /// 更新勋章(含规则,事务) /// public async Task UpdateAsync(long id, MedalInput input) { @@ -104,61 +97,60 @@ public class MedalService(BaseRepository medalRepository, ILogger + { + 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); - return new MedalOutput - { - Id = medal.Id, - Name = medal.Name, - Description = medal.Description, - ImageUrl = medal.ImageUrl, - ConditionType = medal.ConditionType, - ConditionValue = medal.ConditionValue, - SortOrder = medal.SortOrder, - Type = medal.Type, - JournalId = medal.JournalId, - CreatedBy = medal.CreatedBy, - CreatedAt = medal.CreatedAt, - UpdatedBy = medal.UpdatedBy, - UpdatedAt = medal.UpdatedAt - }; + var rules = await GetRulesByMedalIdAsync(medal.Id); + return BuildMedalOutput(medal, rules); } /// - /// 删除勋章(软删除) + /// 删除勋章(软删除,含规则) /// public async Task DeleteAsync(long id) { @@ -171,10 +163,30 @@ public class MedalService(BaseRepository medalRepository, ILogger + { + 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); } @@ -182,7 +194,7 @@ public class MedalService(BaseRepository medalRepository, ILogger - /// 根据ID获取勋章 + /// 根据ID获取勋章(含规则) /// public async Task GetByIdAsync(long id) { @@ -195,26 +207,12 @@ public class MedalService(BaseRepository medalRepository, ILogger - /// 分页查询勋章列表 + /// 分页查询勋章列表(含规则) /// public async Task> GetListAsync(MedalQueryInput input) { @@ -231,31 +229,27 @@ public class MedalService(BaseRepository medalRepository, ILogger totalNumber = 0; - var pageResult = await medalRepository.Queryable() + 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) - .WhereIF(!string.IsNullOrWhiteSpace(input.ConditionType), m => m.ConditionType == input.ConditionType) - .OrderBy(m => m.SortOrder, SqlSugar.OrderByType.Asc) + .OrderBy(m => m.SortOrder) .OrderByDescending(m => m.CreatedAt) - .Select(m => new MedalOutput - { - Id = m.Id, - Name = m.Name, - Description = m.Description, - ImageUrl = m.ImageUrl, - ConditionType = m.ConditionType, - ConditionValue = m.ConditionValue, - SortOrder = m.SortOrder, - Type = m.Type, - JournalId = m.JournalId, - CreatedBy = m.CreatedBy, - CreatedAt = m.CreatedAt, - UpdatedBy = m.UpdatedBy, - UpdatedAt = m.UpdatedAt - }, true) .ToPageListAsync(input.PageIndex, input.PageSize, totalNumber); - return new PageListModel(pageResult, 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; } /// @@ -291,6 +285,19 @@ public class MedalService(BaseRepository medalRepository, ILogger + /// 获取勋章的规则列表 + /// + 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(); + } + /// /// 获取所有启用勋章列表(含当前用户拥有状态) /// @@ -300,7 +307,7 @@ public class MedalService(BaseRepository medalRepository, ILogger m.Status == 1) - .OrderBy(m => m.SortOrder, SqlSugar.OrderByType.Asc) + .OrderBy(m => m.SortOrder) .OrderByDescending(m => m.CreatedAt) .ToListAsync(); @@ -316,8 +323,6 @@ public class MedalService(BaseRepository medalRepository, ILogger medalRepository, ILogger + /// 批量插入规则 + /// + 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 } diff --git a/QYZH.InteractiveMagazine.Service/UserJournalService.cs b/QYZH.InteractiveMagazine.Service/UserJournalService.cs index 321a022..4addc9a 100644 --- a/QYZH.InteractiveMagazine.Service/UserJournalService.cs +++ b/QYZH.InteractiveMagazine.Service/UserJournalService.cs @@ -24,15 +24,14 @@ public class UserJournalService( /// public async Task BindJournalAsync(long userId, BindJournalInput input) { - logger.LogInformation("用户绑定期刊,UserId: {UserId}, JournalId: {JournalId}, JournalInstanceId: {JournalInstanceId}, Type: {Type}", - userId, input.JournalId, input.JournalInstanceId, input.Type); + logger.LogInformation("用户绑定期刊,UserId: {UserId}, JournalId: {JournalId}, Id: {Id}, Type: {Type}", + userId, input.JournalId, input.Id, input.Type); // 校验参数 - if (input.JournalId <= 0) + if (input.JournalId <= 0|| input.Id <= 0) { - throw new BusinessException("期刊Id不能为空", 400); + throw new BusinessException("参数错误,未获取到期刊", 400); } - // 校验用户是否存在 var user = await usersRepository.GetByIdAsync(userId); if (user == null || user.IsDeleted) @@ -56,29 +55,14 @@ public class UserJournalService( throw new BusinessException("该期刊暂未发布,无法绑定", 400); } - // 校验实例化期刊是否存在(如果传入了 JournalInstanceId) - if (input.JournalInstanceId.HasValue && input.JournalInstanceId.Value > 0) - { - var instance = await journalRepository.GetByIdAsync(input.JournalInstanceId.Value); - if (instance == null || instance.IsDeleted) - { - logger.LogWarning("绑定期刊失败,实例化期刊不存在,JournalInstanceId: {JournalInstanceId}", input.JournalInstanceId); - throw new BusinessException("实例化期刊不存在", 404); - } - } - // 防重复绑定:同一用户 + 期刊 + 实例 + 类型 var isExist = userJournalRepository.Any(uj => - uj.UserId == userId && - uj.JournalId == input.JournalId && - uj.JournalInstanceId == input.JournalInstanceId && - uj.Type == input.Type && - !uj.IsDeleted); + uj.Id == input.Id); if (isExist) { logger.LogWarning("重复绑定期刊,UserId: {UserId}, JournalId: {JournalId}, Type: {Type}", userId, input.JournalId, input.Type); - throw new BusinessException("您已绑定过该期刊,无需重复操作", 400); + throw new BusinessException("该期刊已被绑定", 400); } // 检查是否为首次绑定期刊(用于激活宠物) @@ -90,7 +74,7 @@ public class UserJournalService( { UserId = userId, JournalId = input.JournalId, - JournalInstanceId = input.JournalInstanceId, + Id = input.Id, Type = input.Type, Status = "Active", IsDeleted = false, @@ -128,7 +112,6 @@ public class UserJournalService( Id = userJournal.Id, UserId = userJournal.UserId, JournalId = userJournal.JournalId, - JournalInstanceId = userJournal.JournalInstanceId, Type = userJournal.Type, Status = userJournal.Status, CreatedAt = userJournal.CreatedAt @@ -156,8 +139,6 @@ public class UserJournalService( RefAsync totalNumber = 0; var pageResult = await userJournalRepository.Queryable() .Where(uj => uj.UserId == userId) - .WhereIF(input.JournalId.HasValue, uj => uj.JournalId == input.JournalId.Value) - .WhereIF(input.JournalInstanceId.HasValue, uj => uj.JournalInstanceId == input.JournalInstanceId.Value) .WhereIF(!string.IsNullOrWhiteSpace(input.Type), uj => uj.Type == input.Type) .OrderByDescending(uj => uj.CreatedAt) .Select(uj => new BindJournalOutput @@ -165,7 +146,6 @@ public class UserJournalService( Id = uj.Id, UserId = uj.UserId, JournalId = uj.JournalId, - JournalInstanceId = uj.JournalInstanceId, Type = uj.Type, Status = uj.Status, CreatedAt = uj.CreatedAt