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