|
|
@@ -60,9 +60,6 @@ public class TaskService implements TaskServiceInterface {
|
|
|
@Resource
|
|
|
private FamilyRelationshipScoreMapper familyRelationshipScoreMapper;
|
|
|
|
|
|
- @Resource
|
|
|
- private GrowthTaskService growthTaskService;
|
|
|
-
|
|
|
@Resource
|
|
|
private CartService cartService;
|
|
|
|
|
|
@@ -902,7 +899,7 @@ public List<Task> getTodayTasks(Long memberId, String dimensionCode) {
|
|
|
|
|
|
try {
|
|
|
if (child.getUserId() != null) {
|
|
|
- growthTaskService.updateProgress(child.getUserId(), "DAILY_TASK", 1);
|
|
|
+ this.updateProgress(child.getUserId(), "DAILY_TASK", 1);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
log.warn("成长任务进度更新失败: memberId={}, error={}", memberId, e.getMessage());
|
|
|
@@ -1527,4 +1524,189 @@ return 0; // 达到每日扣分上限
|
|
|
log.warn("调研任务自动生成模板失败(不影响任务创建): taskId={}, error={}", task.getId(), e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // ==================== 统一任务系统:成长任务迁移(原 GrowthTaskService) ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一任务系统:更新每日进度型任务的进度(原 growth_task updateProgress)
|
|
|
+ * 按 (userId→familyMemberId, taskKey) 找当日任务实例,累计进度,达标自动完成+发奖
|
|
|
+ * taskKey 匹配约定:title 精确匹配 OR title 以 "[taskKey]" 前缀匹配(迁移时 task_key 拼入 title)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateProgress(Long userId, String taskKey, int increment) {
|
|
|
+ if (userId == null) {
|
|
|
+ // 未绑定登录账号的家庭成员(如仅建档的孩子)无成长任务进度
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ FamilyMember member = familyMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyMember>()
|
|
|
+ .eq(FamilyMember::getUserId, userId)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (member == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
+ cal.set(Calendar.MINUTE, 0);
|
|
|
+ cal.set(Calendar.SECOND, 0);
|
|
|
+ cal.set(Calendar.MILLISECOND, 0);
|
|
|
+ Date startOfDay = cal.getTime();
|
|
|
+ cal.add(Calendar.DAY_OF_MONTH, 1);
|
|
|
+ Date endOfDay = cal.getTime();
|
|
|
+
|
|
|
+ Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
|
|
|
+ .eq(Task::getFamilyMemberId, member.getId())
|
|
|
+ .eq(Task::getIsDailyProgress, 1)
|
|
|
+ .ge(Task::getCreatedAt, startOfDay)
|
|
|
+ .lt(Task::getCreatedAt, endOfDay)
|
|
|
+ .and(w -> w.eq(Task::getTitle, taskKey)
|
|
|
+ .or().likeRight(Task::getTitle, "[" + taskKey + "]"))
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("统一任务进度更新:未找到今日进度型任务 taskKey={}, userId={}", taskKey, userId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if ("completed".equals(task.getStatus())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读当前进度(task_executions.extra.progress),累加
|
|
|
+ TaskExecution exec = taskExecutionMapper.selectOne(new LambdaQueryWrapper<TaskExecution>()
|
|
|
+ .eq(TaskExecution::getTaskId, task.getId())
|
|
|
+ .eq(TaskExecution::getMemberId, member.getId())
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ int progress = 0;
|
|
|
+ if (exec != null && exec.getExtra() != null) {
|
|
|
+ try {
|
|
|
+ progress = JSON.parseObject(exec.getExtra()).getIntValue("progress");
|
|
|
+ } catch (Exception ignore) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ progress += increment;
|
|
|
+ int target = task.getTargetValue() != null ? task.getTargetValue() : 1;
|
|
|
+
|
|
|
+ if (exec == null) {
|
|
|
+ exec = new TaskExecution();
|
|
|
+ exec.setTaskId(task.getId());
|
|
|
+ exec.setMemberId(member.getId());
|
|
|
+ exec.setStatus("started");
|
|
|
+ exec.setStartedAt(new Date());
|
|
|
+ exec.setCreatedAt(new Date());
|
|
|
+ }
|
|
|
+ exec.setStatus("finished");
|
|
|
+ exec.setFinishedAt(new Date());
|
|
|
+ exec.setExtra("{\"progress\":" + progress + ",\"target\":" + target + "}");
|
|
|
+ if (exec.getId() == null) {
|
|
|
+ taskExecutionMapper.insert(exec);
|
|
|
+ } else {
|
|
|
+ taskExecutionMapper.updateById(exec);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 达标自动完成 + 发奖(复用现有奖励链路)
|
|
|
+ if (progress >= target) {
|
|
|
+ awardTaskCompletionRewards(task, member.getId(), new Date());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一任务系统:AI 对话生成任务(原 growth_task createDynamicTask)
|
|
|
+ * 直接写入 tasks 表,source_type=ai
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Long createDynamicTask(Long userId, String title, String description,
|
|
|
+ String dimension, Integer rewardPoints, String sourceConversationId) {
|
|
|
+ User user = userService.getUserInfo(userId);
|
|
|
+ Task task = new Task();
|
|
|
+ task.setFamilyId(user.getFamilyId());
|
|
|
+ task.setCreatorId(userId);
|
|
|
+ task.setExecutorType("child");
|
|
|
+ // 执行者:AI 任务发给当前用户对应家庭成员(若有)
|
|
|
+ FamilyMember member = familyMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyMember>()
|
|
|
+ .eq(FamilyMember::getUserId, userId)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (member != null) {
|
|
|
+ task.setExecutorId(member.getId());
|
|
|
+ task.setFamilyMemberId(member.getId());
|
|
|
+ task.setChildId(member.getId());
|
|
|
+ }
|
|
|
+ task.setTitle(title);
|
|
|
+ task.setDescription(description);
|
|
|
+ task.setPoints(rewardPoints != null ? rewardPoints : 10);
|
|
|
+ task.setCategory("成长");
|
|
|
+ task.setStatus("pending");
|
|
|
+ task.setNeedReview(0);
|
|
|
+ task.setIsTemplate(0);
|
|
|
+ task.setSourceType("ai");
|
|
|
+ task.setSourceId(0L);
|
|
|
+ task.setDimensionCode(dimension != null ? dimension : "body");
|
|
|
+ task.setMemberOnly(0);
|
|
|
+ task.setDeadline(new Date(System.currentTimeMillis() + 7L * 24 * 3600 * 1000)); // 7天有效期
|
|
|
+ task.setCreatedAt(new Date());
|
|
|
+ task.setUpdatedAt(new Date());
|
|
|
+ taskMapper.insert(task);
|
|
|
+ log.info("创建AI动态任务: userId={}, taskId={}, title={}", userId, task.getId(), title);
|
|
|
+ return task.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一任务系统:查询用户每日进度型任务列表(原 growth-task/list)
|
|
|
+ * type: DAILY(NEWBIE 在 Task 5 处理)
|
|
|
+ */
|
|
|
+ public List<Map<String, Object>> getGrowthTaskList(Long userId, String type, String dimension) {
|
|
|
+ FamilyMember member = familyMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyMember>()
|
|
|
+ .eq(FamilyMember::getUserId, userId)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ List<Map<String, Object>> result = new ArrayList<>();
|
|
|
+ if (member == null || !"DAILY".equals(type)) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
+ cal.set(Calendar.MINUTE, 0);
|
|
|
+ cal.set(Calendar.SECOND, 0);
|
|
|
+ cal.set(Calendar.MILLISECOND, 0);
|
|
|
+ Date startOfDay = cal.getTime();
|
|
|
+ cal.add(Calendar.DAY_OF_MONTH, 1);
|
|
|
+ Date endOfDay = cal.getTime();
|
|
|
+
|
|
|
+ List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>()
|
|
|
+ .eq(Task::getFamilyMemberId, member.getId())
|
|
|
+ .eq(Task::getIsDailyProgress, 1)
|
|
|
+ .ge(Task::getCreatedAt, startOfDay)
|
|
|
+ .lt(Task::getCreatedAt, endOfDay)
|
|
|
+ .orderByAsc(Task::getId));
|
|
|
+ for (Task task : tasks) {
|
|
|
+ Map<String, Object> item = new LinkedHashMap<>();
|
|
|
+ item.put("taskLogId", task.getId());
|
|
|
+ item.put("id", task.getId());
|
|
|
+ item.put("type", "DAILY");
|
|
|
+ item.put("title", task.getTitle());
|
|
|
+ item.put("description", task.getDescription());
|
|
|
+ item.put("rewardPoints", task.getPoints());
|
|
|
+ item.put("rewardEnergy", 0);
|
|
|
+ item.put("targetValue", task.getTargetValue() != null ? task.getTargetValue() : 1);
|
|
|
+ item.put("dimension", task.getDimensionCode());
|
|
|
+
|
|
|
+ TaskExecution exec = taskExecutionMapper.selectOne(new LambdaQueryWrapper<TaskExecution>()
|
|
|
+ .eq(TaskExecution::getTaskId, task.getId())
|
|
|
+ .eq(TaskExecution::getMemberId, member.getId())
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ int progress = 0;
|
|
|
+ if (exec != null && exec.getExtra() != null) {
|
|
|
+ try {
|
|
|
+ progress = JSON.parseObject(exec.getExtra()).getIntValue("progress");
|
|
|
+ } catch (Exception ignore) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ item.put("progress", progress);
|
|
|
+ item.put("completed", "completed".equals(task.getStatus()) ? 1 : 0);
|
|
|
+ item.put("claimed", 0); // 统一任务系统:自动发放,无 claimed
|
|
|
+ result.add(item);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
}
|