diff --git a/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs b/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs index d5e3222..5aa5cfb 100644 --- a/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs @@ -62,4 +62,12 @@ public interface IUserAnswerTaskService : IBaseService用户Id /// 批量领取结果 Task BatchClaimPointsAsync(BatchClaimPointsInput input, long userId); + + /// + /// 获取目录树形结构(一级目录和二级目录的完整树形结构,包含任务详情) + /// + /// 期刊Id + /// 用户Id + /// 目录树形结构数据 + Task GetCatalogTreeAsync(long journalId, long userId); } diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/CatalogTreeOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/CatalogTreeOutput.cs new file mode 100644 index 0000000..3259775 --- /dev/null +++ b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/CatalogTreeOutput.cs @@ -0,0 +1,130 @@ +namespace QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService; + +/// +/// 目录树形结构输出(包含一级目录列表) +/// +public class CatalogTreeOutput +{ + /// + /// 一级目录列表 + /// + public List FirstLevelCatalogs { get; set; } = []; +} + +/// +/// 一级目录项输出 +/// +public class FirstLevelCatalogItem +{ + /// + /// 一级目录ID + /// + public long CatalogId { get; set; } + + /// + /// 一级目录名称 + /// + public string CatalogName { get; set; } + + /// + /// 文章篇数(来自二级目录对应的所有有题目的页面数总和) + /// + public int ArticleCount { get; set; } + + /// + /// 任务数量(来自二级目录对应的所有任务按GroupId去重后的总和) + /// + public int TaskCount { get; set; } + + /// + /// 二级目录列表 + /// + public List Children { get; set; } = []; +} + +/// +/// 二级目录项输出(含页码范围、任务数量、状态、总成长值、总积分及任务列表) +/// +public class SecondLevelCatalogItem +{ + /// + /// 二级目录ID + /// + public long CatalogId { get; set; } + + /// + /// 二级目录名称 + /// + public string CatalogName { get; set; } + + /// + /// 起始页码 + /// + public int StartPage { get; set; } + + /// + /// 结束页码 + /// + public int EndPage { get; set; } + + /// + /// 任务数量(按GroupId去重后的数量) + /// + public int TaskCount { get; set; } + + /// + /// 状态(格式如:1/2 进行中、0/2 未开始、2/2 已完成) + /// + public string Status { get; set; } + + /// + /// 总成长值(该二级目录下所有任务的成长值总和,按GroupId去重) + /// + public int TotalGrowthPoints { get; set; } + + /// + /// 总积分(该二级目录下所有任务的积分总和,按GroupId去重) + /// + public int TotalPoints { get; set; } + + /// + /// 任务列表(每个任务的详细信息) + /// + public List Tasks { get; set; } = []; +} + +/// +/// 目录任务项输出(任务详情) +/// +public class CatalogTaskItem +{ + /// + /// 任务分组ID(GroupId) + /// + public long GroupId { get; set; } + + /// + /// 任务名称(取主任务的Task字段) + /// + public string TaskName { get; set; } + + /// + /// 任务状态(未开始、进行中、已完成) + /// + public string Status { get; set; } + + /// + /// 成长值(取主任务的GrowthPoint) + /// + public int GrowthPoints { get; set; } + + /// + /// 积分值(取主任务的Points) + /// + public int Points { get; set; } + + /// + /// 答题时长(分钟,该GroupId下所有任务的AnswerSeconds累加后转换为分钟) + /// + public double AnswerMinutes { get; set; } +} \ No newline at end of file diff --git a/QYZH.InteractiveMagazine.Repository/Core/SqlSugarExtension.cs b/QYZH.InteractiveMagazine.Repository/Core/SqlSugarExtension.cs index 7e94779..07b04e0 100644 --- a/QYZH.InteractiveMagazine.Repository/Core/SqlSugarExtension.cs +++ b/QYZH.InteractiveMagazine.Repository/Core/SqlSugarExtension.cs @@ -1,4 +1,6 @@ -using QYZH.InteractiveMagazine.Models.Entity; +using Microsoft.AspNetCore.Http; +using QYZH.InteractiveMagazine.Infrastructure.Context; +using QYZH.InteractiveMagazine.Models.Entity; using Microsoft.AspNetCore.Http; using QYZH.InteractiveMagazine.Infrastructure.Context; using SqlSugar; @@ -109,7 +111,7 @@ namespace QYZH.InteractiveMagazine.Repository.Core return db; } - + /// /// 添加创建人 创建时间 更新人 更新时间 默认值 /// @@ -126,12 +128,8 @@ namespace QYZH.InteractiveMagazine.Repository.Core { if (entityInfo.PropertyName == "CreatedAt" && (string.IsNullOrWhiteSpace(entityValue) || entityValue == DateTime.MinValue.ToString())) entityInfo.SetValue(DateTime.Now);//修改CreateTime字段 - else if (entityInfo.PropertyName == "CreatedBy" && ShouldSetOperatorName(entityValue, currentUserName)) + else if (entityInfo.PropertyName == "CreatedBy" && (string.IsNullOrWhiteSpace(entityValue))) entityInfo.SetValue(currentUserName);//修改创建人字段 - else if (entityInfo.PropertyName == "UpdatedAt" && (string.IsNullOrWhiteSpace(entityValue) || entityValue == DateTime.MinValue.ToString())) - entityInfo.SetValue(DateTime.Now);//修改UpdatedTime字段 - else if (entityInfo.PropertyName == "UpdatedBy" && ShouldSetOperatorName(entityValue, currentUserName)) - entityInfo.SetValue(currentUserName);//修改更新人字段 else if (entityInfo.PropertyName == "IsDeleted" && string.IsNullOrWhiteSpace(entityValue)) entityInfo.SetValue("0");//修改CreateTime字段 } @@ -141,7 +139,7 @@ namespace QYZH.InteractiveMagazine.Repository.Core { if (entityInfo.PropertyName == "UpdatedAt" && (string.IsNullOrWhiteSpace(entityValue) || entityValue == DateTime.MinValue.ToString())) entityInfo.SetValue(DateTime.Now);//修改UpdatedTime字段 - else if (entityInfo.PropertyName == "UpdatedBy" && ShouldSetOperatorName(entityValue, currentUserName)) + else if (entityInfo.PropertyName == "UpdatedBy" && (string.IsNullOrWhiteSpace(entityValue) || entityValue == "0")) entityInfo.SetValue(currentUserName);//修改更新人字段 } }; diff --git a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs index 3d8a047..1930a15 100644 --- a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs @@ -1314,9 +1314,7 @@ public class UserAnswerTaskService( var newGrowthPointsBalance = user.GrowthPoints + totalGrowthPoints; await answerRepository.Context.Updateable() .SetColumns(u => u.Points == newPointsBalance) - .SetColumns(u => u.GrowthPoints == newGrowthPointsBalance) - .SetColumns(u => u.UpdatedBy == userId.ToString()) - .SetColumns(u => u.UpdatedAt == DateTime.Now) + .SetColumns(u => u.GrowthPoints == newGrowthPointsBalance) .Where(u => u.Id == userId) .ExecuteCommandAsync(); @@ -1326,16 +1324,12 @@ public class UserAnswerTaskService( UserId = userId, ChangeAmount = totalPoints, BalanceAfter = newPointsBalance, - ChangeType = PointsChangeTypeEnum.TaskReward.ToString(), + ChangeType = nameof(PointsChangeTypeEnum.TaskReward), RelatedId = groupId, Description = $"完成任务奖励,GroupId:{mainTask.GroupId}", Type = PointsFlowTypeEnum.Income, - Status = (int)PointsRecordStatusEnum.Success, - IsDeleted = false, - CreatedBy = "系统", - CreatedAt = DateTime.Now, - UpdatedBy = "系统", - UpdatedAt = DateTime.Now + Status = (int)PointsRecordStatusEnum.Success + }; await answerRepository.Context.Insertable(pointsRecord).ExecuteCommandAsync(); @@ -1438,7 +1432,7 @@ public class UserAnswerTaskService( // 3. 在内存中逐个校验每个 GroupId,筛选可领取的任务 // 所有数据已在步骤2中一次性查询完成,这里只做内存筛选 // ============================================ - var claimableTasks = new List<(long GroupId, int Points, int GrowthPoints, float Score, string TaskNo)>(); + var claimableTasks = new List<(long GroupId, int Points, int GrowthPoints, float Score)>(); foreach (var groupId in input.GroupIds) { @@ -1449,8 +1443,7 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = string.Empty, + GroupId = groupId, Message = "任务不存在" }); continue; @@ -1458,30 +1451,13 @@ public class UserAnswerTaskService( // 3.2 判断是否跨页题目并找主任务 bool isCrossPage = relatedTasks.Count > 1; - var mainTask = relatedTasks.FirstOrDefault(t => t.Id == groupId); - - // ============================================ - // 【任务编号计算】 - // 从 JournalPageTask.No 字段按 - 分割,取索引为 2 的部分,前面加"任务" - // 如果找不到主任务,尝试从子任务中计算 - // ============================================ - string taskNo = string.Empty; - var taskForNo = mainTask ?? relatedTasks.FirstOrDefault(); - if (taskForNo != null && !string.IsNullOrEmpty(taskForNo.No)) - { - var parts = taskForNo.No.Split('-'); - if (parts.Length >= 3) - { - taskNo = $"任务{parts[2]}"; - } - } + var mainTask = relatedTasks.FirstOrDefault(t => t.Id == groupId); if (mainTask == null) { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "子题目无法单独领取积分,请从主任务入口领取" }); continue; @@ -1492,8 +1468,7 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "请先完成答题再领取积分" }); continue; @@ -1505,8 +1480,7 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "请先完成答题再领取积分" }); continue; @@ -1524,8 +1498,7 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "跨页题目需要完成所有任务才能领取积分" }); continue; @@ -1537,8 +1510,7 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "积分已领取,请勿重复领取" }); continue; @@ -1553,36 +1525,20 @@ public class UserAnswerTaskService( { result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = "该任务无积分可领取" }); continue; } // 添加到可领取列表 - claimableTasks.Add((groupId, points, growthPoints, score, taskNo)); + claimableTasks.Add((groupId, points, growthPoints, score)); } catch (Exception ex) { - // 异常情况下,尝试从已查询的数据中计算 taskNo - string taskNo = string.Empty; - if (tasksByGroupId.TryGetValue(groupId, out var tasks) && tasks.Count > 0) - { - var task = tasks.FirstOrDefault(t => t.Id == groupId) ?? tasks.FirstOrDefault(); - if (task != null && !string.IsNullOrEmpty(task.No)) - { - var parts = task.No.Split('-'); - if (parts.Length >= 3) - { - taskNo = $"任务{parts[2]}"; - } - } - } result.FailItems.Add(new BatchClaimFailItem { - GroupId = groupId, - TaskNo = taskNo, + GroupId = groupId, Message = ex.Message }); } @@ -1593,6 +1549,7 @@ public class UserAnswerTaskService( // ============================================ // 4. 事务执行所有领取操作 // - 手动更新 Users.Points(积分累加) + // - 手动更新 Users.GrowthPoints(成长值累加) // - 插入积分流水记录 // - 喂养宠物(如有活跃宠物,更新宠物成长值) // ============================================ @@ -1622,8 +1579,7 @@ public class UserAnswerTaskService( // 添加成功详情 result.SuccessItems.Add(new BatchClaimSuccessItem - { - TaskNo = task.TaskNo, + { Points = task.Points, GrowthPoints = task.GrowthPoints, Score = task.Score @@ -1637,31 +1593,27 @@ public class UserAnswerTaskService( await answerRepository.Context.Updateable() .SetColumns(u => u.Points == newPointsBalance) - .SetColumns(u => u.GrowthPoints == newGrowthPointsBalance) - .SetColumns(u => u.UpdatedBy == userId.ToString()) - .SetColumns(u => u.UpdatedAt == DateTime.Now) + .SetColumns(u => u.GrowthPoints == newGrowthPointsBalance) .Where(u => u.Id == userId) .ExecuteCommandAsync(); // 4b. 批量插入积分流水记录 var records = new List(); + var tempNewPointsBalance = user.Points; foreach (var task in claimableTasks) { + tempNewPointsBalance += task.Points; + // 计算每条记录的领取后余额 records.Add(new PointsRecord { UserId = userId, ChangeAmount = task.Points, - BalanceAfter = newPointsBalance, - ChangeType = PointsChangeTypeEnum.TaskReward.ToString(), + BalanceAfter = tempNewPointsBalance, + ChangeType = nameof(PointsChangeTypeEnum.TaskReward), RelatedId = task.GroupId, Description = $"完成任务奖励,GroupId:{task.GroupId}", Type = PointsFlowTypeEnum.Income, Status = (int)PointsRecordStatusEnum.Success, - IsDeleted = false, - CreatedBy = "系统", - CreatedAt = DateTime.Now, - UpdatedBy = "系统", - UpdatedAt = DateTime.Now }); } await answerRepository.Context.Insertable(records).ExecuteCommandAsync(); @@ -1683,8 +1635,269 @@ public class UserAnswerTaskService( #region 5. 组装返回结果 result.FailCount = result.FailItems.Count; - + for (int i = 0; i < result.SuccessItems.Count; i++) + { + result.SuccessItems[i].TaskNo ="任务" + (i + 1); + } + for (int i = 0; i < result.FailItems.Count; i++) + { + result.FailItems[i].TaskNo ="任务" + (i + 1); + } return result; #endregion } + + /// + /// ============================================ + /// 方法思路:获取目录树形结构(一级目录和二级目录的完整树形结构,包含任务详情) + /// 【核心逻辑】 + /// 1. 用户绑定验证:查询 UserJournal 表验证用户是否绑定该杂志 + /// 2. 批量预加载:一次性加载目录、页面、任务、用户作答记录,避免N+1查询 + /// 3. 一级目录统计:文章篇数(二级目录有题目页面数总和)、任务数(GroupId去重总和) + /// 4. 二级目录构建:页码范围、任务数、状态、总成长值、总积分、任务列表 + /// 5. 任务详情:任务名称(取主任务Task字段)、状态、成长值、积分值、答题时长 + /// 【状态判定规则】 + /// - 未开始:无任何任务作答记录 + /// - 进行中:有作答记录但未全部完成 + /// - 已完成:所有任务都完成(Status=1) + /// 【跨页题目处理】 + /// - 任务名称:取主任务(Id == GroupId)的Task字段 + /// - 成长值/积分:取主任务数据,按GroupId去重计算 + /// - 答题时长:该GroupId下所有任务的AnswerSeconds累加后转换为分钟 + /// ============================================ + /// + /// 期刊Id + /// 用户Id + /// 目录树形结构数据 + public async Task GetCatalogTreeAsync(long journalId, long userId) + { + #region 0. 用户绑定验证 + + // 验证用户是否绑定该杂志,未绑定直接返回空结果 + var isBound = await userJournalRepository.Context.Queryable() + .Where(uj => uj.UserId == userId && uj.JournalId == journalId) + .AnyAsync(); + + if (!isBound) + { + return new CatalogTreeOutput(); + } + + #endregion + + #region 1. 批量预加载关联数据 + + // 一次性加载所有关联数据,避免N+1查询 + var allCatalogs = await catalogRepository.Context.Queryable() + .Where(c => c.JournalId == journalId) + .ToListAsync(); + + var allPages = await pageRepository.Context.Queryable() + .Where(p => p.JournalId == journalId) + .ToListAsync(); + + var allTasks = await taskRepository.Context.Queryable() + .Where(t => t.JournalId == journalId) + .ToListAsync(); + + var userAnswers = await answerRepository.Context.Queryable() + .Where(a => a.JournalId == journalId && a.UserId == userId) + .ToListAsync(); + + #endregion + + #region 2. 构建用户作答状态集合 + + // 用户已作答的任务ID集合(包含进行中和已完成) + var userAnsweredTaskIds = userAnswers.Select(a => a.JournalPageTaskId).ToHashSet(); + + // 用户已完成的任务ID集合(Status=1表示已批阅完成) + var userCompletedTaskIds = userAnswers + .Where(a => a.Status == (int)UserAnswerStatusEnum.Complete) + .Select(a => a.JournalPageTaskId) + .ToHashSet(); + + #endregion + + #region 3. 构建树形结构 + + // 获取一级目录(ParentId=0),按排序字段排序 + var firstLevelCatalogs = allCatalogs.Where(c => c.ParentId == 0).OrderBy(c => c.Sort).ToList(); + var result = new CatalogTreeOutput(); + + foreach (var firstCatalog in firstLevelCatalogs) + { + int articleCount = 0; + int taskCount = 0; + var children = new List(); + + // 获取该一级目录下的二级目录,按排序字段排序 + var secondLevelCatalogs = allCatalogs + .Where(c => c.ParentId == firstCatalog.Id) + .OrderBy(c => c.Sort) + .ToList(); + + foreach (var secondCatalog in secondLevelCatalogs) + { + // 获取二级目录下的所有页面,按页码排序 + var secondLevelPages = allPages + .Where(p => p.JournalCatalogId == secondCatalog.Id) + .OrderBy(p => p.PageNum) + .ToList(); + + var secondLevelPageIds = secondLevelPages.Select(p => p.Id).ToHashSet(); + + // 统计有题目的页面数(用于文章篇数计算) + var pagesWithTasks = allTasks + .Where(t => secondLevelPageIds.Contains(t.JournalPageId)) + .Select(t => t.JournalPageId) + .ToHashSet(); + + articleCount += pagesWithTasks.Count; + + // 获取二级目录下的所有任务 + var secondLevelTasks = allTasks.Where(t => secondLevelPageIds.Contains(t.JournalPageId)).ToList(); + + // 按GroupId分组(跨页题目处理) + var groupTasks = secondLevelTasks.GroupBy(t => t.GroupId).ToList(); + var catalogTaskCount = groupTasks.Count; + + // 如果二级目录没有任务,则跳过不显示 + if (catalogTaskCount == 0) + { + continue; + } + + taskCount += catalogTaskCount; + + // 计算页码范围 + var startPage = secondLevelPages.Count > 0 ? secondLevelPages.Min(p => p.PageNum) : 0; + var endPage = secondLevelPages.Count > 0 ? secondLevelPages.Max(p => p.PageNum) : 0; + + // 计算二级目录状态 + var status = CalculateCatalogStatus(groupTasks, userAnsweredTaskIds, userCompletedTaskIds); + + // 计算总成长值和总积分(按GroupId去重,取主任务数据) + var (totalGrowthPoints, totalPoints) = CalculateCatalogPoints(groupTasks); + + // 构建任务列表 + var taskItems = BuildTaskItems(groupTasks, userAnswers, userAnsweredTaskIds, userCompletedTaskIds); + + // 添加二级目录项 + children.Add(new SecondLevelCatalogItem + { + CatalogId = secondCatalog.Id, + CatalogName = secondCatalog.Name ?? string.Empty, + StartPage = startPage, + EndPage = endPage, + TaskCount = catalogTaskCount, + Status = status, + TotalGrowthPoints = totalGrowthPoints, + TotalPoints = totalPoints, + Tasks = taskItems + }); + } + + // 添加一级目录项 + result.FirstLevelCatalogs.Add(new FirstLevelCatalogItem + { + CatalogId = firstCatalog.Id, + CatalogName = firstCatalog.Name ?? string.Empty, + ArticleCount = articleCount, + TaskCount = taskCount, + Children = children + }); + } + + #endregion + + return result; + } + + + #region 私有方法,逻辑处理 + + /// + /// 计算目录状态(格式:已完成数/总数 状态描述) + /// + /// 按GroupId分组的任务列表 + /// 用户已作答任务ID集合 + /// 用户已完成任务ID集合 + /// 状态描述(格式:1/2 进行中、0/2 未开始、2/2 已完成) + private static string CalculateCatalogStatus(List> groupTasks, HashSet userAnsweredTaskIds, HashSet userCompletedTaskIds) + { + var catalogTaskCount = groupTasks.Count; + + // 已完成的GroupId数量(该GroupId下所有任务都完成) + var completedGroupCount = groupTasks.Count(g => g.All(t => userCompletedTaskIds.Contains(t.Id))); + + // 已作答的GroupId数量(该GroupId下至少有一个任务被作答) + var answeredGroupCount = groupTasks.Count(g => g.Any(t => userAnsweredTaskIds.Contains(t.Id))); + + if (answeredGroupCount == 0) + return $"0/{catalogTaskCount} 未开始"; + if (completedGroupCount == catalogTaskCount) + return $"{completedGroupCount}/{catalogTaskCount} 已完成"; + return $"{completedGroupCount}/{catalogTaskCount} 进行中"; + } + + /// + /// 计算目录总成长值和总积分(按GroupId去重) + /// + /// 按GroupId分组的任务列表 + /// 总成长值和总积分 + private static (int TotalGrowthPoints, int TotalPoints) CalculateCatalogPoints(List> groupTasks) + { + // 取每个GroupId的主任务(Id == GroupId),若不存在则取第一个任务 + var mainTasks = groupTasks.ConvertAll(g => g.FirstOrDefault(t => t.Id == g.Key) ?? g.First()); + return (mainTasks.Sum(t => t.GrowthPoint), mainTasks.Sum(t => t.Points)); + } + + /// + /// 构建任务详情列表 + /// + /// 按GroupId分组的任务列表 + /// 用户作答记录 + /// 用户已作答任务ID集合 + /// 用户已完成任务ID集合 + /// 任务详情列表 + private static List BuildTaskItems(List> groupTasks, List userAnswers, HashSet userAnsweredTaskIds, HashSet userCompletedTaskIds) + { + var taskItems = new List(); + + foreach (var group in groupTasks) + { + var groupId = group.Key; + // 取主任务(Id == GroupId),若不存在则取第一个任务 + var mainTask = group.FirstOrDefault(t => t.Id == groupId) ?? group.First(); + + // 计算该GroupId下所有任务的答题时间(秒 → 分钟) + var taskIds = group.Select(t => t.Id).ToHashSet(); + var groupAnswerSeconds = userAnswers + .Where(a => taskIds.Contains(a.JournalPageTaskId)) + .Sum(a => a.AnswerSeconds); + var groupAnswerMinutes = Math.Round(groupAnswerSeconds / 60.0, 2); + + // 判断任务状态 + bool hasAnswer = group.Any(t => userAnsweredTaskIds.Contains(t.Id)); + bool isAllCompleted = group.All(t => userCompletedTaskIds.Contains(t.Id)); + + string taskStatus = !hasAnswer ? "未开始" : (isAllCompleted ? "已完成" : "进行中"); + + taskItems.Add(new CatalogTaskItem + { + GroupId = groupId, + TaskName = mainTask.Task ?? string.Empty, + Status = taskStatus, + GrowthPoints = mainTask.GrowthPoint, + Points = mainTask.Points, + AnswerMinutes = groupAnswerMinutes + }); + } + + return taskItems; + } + + #endregion + } diff --git a/QYZH.InteractiveMagazine.WeChatApi/Controllers/UserAnswerTaskController.cs b/QYZH.InteractiveMagazine.WeChatApi/Controllers/UserAnswerTaskController.cs index c87c2fb..161f663 100644 --- a/QYZH.InteractiveMagazine.WeChatApi/Controllers/UserAnswerTaskController.cs +++ b/QYZH.InteractiveMagazine.WeChatApi/Controllers/UserAnswerTaskController.cs @@ -238,8 +238,7 @@ public class UserAnswerTaskController : WeChatBaseController public async Task> BatchClaimPointsAsync([FromBody] BatchClaimPointsInput input) { try - { - + { var userId = GetCurrentUserId(); if (userId == 0) { @@ -265,4 +264,35 @@ public class UserAnswerTaskController : WeChatBaseController return BaseResponse.Fail("批量领取积分失败,请稍后重试"); } } + + /// + /// 获取目录树形结构(一级目录和二级目录的完整树形结构,包含任务详情) + /// + /// 期刊Id + /// 目录树形结构数据 + [HttpGet("catalog-tree/{journalId:long}")] + public async Task> GetCatalogTreeAsync([Required(ErrorMessage = "参数错误")] long journalId) + { + try + { + var userId = ConstUserId;//GetCurrentUserId(); + if (userId == 0) + { + return BaseResponse.Fail(ResultCode.DENY, "未获取到用户信息"); + } + + if (journalId <= 0) + { + return BaseResponse.Fail(ResultCode.PARAM_ERROR, "期刊Id不能为空"); + } + + var result = await _userAnswerTaskService.GetCatalogTreeAsync(journalId, userId); + return Success(result); + } + catch (Exception ex) + { + _logger.LogError(ex, "获取目录树形结构失败,JournalId: {JournalId}, UserId: {UserId}", journalId, GetCurrentUserId()); + return BaseResponse.Fail("获取目录树形结构失败,请稍后重试"); + } + } } diff --git a/QYZH.InteractiveMagazine.WeChatApi/Controllers/WeChatBaseController.cs b/QYZH.InteractiveMagazine.WeChatApi/Controllers/WeChatBaseController.cs index 989677d..44ca201 100644 --- a/QYZH.InteractiveMagazine.WeChatApi/Controllers/WeChatBaseController.cs +++ b/QYZH.InteractiveMagazine.WeChatApi/Controllers/WeChatBaseController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using QYZH.InteractiveMagazine.Infrastructure.Auth; +using QYZH.InteractiveMagazine.Infrastructure.Context; using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Enum; using System.Security.Claims; diff --git a/QYZH.InteractiveMagazine.slnx b/QYZH.InteractiveMagazine.slnx index 3a2a8cf..93a5979 100644 --- a/QYZH.InteractiveMagazine.slnx +++ b/QYZH.InteractiveMagazine.slnx @@ -9,6 +9,8 @@ - + + +