From a6db06c6cba8dd58a79330d0d0c7746ebb972813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=B7=E6=AD=A6=20=E9=BB=84?= <865114447@qq.com> Date: Mon, 29 Jun 2026 17:16:38 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BatchClaimPointsOutput.cs | 5 +++ .../ClaimTaskPointsOutput.cs | 5 +++ .../UserAnswerTaskService.cs | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/BatchClaimPointsOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/BatchClaimPointsOutput.cs index 4054b17..f325be9 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/BatchClaimPointsOutput.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/BatchClaimPointsOutput.cs @@ -67,6 +67,11 @@ public class BatchClaimSuccessItem /// public string TaskName { get; set; } + /// + /// 任务编号(从 JournalPageTask.No 字段按 - 分割取索引2) + /// + public string TaskNo { get; set; } + /// /// 积分值 /// diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/ClaimTaskPointsOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/ClaimTaskPointsOutput.cs index 41f3d12..1b8c131 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/ClaimTaskPointsOutput.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/ClaimTaskPointsOutput.cs @@ -30,6 +30,11 @@ public class ClaimTaskPointsOutput /// public string TaskName { get; set; } + /// + /// 任务编号(从 JournalPageTask.No 字段按 - 分割取索引2) + /// + public string TaskNo { get; set; } + /// /// 题目得分(从 JournalPageTaskUserAnswer 表获取,JournalPageTaskId == GroupId 的 Score) /// diff --git a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs index d1093cb..7ce542d 100644 --- a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs @@ -1257,6 +1257,22 @@ public class UserAnswerTaskService( OperatorName = "系统" }); + // ============================================ + // 【任务编号计算】 + // 从 JournalPageTask.No 字段按 - 分割,取索引为 2 的部分 + // No 最多出现索引为 3(即最多4段,0-3) + // 例如:"A-B-C-D" → 分割后 ["A","B","C","D"] → 取索引2 = "C" + // ============================================ + string taskNo = string.Empty; + if (!string.IsNullOrEmpty(mainTask.No)) + { + var parts = mainTask.No.Split('-'); + if (parts.Length >= 3) + { + taskNo = parts[2]; + } + } + return new ClaimTaskPointsOutput { RecordId = addPointsResult.RecordId, @@ -1264,6 +1280,7 @@ public class UserAnswerTaskService( NewBalance = addPointsResult.NewBalance, AddedAmount = addPointsResult.AddedAmount, TaskName = mainTask.Task ?? string.Empty, + TaskNo = !string.IsNullOrWhiteSpace(taskNo) ? "任务:"+ taskNo : string.Empty, Score = totalScore }; #endregion @@ -1483,6 +1500,22 @@ public class UserAnswerTaskService( // 获取任务名称 var taskName = mainTask.Task ?? string.Empty; + + // ============================================ + // 【任务编号计算】 + // 从 JournalPageTask.No 字段按 - 分割,取索引为 2 的部分 + // No 最多出现索引为 3(即最多4段,0-3) + // 例如:"A-B-C-D" → 分割后 ["A","B","C","D"] → 取索引2 = "C" + // ============================================ + string taskNo = string.Empty; + if (!string.IsNullOrEmpty(mainTask.No)) + { + var parts = mainTask.No.Split('-'); + if (parts.Length >= 3) + { + taskNo = parts[2]; + } + } #endregion #region 3.7 调用积分服务并记录结果 @@ -1508,6 +1541,7 @@ public class UserAnswerTaskService( { GroupId = groupId, TaskName = taskName, + TaskNo = !string.IsNullOrWhiteSpace(taskNo) ? "任务:" + taskNo : string.Empty, Points = points, GrowthPoints = growthPoints, Score = score From 5481c091f219cb61f68644b4b88632b15bed4d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=B7=E6=AD=A6=20=E9=BB=84?= <865114447@qq.com> Date: Mon, 29 Jun 2026 17:49:39 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IUserAnswerTaskService.cs | 24 --- .../UserAnswerTaskService/AddStudentInput.cs | 18 -- .../UserAnswerTaskService/AddStudentOutput.cs | 43 ----- .../JournalListOutput.cs | 32 ---- .../UserAnswerTaskService.cs | 159 ------------------ .../WeChat/UserAnswerTaskController.cs | 96 ----------- 6 files changed, 372 deletions(-) delete mode 100644 QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentInput.cs delete mode 100644 QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentOutput.cs delete mode 100644 QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/JournalListOutput.cs diff --git a/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs b/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs index 5ad013c..4621c1a 100644 --- a/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.IService/IUserAnswerTaskService.cs @@ -62,28 +62,4 @@ public interface IUserAnswerTaskService : IBaseService用户Id /// 批量领取结果 Task BatchClaimPointsAsync(BatchClaimPointsInput input, long userId); - - /// - /// 获取杂志列表 - /// - /// 用户Id - /// 查询类型:Bound=已绑定,Unbound=未绑定(添加书籍用),默认是:Bound - /// 杂志列表 - Task> GetJournalListAsync(long userId, string? queryType); - - /// - /// 添加用户与杂志关联(绑定杂志) - /// - /// 杂志ID - /// 用户ID - /// 是否绑定成功(已绑定过返回false) - Task AddUserJournalAsync(long journalId, long userId); - - /// - /// 新增学生 - /// - /// 新增学生参数 - /// 当前登录用户微信UserId(WxUserId) - /// 新增学生结果 - Task AddStudentAsync(AddStudentInput input, long wxUserId); } diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentInput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentInput.cs deleted file mode 100644 index 32acfac..0000000 --- a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentInput.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService -{ - /// - /// 新增学生输入 - /// - public class AddStudentInput - { - /// - /// 昵称 - /// - public string? Name { get; set; } - - /// - /// 头像地址 - /// - public string? AvatarUrl { get; set; } - } -} \ No newline at end of file diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentOutput.cs deleted file mode 100644 index 8a073bf..0000000 --- a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/AddStudentOutput.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService -{ - /// - /// 新增学生输出 - /// - public class AddStudentOutput - { - /// - /// 学生Id - /// - public long Id { get; set; } - - /// - /// 关联微信用户Id - /// - public long WxUserId { get; set; } - - /// - /// 昵称 - /// - public string? Name { get; set; } - - /// - /// 头像地址 - /// - public string? AvatarUrl { get; set; } - - /// - /// 用户类型 - /// - public string Type { get; set; } = "Normal"; - - /// - /// 当前成长值 - /// - public int GrowthPoints { get; set; } - - /// - /// 积分余额 - /// - public int Points { get; set; } - } -} \ No newline at end of file diff --git a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/JournalListOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/JournalListOutput.cs deleted file mode 100644 index ece7bd6..0000000 --- a/QYZH.InteractiveMagazine.Models/Dto/UserAnswerTaskService/JournalListOutput.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService; - -/// -/// 杂志列表输出 -/// -public class JournalListOutput -{ - /// - /// 杂志Id - /// - public long Id { get; set; } - - /// - /// 杂志名称 - /// - public string Name { get; set; } - - /// - /// 杂志标题 - /// - public string Title { get; set; } - - /// - /// 封面 - /// - public string Cover { get; set; } - - /// - /// 是否已绑定 - /// - public bool IsBound { get; set; } -} diff --git a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs index 0391516..0fdd4c0 100644 --- a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs @@ -1570,163 +1570,4 @@ public class UserAnswerTaskService( return result; #endregion } - - /// - /// ============================================ - /// 方法思路:获取杂志列表 - /// 1. 查询所有已归档的杂志(Status=Archive) - /// 2. 查询用户已绑定的杂志ID列表 - /// 3. 根据queryType过滤(大小写不敏感): - /// - "Bound":只返回已绑定的杂志 - /// - "Unbound":只返回未绑定的杂志 - /// - 其他:返回空集合 - /// 4. 返回每个杂志的ID、名称、标题、封面、是否已绑定 - /// ============================================ - /// - /// 用户ID - /// 查询类型:bound/unbound(大小写不敏感),其他返回空 - /// 杂志列表 - public async Task> GetJournalListAsync(long userId, string? queryType = "Bound") - { - #region 1. 查询所有已归档杂志 - // 查询所有已归档且未删除的杂志 - var allJournals = await journalRepository.Queryable() - .Where(j => !j.IsDeleted && j.Status == (int)JournalStatusEnum.Archive) - .OrderByDescending(j => j.CreatedAt) - .ToListAsync(); - #endregion - - #region 2. 查询用户已绑定杂志 - // 查询用户已绑定的杂志ID列表 - var userJournals = await userJournalRepository.Context.Queryable() - .Where(uj => uj.UserId == userId && !uj.IsDeleted) - .Select(uj => uj.JournalId) - .ToListAsync(); - - var boundJournalIds = userJournals.ToHashSet(); - #endregion - - #region 3. 根据queryType过滤 - // ============================================ - // 【大小写兼容处理 + 合法值校验】 - // queryType 只接受两种值(大小写不敏感): - // - "Bound" / "bound" / "BOUND" → 返回已绑定杂志 - // - "Unbound" / "unbound" / "UNBOUND" → 返回未绑定杂志 - // - 空 / 其他值 → 返回空集合 - // ============================================ - var normalizedQueryType = queryType?.ToLowerInvariant() ?? string.Empty; - - IEnumerable filteredJournals; - if (normalizedQueryType == "bound") - { - filteredJournals = allJournals.Where(j => boundJournalIds.Contains(j.Id)); - } - else if (normalizedQueryType == "unbound") - { - filteredJournals = allJournals.Where(j => !boundJournalIds.Contains(j.Id)); - } - else - { - // 非 Bound/Unbound 类型,返回空集合 - filteredJournals = Enumerable.Empty(); - } - #endregion - - #region 4. 返回结果映射 - var result = filteredJournals.Select(j => new JournalListOutput - { - Id = j.Id, - Name = j.Name ?? string.Empty, - Title = j.Title ?? string.Empty, - Cover = j.Cover ?? string.Empty, - IsBound = boundJournalIds.Contains(j.Id) - }).ToList(); - - return result; - #endregion - } - - /// - /// ============================================ - /// 方法思路:添加用户与杂志关联(绑定杂志) - /// 1. 验证杂志是否存在 - /// 2. 检查用户是否已绑定过该杂志 - /// - 查询 UserJournal 表,条件:UserId + JournalId - /// 3. 已绑定过:返回 false - /// 4. 未绑定:插入 UserJournal 记录,返回 true - /// ============================================ - /// - /// 杂志ID - /// 用户ID - /// 是否绑定成功(已绑定过返回false) - public async Task AddUserJournalAsync(long journalId, long userId) - { - #region 1. 验证杂志是否存在 - var journal = await journalRepository.Queryable() - .Where(j => j.Id == journalId && !j.IsDeleted) - .FirstAsync(); - - if (journal == null) - { - throw new BusinessException("杂志不存在", 404); - } - #endregion - - #region 2. 检查用户是否已绑定过该杂志 - var exist = await userJournalRepository.Context.Queryable() - .Where(uj => uj.UserId == userId && uj.JournalId == journalId && !uj.IsDeleted) - .AnyAsync(); - - if (exist) - { - // 已绑定过,返回 false - return false; - } - #endregion - - #region 3. 插入 UserJournal 记录 - var userJournal = new UserJournal - { - UserId = userId, - JournalId = journalId, - Type = UserJournalTypeEnum.Subscribe - }; - - var result = await userJournalRepository.InsertAsync(userJournal); - return result; - #endregion - } - - /// - /// ============================================ - /// 方法思路:新增学生 - /// 1. 创建新的Users记录 - /// 2. WxUserId设置为当前登录人ID(wxUserId参数传入) - /// 3. 初始化积分和成长值为0 - /// 4. 用户类型设置为普通用户(Normal) - /// 5. 插入数据库并返回结果 - /// ============================================ - /// - /// 新增学生输入(姓名、头像URL) - /// 当前登录人ID(微信用户ID) - /// 是否插入成功 - public async Task AddStudentAsync(AddStudentInput input, long wxUserId) - { - #region 1. 创建学生记录 - var student = new Users - { - WxUserId = wxUserId, - Name = input.Name, - AvatarUrl = input.AvatarUrl, - GrowthPoints = 0, - Points = 0, - Type = UsersTypeEnum.Normal, - IsLastOnline = false - }; - #endregion - - #region 2. 插入数据库 - return await usersRepository.InsertAsync(student); - #endregion - } } diff --git a/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/UserAnswerTaskController.cs b/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/UserAnswerTaskController.cs index e2d5201..a558df6 100644 --- a/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/UserAnswerTaskController.cs +++ b/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/UserAnswerTaskController.cs @@ -262,100 +262,4 @@ public class UserAnswerTaskController : WeChatBaseController return BaseResponse.Fail("批量领取积分失败,请稍后重试"); } } - - /// - /// 获取杂志列表 - /// - /// 查询类型:bound=已绑定,unbound=未绑定(添加杂志用列表),默认是:bound - /// 杂志列表 - [HttpGet("journal-list")] - public async Task>> GetJournalListAsync(string? queryType = "bound") - { - try - { - var userId = GetCurrentUserId(); - if (userId == 0) - { - return BaseResponse>.Fail(ResultCode.DENY, "未获取到用户信息"); - } - - var result = await _userAnswerTaskService.GetJournalListAsync(userId, queryType); - return Success(result); - } - catch (BusinessException ex) - { - _logger.LogWarning(ex, "查询杂志列表业务异常,UserId: {UserId}", GetCurrentUserId()); - return BaseResponse>.Fail(ex.Message); - } - catch (Exception ex) - { - _logger.LogError(ex, "查询杂志列表失败,UserId: {UserId}", GetCurrentUserId()); - return BaseResponse>.Fail("查询杂志列表失败,请稍后重试"); - } - } - - /// - /// 绑定杂志(添加用户与杂志关联) - /// - /// 杂志ID - /// 是否绑定成功(已绑定过返回false) - [HttpPost("add-user-journal/{journalId:long}")] - public async Task> AddUserJournalAsync([Required(ErrorMessage = "参数错误")] long journalId) - { - try - { - var userId = GetCurrentUserId(); - if (userId == 0) - { - return BaseResponse.Fail(ResultCode.DENY, "未获取到用户信息"); - } - - var result = await _userAnswerTaskService.AddUserJournalAsync(journalId, userId); - return Success(result); - } - catch (BusinessException ex) - { - _logger.LogWarning(ex, "绑定杂志业务异常,UserId: {UserId}, JournalId: {JournalId}", GetCurrentUserId(), journalId); - return BaseResponse.Fail(ex.Message); - } - catch (Exception ex) - { - _logger.LogError(ex, "绑定杂志失败,UserId: {UserId}, JournalId: {JournalId}", GetCurrentUserId(), journalId); - return BaseResponse.Fail("绑定杂志失败,请稍后重试"); - } - } - - /// - /// 新增学生 - /// - /// 新增学生参数 - /// 新增学生结果 - [HttpPost("add-student")] - public async Task> AddStudentAsync([FromBody] AddStudentInput input) - { - try - { - var userId = GetCurrentUserId(); - if (userId == 0) - { - return BaseResponse.Fail(ResultCode.DENY, "未获取到用户信息"); - } - if (GetCurrentWxUserId() == null) - { - return BaseResponse.Fail(ResultCode.DENY, "未获取到微信信息"); - } - var result = await _userAnswerTaskService.AddStudentAsync(input, GetCurrentWxUserId()!.Value); - return Success(result); - } - catch (BusinessException ex) - { - _logger.LogWarning(ex, "新增学生业务异常,UserId: {UserId}", GetCurrentUserId()); - return BaseResponse.Fail(ex.Message); - } - catch (Exception ex) - { - _logger.LogError(ex, "新增学生失败,UserId: {UserId}", GetCurrentUserId()); - return BaseResponse.Fail("新增学生失败,请稍后重试"); - } - } }