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

feat(admin): family list add member/report/plan/task count columns

E2E Test Bot 1 неделя назад
Родитель
Сommit
afb3e1a80e

+ 46 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminController.java

@@ -1,7 +1,9 @@
 package com.etotem.cfc.controller.admin;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.etotem.cfc.common.AdminRoles;
 import com.etotem.cfc.common.Result;
@@ -33,6 +35,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.stream.Collectors;
 import com.etotem.cfc.util.SortUtil;
 import com.etotem.cfc.util.ParamUtils;
 
@@ -58,6 +61,12 @@ public class AdminController {
     @Resource
     private FamilyMapper familyMapper;
 
+    @Resource
+    private HealthReportMapper healthReportMapper;
+
+    @Resource
+    private HealthPlanMapper healthPlanMapper;
+
     @Resource
     private TaskTemplateMapper taskTemplateMapper;
 
@@ -809,9 +818,46 @@ public class AdminController {
         wrapper.orderByDesc(Family::getCreatedAt);
         SortUtil.applySort(wrapper);
         Page<Family> result = familyMapper.selectPage(pageParam, wrapper);
+        // 统计列回填:当前成员数 / 上传报告数 / 方案数 / 任务数(仅当前页批量聚合)
+        List<Family> records = result.getRecords();
+        if (records != null && !records.isEmpty()) {
+            List<Long> ids = records.stream().map(Family::getId).collect(Collectors.toList());
+            Map<Long, Long> memberCnt = countByFamilyIds(familyMemberMapper, ids, "status = 'active'");
+            Map<Long, Long> reportCnt = countByFamilyIds(healthReportMapper, ids, null);
+            Map<Long, Long> planCnt   = countByFamilyIds(healthPlanMapper, ids, null);
+            Map<Long, Long> taskCnt   = countByFamilyIds(taskMapper, ids, null);
+            for (Family f : records) {
+                f.setMemberCount(memberCnt.getOrDefault(f.getId(), 0L));
+                f.setReportCount(reportCnt.getOrDefault(f.getId(), 0L));
+                f.setPlanCount(planCnt.getOrDefault(f.getId(), 0L));
+                f.setTaskCount(taskCnt.getOrDefault(f.getId(), 0L));
+            }
+        }
         return Result.success(result);
     }
 
+    /**
+     * 按家庭ID集合批量统计 COUNT(selectMaps + groupBy,COUNT 返回 Long)。
+     * extraCond 为额外过滤条件 SQL 片段(如 "status = 'active'"),null/空 表示不过滤。
+     */
+    private <T> Map<Long, Long> countByFamilyIds(BaseMapper<T> mapper, List<Long> ids, String extraCond) {
+        QueryWrapper<T> qw = new QueryWrapper<>();
+        qw.select("family_id as k", "count(*) as v").in("family_id", ids);
+        if (extraCond != null && !extraCond.isEmpty()) {
+            qw.apply(extraCond);
+        }
+        qw.groupBy("family_id");
+        Map<Long, Long> 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(((Number) k).longValue(), ((Number) v).longValue());
+            }
+        }
+        return out;
+    }
+
     @PostMapping("/families/{id}")
     public Result<Family> getFamily(@PathVariable Long id,
                                     @RequestAttribute("role") String role) {

+ 13 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/Family.java

@@ -1,6 +1,7 @@
 package com.etotem.cfc.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -36,6 +37,18 @@ public class Family implements Serializable {
 
     private Date updatedAt;
 
+    @TableField(exist = false)
+    private Long memberCount;   // 当前成员数(family_members status=active)
+
+    @TableField(exist = false)
+    private Long reportCount;   // 上传报告数(health_reports)
+
+    @TableField(exist = false)
+    private Long planCount;     // 方案数(health_plans)
+
+    @TableField(exist = false)
+    private Long taskCount;     // 任务数(tasks)
+
     public Long getCreatorId() { return creatorId; }
     public void setCreatorId(Long creatorId) { this.creatorId = creatorId; }
 }

+ 12 - 0
cfc-web/src/views/Families.vue

@@ -53,6 +53,18 @@
             <span class="sort-header" @click.stop="onSortClick('createdAt', $event)">创建时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
           </template>
         </el-table-column>
+        <el-table-column prop="memberCount" label="当前成员数" width="110">
+          <template slot-scope="scope">{{ scope.row.memberCount || 0 }}</template>
+        </el-table-column>
+        <el-table-column prop="reportCount" label="上传报告数" width="110">
+          <template slot-scope="scope">{{ scope.row.reportCount || 0 }}</template>
+        </el-table-column>
+        <el-table-column prop="planCount" label="方案数" width="100">
+          <template slot-scope="scope">{{ scope.row.planCount || 0 }}</template>
+        </el-table-column>
+        <el-table-column prop="taskCount" label="任务数" width="100">
+          <template slot-scope="scope">{{ scope.row.taskCount || 0 }}</template>
+        </el-table-column>
         <el-table-column label="操作" width="250" fixed="right">
           <template slot-scope="{ row }">
             <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>