DailyOverviewService.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package com.etotem.cfc.service;
  2. import com.etotem.cfc.dto.DailyOverviewVO;
  3. import com.etotem.cfc.dto.DanReportUploadVO;
  4. import com.etotem.cfc.entity.ArticleReadingRecord;
  5. import com.etotem.cfc.entity.AssessmentRecord;
  6. import com.etotem.cfc.entity.Task;
  7. import com.etotem.cfc.mapper.ArticleReadingRecordMapper;
  8. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  9. import org.springframework.stereotype.Service;
  10. import javax.annotation.Resource;
  11. import java.text.SimpleDateFormat;
  12. import java.util.*;
  13. /**
  14. * 今日任务聚合服务(只读,零新业务规则,全部复用现有查询)
  15. */
  16. @Service
  17. public class DailyOverviewService {
  18. @Resource
  19. private HealthCheckinService healthCheckinService;
  20. @Resource
  21. private FinanceCheckinService financeCheckinService;
  22. @Resource
  23. private EmotionCheckinService emotionCheckinService;
  24. @Resource
  25. private GrowthTaskService growthTaskService;
  26. @Resource
  27. private TaskService taskService;
  28. @Resource
  29. private ArticleReadingRecordMapper articleReadingRecordMapper;
  30. @Resource
  31. private AssessmentService assessmentService;
  32. @Resource
  33. private DanReportUploadService danReportUploadService;
  34. private static final String TODAY_FMT = "yyyy-MM-dd";
  35. public DailyOverviewVO aggregate(Long userId, Long memberId, Long familyId) {
  36. String today = new SimpleDateFormat(TODAY_FMT).format(new Date());
  37. DailyOverviewVO vo = new DailyOverviewVO();
  38. vo.setMemberId(memberId);
  39. vo.setDate(today);
  40. vo.setCheckins(buildCheckins(userId, memberId, today));
  41. vo.setTasks(buildTasks(userId, memberId, familyId));
  42. vo.setActivities(buildActivities(memberId));
  43. vo.setAssessments(buildAssessments(memberId, familyId));
  44. vo.setHasMore(false);
  45. return vo;
  46. }
  47. // ---------- 打卡类(最多 3 项:健康/财商/情绪) ----------
  48. private List<DailyOverviewVO.CheckinItem> buildCheckins(Long userId, Long memberId, String today) {
  49. List<DailyOverviewVO.CheckinItem> list = new ArrayList<>();
  50. list.add(buildCheckin("health", "健康打卡", "/pages/health/daily-checkin",
  51. hasTodayRecord(healthCheckinService.getCheckins(userId, memberId, null), today,
  52. o -> ((com.etotem.cfc.entity.HealthCheckin) o).getCheckinDate())));
  53. list.add(buildCheckin("wealth", "财商打卡", "/pages/wealth-sub/checkin",
  54. hasTodayRecord(financeCheckinService.getCheckins(userId, memberId, null), today,
  55. o -> ((com.etotem.cfc.entity.FinanceCheckin) o).getCheckinDate())));
  56. list.add(buildCheckin("mind", "情绪打卡", "/pages/mind-detail/emotion-checkin",
  57. hasTodayRecord(emotionCheckinService.getCheckinList(memberId, 1, 1, userId, true), today,
  58. o -> ((com.etotem.cfc.dto.EmotionCheckinVO) o).getCheckinDate())));
  59. return list;
  60. }
  61. private DailyOverviewVO.CheckinItem buildCheckin(String key, String label, String route, boolean done) {
  62. DailyOverviewVO.CheckinItem item = new DailyOverviewVO.CheckinItem();
  63. item.setKey(key);
  64. item.setLabel(label);
  65. item.setRoute(route);
  66. item.setDone(done);
  67. return item;
  68. }
  69. /** 今日过滤:dateGetter 返回 java.util.Date 或 String,统一格式化为 yyyy-MM-dd 后与 today 比较 */
  70. private boolean hasTodayRecord(List<?> records, String today, java.util.function.Function<Object, Object> dateGetter) {
  71. if (records == null || records.isEmpty()) return false;
  72. SimpleDateFormat fmt = new SimpleDateFormat(TODAY_FMT);
  73. for (Object rec : records) {
  74. Object d = dateGetter.apply(rec);
  75. if (d == null) continue;
  76. String ds;
  77. if (d instanceof java.util.Date) {
  78. ds = fmt.format((java.util.Date) d);
  79. } else {
  80. ds = String.valueOf(d);
  81. }
  82. if (ds != null && ds.startsWith(today)) return true;
  83. }
  84. return false;
  85. }
  86. // ---------- 任务类 ----------
  87. private DailyOverviewVO.TaskSummary buildTasks(Long userId, Long memberId, Long familyId) {
  88. DailyOverviewVO.TaskSummary s = new DailyOverviewVO.TaskSummary();
  89. s.setPendingAccept(0);
  90. List<Task> pending = taskService.getMyPendingTasks(memberId);
  91. s.setPendingAccept(pending == null ? 0 : pending.size());
  92. // 有 familyId 时按家庭聚合(方案任务可能挂在任意成员);否则按当前成员
  93. int todo = 0;
  94. int done = 0;
  95. List<Task> todayTasks = familyId != null
  96. ? taskService.getTodayTasksByFamily(familyId)
  97. : taskService.getTodayTasks(memberId);
  98. if (todayTasks != null) {
  99. for (Task t : todayTasks) {
  100. if ("completed".equals(t.getStatus())) {
  101. done++;
  102. } else if ("pending".equals(t.getStatus()) || "pending_review".equals(t.getStatus())
  103. || "in_progress".equals(t.getStatus()) || "locked".equals(t.getStatus())) {
  104. todo++;
  105. }
  106. }
  107. }
  108. Map<String, String> params = new HashMap<>();
  109. params.put("type", "DAILY");
  110. List<Map<String, Object>> dailyList = growthTaskService.getTaskList(userId, params);
  111. if (dailyList != null) {
  112. for (Map<String, Object> t : dailyList) {
  113. Object c = t.get("completed");
  114. boolean isDone = c != null && ("1".equals(String.valueOf(c)) || Boolean.TRUE.equals(c));
  115. if (isDone) done++; else todo++;
  116. }
  117. }
  118. s.setTodoToday(todo);
  119. s.setDoneToday(done);
  120. s.setRoute("/pages/tasks/tasks");
  121. return s;
  122. }
  123. // ---------- 阅读活动类 ----------
  124. private DailyOverviewVO.ActivitySummary buildActivities(Long memberId) {
  125. DailyOverviewVO.ActivitySummary s = new DailyOverviewVO.ActivitySummary();
  126. Long count = articleReadingRecordMapper.selectCount(
  127. new LambdaQueryWrapper<ArticleReadingRecord>()
  128. .eq(ArticleReadingRecord::getChildId, memberId)
  129. .apply("DATE(read_at) = CURDATE()"));
  130. s.setArticleReadToday(count == null ? 0 : count.intValue());
  131. s.setActivityAvailable(0); // v1 无现成可参与活动数查询,预留
  132. s.setArticleRoute("/pages/article-center/index");
  133. s.setActivityRoute("/pages/activity/index");
  134. return s;
  135. }
  136. // ---------- 测评报告类 ----------
  137. private DailyOverviewVO.AssessmentSummary buildAssessments(Long memberId, Long familyId) {
  138. DailyOverviewVO.AssessmentSummary s = new DailyOverviewVO.AssessmentSummary();
  139. int ongoing = 0;
  140. if (familyId != null) {
  141. List<AssessmentRecord> records = assessmentService.getFamilyRecords(familyId);
  142. if (records != null) {
  143. for (AssessmentRecord r : records) {
  144. if ("pending".equals(r.getStatus()) && memberId.equals(r.getChildId())) {
  145. ongoing++;
  146. }
  147. }
  148. }
  149. }
  150. s.setOngoing(ongoing);
  151. int reportPending = 0;
  152. try {
  153. com.etotem.cfc.common.Result<List<DanReportUploadVO>> uploadRes =
  154. danReportUploadService.listByMember(memberId, null);
  155. if (uploadRes != null && uploadRes.getCode() == 200 && uploadRes.getData() != null) {
  156. for (DanReportUploadVO vo : uploadRes.getData()) {
  157. if ("pending".equals(vo.getDraftStatus())) reportPending++;
  158. }
  159. }
  160. } catch (Exception e) {
  161. reportPending = 0; // DAN 报告子模块异常不阻断聚合
  162. }
  163. s.setReportPending(reportPending);
  164. s.setRoute("/pages/assessment/results");
  165. return s;
  166. }
  167. }