|
@@ -0,0 +1,173 @@
|
|
|
|
|
+package com.etotem.cfc.service;
|
|
|
|
|
+
|
|
|
|
|
+import com.etotem.cfc.dto.DailyOverviewVO;
|
|
|
|
|
+import com.etotem.cfc.dto.DanReportUploadVO;
|
|
|
|
|
+import com.etotem.cfc.entity.ArticleReadingRecord;
|
|
|
|
|
+import com.etotem.cfc.entity.AssessmentRecord;
|
|
|
|
|
+import com.etotem.cfc.entity.Task;
|
|
|
|
|
+import com.etotem.cfc.mapper.ArticleReadingRecordMapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 今日任务聚合服务(只读,零新业务规则,全部复用现有查询)
|
|
|
|
|
+ */
|
|
|
|
|
+@Service
|
|
|
|
|
+public class DailyOverviewService {
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private HealthCheckinService healthCheckinService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private FinanceCheckinService financeCheckinService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private EmotionCheckinService emotionCheckinService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private GrowthTaskService growthTaskService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private TaskService taskService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private ArticleReadingRecordMapper articleReadingRecordMapper;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private AssessmentService assessmentService;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private DanReportUploadService danReportUploadService;
|
|
|
|
|
+
|
|
|
|
|
+ private static final String TODAY_FMT = "yyyy-MM-dd";
|
|
|
|
|
+
|
|
|
|
|
+ public DailyOverviewVO aggregate(Long userId, Long memberId, Long familyId) {
|
|
|
|
|
+ String today = new SimpleDateFormat(TODAY_FMT).format(new Date());
|
|
|
|
|
+ DailyOverviewVO vo = new DailyOverviewVO();
|
|
|
|
|
+ vo.setMemberId(memberId);
|
|
|
|
|
+ vo.setDate(today);
|
|
|
|
|
+ vo.setCheckins(buildCheckins(userId, memberId, today));
|
|
|
|
|
+ vo.setTasks(buildTasks(userId, memberId));
|
|
|
|
|
+ vo.setActivities(buildActivities(memberId));
|
|
|
|
|
+ vo.setAssessments(buildAssessments(memberId, familyId));
|
|
|
|
|
+ vo.setHasMore(false);
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ---------- 打卡类(最多 3 项:健康/财商/情绪) ----------
|
|
|
|
|
+
|
|
|
|
|
+ private List<DailyOverviewVO.CheckinItem> buildCheckins(Long userId, Long memberId, String today) {
|
|
|
|
|
+ List<DailyOverviewVO.CheckinItem> list = new ArrayList<>();
|
|
|
|
|
+ list.add(buildCheckin("health", "健康打卡", "/pages/health/daily-checkin",
|
|
|
|
|
+ hasTodayRecord(healthCheckinService.getCheckins(userId, memberId, null), today,
|
|
|
|
|
+ o -> ((com.etotem.cfc.entity.HealthCheckin) o).getCheckinDate())));
|
|
|
|
|
+ list.add(buildCheckin("wealth", "财商打卡", "/pages/wealth-sub/checkin",
|
|
|
|
|
+ hasTodayRecord(financeCheckinService.getCheckins(userId, memberId, null), today,
|
|
|
|
|
+ o -> ((com.etotem.cfc.entity.FinanceCheckin) o).getCheckinDate())));
|
|
|
|
|
+ list.add(buildCheckin("mind", "情绪打卡", "/pages/mind-detail/emotion-checkin",
|
|
|
|
|
+ hasTodayRecord(emotionCheckinService.getCheckinList(memberId, 1, 1, userId, true), today,
|
|
|
|
|
+ o -> ((com.etotem.cfc.dto.EmotionCheckinVO) o).getCheckinDate())));
|
|
|
|
|
+ return list;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private DailyOverviewVO.CheckinItem buildCheckin(String key, String label, String route, boolean done) {
|
|
|
|
|
+ DailyOverviewVO.CheckinItem item = new DailyOverviewVO.CheckinItem();
|
|
|
|
|
+ item.setKey(key);
|
|
|
|
|
+ item.setLabel(label);
|
|
|
|
|
+ item.setRoute(route);
|
|
|
|
|
+ item.setDone(done);
|
|
|
|
|
+ return item;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 今日过滤:dateGetter 返回 java.util.Date 或 String,统一格式化为 yyyy-MM-dd 后与 today 比较 */
|
|
|
|
|
+ private boolean hasTodayRecord(List<?> records, String today, java.util.function.Function<Object, Object> dateGetter) {
|
|
|
|
|
+ if (records == null || records.isEmpty()) return false;
|
|
|
|
|
+ SimpleDateFormat fmt = new SimpleDateFormat(TODAY_FMT);
|
|
|
|
|
+ for (Object rec : records) {
|
|
|
|
|
+ Object d = dateGetter.apply(rec);
|
|
|
|
|
+ if (d == null) continue;
|
|
|
|
|
+ String ds;
|
|
|
|
|
+ if (d instanceof java.util.Date) {
|
|
|
|
|
+ ds = fmt.format((java.util.Date) d);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ds = String.valueOf(d);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ds != null && ds.startsWith(today)) return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ---------- 任务类 ----------
|
|
|
|
|
+
|
|
|
|
|
+ private DailyOverviewVO.TaskSummary buildTasks(Long userId, Long memberId) {
|
|
|
|
|
+ DailyOverviewVO.TaskSummary s = new DailyOverviewVO.TaskSummary();
|
|
|
|
|
+ s.setPendingAccept(0);
|
|
|
|
|
+
|
|
|
|
|
+ List<Task> pending = taskService.getMyPendingTasks(memberId);
|
|
|
|
|
+ s.setPendingAccept(pending == null ? 0 : pending.size());
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, String> params = new HashMap<>();
|
|
|
|
|
+ params.put("type", "DAILY");
|
|
|
|
|
+ List<Map<String, Object>> dailyList = growthTaskService.getTaskList(userId, params);
|
|
|
|
|
+ int todo = 0;
|
|
|
|
|
+ int done = 0;
|
|
|
|
|
+ if (dailyList != null) {
|
|
|
|
|
+ for (Map<String, Object> t : dailyList) {
|
|
|
|
|
+ Object c = t.get("completed");
|
|
|
|
|
+ boolean isDone = c != null && ("1".equals(String.valueOf(c)) || Boolean.TRUE.equals(c));
|
|
|
|
|
+ if (isDone) done++; else todo++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s.setTodoToday(todo);
|
|
|
|
|
+ s.setDoneToday(done);
|
|
|
|
|
+ s.setRoute("/pages/tasks/tasks");
|
|
|
|
|
+ return s;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ---------- 阅读活动类 ----------
|
|
|
|
|
+
|
|
|
|
|
+ private DailyOverviewVO.ActivitySummary buildActivities(Long memberId) {
|
|
|
|
|
+ DailyOverviewVO.ActivitySummary s = new DailyOverviewVO.ActivitySummary();
|
|
|
|
|
+ Long count = articleReadingRecordMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<ArticleReadingRecord>()
|
|
|
|
|
+ .eq(ArticleReadingRecord::getChildId, memberId)
|
|
|
|
|
+ .apply("DATE(read_at) = CURDATE()"));
|
|
|
|
|
+ s.setArticleReadToday(count == null ? 0 : count.intValue());
|
|
|
|
|
+ s.setActivityAvailable(0); // v1 无现成可参与活动数查询,预留
|
|
|
|
|
+ s.setArticleRoute("/pages/article-center/index");
|
|
|
|
|
+ s.setActivityRoute("/pages/activity/index");
|
|
|
|
|
+ return s;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ---------- 测评报告类 ----------
|
|
|
|
|
+
|
|
|
|
|
+ private DailyOverviewVO.AssessmentSummary buildAssessments(Long memberId, Long familyId) {
|
|
|
|
|
+ DailyOverviewVO.AssessmentSummary s = new DailyOverviewVO.AssessmentSummary();
|
|
|
|
|
+
|
|
|
|
|
+ int ongoing = 0;
|
|
|
|
|
+ if (familyId != null) {
|
|
|
|
|
+ List<AssessmentRecord> records = assessmentService.getFamilyRecords(familyId);
|
|
|
|
|
+ if (records != null) {
|
|
|
|
|
+ for (AssessmentRecord r : records) {
|
|
|
|
|
+ if ("pending".equals(r.getStatus()) && memberId.equals(r.getChildId())) {
|
|
|
|
|
+ ongoing++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s.setOngoing(ongoing);
|
|
|
|
|
+
|
|
|
|
|
+ int reportPending = 0;
|
|
|
|
|
+ try {
|
|
|
|
|
+ com.etotem.cfc.common.Result<List<DanReportUploadVO>> uploadRes =
|
|
|
|
|
+ danReportUploadService.listByMember(memberId, null);
|
|
|
|
|
+ if (uploadRes != null && uploadRes.getCode() == 200 && uploadRes.getData() != null) {
|
|
|
|
|
+ for (DanReportUploadVO vo : uploadRes.getData()) {
|
|
|
|
|
+ if ("pending".equals(vo.getDraftStatus())) reportPending++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ reportPending = 0; // DAN 报告子模块异常不阻断聚合
|
|
|
|
|
+ }
|
|
|
|
|
+ s.setReportPending(reportPending);
|
|
|
|
|
+ s.setRoute("/pages/assessment/results");
|
|
|
|
|
+ return s;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|