Merge branch 'master' of http://8.137.159.94:3000/glz/QYZH.InteractiveMagazine
This commit is contained in:
@ -8,7 +8,7 @@ public class BatchClaimPointsInput
|
||||
/// <summary>
|
||||
/// 任务分组Id列表(JournalPageTaskGroupId)
|
||||
/// </summary>
|
||||
public List<long> GroupIds { get; set; } = [];
|
||||
public HashSet<long> GroupIds { get; set; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -73,6 +73,11 @@ public class BatchClaimFailItem
|
||||
/// </summary>
|
||||
public long GroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务编号(从 JournalPageTask.No 字段按 - 分割取索引2,前面加"任务")
|
||||
/// </summary>
|
||||
public string TaskNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败原因
|
||||
/// </summary>
|
||||
|
||||
@ -63,7 +63,7 @@ namespace QYZH.InteractiveMagazine.Models.Entity
|
||||
/// Default:0
|
||||
/// Nullable:False
|
||||
/// </summary>
|
||||
public float GrowthPoints { get; set; }
|
||||
public int GrowthPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Desc:题目得分
|
||||
|
||||
@ -1218,7 +1218,7 @@ public class UserAnswerTaskService(
|
||||
var mainTask = relatedTasks.FirstOrDefault(t => t.Id == groupId);
|
||||
if (mainTask == null)
|
||||
{
|
||||
throw new BusinessException("子题目无法单独领取积分,请从主任务入口领取", ResultCode.BAD_REQUEST);
|
||||
throw new BusinessException("跨页题目需要完成所有任务才能领取积分", ResultCode.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 查询用户答题记录
|
||||
@ -1275,8 +1275,8 @@ public class UserAnswerTaskService(
|
||||
}
|
||||
|
||||
// 积分、成长值、得分(均取主任务数据)
|
||||
int totalPoints = mainTask.Points;
|
||||
int totalGrowthPoints = mainTask.GrowthPoint;
|
||||
int totalPoints = mainTaskAnswer.Points;
|
||||
int totalGrowthPoints = mainTaskAnswer.GrowthPoints;
|
||||
float score = mainTaskAnswer.Score;
|
||||
|
||||
if (totalPoints <= 0)
|
||||
@ -1315,6 +1315,7 @@ public class UserAnswerTaskService(
|
||||
await answerRepository.Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == newPointsBalance)
|
||||
.SetColumns(u => u.GrowthPoints == newGrowthPointsBalance)
|
||||
.SetColumns(u => u.UpdatedBy == userId.ToString())
|
||||
.SetColumns(u => u.UpdatedAt == DateTime.Now)
|
||||
.Where(u => u.Id == userId)
|
||||
.ExecuteCommandAsync();
|
||||
@ -1401,82 +1402,111 @@ public class UserAnswerTaskService(
|
||||
{
|
||||
throw new BusinessException("任务分组Id列表不能为空", ResultCode.BAD_REQUEST);
|
||||
}
|
||||
|
||||
var groupIds = input.GroupIds.Distinct().ToList();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2. 批量查询已领取的积分记录
|
||||
// 批量查询已领取的积分记录(用于重复领取校验)
|
||||
#region 2. 批量查询所有数据(一次性查询,避免N+1)
|
||||
// ============================================
|
||||
// 2. 批量查询所有数据
|
||||
// - 所有 GroupId 对应的任务(JournalPageTask)
|
||||
// - 所有 GroupId 对应的用户答题记录(JournalPageTaskUserAnswer)
|
||||
// - 已领取的积分记录(用于重复领取校验)
|
||||
// ============================================
|
||||
|
||||
// 2.1 批量查询所有相关任务(按 GroupId 分组)
|
||||
var allTasks = await taskRepository.Context.Queryable<JournalPageTask>()
|
||||
.Where(t => input.GroupIds.Contains(t.GroupId))
|
||||
.ToListAsync();
|
||||
var tasksByGroupId = allTasks.GroupBy(t => t.GroupId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
// 2.2 批量查询所有用户答题记录(按 JournalPageTaskGroupId 分组)
|
||||
var allUserAnswers = await answerRepository.Context.Queryable<JournalPageTaskUserAnswer>()
|
||||
.Where(a => input.GroupIds.Contains(a.JournalPageTaskGroupId) && a.UserId == userId)
|
||||
.ToListAsync();
|
||||
var answersByGroupId = allUserAnswers.GroupBy(a => a.JournalPageTaskGroupId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
// 2.3 批量查询已领取的积分记录(用于重复领取校验)
|
||||
var claimedRecords = await answerRepository.Context.Queryable<PointsRecord>()
|
||||
.Where(r => groupIds.Contains((long)r.RelatedId!) && r.UserId == userId)
|
||||
.Where(r => r.ChangeType == PointsChangeTypeEnum.TaskReward.ToString())
|
||||
.Where(r => input.GroupIds.Contains((long)r.RelatedId!) && r.UserId == userId)
|
||||
.Where(r => r.ChangeType == nameof(PointsChangeTypeEnum.TaskReward))
|
||||
.ToListAsync();
|
||||
var claimedGroupIds = claimedRecords.Select(r => r.RelatedId!.Value).ToHashSet();
|
||||
#endregion
|
||||
|
||||
#region 3. 逐个校验每个 GroupId,筛选可领取的任务
|
||||
// 存储可领取的任务信息
|
||||
var claimableTasks = new List<(long GroupId, int Points, int GrowthPoints, float Score, string TaskName, string TaskNo)>();
|
||||
#region 3. 内存中筛选可领取的任务
|
||||
// ============================================
|
||||
// 3. 在内存中逐个校验每个 GroupId,筛选可领取的任务
|
||||
// 所有数据已在步骤2中一次性查询完成,这里只做内存筛选
|
||||
// ============================================
|
||||
var claimableTasks = new List<(long GroupId, int Points, int GrowthPoints, float Score, string TaskNo)>();
|
||||
|
||||
foreach (var groupId in groupIds)
|
||||
foreach (var groupId in input.GroupIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
#region 3.1 根据 GroupId 查询所有相关任务
|
||||
var relatedTasks = await taskRepository.Context.Queryable<JournalPageTask>()
|
||||
.Where(t => t.GroupId == groupId)
|
||||
.ToListAsync();
|
||||
|
||||
if (relatedTasks == null || relatedTasks.Count == 0)
|
||||
// 3.1 从内存中获取相关任务
|
||||
if (!tasksByGroupId.TryGetValue(groupId, out var relatedTasks) || relatedTasks.Count == 0)
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = string.Empty,
|
||||
Message = "任务不存在"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3.2 判断是否跨页题目并找主任务
|
||||
// 3.2 判断是否跨页题目并找主任务
|
||||
bool isCrossPage = relatedTasks.Count > 1;
|
||||
// 主任务:Id == GroupId
|
||||
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]}";
|
||||
}
|
||||
}
|
||||
|
||||
if (mainTask == null)
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "子题目无法单独领取积分,请从主任务入口领取"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3.3 查询用户答题记录
|
||||
var userAnswers = await answerRepository.Context.Queryable<JournalPageTaskUserAnswer>()
|
||||
.Where(a => a.JournalPageTaskGroupId == groupId && a.UserId == userId)
|
||||
.ToListAsync();
|
||||
|
||||
if (userAnswers == null || userAnswers.Count == 0)
|
||||
// 3.3 从内存中获取用户答题记录
|
||||
if (!answersByGroupId.TryGetValue(groupId, out var userAnswers) || userAnswers.Count == 0)
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "请先完成答题再领取积分"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3.4 完成校验
|
||||
// 校验主任务完成状态:Status=1
|
||||
// 3.4 完成校验
|
||||
var mainTaskAnswer = userAnswers.FirstOrDefault(a => a.JournalPageTaskId == groupId);
|
||||
if (mainTaskAnswer == null || mainTaskAnswer.Status != (int)UserAnswerStatusEnum.Complete)
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "请先完成答题再领取积分"
|
||||
});
|
||||
continue;
|
||||
@ -1485,43 +1515,38 @@ public class UserAnswerTaskService(
|
||||
// 跨页题目:校验所有任务
|
||||
if (isCrossPage)
|
||||
{
|
||||
bool allCompleted = true;
|
||||
foreach (var task in relatedTasks)
|
||||
bool allCompleted = relatedTasks.All(task =>
|
||||
{
|
||||
var answer = userAnswers.FirstOrDefault(a => a.JournalPageTaskId == task.Id);
|
||||
if (answer == null || answer.Status != (int)UserAnswerStatusEnum.Complete)
|
||||
{
|
||||
allCompleted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer != null && answer.Status == (int)UserAnswerStatusEnum.Complete;
|
||||
});
|
||||
if (!allCompleted)
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "跨页题目需要完成所有任务才能领取积分"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3.5 重复领取校验
|
||||
// 3.5 重复领取校验
|
||||
if (claimedGroupIds.Contains(groupId))
|
||||
{
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "积分已领取,请勿重复领取"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3.6 计算积分、成长值、得分
|
||||
int points = mainTask.Points;
|
||||
int growthPoints = mainTask.GrowthPoint;
|
||||
// 3.6 计算积分、成长值、得分
|
||||
int points = mainTaskAnswer.Points;
|
||||
int growthPoints = mainTaskAnswer.GrowthPoints;
|
||||
float score = mainTaskAnswer.Score;
|
||||
|
||||
if (points <= 0)
|
||||
@ -1529,34 +1554,35 @@ public class UserAnswerTaskService(
|
||||
result.FailItems.Add(new BatchClaimFailItem
|
||||
{
|
||||
GroupId = groupId,
|
||||
TaskNo = taskNo,
|
||||
Message = "该任务无积分可领取"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
var taskName = mainTask.Task ?? string.Empty;
|
||||
|
||||
// 任务编号计算
|
||||
string taskNo = string.Empty;
|
||||
if (!string.IsNullOrEmpty(mainTask.No))
|
||||
{
|
||||
var parts = mainTask.No.Split('-');
|
||||
if (parts.Length >= 3)
|
||||
{
|
||||
taskNo = $"任务{parts[2]}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
// 添加到可领取列表
|
||||
claimableTasks.Add((groupId, points, growthPoints, score, taskName, taskNo));
|
||||
claimableTasks.Add((groupId, points, growthPoints, score, taskNo));
|
||||
}
|
||||
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,
|
||||
Message = ex.Message
|
||||
});
|
||||
}
|
||||
@ -1612,6 +1638,7 @@ public class UserAnswerTaskService(
|
||||
await answerRepository.Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == newPointsBalance)
|
||||
.SetColumns(u => u.GrowthPoints == newGrowthPointsBalance)
|
||||
.SetColumns(u => u.UpdatedBy == userId.ToString())
|
||||
.SetColumns(u => u.UpdatedAt == DateTime.Now)
|
||||
.Where(u => u.Id == userId)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
@ -203,7 +203,7 @@ public class UserAnswerTaskController : WeChatBaseController
|
||||
{
|
||||
try
|
||||
{
|
||||
var userId = ConstUserId;//GetCurrentUserId();
|
||||
var userId = GetCurrentUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return BaseResponse<ClaimTaskPointsOutput>.Fail(ResultCode.DENY, "未获取到用户信息");
|
||||
@ -239,7 +239,7 @@ public class UserAnswerTaskController : WeChatBaseController
|
||||
{
|
||||
try
|
||||
{
|
||||
var userId = GetCurrentUserId();
|
||||
var userId = ConstUserId;//GetCurrentUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return BaseResponse<BatchClaimPointsOutput>.Fail(ResultCode.DENY, "未获取到用户信息");
|
||||
|
||||
Reference in New Issue
Block a user