|
|
@@ -0,0 +1,114 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.etotem.cfc.dto.*;
|
|
|
+import com.etotem.cfc.entity.*;
|
|
|
+import com.etotem.cfc.mapper.*;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 家庭信息查看服务:家庭概览(基本信息+计数+报告/方案明细)与任务分页。
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class FamilyAdminOverviewService {
|
|
|
+ @Resource private FamilyMapper familyMapper;
|
|
|
+ @Resource private HealthReportMapper reportMapper;
|
|
|
+ @Resource private HealthPlanMapper planMapper;
|
|
|
+ @Resource private TaskMapper taskMapper;
|
|
|
+ @Resource private UserMapper userMapper;
|
|
|
+
|
|
|
+ public FamilyOverviewDTO buildOverview(Long familyId) {
|
|
|
+ Family family = familyMapper.selectById(familyId);
|
|
|
+ if (family == null) throw new RuntimeException("家庭不存在");
|
|
|
+
|
|
|
+ FamilyOverviewDTO dto = new FamilyOverviewDTO();
|
|
|
+ Map<String,Object> f = new HashMap<>();
|
|
|
+ f.put("id", family.getId()); f.put("name", family.getName());
|
|
|
+ f.put("inviteCode", family.getInviteCode()); f.put("creatorId", family.getCreatorId());
|
|
|
+ f.put("createdAt", family.getCreatedAt());
|
|
|
+ f.put("province", family.getProvince()); f.put("city", family.getCity());
|
|
|
+ f.put("district", family.getDistrict()); f.put("street", family.getStreet());
|
|
|
+ dto.setFamily(f);
|
|
|
+
|
|
|
+ User creator = family.getCreatorId() != null ? userMapper.selectById(family.getCreatorId()) : null;
|
|
|
+ dto.setCreatorName(creator != null && creator.getNickname() != null ? creator.getNickname() : "");
|
|
|
+ dto.setCreatorRealName(creator != null && creator.getRealName() != null ? creator.getRealName() : "");
|
|
|
+
|
|
|
+ FamilyOverviewCounts counts = new FamilyOverviewCounts();
|
|
|
+ counts.setReports(reportMapper.selectCount(new LambdaQueryWrapper<HealthReport>().eq(HealthReport::getFamilyId, familyId)));
|
|
|
+ counts.setPlans(planMapper.selectCount(new LambdaQueryWrapper<HealthPlan>().eq(HealthPlan::getFamilyId, familyId)));
|
|
|
+ counts.setTasks(taskMapper.selectCount(new LambdaQueryWrapper<Task>().eq(Task::getFamilyId, familyId)));
|
|
|
+ counts.setReportTypeCounts(countBy(reportMapper, "report_type", "family_id", familyId));
|
|
|
+ counts.setTaskStatusCounts(countBy(taskMapper, "status", "family_id", familyId));
|
|
|
+ dto.setCounts(counts);
|
|
|
+
|
|
|
+ // 报告明细:全量、按报告日期倒序(同日期按 id 倒序)
|
|
|
+ List<HealthReport> reports = reportMapper.selectList(new LambdaQueryWrapper<HealthReport>()
|
|
|
+ .eq(HealthReport::getFamilyId, familyId)
|
|
|
+ .orderByDesc(HealthReport::getReportDate).orderByDesc(HealthReport::getId));
|
|
|
+ List<FamilyReportItemVO> reportVOs = new ArrayList<>();
|
|
|
+ for (HealthReport r : reports) {
|
|
|
+ FamilyReportItemVO vo = new FamilyReportItemVO();
|
|
|
+ vo.setId(r.getId()); vo.setReportType(r.getReportType()); vo.setReportNumber(r.getReportNumber());
|
|
|
+ vo.setReportDate(r.getReportDate()); vo.setPersonName(r.getPersonName()); vo.setSubjectId(r.getSubjectId());
|
|
|
+ vo.setStatus(r.getStatus()); vo.setOverallScore(r.getOverallScore());
|
|
|
+ vo.setGutHealthScore(r.getGutHealthScore()); vo.setCreatedAt(r.getCreatedAt());
|
|
|
+ reportVOs.add(vo);
|
|
|
+ }
|
|
|
+ dto.setReports(reportVOs);
|
|
|
+
|
|
|
+ // 方案明细:全量、按创建时间倒序(同时间按 id 倒序)
|
|
|
+ List<HealthPlan> plans = planMapper.selectList(new LambdaQueryWrapper<HealthPlan>()
|
|
|
+ .eq(HealthPlan::getFamilyId, familyId)
|
|
|
+ .orderByDesc(HealthPlan::getCreatedAt).orderByDesc(HealthPlan::getId));
|
|
|
+ List<FamilyPlanItemVO> planVOs = new ArrayList<>();
|
|
|
+ for (HealthPlan p : plans) {
|
|
|
+ FamilyPlanItemVO vo = new FamilyPlanItemVO();
|
|
|
+ vo.setId(p.getId()); vo.setPlanType(p.getPlanType()); vo.setMemberName(p.getMemberName());
|
|
|
+ vo.setGoal(p.getGoal()); vo.setStatus(p.getStatus()); vo.setTotalDays(p.getTotalDays());
|
|
|
+ vo.setTeacherId(p.getTeacherId()); vo.setCreatedAt(p.getCreatedAt());
|
|
|
+ planVOs.add(vo);
|
|
|
+ }
|
|
|
+ dto.setPlans(planVOs);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分组计数:selectMaps + groupBy(MyBatis-Plus 3.5.3.1 的 selectCount 不支持分组,
|
|
|
+ * 分组必须走 selectMaps;COUNT 返回 Long,映射为 Integer)。
|
|
|
+ */
|
|
|
+ private <T> Map<String,Integer> countBy(com.baomidou.mybatisplus.core.mapper.BaseMapper<T> mapper,
|
|
|
+ String groupCol, String familyCol, Long familyId) {
|
|
|
+ QueryWrapper<T> qw = new QueryWrapper<>();
|
|
|
+ qw.select(groupCol + " as k", "count(*) as v").eq(familyCol, familyId).groupBy(groupCol);
|
|
|
+ Map<String,Integer> out = new HashMap<>();
|
|
|
+ for (Map<String,Object> row : mapper.selectMaps(qw)) {
|
|
|
+ Object k = row.get("k"); Object v = row.get("v");
|
|
|
+ if (k != null && v != null) out.put(String.valueOf(k), ((Number) v).intValue());
|
|
|
+ }
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Page<TaskItemVO> pageTasks(Long familyId, long page, long size) {
|
|
|
+ long safeSize = Math.min(Math.max(size, 1), 100);
|
|
|
+ Page<Task> raw = taskMapper.selectPage(new Page<>(page, safeSize),
|
|
|
+ new LambdaQueryWrapper<Task>().eq(Task::getFamilyId, familyId)
|
|
|
+ .orderByDesc(Task::getCreatedAt).orderByDesc(Task::getId));
|
|
|
+ Page<TaskItemVO> out = new Page<>(raw.getCurrent(), raw.getSize(), raw.getTotal());
|
|
|
+ out.setRecords(new ArrayList<>());
|
|
|
+ for (Task t : raw.getRecords()) {
|
|
|
+ TaskItemVO vo = new TaskItemVO();
|
|
|
+ vo.setId(t.getId()); vo.setTitle(t.getTitle()); vo.setStatus(t.getStatus());
|
|
|
+ vo.setCategory(t.getCategory()); vo.setPoints(t.getPoints()); vo.setDeadline(t.getDeadline());
|
|
|
+ vo.setChildId(t.getChildId()); vo.setExecutorType(t.getExecutorType());
|
|
|
+ vo.setTaskType(t.getTaskType()); vo.setSourceType(t.getSourceType());
|
|
|
+ vo.setCreatedAt(t.getCreatedAt()); vo.setCompletedAt(t.getCompletedAt());
|
|
|
+ out.getRecords().add(vo);
|
|
|
+ }
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+}
|