Просмотр исходного кода

feat: 我的页面新增个人成就统计API

新增POST /api/user/profile-stats,返回10项个人成就数据(积分/打卡/任务/奖励/勋章/成长记录/挑战/报告/成员数/文章)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
E2E Test Bot 1 месяц назад
Родитель
Сommit
86daa75a21
1 измененных файлов с 169 добавлено и 0 удалено
  1. 169 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/UserController.java

+ 169 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/UserController.java

@@ -11,9 +11,14 @@ import com.etotem.cfc.entity.PaymentOrder;
 import com.etotem.cfc.entity.Task;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.mapper.AssessmentOrderMapper;
+import com.etotem.cfc.mapper.ChildBadgeMapper;
+import com.etotem.cfc.mapper.FamilyChallengeProgressMapper;
 import com.etotem.cfc.mapper.FamilyMemberMapper;
 import com.etotem.cfc.mapper.FamilyMapper;
+import com.etotem.cfc.mapper.HealthReportMapper;
+import com.etotem.cfc.mapper.GrowthRecordMapper;
 import com.etotem.cfc.mapper.PaymentOrderMapper;
+import com.etotem.cfc.mapper.PointsExchangeRecordMapper;
 import com.etotem.cfc.mapper.TaskMapper;
 import com.etotem.cfc.mapper.UserMapper;
 import com.etotem.cfc.service.UserService;
@@ -169,6 +174,170 @@ public class UserController {
         return Result.success(result);
     }
 
