Browse Source

chore: auto bump version and changelog [skip ci]

iwt 3 months ago
parent
commit
11cd6bf725

+ 60 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -5582,6 +5582,66 @@ try {
     } catch (Exception e) {
     } catch (Exception e) {
         log.warn("创建health_interaction表失败: {}", e.getMessage());
         log.warn("创建health_interaction表失败: {}", e.getMessage());
     }
     }
+
+    // 迁移110: 创建 health_circle 表(P3 健康圈)
+    try {
+        jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_circle (" +
+            "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+            "name VARCHAR(100) NOT NULL COMMENT '圈名称', " +
+            "description VARCHAR(500) COMMENT '圈描述', " +
+            "creator_family_id BIGINT COMMENT '创建家庭ID', " +
+            "invite_code VARCHAR(32) COMMENT '邀请码', " +
+            "member_limit INT DEFAULT 50 COMMENT '成员上限', " +
+            "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/closed', " +
+            "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
+            "INDEX idx_invite_code (invite_code), " +
+            "INDEX idx_creator (creator_family_id)" +
+        ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈'");
+        log.info("已创建health_circle表");
+    } catch (Exception e) {
+        log.warn("创建health_circle表失败: {}", e.getMessage());
+    }
+
+    // 迁移111: 创建 health_circle_member 表(P3 健康圈成员)
+    try {
+        jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_circle_member (" +
+            "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+            "circle_id BIGINT NOT NULL COMMENT '圈ID', " +
+            "family_id BIGINT NOT NULL COMMENT '家庭ID', " +
+            "role VARCHAR(20) DEFAULT 'member' COMMENT '角色 member/admin', " +
+            "joined_at DATETIME COMMENT '加入时间', " +
+            "left_at DATETIME COMMENT '退出时间', " +
+            "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/inactive', " +
+            "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
+            "INDEX idx_circle_id (circle_id), " +
+            "INDEX idx_family_id (family_id)" +
+        ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈成员'");
+        log.info("已创建health_circle_member表");
+    } catch (Exception e) {
+        log.warn("创建health_circle_member表失败: {}", e.getMessage());
+    }
+
+    // 迁移112: 创建 circle_challenge 表(P3 圈挑战)
+    try {
+        jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS circle_challenge (" +
+            "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+            "circle_id BIGINT NOT NULL COMMENT '圈ID', " +
+            "challenge_type VARCHAR(50) NOT NULL COMMENT '挑战类型 checkin/step/meditation', " +
+            "title VARCHAR(200) NOT NULL COMMENT '挑战标题', " +
+            "description VARCHAR(500) COMMENT '挑战描述', " +
+            "duration_days INT DEFAULT 7 COMMENT '持续天数', " +
+            "period VARCHAR(20) DEFAULT 'weekly' COMMENT '周期 weekly/monthly', " +
+            "start_date DATETIME COMMENT '开始日期', " +
+            "end_date DATETIME COMMENT '结束日期', " +
+            "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/completed/cancelled', " +
+            "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
+            "INDEX idx_circle_id (circle_id), " +
+            "INDEX idx_status (status)" +
+        ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='圈挑战'");
+        log.info("已创建circle_challenge表");
+    } catch (Exception e) {
+        log.warn("创建circle_challenge表失败: {}", e.getMessage());
+    }
     }
     }
 
 
     private void runMigration82() {
     private void runMigration82() {

+ 46 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ShareService.java

@@ -2,9 +2,11 @@ package com.etotem.cfc.service;
 
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.entity.FamilyMember;
+import com.etotem.cfc.entity.HealthCheckin;
 import com.etotem.cfc.entity.ShareEvent;
 import com.etotem.cfc.entity.ShareEvent;
 import com.etotem.cfc.entity.ShareRead;
 import com.etotem.cfc.entity.ShareRead;
 import com.etotem.cfc.mapper.FamilyMemberMapper;
 import com.etotem.cfc.mapper.FamilyMemberMapper;
+import com.etotem.cfc.mapper.HealthCheckinMapper;
 import com.etotem.cfc.mapper.ShareEventMapper;
 import com.etotem.cfc.mapper.ShareEventMapper;
 import com.etotem.cfc.mapper.ShareReadMapper;
 import com.etotem.cfc.mapper.ShareReadMapper;
 import com.etotem.cfc.service.SysConfigService;
 import com.etotem.cfc.service.SysConfigService;
@@ -37,6 +39,9 @@ public class ShareService {
     @Resource
     @Resource
     private FamilyMemberMapper familyMemberMapper;
     private FamilyMemberMapper familyMemberMapper;
 
 
+    @Resource
+    private HealthCheckinMapper healthCheckinMapper;
+
     public ShareEvent createShareEvent(Long userId, String targetType, Long targetId,
     public ShareEvent createShareEvent(Long userId, String targetType, Long targetId,
             String shareChannel, String title) {
             String shareChannel, String title) {
         ShareEvent event = new ShareEvent();
         ShareEvent event = new ShareEvent();
@@ -126,4 +131,45 @@ public class ShareService {
         stats.put("totalRewardPoints", totalRewards);
         stats.put("totalRewardPoints", totalRewards);
         return stats;
         return stats;
     }
     }
+
+    public Map<String, Object> getFamilyFootprint(Long familyId) {
+        Map<String, Object> result = new HashMap<>();
+        List<Map<String, Object>> members = new java.util.ArrayList<>();
+        int totalScore = 0;
+        int totalCheckinDays = 0;
+
+        if (familyId != null) {
+            List<FamilyMember> familyMembers = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>().eq(FamilyMember::getFamilyId, familyId)
+            );
+            for (FamilyMember fm : familyMembers) {
+                Map<String, Object> memberData = new HashMap<>();
+                memberData.put("name", fm.getNickname());
+                memberData.put("avatar", fm.getAvatar());
+
+                List<HealthCheckin> checkins = healthCheckinMapper.selectList(
+                    new LambdaQueryWrapper<HealthCheckin>()
+                        .eq(HealthCheckin::getUserId, fm.getUserId())
+                        .orderByDesc(HealthCheckin::getCheckinDate)
+                );
+                int streakDays = 0;
+                int score = 0;
+                if (checkins != null && !checkins.isEmpty()) {
+                    streakDays = checkins.size();
+                    score = checkins.stream()
+                        .filter(c -> c.getEarnedEnergy() != null)
+                        .mapToInt(HealthCheckin::getEarnedEnergy).sum();
+                }
+                memberData.put("streakDays", streakDays);
+                memberData.put("score", score);
+                members.add(memberData);
+                totalScore += score;
+                totalCheckinDays = Math.max(totalCheckinDays, streakDays);
+            }
+        }
+        result.put("members", members);
+        result.put("totalScore", totalScore);
+        result.put("totalCheckinDays", totalCheckinDays);
+        return result;
+    }
 }
 }

+ 45 - 0
cfc-backend/src/main/resources/schema.sql

@@ -3048,3 +3048,48 @@ CREATE TABLE IF NOT EXISTS health_interaction (
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     INDEX idx_family_action (family_id, action_type, action_id)
     INDEX idx_family_action (family_id, action_type, action_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康互动记录(点赞)';
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康互动记录(点赞)';
+
+-- 健康圈表(P3 健康社区扩散)
+CREATE TABLE IF NOT EXISTS health_circle (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    name VARCHAR(100) NOT NULL COMMENT '圈名称',
+    description VARCHAR(500) COMMENT '圈描述',
+    creator_family_id BIGINT COMMENT '创建家庭ID',
+    invite_code VARCHAR(32) COMMENT '邀请码',
+    member_limit INT DEFAULT 50 COMMENT '成员上限',
+    status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/closed',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    INDEX idx_invite_code (invite_code),
+    INDEX idx_creator (creator_family_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈';
+
+-- 健康圈成员表(P3)
+CREATE TABLE IF NOT EXISTS health_circle_member (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    circle_id BIGINT NOT NULL COMMENT '圈ID',
+    family_id BIGINT NOT NULL COMMENT '家庭ID',
+    role VARCHAR(20) DEFAULT 'member' COMMENT '角色 member/admin',
+    joined_at DATETIME COMMENT '加入时间',
+    left_at DATETIME COMMENT '退出时间',
+    status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/inactive',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    INDEX idx_circle_id (circle_id),
+    INDEX idx_family_id (family_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈成员';
+
+-- 圈挑战表(P3)
+CREATE TABLE IF NOT EXISTS circle_challenge (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    circle_id BIGINT NOT NULL COMMENT '圈ID',
+    challenge_type VARCHAR(50) NOT NULL COMMENT '挑战类型 checkin/step/meditation',
+    title VARCHAR(200) NOT NULL COMMENT '挑战标题',
+    description VARCHAR(500) COMMENT '挑战描述',
+    duration_days INT DEFAULT 7 COMMENT '持续天数',
+    period VARCHAR(20) DEFAULT 'weekly' COMMENT '周期 weekly/monthly',
+    start_date DATETIME COMMENT '开始日期',
+    end_date DATETIME COMMENT '结束日期',
+    status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/completed/cancelled',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    INDEX idx_circle_id (circle_id),
+    INDEX idx_status (status)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='圈挑战';

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-d73cb0192bfde3fb2224e5410f798f671ee4abc5
+d3a9926a28466c333a3084b5a74b8a01d399ac36