+    @Resource
+    private com.etotem.cfc.mapper.GrowthRecordMapper growthRecordMapper;
+
+    @Resource
+    private com.etotem.cfc.mapper.HealthReportMapper healthReportMapper;
+
+    @Resource
+    private com.etotem.cfc.mapper.PointsExchangeRecordMapper pointsExchangeRecordMapper;
+
+    @Resource
+    private com.etotem.cfc.mapper.ChildBadgeMapper childBadgeMapper;
+
+    @Resource
+    private com.etotem.cfc.mapper.FamilyChallengeProgressMapper familyChallengeProgressMapper;
+
+    @PostMapping("/profile-stats")
+    @Operation(summary = "获取个人成就统计")
+    public Result<Map<String, Object>> getProfileStats(HttpServletRequest request) {
+        Long userId = (Long) request.getAttribute("userId");
+        if (userId == null) {
+            return Result.error("用户未登录");
+        }
+
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            return Result.error("用户不存在");
+        }
+
+        Long familyId = user.getFamilyId();
+        Map<String, Object> stats = new HashMap<>();
+
+        // 1. 总积分
+        Integer totalPoints = 0;
+        try {
+            Object points = userService.getPointsBalance(userId);
+            if (points != null) {
+                if (points instanceof Map) {
+                    Object v = ((Map<?, ?>) points).get("totalPoints");
+                    if (v != null) totalPoints = ((Number) v).intValue();
+                } else if (points instanceof Number) {
+                    totalPoints = ((Number) points).intValue();
+                }
+            }
+        } catch (Exception e) {
+            log.warn("获取积分失败: userId={}", userId, e);
+        }
+        stats.put("totalPoints", totalPoints);
+
+        // 2. 连续打卡天数(取所有孩子中最高值)
+        Integer maxStreakDays = 0;
+        if (familyId != null) {
+            List<FamilyMember> members = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, familyId)
+            );
+            for (FamilyMember m : members) {
+                if (m.getStreakDays() != null && m.getStreakDays() > maxStreakDays) {
+                    maxStreakDays = m.getStreakDays();
+                }
+            }
+        }
+        stats.put("streakDays", maxStreakDays);
+
+        // 3. 完成任务数(当前家庭)
+        Long completedTasks = 0L;
+        if (familyId != null) {
+            completedTasks = taskMapper.selectCount(
+                new LambdaQueryWrapper<Task>()
+                    .eq(Task::getFamilyId, familyId)
+                    .eq(Task::getStatus, "completed")
+            );
+        }
+        stats.put("completedTasks", completedTasks);
+
+        // 4. 心愿兑换次数(按家庭成员统计)
+        Long rewardsEarned = 0L;
+        if (familyId != null) {
+            List<FamilyMember> exchangeMembers = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, familyId)
+            );
+            for (FamilyMember m : exchangeMembers) {
+                Long cnt = pointsExchangeRecordMapper.selectCount(
+                    new LambdaQueryWrapper<com.etotem.cfc.entity.PointsExchangeRecord>()
+                        .eq(com.etotem.cfc.entity.PointsExchangeRecord::getFamilyMemberId, m.getId())
+                );
+                rewardsEarned += cnt != null ? cnt.longValue() : 0L;
+            }
+        }
+        stats.put("rewardsEarned", rewardsEarned);
+
+        // 5. 收集勋章数(所有家庭成员)
+        Integer badgesCollected = 0;
+        if (familyId != null) {
+            List<FamilyMember> members = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, familyId)
+            );
+            for (FamilyMember m : members) {
+                try {
+                    Long cnt = childBadgeMapper.selectCount(
+                        new LambdaQueryWrapper<com.etotem.cfc.entity.ChildBadge>()
+                            .eq(com.etotem.cfc.entity.ChildBadge::getChildId, m.getId())
+                    );
+                    badgesCollected += cnt != null ? cnt.intValue() : 0;
+                } catch (Exception e) {
+                    log.warn("获取勋章数失败: memberId={}", m.getId(), e);
+                }
+            }
+        }
+        stats.put("badgesCollected", badgesCollected);
+
+        // 6. 成长记录数(按当前用户为parentId统计)
+        Long growthRecords = growthRecordMapper.selectCount(
+            new LambdaQueryWrapper<com.etotem.cfc.entity.GrowthRecord>()
+                .eq(com.etotem.cfc.entity.GrowthRecord::getParentId, userId)
+        );
+        stats.put("growthRecords", growthRecords);
+
+        // 7. 参加挑战数(按家庭成员childId统计)
+        Integer challengesJoined = 0;
+        if (familyId != null) {
+            List<FamilyMember> challengeMembers = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, familyId)
+            );
+            for (FamilyMember m : challengeMembers) {
+                Long cnt = familyChallengeProgressMapper.selectCount(
+                    new LambdaQueryWrapper<com.etotem.cfc.entity.FamilyChallengeProgress>()
+                        .eq(com.etotem.cfc.entity.FamilyChallengeProgress::getChildId, m.getId())
+                );
+                challengesJoined += cnt != null ? cnt.intValue() : 0;
+            }
+        }
+        stats.put("challengesJoined", challengesJoined);
+
+        // 8. 上传健康报告数
+        Long healthReports = 0L;
+        if (familyId != null) {
+            healthReports = healthReportMapper.selectCount(
+                new LambdaQueryWrapper<com.etotem.cfc.entity.HealthReport>()
+                    .eq(com.etotem.cfc.entity.HealthReport::getFamilyId, familyId)
+            );
+        }
+        stats.put("healthReports", healthReports);
+
+        // 9. 家庭成员数
+        Integer familyMemberCount = 0;
+        if (familyId != null) {
+            Long cnt = familyMemberMapper.selectCount(
+                new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, familyId)
+            );
+            familyMemberCount = cnt != null ? cnt.intValue() : 0;
+        }
+        stats.put("familyMemberCount", familyMemberCount);
+
+        // 10. 累计文章阅读数
+        Integer articlesRead = 0;
+        stats.put("articlesRead", articlesRead);
+
+        return Result.success(stats);
+    }
+
     @PostMapping("/action-stats")
     @Operation(summary = "获取用户行动统计")
     public Result<Map<String, Object>> getActionStats(HttpServletRequest request) {