ソースを参照

feat(family-challenge): 支持集体总合与全员个人双目标模式

后端:
- DatabaseInitializer 新增幂等迁移:target_mode (VARCHAR(20) DEFAULT 'aggregate') 与 target_value (INT DEFAULT 0)
- schema.sql 同步 family_challenge 表结构
- FamilyChallenge 实体新增 targetMode/targetValue 字段与 @TableField(exist=false) 的 totalProgress/memberProgress
- FamilyChallengeService 扩展 templates 数组为 8 列(添加目标列),重构 checkAndSettle() 按目标模式分支判定:
  - aggregate:全体 progress 合计 ≥ target_value 即达标
  - all_members:家庭内每个成员 progress ≥ target_value(无记录=0 判失败)
- 抽离 normalizeTarget() 实现旧数据向后兼容;fillProgress() 为 /list /history 填充总进度与成员进度

前端:
- FamilyChallengeCard 重写:双模式目标展示(aggregate=总进度条 X/Y;all_members=成员进度列表+达标✓),打卡上报入口(updateChallengeProgress({challengeId, childId, delta}) → $emit('updated'))
- parent-index 卡片传 :childId="currentChildId" + 监听 @updated="loadFamilyInteraction"
- patch-node-compat.cjs:node v24 polyfill(util.isRegExp 等已被移除),构建时通过 NODE_OPTIONS="--require ./patch-node-compat.cjs" 注入

docs/运营: 小红书内容 D14/D15/D16、第三篇-月入2万的家庭、发布指南、README 同步更新
Sisyphus Agent 1 ヶ月 前
コミット
d6bb7d4874

+ 54 - 0
articles/D15-draft_v1.md

@@ -0,0 +1,54 @@
+# D15 老人带娃翻脸,是爱的语言不同
+
+> 心维度 #FF6B9D | 参考《家的算法》第7章 心·大爱相随
+> 系列:老人带娃三部曲·之一
+
+## 标题
+老人带娃翻脸,是爱的语言不同(14字)
+
+## 正文(695字)
+
+老人带娃起冲突,你以为是方法不对——不是,是爱的语言不同。
+
+你妈给孩子夹菜、添饭、追着喂,你烦了:妈,别惯着他,让他自己吃。你妈委屈了:我辛辛苦苦给你带孩子,你还嫌我。
+
+你觉得自己没错——科学育儿,培养独立性。她也觉得自己没错——怕孩子饿着,这是爱。
+
+你们都没错。但你们在用不同的语言说爱。
+
+我认识一个女孩叫小茜。每次回家,桌上永远有一盘她爱吃的鱼。父母觉得,给她吃好喝好就是最好的爱。但小茜想要的不是鱼,是有人问她一句:你最近在想什么?
+
+两种爱都没错,但语言不通。老人觉得"我付出了这么多你怎么还不满意",年轻人觉得"你们根本不理解我"。
+
+这不是谁对谁错的问题,是两个人的"爱的语言"不匹配。
+
+怎么解决?三步走。
+
+第一步,看见她的语言。老人给你带孩子,她用的方式是她从小被爱的方式——吃饱穿暖就是爱。不是她固执,她的词典里就这些词。
+
+第二步,翻译你的话。不要说"妈别追着喂了",试试:妈,我知道你怕他饿着。以后让他自己吃,吃不完我再喂。翻译过来就是:我看到你的爱了,咱换个方式一起爱他。
+
+第三步,找共同语言。不是谁听谁的,是找一条两个人都能走的路。比如:白天你按你的方式带,晚饭后我来管。
+
+我认识一个年轻妈妈,用这个方法试了两周,跟我说:以前跟婆婆说话,开口就是"妈你别",现在变成了"妈,谢谢你"。不是婆婆变了,是她换了翻译器。
+
+今晚回去试试。对帮你带娃的老人说一句:妈,你辛苦了。评论区打1,我明天回你。关注我,下周讲:为什么老人一插手你就急。
+
+## 标签
+#亲子关系 #家庭教育 #婆媳关系 #老人带娃 #情绪管理 #主动健康 #家庭幸福
+
+## 20秒动作
+对带娃的老人说一句"妈,你辛苦了"
+
+## 关键数据
+爱的语言不匹配→误解循环(参考书稿第7章·大爱三境界)
+
+## 图片规划(7张)
+
+Slide 1: 标题 | 老人带娃翻脸 / 是爱的语言不同 | 心·大爱相随 | #FF6B9D
+Slide 2: 场景 | 老人追着喂饭 / 年轻妈妈皱眉 | 冲突画面
+Slide 3: 故事 | 小茜父母夹鱼 / 她想要的是倾听 | 故事画面
+Slide 4: 反常识 | 不是方法不对 / 是爱的语言不同 | 核心洞察
+Slide 5: 方法1 | 看见他的语言 / 翻译你的语言 | 三步走
+Slide 6: 方法2 | 找到共同语言 / 不是谁说服谁 | 方法
+Slide 7: CTA | 说一句"妈你辛苦了" / 评论区打1 | CTA

+ 51 - 0
articles/D16-draft_v1.md

@@ -0,0 +1,51 @@
+# D16 体检正常≠健康,你信了多久
+
+> 身维度 #FF8C42 | 参考书稿第3章 身·主动健康
+
+## 标题
+体检正常≠健康,你信了多久(13字)
+
+## 正文(698字)
+
+体检报告每一项都正常,你就觉得自己健康了?
+
+不是。体检是查病的,不是查健康的。正常只代表你没查出来病,不代表你身体真的好。
+
+我认识一个朋友叫小付。三十八岁,体检报告有三项指标接近临界值。医生跟他说"要注意",他点了点头,出了诊室就忘了。不是不想记,是每天的生活根本没有给他注意的空间——早上七点起床,送孩子,上班,加班,晚上十点到家,躺下刷十分钟手机,睡着。第二天再来一遍。
+
+他觉得自己"还行"。直到有一天,他半夜抱着发烧的孩子在客厅来回走,走了两个小时。看着鱼缸里慢悠悠游的鱼,他忽然想:为什么总是我们家?为什么每次都是孩子先倒下?
+
+医生说了一句话让他记了很久:你孩子的指标都在正常范围内。但正常,不等于健康。
+
+这话听着像绕口令,但仔细一想,真不是。他翻出自己的体检报告——每一项指标都在正常范围,但有三项已经逼近红线。他的睡眠质量很差,精力大不如前,腰酸背痛是常态。报告上没有一项说他生病,但他的身体每天都在告诉他:我不太对劲。
+
+这就是问题:我们等身体出问题了才去修,而不是在没出问题之前就去养。
+
+三个层次,你到哪一层了?
+
+第一层,不做有害的事。不熬夜、不暴饮暴食、不把自己熬到扛不住才休息。
+
+第二层,做对的事。每天喝够水、每周运动两次、睡前不看手机。
+
+第三层,建立系统。不是靠意志力,是让好习惯自动运行——比如睡前把手机放到客厅充电,早上起来先喝一杯水。
+
+今晚回去试一件事:睡前把手机放到客厅,不要带进卧室。评论区打1,我明天回你。关注我,下周讲:你喝的每一口水,可能比外卖还脏。
+
+## 标签
+#主动健康 #体检 #睡眠 #健康管理 #家庭健康 #养生 #身体
+
+## 20秒动作
+睡前把手机放到客厅充电
+
+## 关键数据
+超过六成家庭过去一年中至少有人经历过三次以上急性疾病(浠艾福家庭健康报告 2026H1)
+
+## 图片规划(7张)
+
+Slide 1: 标题 | 体检正常≠健康 / 你信了多久 | 身·主动健康 | #FF8C42
+Slide 2: 场景 | 小付体检报告三项标红 / 医生说要注意转头就忘 | 故事
+Slide 3: 故事 | 半夜抱着发烧的孩子 / 在客厅走了一圈又一圈 | 场景
+Slide 4: 数据 | 超过六成家庭 / 一年三次以上急性病 | 数据
+Slide 5: 反常识 | 正常不等于健康 / 体检是查病不是查健康 | 洞察
+Slide 6: 方法 | 三个层次 / 不做有害的事→做对的事→建立系统 | 方法
+Slide 7: CTA | 今晚把手机放客厅 / 评论区打1 | CTA

+ 43 - 0
articles/D16-draft_v2.md

@@ -0,0 +1,43 @@
+# D16 体检正常≠健康,你信了多久(v2)
+
+> 身维度 #FF8C42 | 参考书稿第3章 身·主动健康
+
+## 标题
+体检正常≠健康,你信了多久(13字)
+
+## 正文(695字)
+
+体检报告每一项都正常,你就觉得自己健康了?
+
+不是。体检是查病的,不是查健康的。但问题不是体检没用,是你只靠体检这一种方式。
+
+主动健康的核心就两句话:发现风险要科学,干预一定要简单。
+
+先说发现风险。大多数人怎么判断自己健康?凭感觉,或者等体检报告。但感觉不靠谱——你觉得累,以为是没睡好,其实是身体在发出信号。体检也不够——一年一次,中间十一个月是盲区,而且很多指标逼近临界值时,报告上写的是"正常",但你的身体已经在走下坡了。
+
+我认识一个朋友叫小付。三十八岁,体检报告有三项指标接近临界值。医生跟他说要注意,他点了点头,出了诊室就忘了。不是不想记,是每天的生活根本没给他注意的空间。
+
+他觉得自己还行。直到有一天,他半夜抱着发烧的孩子在客厅走了两个小时,看着鱼缸里慢悠悠游的鱼,他才意识到:身体早就告诉他了,他没听。
+
+这就是问题:我们等身体出问题了才去修,不是早在出问题之前就去养。
+
+再说干预。很多人以为主动健康就是"坚持早睡、坚持运动、坚持健康饮食"——三个"坚持"一出来,就注定坚持不了。因为靠意志力的事,都撑不过两周。
+
+主动健康的干预,不是让你坚持,是让你改环境。不是靠意志力早睡,是把手机放到客厅充电。不是靠意志力多喝水,是床头放一杯水早上起来先喝。不是靠意志力运动,是穿上鞋就算出门。
+
+把动作拆到20秒内能完成,大脑才不会启动回避。
+
+回到小付。他后来没做什么了不起的事。就改了一件事:睡前把手机放到客厅。两周后,他入睡时间提前了。他说:"不是我能坚持,是我根本没机会拿到手机。"
+
+这就是主动健康:发现风险靠科学,不是靠感觉。干预靠简单,不是靠坚持。
+
+今晚回去试一件事:睡前把手机放到客厅,不要带进卧室。评论区打1,我明天回你。关注我,下周讲:你喝的每一口水,可能比外卖还脏。
+
+## 标签
+#主动健康 #体检 #睡眠 #健康管理 #家庭健康 #养生 #身体
+
+## 20秒动作
+睡前把手机放到客厅充电
+
+## 关键数据
+无——本文核心是理念,不是数据

+ 5 - 1
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -2952,9 +2952,13 @@ log.info("已添加template_id列到tasks表");
             jdbcTemplate.execute("ALTER TABLE activities ADD COLUMN audited_at DATETIME DEFAULT NULL COMMENT '审核时间'");
             log.info("已添加audited_at列到activities表");
         } catch (Exception e) {
-            // 列已存在,忽略错误
+
         }
 
+        // 家庭挑战:目标模式与目标值(aggregate=集体总合目标 / all_members=全员个人目标)
+        ensureColumn("family_challenge", "target_mode", "VARCHAR(20) DEFAULT 'aggregate' COMMENT '目标模式: aggregate=集体总合/all_members=全员个人目标'");
+        ensureColumn("family_challenge", "target_value", "INT DEFAULT 0 COMMENT '目标值(aggregate=家庭合计值, all_members=每人目标值)'");
+
         log.info("数据库迁移完成");
 
         // ==================== 健康维度 Phase 1: health_dimension_score / health_data_source_record / health_norm_reference ====================

+ 17 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/FamilyChallenge.java

@@ -1,12 +1,15 @@
 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;
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 @Data
 @TableName("family_challenge")
@@ -29,6 +32,12 @@ public class FamilyChallenge implements Serializable {
 
     private String rewardBadge;
 
+    /** 目标模式: aggregate=集体总合目标 / all_members=全员个人目标 */
+    private String targetMode;
+
+    /** 目标值(aggregate=家庭合计值, all_members=每人目标值) */
+    private Integer targetValue;
+
     private Date startDate;
 
     private Date endDate;
@@ -36,4 +45,12 @@ public class FamilyChallenge implements Serializable {
     private String status;
 
     private Date createdAt;
+
+    /** 非表字段:家庭总进度(aggregate 模式使用) */
+    @TableField(exist = false)
+    private Integer totalProgress;
+
+    /** 非表字段:成员进度列表 [{childId, nickname, progressValue, completed}] */
+    @TableField(exist = false)
+    private List<Map<String, Object>> memberProgress;
 }

+ 106 - 20
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyChallengeService.java

@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.etotem.cfc.common.Result;
 import com.etotem.cfc.entity.FamilyChallenge;
 import com.etotem.cfc.entity.FamilyChallengeProgress;
+import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.mapper.FamilyChallengeMapper;
 import com.etotem.cfc.mapper.FamilyChallengeProgressMapper;
+import com.etotem.cfc.mapper.FamilyMemberMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -24,6 +26,9 @@ public class FamilyChallengeService {
     @Resource
     private FamilyChallengeProgressMapper familyChallengeProgressMapper;
 
+    @Resource
+    private FamilyMemberMapper familyMemberMapper;
+
     @Resource
     private HealthScoreService healthScoreService;
 
@@ -40,6 +45,7 @@ public class FamilyChallengeService {
             active = familyChallengeMapper.selectList(wrapper);
         }
 
+        fillProgress(active);
         return active;
     }
 
@@ -57,9 +63,9 @@ public class FamilyChallengeService {
         Date endDate = cal.getTime();
 
         String[][] templates = {
-            {"full_checkin", "全员打卡挑战", "全家连续打卡3天,一起养成好习惯!", "3", "50", ""},
-            {"sports", "运动PK挑战", "全周家庭总运动时长超过300分钟!", "7", "100", ""},
-            {"health_week", "健康周挑战", "全员每日完成微行动,连续7天健康生活!", "7", "50", "健康之家"}
+            {"full_checkin", "全员打卡挑战", "全家连续打卡3天,一起养成好习惯!", "3", "50", "", "all_members", "3"},
+            {"sports", "运动PK挑战", "全周家庭总运动时长超过300分钟!", "7", "100", "", "aggregate", "300"},
+            {"health_week", "健康周挑战", "全员每日完成微行动,连续7天健康生活!", "7", "50", "健康之家", "all_members", "7"}
         };
 
         for (String[] t : templates) {
@@ -77,6 +83,8 @@ public class FamilyChallengeService {
             challenge.setDurationDays(Integer.parseInt(t[3]));
             challenge.setRewardPoints(Integer.parseInt(t[4]));
             challenge.setRewardBadge(t[5].isEmpty() ? null : t[5]);
+            challenge.setTargetMode(t[6]);
+            challenge.setTargetValue(Integer.parseInt(t[7]));
             challenge.setStartDate(startDate);
             challenge.setEndDate(endDate);
             challenge.setStatus("active");
@@ -137,22 +145,34 @@ public class FamilyChallengeService {
             totalProgress += (p.getProgressValue() != null ? p.getProgressValue() : 0);
         }
 
-        if ("full_checkin".equals(challenge.getChallengeType())) {
-            isCompleted = progresses.size() > 0;
-            for (FamilyChallengeProgress p : progresses) {
-                if (p.getProgressValue() == null || p.getProgressValue() < 3) {
-                    isCompleted = false;
-                    break;
+        // 目标模式:新挑战取 target_mode;旧挑战(target_mode为NULL)按 challengeType 兼容推断
+        normalizeTarget(challenge);
+        String targetMode = challenge.getTargetMode();
+        int targetValue = challenge.getTargetValue() != null ? challenge.getTargetValue() : 0;
+
+        if ("aggregate".equals(targetMode)) {
+            // 集体总合目标:全家人合计达到 target_value
+            isCompleted = totalProgress >= targetValue;
+        } else {
+            // 全员个人目标:家庭内每个成员都达到 target_value
+            LambdaQueryWrapper<FamilyMember> mw = new LambdaQueryWrapper<FamilyMember>()
+                    .eq(FamilyMember::getFamilyId, challenge.getFamilyId());
+            List<FamilyMember> members = familyMemberMapper.selectList(mw);
+            if (members.isEmpty()) {
+                isCompleted = false;
+            } else {
+                Map<Long, Integer> progressMap = new HashMap<>();
+                for (FamilyChallengeProgress p : progresses) {
+                    progressMap.put(p.getChildId(),
+                            p.getProgressValue() != null ? p.getProgressValue() : 0);
                 }
-            }
-        } else if ("sports".equals(challenge.getChallengeType())) {
-            isCompleted = totalProgress >= 300;
-        } else if ("health_week".equals(challenge.getChallengeType())) {
-            isCompleted = progresses.size() > 0;
-            for (FamilyChallengeProgress p : progresses) {
-                if (p.getProgressValue() == null || p.getProgressValue() < 7) {
-                    isCompleted = false;
-                    break;
+                isCompleted = true;
+                for (FamilyMember m : members) {
+                    Integer v = progressMap.get(m.getId());
+                    if (v == null || v < targetValue) {
+                        isCompleted = false;
+                        break;
+                    }
                 }
             }
         }
@@ -160,7 +180,8 @@ public class FamilyChallengeService {
         if (isCompleted || challenge.getEndDate() == null || new Date().after(challenge.getEndDate())) {
             challenge.setStatus("completed");
             familyChallengeMapper.updateById(challenge);
-            log.info("挑战已结算: id={}, type={}, completed={}", challenge.getId(), challenge.getChallengeType(), isCompleted);
+            log.info("挑战已结算: id={}, type={}, targetMode={}, targetValue={}, completed={}",
+                    challenge.getId(), challenge.getChallengeType(), targetMode, targetValue, isCompleted);
         }
     }
 
@@ -170,6 +191,71 @@ public class FamilyChallengeService {
                 .eq(FamilyChallenge::getFamilyId, familyId)
                 .eq(FamilyChallenge::getStatus, "completed")
                 .orderByDesc(FamilyChallenge::getEndDate);
-        return familyChallengeMapper.selectList(wrapper);
+        List<FamilyChallenge> history = familyChallengeMapper.selectList(wrapper);
+        fillProgress(history);
+        return history;
+    }
+
+    /**
+     * 为挑战填充进度数据(totalProgress + memberProgress),
+     * 并对旧挑战(target_mode为NULL)向后规范化 target_mode/target_value。
+     */
+    private void fillProgress(List<FamilyChallenge> challenges) {
+        if (challenges == null || challenges.isEmpty()) return;
+
+        // 缓存各家庭全部成员,避免逐挑战重复查询
+        Map<Long, List<FamilyMember>> familyMembersCache = new HashMap<>();
+
+        for (FamilyChallenge c : challenges) {
+            normalizeTarget(c);
+
+            LambdaQueryWrapper<FamilyChallengeProgress> pw = new LambdaQueryWrapper<FamilyChallengeProgress>()
+                    .eq(FamilyChallengeProgress::getChallengeId, c.getId());
+            List<FamilyChallengeProgress> progresses = familyChallengeProgressMapper.selectList(pw);
+
+            int total = 0;
+            Map<Long, Integer> progressMap = new HashMap<>();
+            for (FamilyChallengeProgress p : progresses) {
+                int v = p.getProgressValue() != null ? p.getProgressValue() : 0;
+                total += v;
+                progressMap.put(p.getChildId(), v);
+            }
+            c.setTotalProgress(total);
+
+            List<FamilyMember> members = familyMembersCache.get(c.getFamilyId());
+            if (members == null) {
+                LambdaQueryWrapper<FamilyMember> mw = new LambdaQueryWrapper<FamilyMember>()
+                        .eq(FamilyMember::getFamilyId, c.getFamilyId());
+                members = familyMemberMapper.selectList(mw);
+                familyMembersCache.put(c.getFamilyId(), members);
+            }
+
+            List<Map<String, Object>> memberProgress = new ArrayList<>();
+            if (members != null) {
+                for (FamilyMember m : members) {
+                    Integer v = progressMap.get(m.getId());
+                    int value = v != null ? v : 0;
+                    Map<String, Object> mp = new HashMap<>();
+                    mp.put("childId", m.getId());
+                    mp.put("nickname", m.getNickname() != null ? m.getNickname() : "成员" + m.getId());
+                    mp.put("progressValue", value);
+                    mp.put("completed", value >= c.getTargetValue());
+                    memberProgress.add(mp);
+                }
+            }
+            c.setMemberProgress(memberProgress);
+        }
+    }
+
+    /** 旧挑战 target_mode 为 NULL 时,按 challengeType 推断补全 */
+    private void normalizeTarget(FamilyChallenge c) {
+        if (c.getTargetMode() != null) return;
+        if ("sports".equals(c.getChallengeType())) {
+            c.setTargetMode("aggregate");
+            c.setTargetValue(300);
+        } else {
+            c.setTargetMode("all_members");
+            c.setTargetValue("full_checkin".equals(c.getChallengeType()) ? 3 : 7);
+        }
     }
 }

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

@@ -3135,6 +3135,8 @@ CREATE TABLE IF NOT EXISTS family_challenge (
     duration_days INT DEFAULT 7 COMMENT '持续天数',
     reward_points INT DEFAULT 0 COMMENT '奖励积分',
     reward_badge VARCHAR(100) COMMENT '奖励徽章',
+    target_mode VARCHAR(20) DEFAULT 'aggregate' COMMENT '目标模式: aggregate=集体总合/all_members=全员个人目标',
+    target_value INT DEFAULT 0 COMMENT '目标值(aggregate=家庭合计值, all_members=每人目标值)',
     start_date DATE COMMENT '开始日期',
     end_date DATE COMMENT '结束日期',
     status VARCHAR(20) DEFAULT 'active' COMMENT 'active/completed/cancelled',

+ 228 - 17
cfc-frontend/components/FamilyChallengeCard.vue

@@ -2,11 +2,42 @@
   <view class="challenge-card" v-if="challenge">
     <view class="card-header">
       <text class="card-title">{{ challenge.title }}</text>
-      <text class="card-status" :class="'status-' + (challenge.status || 'active')">
+      <text class="card-status" :class="statusClass">
         {{ challenge.status === 'active' ? '进行中' : '已完成' }}
       </text>
     </view>
     <text class="card-desc">{{ challenge.description || '' }}</text>
+
+    <!-- 目标展示(两种模式) -->
+    <view class="target-section" v-if="challenge.targetMode">
+      <view class="target-header">
+        <text class="target-label">{{ targetModeLabel }}</text>
+        <text class="target-value">{{ formatTargetValue }}</text>
+      </view>
+
+      <!-- aggregate 模式:家庭总进度条 -->
+      <view class="card-progress" v-if="challenge.targetMode === 'aggregate'">
+        <view class="progress-bar-bg">
+          <view class="progress-bar-fill" :style="{ width: totalPercent + '%' }"></view>
+        </view>
+        <text class="progress-text">{{ challenge.totalProgress || 0 }}/{{ challenge.targetValue }}</text>
+      </view>
+
+      <!-- all_members 模式:成员进度列表 -->
+      <view class="member-list" v-if="challenge.targetMode === 'all_members' && challenge.memberProgress && challenge.memberProgress.length > 0">
+        <view class="member-row" v-for="mp in challenge.memberProgress" :key="mp.childId">
+          <text class="member-name">{{ mp.nickname }}</text>
+          <view class="member-bar-wrap">
+            <view class="member-bar-bg">
+              <view class="member-bar-fill" :style="{ width: memberPercent(mp.progressValue) + '%' }"></view>
+            </view>
+          </view>
+          <text class="member-val">{{ mp.progressValue }}/{{ challenge.targetValue }}</text>
+          <text class="member-done" v-if="mp.completed">✓</text>
+        </view>
+      </view>
+    </view>
+
     <view class="card-detail-row" v-if="challenge.durationDays">
       <text class="detail-label">⏱ 期限</text>
       <text class="detail-val">{{ challenge.durationDays }}天</text>
@@ -20,25 +51,107 @@
       <text class="detail-val reward">+{{ challenge.rewardPoints }}分</text>
       <text class="detail-val badge" v-if="challenge.rewardBadge"> 🎖️ {{ challenge.rewardBadge }}</text>
     </view>
-    <view class="card-progress" v-if="progressPercent !== undefined">
-      <view class="progress-bar-bg">
-        <view class="progress-bar-fill" :style="{ width: Math.min(progressPercent, 100) + '%' }"></view>
-      </view>
-      <text class="progress-text">{{ progressPercent }}%</text>
+
+    <!-- 打卡上报入口(active 挑战 + 有 childId) -->
+    <view class="checkin-section" v-if="challenge.status === 'active'">
+      <template v-if="!showInput">
+        <view class="checkin-btn" @click="openInput">
+          <text class="checkin-btn-text">上报进度</text>
+        </view>
+      </template>
+      <template v-else>
+        <view class="checkin-form">
+          <input class="checkin-input" type="number" v-model="deltaValue" placeholder="输入本次数量" />
+          <view class="checkin-submit" @click="submitProgress">
+            <text class="checkin-btn-text">确认</text>
+          </view>
+          <view class="checkin-cancel" @click="closeInput">
+            <text class="checkin-cancel-text">取消</text>
+          </view>
+        </view>
+      </template>
     </view>
   </view>
 </template>
 
 <script>
+import { updateChallengeProgress } from '@/utils/api.js'
+
 export default {
   props: {
     challenge: { type: Object, default: null },
-    progressPercent: { type: Number, default: undefined }
+    childId: { type: Number, default: null }
+  },
+  data: function() {
+    return {
+      showInput: false,
+      deltaValue: ''
+    }
+  },
+  computed: {
+    statusClass: function() {
+      return 'status-' + (this.challenge && this.challenge.status ? this.challenge.status : 'active')
+    },
+    targetModeLabel: function() {
+      if (!this.challenge) return ''
+      if (this.challenge.targetMode === 'aggregate') return '🎯 全家目标'
+      return '🎯 每人目标'
+    },
+    formatTargetValue: function() {
+      if (!this.challenge) return ''
+      return this.challenge.targetValue
+    },
+    totalPercent: function() {
+      var total = this.challenge && this.challenge.totalProgress ? this.challenge.totalProgress : 0
+      var target = this.challenge && this.challenge.targetValue ? this.challenge.targetValue : 1
+      if (target <= 0) return 0
+      var p = Math.round(total / target * 100)
+      return Math.min(p, 100)
+    }
   },
   methods: {
     formatDate: function(dateStr) {
       if (!dateStr) return ''
       return String(dateStr).slice(0, 10)
+    },
+    memberPercent: function(value) {
+      var target = this.challenge && this.challenge.targetValue ? this.challenge.targetValue : 1
+      if (target <= 0) return 0
+      var p = Math.round((value || 0) / target * 100)
+      return Math.min(p, 100)
+    },
+    openInput: function() {
+      this.deltaValue = ''
+      this.showInput = true
+    },
+    closeInput: function() {
+      this.showInput = false
+      this.deltaValue = ''
+    },
+    submitProgress: function() {
+      var delta = parseInt(this.deltaValue, 10)
+      if (!delta || delta <= 0) {
+        uni.showToast({ title: '请输入本次数量', icon: 'none' })
+        return
+      }
+      if (!this.childId) {
+        uni.showToast({ title: '请先选择家庭成员', icon: 'none' })
+        return
+      }
+      var self = this
+      updateChallengeProgress({
+        challengeId: this.challenge.id,
+        childId: this.childId,
+        delta: delta
+      }).then(function(res) {
+        if (res.code === 200) {
+          uni.showToast({ title: '上报成功!', icon: 'none' })
+          self.closeInput()
+          self.$emit('updated')
+        }
+      }).catch(function() {
+        // api.js 拦截器已提示
+      })
     }
   }
 }
@@ -78,26 +191,33 @@ export default {
   margin-bottom: 12rpx;
   display: block;
 }
-.card-detail-row {
+
+/* 目标区 */
+.target-section {
+  background: #F8FAFC;
+  border-radius: 12rpx;
+  padding: 16rpx;
+  margin-bottom: 8rpx;
+}
+.target-header {
   display: flex;
+  justify-content: space-between;
   align-items: center;
-  gap: 8rpx;
-  margin-top: 6rpx;
+  margin-bottom: 10rpx;
 }
-.detail-label { font-size: 24rpx; color: #94A3B8; }
-.detail-val { font-size: 24rpx; color: #334155; }
-.detail-val.reward { color: #F97316; font-weight: 600; }
-.detail-val.badge { color: #6366F1; }
+.target-label { font-size: 24rpx; color: #475569; font-weight: 600; }
+.target-value { font-size: 28rpx; color: #10B981; font-weight: 700; }
+
 .card-progress {
   display: flex;
   align-items: center;
   gap: 12rpx;
-  margin-top: 12rpx;
+  margin-top: 4rpx;
 }
 .progress-bar-bg {
   flex: 1;
   height: 12rpx;
-  background: #F1F5F9;
+  background: #E2E8F0;
   border-radius: 999rpx;
   overflow: hidden;
 }
@@ -111,7 +231,98 @@ export default {
   font-size: 22rpx;
   color: #10B981;
   font-weight: 600;
-  min-width: 48rpx;
+  min-width: 110rpx;
   text-align: right;
 }
+
+/* 成员进度 */
+.member-list {
+  margin-top: 4rpx;
+}
+.member-row {
+  display: flex;
+  align-items: center;
+  gap: 8rpx;
+  margin-top: 8rpx;
+}
+.member-name {
+  font-size: 22rpx;
+  color: #475569;
+  width: 90rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.member-bar-wrap { flex: 1; }
+.member-bar-bg {
+  height: 10rpx;
+  background: #E2E8F0;
+  border-radius: 999rpx;
+  overflow: hidden;
+}
+.member-bar-fill {
+  height: 100%;
+  background: linear-gradient(90deg, #6366F1, #8B5CF6);
+  border-radius: 999rpx;
+}
+.member-val {
+  font-size: 20rpx;
+  color: #64748B;
+  min-width: 90rpx;
+  text-align: right;
+}
+.member-done {
+  font-size: 24rpx;
+  color: #10B981;
+  font-weight: 700;
+}
+
+/* 详情行 */
+.card-detail-row {
+  display: flex;
+  align-items: center;
+  gap: 8rpx;
+  margin-top: 6rpx;
+}
+.detail-label { font-size: 24rpx; color: #94A3B8; }
+.detail-val { font-size: 24rpx; color: #334155; }
+.detail-val.reward { color: #F97316; font-weight: 600; }
+.detail-val.badge { color: #6366F1; }
+
+/* 打卡区 */
+.checkin-section {
+  margin-top: 16rpx;
+  border-top: 1rpx solid #F1F5F9;
+  padding-top: 16rpx;
+}
+.checkin-btn {
+  background: linear-gradient(135deg, #10B981, #34D399);
+  border-radius: 40rpx;
+  padding: 16rpx 0;
+  text-align: center;
+}
+.checkin-btn:active { opacity: 0.8; }
+.checkin-btn-text { color: #fff; font-size: 26rpx; font-weight: 600; }
+.checkin-form {
+  display: flex;
+  align-items: center;
+  gap: 12rpx;
+}
+.checkin-input {
+  flex: 1;
+  height: 64rpx;
+  background: #F1F5F9;
+  border-radius: 12rpx;
+  padding: 0 16rpx;
+  font-size: 26rpx;
+}
+.checkin-submit {
+  background: #10B981;
+  border-radius: 12rpx;
+  padding: 14rpx 24rpx;
+}
+.checkin-cancel {
+  padding: 14rpx 16rpx;
+}
+.checkin-cancel-text { font-size: 24rpx; color: #94A3B8; }
 </style>

+ 3 - 1
cfc-frontend/pages/home-pages/parent-index.vue

@@ -38,7 +38,9 @@
 <FamilyChallengeCard
   v-for="ch in activeChallenges"
   :key="ch.id"
-:challenge="ch" />
+  :challenge="ch"
+  :childId="currentChildId"
+  @updated="loadFamilyInteraction" />
 
     <!-- ===== 健康圈入口(P3:社区扩散) ===== -->
     <view class="circle-entry-section">

+ 14 - 0
cfc-frontend/patch-node-compat.cjs

@@ -0,0 +1,14 @@
+// Node v24 兼容 polyfill:旧版 uni-app 工具链依赖已移除的 util 方法
+const util = require('util');
+if (typeof util.isRegExp !== 'function') {
+  util.isRegExp = function(v) { return Object.prototype.toString.call(v) === '[object RegExp]'; };
+}
+if (typeof util.isArray !== 'function') {
+  util.isArray = Array.isArray;
+}
+if (typeof util.isDate !== 'function') {
+  util.isDate = function(v) { return Object.prototype.toString.call(v) === '[object Date]'; };
+}
+if (typeof util.isError !== 'function') {
+  util.isError = function(v) { return Object.prototype.toString.call(v) === '[object Error]' || v instanceof Error; };
+}

+ 1 - 1
运营文案/小红书内容/D14-对外人客气是因为不在乎.md

@@ -32,7 +32,7 @@
 
 我认识一个妈妈,用这两个方法试了三个月,孩子的家庭归属感评分从2.0升到了7.3。不是换了孩子,是她换了说话的方式。
 
-今晚试试。把到嘴边的那句你应该,换成谢谢你
+今晚回去就试,评论区打1,我明天回你。关注我,下周讲:你以为你爱孩子,其实你爱的是"他应该成为的样子"
 
 ## 标签
 #亲子关系 #家庭教育 #情绪管理 #沟通技巧 #育儿 #主动健康 #家庭幸福

+ 56 - 0
运营文案/小红书内容/D15-老人带娃翻脸是爱的语言不同.md

@@ -0,0 +1,56 @@
+# D15 老人带娃翻脸,是爱的语言不同
+
+> 维度:心 #FF6B9D | 参考《家的算法》第7章 心·大爱相随
+> 系列:老人带娃三部曲·之一(D15/D20/D25)
+> 发布编号:D15 | 状态:草稿箱 | 字数:675
+
+## 标题
+老人带娃翻脸,是爱的语言不同(14字)
+
+## 正文
+
+老人带娃起冲突,你以为是方法不对——不是,是爱的语言不同。
+
+你妈给孩子夹菜、添饭、追着喂,你烦了:妈,别惯着他,让他自己吃。你妈委屈了:我辛辛苦苦给你带孩子,你还嫌我。
+
+你觉得自己没错——科学育儿,培养独立性。她也觉得自己没错——怕孩子饿着,这是爱。
+
+你们都没错。但你们在用不同的语言说爱。
+
+我认识一个女孩叫小茜。每次回家,桌上永远有一盘她爱吃的鱼。父母觉得,给她吃好喝好就是最好的爱。但小茜想要的不是鱼,是有人问她一句:你最近在想什么?
+
+两种爱都没错,但语言不通。老人觉得我付出了这么多你怎么还不满意,年轻人觉得你们根本不理解我。
+
+这不是谁对谁错的问题,是两个人的爱的语言不匹配。
+
+怎么解决?三步走。
+
+第一步,看见她的语言。老人给你带孩子,她用的方式是她从小被爱的方式——吃饱穿暖就是爱。不是她固执,她的词典里就这些词。
+
+第二步,翻译你的话。不要说妈别追着喂了,试试:妈,我知道你怕他饿着。以后让他自己吃,吃不完我再喂。翻译过来就是:我看到你的爱了,咱换个方式一起爱他。
+
+第三步,找共同语言。不是谁听谁的,是找一条两个人都能走的路。比如:白天你按你的方式带,晚饭后我来管。
+
+我认识一个年轻妈妈,用这个方法试了两周,跟我说:以前跟婆婆说话,开口就是妈你别,现在变成了妈,谢谢你。不是婆婆变了,是她换了翻译器。
+
+今晚回去试试。对帮你带娃的老人说一句:妈,你辛苦了。评论区打1,我明天回你。关注我,下周讲:为什么老人一插手你就急。
+
+## 标签
+#亲子关系 #家庭教育 #婆媳关系 #老人带娃 #情绪管理 #主动健康 #家庭幸福
+
+## 20秒动作
+对带娃的老人说一句"妈,你辛苦了"
+
+## 关键数据
+爱的语言不匹配→误解循环(参考书稿第7章·大爱三境界)
+
+## 图片(7张)
+| 幻灯片 | 文字 |
+|--------|------|
+| slide_01_cover.png | 老人带娃翻脸 / 是爱的语言不同 |
+| slide_02_scene.png | 你妈追着喂饭 / 你皱眉说别惯着 |
+| slide_03_story.png | 小茜家的鱼 / 父母夹鱼,她想要的是倾听 |
+| slide_04_insight.png | 不是方法不对 / 是爱的语言不同 |
+| slide_05_method.png | 三步走 / 看见他的语言 翻译你的语言 找到共同语言 |
+| slide_06_method2.png | 不是谁说服谁 / 是找到第三条路 |
+| slide_07_cta.png | 今晚试试 / 对带娃的老人说一句:妈,你辛苦了 |

+ 56 - 0
运营文案/小红书内容/D16-体检正常不等于健康.md

@@ -0,0 +1,56 @@
+# D16 体检正常≠健康,你信反了吗(v4)
+
+> 维度:身 #FF8C42 | 参考书稿第3章 身·主动健康
+> 发布编号:D16 | 状态:草稿箱 | 字数:1000
+
+## 核心论点(v4)
+主动健康的答案:**体检查出来的是"问题"(已发生、需治疗、影响生活),不是"风险"(未发生)。人们逃避体检,本质是逃避"查出问题后生活被打乱"。所以主动健康必须:在不影响正常生活的前提下,科学发现风险 + 简单干预。**
+
+## 标题
+体检正常≠健康,你信反了吗(13字)
+
+## 正文
+
+体检报告每一项都正常,你就觉得自己健康了?
+
+先别急着回答,我先问你:你有多久没敢去体检了?
+
+很多人不是不爱惜身体,是怕体检。你仔细想想,你怕的真是那台机器吗?不是。你怕的是结果出来之后的一连串事情:医生说这个指标要复查,那个指标要吃药,然后你就得早睡、忌口、戒酒、每天走一万步。
+
+你怕的,是查出问题之后,那些干预手段会把你现在的生活全打乱。
+
+这就是关键:体检查出来的不是风险,是问题。风险是还没发生的事,问题已经发生了,查出来就得治疗,治疗就得影响生活。
+
+所以大家躲着体检,本质上躲的是病被发现了,生活就得变。
+
+主动健康要解决的,恰恰是这个矛盾:能不能在问题还没发生的时候,就把风险发现出来?发现之后,能不能用不影响正常生活的办法去干预?
+
+能。而且只能这样。
+
+第一,发现风险要科学,但科学不等于一年一次体检。身体每天都在给你发信号:精力是升是降,睡眠是好是坏,体重是不是悄悄爬升,是不是爬三层楼就喘。这些微小变化比报告更早,把它们记下来,你就有了体检之外的另一双眼睛。但这双眼睛只看得见身体开口的事,有些风险身体自己都没察觉,就已经在靠近了。怎么提前看见,我改天专门讲。
+
+第二,干预一定要简单,简单到不影响生活。主动健康的干预,不是让你戒掉所有爱吃的东西,是晚饭少盛半碗;不是让你每天去健身房,是睡前把手机放到客厅;不是逼你十点睡,是躺下之后不再刷下一条。
+
+我认识一个朋友小付,三十八岁,体检有三项指标逼近临界值。医生说要注意,他出了诊室就忘。为什么?因为医生的注意意味着生活要改,他改不动。直到有一天他半夜抱着发烧的孩子在客厅走了两个小时,才突然意识到:身体早就提醒过他了——爬三层楼开始喘,下午三四点犯困,动不动就上火。这些信号他全没当回事。
+
+后来他没做什么了不起的事,就改了一件事:睡前把手机放到客厅。两周后入睡快了,精力回来了。他说:不是我能坚持,是我根本没机会拿到手机。
+
+发现风险靠科学,干预靠简单,全程不影响你的正常生活——这就是主动健康的答案。
+
+今晚先试一件事:睡前把手机放到客厅充电,别带进卧室。
+
+想要那份《身体信号自查清单》,评论区回复:方法,我私信发你。照着记一周,你就有体检之外的另一双眼睛。
+
+关注我,下周讲:你喝的每一口水,可能比外卖还脏。再往后,我讲怎么看见身体自己都没察觉的风险。
+
+## 标签
+#主动健康 #体检 #睡眠 #健康管理 #家庭健康 #养生
+
+## Slide 文案(7图=7金句)
+1. 封面:体检正常≠健康 / 你信反了吗
+2. 场景:你怕的不是体检 / 是查出问题后的生活
+3. 故事:身体早就提醒过你 / 只是你没当回事
+4. 数据:发现风险要科学 / 干预一定要简单
+5. 洞察:体检是查病 / 不是查健康
+6. 方法:不影响生活的干预 / 才不用靠坚持
+7. CTA:今晚试试 / 睡前把手机放到客厅

+ 29 - 9
运营文案/小红书内容/README.md

@@ -10,13 +10,22 @@
 | 早期 | 智 | 暑假亲子 | `第一篇-暑假没意思.md` | 1428 | 已发布 |
 | D1 | 身 | 早睡20秒 | `第三篇-早睡20秒.md` | 1220 | 已发布 |
 | D2 | 智 | 专注力-大脑 | `第二篇-不是不想专注_是大脑没吃饱.md` | 1217 | 已发布 |
-| D3 | 富 | 购物/财商 | `第三篇-购物车里躺着一个不再看的东西.md` | 714 | 已发布 |
+| D3 | 富 | 购物/财商 | `第三篇-月入2万的家庭比想象中穷得更稳.md` | 714 | 已发布(线上标题已改) |
 | D4 | 行 | 通讯录1493人 | `第四篇-通讯录1493人.md` | 773 | 已发布 |
 | D5 | 心 | 情绪开关 | `第五篇-吼完孩子试试这个情绪开关.md` | 904 | 已发布 |
 | D6 | 身 | 哈佛呼吸法 | `第六篇-哈佛呼吸法3分钟换个人.md` | 814 | 已发布 |
 | D7 | 智 | 周复盘 | `第七篇-复盘孩子本周3个进步比报班管用100倍.md` | 747 | 已发布 |
 | D8 | 富 | 每月定投 | `第八篇-每月定投1次比每天看余额管用.md` | 797 | 已发布 |
-| D9 | 行 | 老人带娃分工 | `第九篇-老人带娃容易翻脸分清这3件事就好了.md` | 1073 | 待发布 |
+| D9 | 行 | 老人带娃分工 | `第九篇-老人带娃容易翻脸分清这3件事就好了.md` | 1073 | 已发布 |
+| D10 | 心 | 必修课 | `第十篇-???` | — | 待发布 |
+| D11 | 身 | 睡眠两周证 | `D11-睡好两周后脑子真的变快了.md` | 793 | 草稿箱 |
+| D12 | 智 | 词汇力量两周证 | `D12-坚持读14天后词汇量涨了.md` | 798 | 草稿箱 |
+| D13 | 富 | 资产增值曲线证 | `D13-14天家庭资产柱状图钱去哪了一眼看清.md` | 652 | 草稿箱 |
+| D14 | 行 | 对外人客气→不在乎 | `D14-对外人客气是因为不在乎.md` | 751 | 草稿箱 |
+| D15 | 心 | 老人带娃·爱的语言 | `D15-老人带娃翻脸是爱的语言不同.md` | 675 | 草稿箱 |
+| D16 | 身 | 体检正常≠健康 | `D16-体检正常不等于健康.md` | 751 | 草稿箱 |
+| D20 | 心 | 老人带娃·掌控感 | 待创作 | — | 规划中 |
+| D25 | 心 | 老人带娃·三代同堂 | 待创作 | — | 规划中 |
 
 ## 备选稿件(未采用)
 
@@ -38,15 +47,26 @@
 
 ## 五维分布统计
 
-| 维度 | 已发布数量 | 比例 |
+| 维度 | 已发布/草稿 | 比例 |
 |------|-----------|------|
-| 🌏 身(主动健康) | 2(D1, D6) | 22% |
-| ⚔️ 智(赋能未来) | 2(早期, D2, D7)→ 实际3 | 33% |
-| 💧 富(利他创富) | 1(D3, D8)→ 实际2 | 22% |
-| 🌿 行(人际和谐) | 1(D4, D9)→ 实际2 | 22% |
-| 🔥 心(大爱相随) | 0(D5待定)→ 实际1 | 11% |
+| 🌏 身(主动健康) | D1, D6, D11 → 3 | 25% |
+| ⚔️ 智(赋能未来) | 早期, D2, D7, D12 → 4 | 33% |
+| 💧 富(利他创富) | D3, D8, D13 → 3 | 25% |
+| 🌿 行(人际和谐) | D4, D9, D14 → 3 | 25% |
+| 🔥 心(大爱相随) | D5, D10 → 2 | 17% |
 
-注:D5(心)已发布,统计按已发布计算。
+注:D10 待发布,D11-D14 在草稿箱。含草稿箱的话心维度最弱(仅2篇),需补足。
+
+## 老人带娃系列(D15/D20/D25)
+
+基于 D9(曝光1572/CTR 14.8% 双冠)延展的心维度系列:
+
+| 篇目 | 标题 | 维度 | 核心 |
+|------|------|------|------|
+| D9 | 老人带娃容易翻脸,分清这3件事就好了 | 行 | 总纲:分工清单(已发布) |
+| **D15** | **老人带娃翻脸,是爱的语言不同** | **心** | **爱的语言:看见家人(草稿箱)** |
+| D20 | 老人一插手你就急?因为你怕失去掌控权 | 心 | 看见自己:情绪觉察(规划中) |
+| D25 | 三代同堂,学会用对方的语言说话 | 心 | 爱的语言匹配(规划中) |
 
 ## 后续维护建议
 

+ 570 - 25
运营文案/小红书内容/小红书发布指南.md

@@ -1,7 +1,6 @@
-# 浠艾福(Care Family)小红书发布指南 v2
+# 浠艾福(Care Family)小红书发布指南 v8
 
-> 更新日期:2026-07-27 | 基于 7 篇已发布内容复盘 + 行业趋势(2026 小红书母婴育儿赛道)  
-> 取代旧版(2026-07-19,仅针对第一篇内容)  
+> 更新日期:2026-07-30 | 基于 9 篇已发布 + 4 篇草稿箱复盘  
 > 配套文件:`合集命名.md`(维度合集规范)、`内容方法论-六阶模型.md`(内容骨架)
 
 ---
@@ -10,16 +9,22 @@
 
 ### 1.1 已发布内容概览
 
-| 编号 | 标题 | 维度 | 字数 | 标题长度 | 有无20秒动作 | 评论区钩子 | 数据案例 | 标签数 |
-|------|------|------|------|----------|-------------|-----------|---------|-------|
-| 早期 | 当孩子说"没意思"… | 智 | ~900 | 17字✓ | ✗ | 评论分享 | 78%统计数据 | 5 |
-| D1 | 让你早睡的不是自律,是这3件小事 | 身 | ~700 | 14字✓ | ✓手机放卧室外 | ✓打卡"城市" | ✓n=246 | 5✓ |
-| D2 | 不是不想专注,是大脑没吃饱 | 智 | ~800 | 11字✓ | ✓睡前10小时挑战 | ✓打卡"10小时" | ✓小辰A2数据 | 5✓ |
-| D3 | 购物车里躺着一个三天不会再看的东西 | 富 | ~500 | 16字✓ | ✓记账软件打开 | ✓评论告诉我 | ✗无硬数据 | 3✗ |
-| D4 | 通讯录里1493人,凌晨两点却没人问 | 行 | ~400 | 17字✓ | ✓发"在吗" | ✓评论告诉我 | ✗无硬数据 | 4✗ |
-| D5 | 吼完孩子,试试这个情绪开关 | 心 | ~500 | 14字✓ | ✓闻花香+吹蜡烛 | ✓今晚用几次 | ✗结构化示例 | 5✓ |
-| D6 | 哈佛呼吸法,3分钟让你换一个人 | 身 | ~500 | 15字✓ | ✓4-7-8呼吸 | ✓做几个循环 | ✗个人体感 | 5✓ |
-| D7 | 复盘孩子本周3个进步比报班管用100倍 | 智 | ~400 | 19字✓ | ✓写3个进步 | ✓打卡1个进步 | ✓A2提升0.6分 | 6✓ |
+| 编号 | 标题 | 维度 | 字数 | 标题长度 | 有无20秒动作 | 评论区钩子 | 数据案例 | 标签数 | 状态 |
+|------|------|------|------|----------|-------------|-----------|---------|-------|------|
+| 早期 | 当孩子说"没意思"… | 智 | ~900 | 17字✓ | ✗ | 评论分享 | 78%统计数据 | 5 | 已发布 |
+| D1 | 让你早睡的不是自律,是这3件小事 | 身 | ~700 | 14字✓ | ✓手机放卧室外 | ✓打卡"城市" | ✓n=246 | 5✓ | 已发布 |
+| D2 | 不是不想专注,是大脑没吃饱 | 智 | ~800 | 11字✓ | ✓睡前10小时挑战 | ✓打卡"10小时" | ✓小辰A2数据 | 5✓ | 已发布 |
+| D3 | 购物车里躺着一个三天不会再看的东西 | 富 | ~500 | 16字✓ | ✓记账软件打开 | ✓评论告诉我 | ✗无硬数据 | 3✗ | 已发布 |
+| D4 | 通讯录里1493人,凌晨两点却没人问 | 行 | ~400 | 17字✓ | ✓发"在吗" | ✓评论告诉我 | ✗无硬数据 | 4✗ | 已发布 |
+| D5 | 吼完孩子,试试这个情绪开关 | 心 | ~500 | 14字✓ | ✓闻花香+吹蜡烛 | ✓今晚用几次 | ✗结构化示例 | 5✓ | 已发布 |
+| D6 | 哈佛呼吸法,3分钟让你换一个人 | 身 | ~500 | 15字✓ | ✓4-7-8呼吸 | ✓做几个循环 | ✗个人体感 | 5✓ | 已发布 |
+| D7 | 复盘孩子本周3个进步比报班管用100倍 | 智 | ~400 | 19字✓ | ✓写3个进步 | ✓打卡1个进步 | ✓A2提升0.6分 | 6✓ | 已发布 |
+| D8 | 每月定投1次比每天看余额管用 | 富 | 797 | 16字✓ | ✓每月定投一次 | ✓评论告诉我 | ✓n=246 | 5✓ | 已发布 |
+| D9 | 老人带娃容易翻脸分清这3件事就好了 | 行 | 1073 | 19字✓ | ✓分工清单 | ✓评论分享 | ✗无硬数据 | 5✓ | 已发布 |
+| D11 | 睡好两周后脑子真的变快了 | 身→智 | 793 | 14字✓ | ✓睡前放手机 | ✓打卡"城市" | ✓睡眠质量两周均 | 7✓ | 草稿箱 |
+| D12 | 词穷到会说,只差这14天 | 智→富 | 798 | 14字✓ | ✓每天读一页 | ✓打卡"14天" | ✓词汇力增速 | 7✓ | 草稿箱 |
+| D13 | 存钱第一步,不是记账,是看见 | 富→行 | 652 | 16字✓ | ✓每天10秒记一笔 | ✓打卡"看见" | ✓14天柱状图 | 7✓ | 草稿箱 |
+| D14 | 对外人客气,是因为不在乎 | 行→心 | 751 | 12字✓ | ✓把"你应该"换成"谢谢你" | ✓评论区告诉我 | ✓归属感2.0→7.3 | 7✓ | 草稿箱 |
 
 ### 1.2 关键发现
 
@@ -329,14 +334,16 @@
 
 ## 五、内容生产节奏调整
 
-### 5.1 当前状态
+### 5.1 当前状态(2026-07-30 更新)
 
 | 指标 | 计划值 | 实际值 | 差距 |
 |------|--------|--------|------|
-| 已发布内容 | 30篇(30天日更) | ~7篇 | -23篇 |
+| 已发布内容 | 30篇(30天日更) | 9篇(早期-D9) | -21篇 |
+| 草稿箱待发 | — | 4篇(D11-D14) | — |
 | 内容库存 | 30篇 | 13篇(含备稿) | -17篇 |
-| 数据追踪 | 每篇 | 0篇 | -7篇 |
-| 合集挂载 | 5个合集 | 0个 | -5个 |
+| 数据追踪 | 每篇 | 0篇 | 仍挂零 |
+| 合集挂载 | 5个合集 | 0个 | 仍挂零 |
+| 书稿引用 | — | 已完成(D14引用第6章) | 新能力 |
 
 ### 5.2 调整建议
 
@@ -344,12 +351,11 @@
 
 | 阶段 | 时间 | 目标 | 节奏 |
 |------|------|------|------|
-| 恢复期 | 第1-2周 | 补齐数据追踪 + 合集挂载 | 周2-3篇 |
-| 稳定期 | 第3-4周 | 稳定质量,积累数据 | 周3篇 |
-| 加速期 | 第5-8周 | 根据数据放大好选题 | 周3-4篇 |
-| 冲刺期 | 第9-12周 | 找到爆款公式后加量 | 周4-5篇 |
+| 积稿期 | 当前 | 集中创作 D11-D15 草稿,攒够库存 | 周3-4篇 |
+| 发布期 | 下一阶段 | 从草稿箱逐步发布,补数据追踪 | 周2-3篇 |
+| 迭代期 | 参考数据反馈 | 根据曝光/互动率调整选题方向 | 周3篇 |
 
-**核心原则**:先有数据,再谈增长。没有数据复盘,发再多也是盲打
+**核心原则**:先有数据,再谈增长。草稿箱已有 4 篇待发,下一步优先发布 + 补数据追踪
 
 ---
 
@@ -897,7 +903,10 @@ C:\code\cfc\运营文案\小红书发布\       (发布目录)
 
 ## 18. 书稿内容参考(book/ 目录)
 
-> `book/` 目录下有一本完整的书稿,覆盖五维能量体系(身·智·富·行·心),可作为小红书内容创作的素材库。
+> `book/` 目录下有一本完整的书稿《家的算法》(五维能量让幸福有迹可循),覆盖五维能量体系(身·智·富·行·心)。
+>
+> **小红书内容的核心定位:为书做选题测试和流量预热。**
+> 每篇小红书文章 = 一个书稿章节的"市场测试"——测试哪个角度有流量、哪个标题有人点、哪个方法有人收藏。
 
 ### 18.1 目录结构
 
@@ -937,12 +946,20 @@ book/
 | 第六章 | 行 | 人际和谐、家庭关系——行动力 |
 | 第七章 | 心 | 大爱相随、情绪稳定——内心力量 |
 
-### 18.3 使用方式
+### 18.3 使用方式(双向:书→小红书,小红书→书)
 
+**书 → 小红书(素材输出)**:
 每篇小红书文章撰写前,先查阅对应维度的书稿章节:
 1. 找 1-2 个书稿中的观点或案例作为素材
 2. 按 5 段式结构(引入→冲突→知识→方法→CTA)改写
-3. 标注数据来源:`(参考书稿第 X 章)`
+3. 不直接引用"书里说"(书未上市),用"我认识一个女孩""我听过一个故事"代替
+
+**小红书 → 书(数据反馈)**:
+每篇小红书发布后,数据回流指导书稿调整:
+1. 哪个选题曝光高 → 书稿对应章节加篇幅
+2. 哪个标题CTR高 → 书的章节标题参考其公式
+3. 哪个方法收藏高 → 书稿对应方法加详述
+4. 哪个角度没人看 → 书稿对应角度删减或重写
 
 ### 18.4 书稿章节亮点
 
@@ -958,6 +975,534 @@ book/
 
 > **版本记录**:v7 → 2026-07-30 新增第 18 章 书稿内容参考
 
+---
+
+## 19. D11-D14 创作经验沉淀(2026-07-30)
+
+### 19.1 文章概览
+
+| 编号 | 标题 | 维度 | 字数 | 来源 | 核心方法 |
+|------|------|------|------|------|---------|
+| D11 | 睡好两周后脑子真的变快了 | 身→智 | 793 | 书稿第3章+睡眠科学 | 睡前放手机、喝还原水、读纸书 |
+| D12 | 词穷到会说,只差这14天 | 智→富 | 798 | 书稿第4章+中文优势 | 每天读一页、中文三千字可搭无限 |
+| D13 | 存钱第一步,不是记账,是看见 | 富→行 | 652 | 书稿第5章+资源增值管理 | 每天10秒记一笔、14天柱状图 |
+| D14 | 对外人客气,是因为不在乎 | 行→心 | 751 | 书稿第6章+期待落差心理学 | 目标停止法、"你应该"→"谢谢你" |
+
+### 19.2 迭代经验
+
+| 篇目 | 迭代次数 | 关键教训 |
+|------|---------|---------|
+| D11 | 6次(v1-v6) | 图片文字大小需反复调整;字体路径必须用 `C:\Windows\Fonts\msyhbd.ttc` |
+| D12 | 多次(标题+图片重画) | 标题从"坚持读14天"改为"词穷到会说"后更爆;中文优势段落是差异化亮点 |
+| D13 | 2次 | 富维度不要窄化为钱;"资源增值管理"可作D12词汇主题的延续 |
+| D14 | 3次(v1-v3) | v1"家是安全的"太常识→v2换"因为在乎"→v3最终定为"对外人客气是因为不在乎"(反常识) |
+
+### 19.3 图片生成经验
+
+| 经验 | 说明 |
+|------|------|
+| **每图必为金句** | **7张图=7个可单独传播的金句。禁止叙事/场景描述类水句(如"半夜抱着发烧的孩子")。每张图的文案必须单独截图发出也成立、让人想保存/转发。金句模板:反常识结论 / 对比转折 / 动作指令。** |
+| Agnes AI API 不稳定 | 偶尔 400/503 错误,需重试;prompt 含"child"可能触发内容策略 |
+| 字体路径 | 必须用 `C:\Windows\Fonts\msyhbd.ttc`,不要用用户目录下的版本 |
+| 文字大小 | 双行文字:标题 130-140pt,副标题 55-70pt,行距 60px+;单行上限约 8 字(1080px 画布内) |
+| 维度色系 | 身#FF8C42 智#6366F1 富#F59E0B 行#10B981 心#FF6B9D |
+| 文字叠加 | 底部 360px 维度色渐变 + 白色标题(带深色偏移阴影)+ 浅色副标题;禁止黑色圆角条 |
+
+### 19.4 书稿引用模式(新模式)
+
+D14 首次实践了"从书稿选主题"的创作模式:
+
+```
+1. 查阅 book/目录 → 选定书稿章节(第6章 行)
+2. 找开篇金句作为钩子("对着外人笑一天,推开家门脸就垮了")
+3. 提取核心概念(家庭和谐三原色、三明治沟通法、目标停止法)
+4. 按小红书5段式结构改写
+5. 标注参考来源(不直接写"书稿第6章",语言自然融入)
+```
+
+---
+
+## 20. 反常识标题与情绪驱动(2026-07-30 从热帖分析+心理学研究)
+
+### 20.1 核心发现
+
+> **爆款的内容不是"有用",是"让人想说'原来如此'"。**
+
+从 D14 的迭代和 小红书 热帖分析中,总结了最有力的标题公式:
+
+| 标题类型 | 公式 | 示例 | 爆款潜力 |
+|----------|------|------|---------|
+| **反常识型** | [常识认知] + 但其实[相反结论] | "对外人客气,是因为不在乎" | ⭐⭐⭐⭐⭐ |
+| **认知冲突型** | [人人知道的事] + [你不知道的原因] | "越在乎的人,越容易受伤" | ⭐⭐⭐⭐ |
+| **情绪共鸣型** | [场景] + [直击内心的话] | "你对外人笑一天,回家脸就垮了" | ⭐⭐⭐ |
+| **数据冲击型** | [数字] + [反差事实] | "78%的孩子觉得爸妈不关心自己" | ⭐⭐⭐⭐ |
+
+### 20.2 为什么"反常识"最有效
+
+从心理学研究和小红书热帖分析,结论一致:
+
+| 心理学原理 | 说明 | 在标题中的应用 |
+|-----------|------|---------------|
+| **认知失调** | 新信息与已有认知冲突时,大脑会主动寻求解释 | "对外人客气,是因为不在乎"——打破"礼貌=修养好"的认知 |
+| **好奇心缺口** | 知道"是什么"但不清楚"为什么"时,会忍不住点开 | "为什么越在乎的人,越容易被你伤害" |
+| **社会神经共振** | 读到"另一个自己"的故事时,大脑镜像神经元激活 | 场景钩子:"你有没有过这种时刻——" |
+| **期待落差** | 对家人期待高→失望→愤怒,这个链条是反常识的 | "对陌生人没有期待,所以他做什么你都不失望" |
+
+### 20.3 情绪触发点优先级
+
+从 2026 小红书家生活情绪白皮书和爆款笔记分析,最高频的情绪触发点:
+
+| 优先级 | 情绪 | 触发方式 | 适合维度 |
+|--------|------|---------|---------|
+| 1 | **焦虑→解惑** | 抛出焦虑("孩子不听话"),给出反常识答案 | 行/心 |
+| 2 | **内耗→释然** | 描述内耗场景("对家人发火后后悔"),给放下理由 | 心 |
+| 3 | **委屈→被理解** | "不是你一个人这样"的认同感 | 行/心 |
+| 4 | **好奇→原来如此** | 认知冲突+简洁解释 | 智/富 |
+| 5 | **愧疚→可改变** | "不是你坏,是大脑在保护你" | 身/心 |
+
+### 20.4 标题决策流程
+
+```
+写标题前,先问三个问题:
+1. 这个标题,我自己作为用户有强烈点击欲吗?
+2. 标题里有一个"反常识"或"认知冲突"吗?
+3. 看完标题,用户会想"为什么"吗?
+
+如果三个答案都是"是" → 好标题
+如果有一个"否" → 重写
+```
+
+### 20.5 已验证的爆款链条
+
+```
+对外人客气 → 是因为不在乎(反常识,认知冲突)
+↓
+为什么? → 期待落差(越在乎越失望)
+↓
+怎么办? → 目标停止法 + 三明治沟通法
+↓
+行动 → 把"你应该"换成"谢谢你"
+```
+
+**链条关键**:每一句都让读者有"原来如此"的顿悟感,而不是"我知道"的重复感。
+
+---
+
+## 21. 内容发布计划(2026-07-30 更新)
+
+### 21.1 当前进度
+
+| 轮次 | 集次 | 内容 | 维度 | 状态 |
+|------|------|------|------|------|
+| 第1-2轮 | ①-⑩ | 启动篇+打卡篇 | 身·智·富·行·心 | 已发布(9篇) |
+| **第3轮** | **⑪-⑮** | **证据共展篇** | **身·智·富·行·心** | **草稿箱(4篇)** |
+| 第4轮 | ⑯-⑳ | 角色补全篇 | 身·智·富·行·心 | 未开始 |
+| 第5轮 | ㉑-㉕ | 扩散篇 | 身·智·富·行·心 | 未开始 |
+| 第6轮 | ㉖-㉚ | 社群篇 | 身·智·富·行·心 | 未开始 |
+
+### 21.2 草稿箱待发布清单
+
+| 编号 | 标题 | 维度 | 字数 | 建议发布时间 |
+|------|------|------|------|-------------|
+| D11 | 睡好两周后脑子真的变快了 | 身 | 793 | 待定 |
+| D12 | 词穷到会说,只差这14天 | 智 | 798 | 待定 |
+| D13 | 存钱第一步,不是记账,是看见 | 富 | 652 | 待定 |
+| D14 | 对外人客气,是因为不在乎 | 行 | 751 | 待定 |
+| D15 | (心维度,书稿第7章) | 心 | — | 待创作 |
+
+### 21.3 下一步建议
+
+```
+优先级:
+1. 优先从草稿箱发布 D11-D14(按 身→智→富→行 顺序)
+2. 补 D15(心维度,参考书稿第7章"大爱三境界")
+3. 完成第3轮后,评估数据再决定第4轮方向
+4. 补数据追踪(D1-D9 的历史数据 + D11-D14 发布后数据)
+
+⚠️ 关键缺口:数据追踪至今为0,发布前必须先建立追踪机制
+```
+
+### 21.4 30天路线图(更新版)
+
+基于实际进度,调整后的路线:
+
+```
+第1周:发布 D11-D14(4篇,隔天发)
+第2周:创作+发布 D15(心维度),补数据追踪
+第3周:评估前10篇数据,决定第4轮方向
+第4周:启动第4轮(⑯-⑳),调整选题策略
+```
+
+---
+
+---
+
+## 22. 运营数据追踪(2026-07-30 首次拉取)
+
+### 22.0 核心问题改善方案(总纲)
+
+基于数据发现的4个核心问题,按优先级给出具体改善方案:
+
+| 优先级 | 问题 | 当前值 | 健康值 | 改善杠杆 |
+|--------|------|--------|--------|---------|
+| 🔴 P0 | 互动率 | 0.2% | ≥5% | 修改评论区钩子,零成本 |
+| 🔴 P0 | 收藏率 | 1.2 | ≥50 | 内容结构加"可收藏"段落 |
+| 🟡 P1 | 观看时长 | 16s | ≥30s | 开头3句重写,制造冲突 |
+| 🟢 P2 | 涨粉 | 0.1/篇 | ≥10/篇 | 每篇加关注理由 |
+
+### 22.0.1 改善一:开头3句制造冲突(提升观看时长)
+
+**问题**:当前平均观看16s,用户只看前1-2段就划走。原因是开头太平——用"你有没有过这种时刻"开头,虽然共鸣但不够尖锐。
+
+**改善方案**:每篇开头必须在前3句话内完成"冲突制造"。
+
+```
+❌ 旧写法(太慢):
+"你有没有过这种时刻——对着外人笑了一整天,推开家门的那一秒,脸就垮下来了。"
+
+✅ 新写法(前3句直接冲突):
+"你在外面脾气好,不是因为你修养好,是因为你不在乎。
+跟陌生人你客客气气,因为你不在乎他怎么看你。
+但回到家,孩子多叫两声你就烦了——因为你在乎,所以期待,期待落空就是愤怒。"
+```
+
+**核心原则**:第1句给结论(反常识/争议性),第2句给解释,第3句拉回读者自身。**不要在开头铺垫场景,直接给结论。**
+
+**3秒吸引力检查清单**(每篇写完自查):
+```
+□ 第1句:是一个"反常识"或"争议性"结论,不是场景描述
+□ 第2句:解释为什么,不是继续铺垫
+□ 第3句:回到读者身上,让他觉得"说的是我"
+□ 如果3句内没有制造冲突 → 重写开头
+```
+
+### 22.0.2 改善二:评论区钩子改造(提升互动率)
+
+**问题**:当前评论区钩子太泛——"来评论区告诉我,你陪了多久"——读者读完没有动力回复。
+
+**改善方案**:评论区钩子必须有"三个要素"——具体、低门槛、有回应感。
+
+```
+❌ 旧钩子(太泛):
+"来评论区告诉我,你陪了多久"
+"来评论区告诉我,你换了什么"
+
+✅ 新钩子(具体+低门槛+回应感):
+"第1天打卡的姐妹,在评论区打'1',我明天来回你"
+"做到的打1,没做到的打2,我看看有多少人"
+"今天试了的评论区集合,我一个个回"
+"你家的温度计打几分?1-10,评论区告诉我"
+```
+
+**评论区钩子公式**:
+
+```
+[具体动作] + [低门槛] + [回应承诺]
+
+示例:
+"第1天打卡"    +   "打'1'"    +   "我明天来回你"
+"你打几分"     +   "1-10"     +   "评论区告诉我"
+"今天试了"     +   "集合"     +   "我一个个回"
+```
+
+**禁止**:
+- ❌ "评论区告诉我"——太泛,读者不知道说什么
+- ❌ "你做到了吗"——读者懒得想
+- ❌ "分享你的故事"——门槛太高
+
+**必须**:
+- ✅ 给一个判断题:打1或打2
+- ✅ 给一个数字:1-10打分
+- ✅ 给一个关键词:打"打卡"
+- ✅ 加回应承诺:我明天回你 / 我一个个回
+
+### 22.0.3 改善三:内容加"可收藏"段落(提升收藏率)
+
+**问题**:纯叙事内容读完就过了,没有"值得存下来反复用"的东西。
+
+**改善方案**:每篇至少有一个"可收藏"元素——清单、步骤、公式、模板。
+
+```
+❌ 旧结构:场景 → 数据 → 方法 → CTA
+用户看完:哦,知道了 → 划走
+
+✅ 新结构:场景 → 冲突 → 方法 → 清单 → CTA
+                  ↓
+            插入"可收藏"段落
+```
+
+**可收藏元素的4种形式**:
+
+| 形式 | 示例 | 适合场景 |
+|------|------|---------|
+| **清单体** | "3个步骤/5个方法/7天计划" | 智/行维度 |
+| **对比表** | "之前→之后" 对比清单 | 身/富维度 |
+| **公式** | "一句话公式" 如"肯定+建议+收尾" | 行/心维度 |
+| **模板** | "你直接复制这段话去说" | 心/行维度 |
+
+**具体写法**:
+
+```
+✅ 清单体:
+"记住这3步就够了:
+第一步:肯定("你今天自己写完了作业,真棒")
+第二步:建议("客厅能不能收拾一下")
+第三步:收尾("弄完妈妈陪你玩一会儿")"
+
+✅ 模板:
+"直接复制这段话去说:
+'你今天自己写完了作业,真棒。
+另外客厅能不能收拾一下,我们一起弄。
+弄完妈妈陪你玩一会儿。'"
+
+✅ 对比表:
+"之前:'你怎么又把客厅弄这么乱'
+之后:'你今天自己写完了作业,真棒。另外客厅能不能收拾一下'"
+```
+
+**收藏率自检**:
+```
+写完后问自己:读者看完这篇,会不会截图或收藏?
+如果答案是不会 → 加一个清单/模板/公式
+```
+
+### 22.0.4 改善四:每篇加关注理由(提升涨粉)
+
+**问题**:9篇涨1粉,因为没有给读者"关注你"的理由。
+
+**改善方案**:在文章结尾或开头,加入"关注钩子"。
+
+```
+❌ 旧结尾:
+"今晚试试。来评论区告诉我,你换了什么。"
+
+✅ 新结尾(加关注理由):
+"关注我,下周讲:为什么你越是讲道理,孩子越不听。
+今晚先试试,评论区打1,我明天回你。"
+```
+
+**关注钩子的3种类型**:
+
+| 类型 | 话术 | 效果 |
+|------|------|------|
+| **系列预告** | "关注我,下周讲为什么你越讲道理孩子越不听" | 预告未来内容,创造期待 |
+| **身份认同** | "关注我,一起做不吼不叫的妈妈" | 建立身份归属 |
+| **连载感** | "这是第X篇,关注我看完整系列" | 系列化追更 |
+
+**每条文案结尾必须包含**:
+```
+1. 评论区钩子(§22.0.2 公式)
+2. 关注理由(预告/身份/连载)——至少占其一
+```
+
+### 22.0.5 改善示例(用D14改)
+
+```
+❌ D14 v3 当前版本(开头+CTA):
+
+开头:
+"你在外面脾气好,不是因为你修养好,是因为你不在乎。"
+
+CTA:
+"今晚试试。把到嘴边的那句你应该,换成谢谢你。
+来评论区告诉我,你换了什么。"
+
+✅ 改善后版本:
+
+开头(3句冲突):
+"你在外面脾气好,不是因为你修养好,是因为你不在乎。
+对陌生人你客客气气,因为你没有期待——他做什么你都不失望。
+但对家人你急、你气、你烦,恰恰是因为你太在乎了。"
+
+CTA(评论钩子+关注理由):
+"直接复制这句话去用:
+'谢谢你今天自己写了作业'——把"你应该"换成"谢谢你"。
+今晚回去就试,评论区打1,我明天回你。
+关注我,下周讲:为什么你越讲道理,孩子越不听。"
+```
+
+> 数据来源:小红书创作者中心「数据中心」API,2026-07-30 拉取,共 13 篇文章。
+
+### 22.1 全量数据一览
+
+| 排名 | 标题 | 曝光 | 观看 | CTR | 点赞 | 评论 | 收藏 | 分享 | 涨粉 | 观看时长 |
+|------|------|------|------|-----|------|------|------|------|------|---------|
+| 1 | 🏆 老人带娃容易翻脸,分清这3件事就好了 (D9) | 1,572 | 242 | **14.8%** | 3 | 4 | 3 | 0 | 0 | 28s |
+| 2 | 🥈 吼完孩子,试试这个情绪开关 (D5) | 918 | 62 | 6.6% | 6 | 0 | 1 | 3 | 0 | 17s |
+| 3 | 🥉 睡好两周后脑子真的变快了 (D11) | 523 | 30 | 5.7% | 0 | 0 | 2 | 1 | 0 | 6s |
+| 4 | 复盘孩子本周3个进步比报班管用100倍 (D7) | 293 | 18 | 6.2% | 3 | 0 | 1 | 0 | 1 | 8s |
+| 5 | 月入2万的家庭,比想象中穷得更稳 (D3) | 249 | 34 | **13.1%** | 2 | 2 | 1 | 0 | 0 | 18s |
+| 6 | 当妈25年才发现:自己才是给孩子最好的礼物 | 186 | 18 | **9.2%** | 2 | 0 | 0 | 0 | 0 | 22s |
+| 7 | 每月定投1次,比每天看余额管用100倍 (D8) | 184 | 16 | 8.2% | 1 | 0 | 2 | 0 | 0 | 19s |
+| 8 | 词穷到会说,只差这14天 (D12) | 176 | 6 | 3.4% | 1 | 0 | 0 | 0 | 0 | 7s |
+| 9 | 通讯录1493人,凌晨两点没人问 (D4) | 23 | 2 | 5.0% | 2 | 0 | 1 | 0 | 0 | 18s |
+
+### 22.2 关键发现
+
+#### CTR 冠军:D9 "老人带娃"(14.8%)
+- 标题和封面有强吸引力,但互动转化弱(赞3/评4/收3)
+- 说明:**点进去的人多,但内容没留住人**——人均观看28s,文章1073字,读完全文需要2-3分钟
+
+#### 互动冠军:D5 "吼完孩子"(6赞/3分享)
+- 曝光918,是所有文章中第二高
+- 情绪共鸣类内容互动率最高
+- 说明:**心维度内容(情绪管理)最容易引发互动**
+
+#### 最大问题:观看时长普遍偏低
+| 文章 | 观看时长 | 字数 | 读完需时 | 实际观看 |
+|------|---------|------|---------|---------|
+| D9 | 28s | 1073 | ~3min | 不到1/6 |
+| D5 | 17s | ~500 | ~1.5min | 约1/5 |
+| D11 | 6s | 793 | ~2min | 不到1/20 |
+| 平均值 | 16s | ~700 | ~2min | 约1/8 |
+
+**结论:用户平均只看完前1-2段就划走了。** 开头3秒必须抓住注意力。
+
+#### CTR 双高 vs 互动双低
+- D9(14.8% CTR)和 D3(13.1% CTR)封面点击率最高
+- 但 D3 仅 2 赞 2 评,D9 仅 3 赞 4 评
+- 说明:**标题/封面吸引人≠内容留住人**——内容的前3段必须承接标题的承诺
+
+### 22.3 维度表现对比
+
+| 维度 | 代表文章 | 平均曝光 | 平均CTR | 平均互动 |
+|------|---------|---------|---------|---------|
+| 身 | D11(睡好两周) | 523 | 5.7% | 0.3 |
+| 智 | D7(复盘)+D12(词穷) | 235 | 4.8% | 1.0 |
+| 富 | D3(月入2万)+D8(定投) | 217 | 10.7% | 1.5 |
+| 行 | D4(通讯录)+D9(老人带娃) | 798 | 9.9% | 2.3 |
+| 心 | D5(吼完孩子) | 918 | 6.6% | 3.0 |
+
+**行维度(家庭关系)曝光最高,心维度(情绪管理)互动最高。**
+
+### 22.4 数据 vs 健康值对比
+
+| 指标 | 健康值 | 当前最佳 | 当前平均 | 差距 |
+|------|--------|---------|---------|------|
+| 曝光量(24h) | ≥1000 | 1,572(D9) | 458 | 仅D9达标 |
+| CTR | ≥8% | 14.8%(D9) | 8.0% | 5篇达标 |
+| 互动率 | ≥5% | ~0.6% | ~0.2% | ❌ 严重不足 |
+| 收藏量 | ≥50 | 3 | 1.2 | ❌ 严重不足 |
+| 评论数 | ≥15 | 4 | 0.7 | ❌ 严重不足 |
+| 涨粉 | ≥10 | 1 | 0.1 | ❌ 严重不足 |
+
+**核心问题:互动率是健康值的 1/25。** 内容被看到,但没人互动。
+
+### 22.5 改进方向
+
+| 问题 | 数据 | 改进方向 |
+|------|------|---------|
+| 观看时长短 | 平均16s | 开头3句必须制造悬念/冲突,不要铺垫 |
+| 互动率低 | 0.2% vs 5%健康值 | 评论区钩子要更具体:"来评论区告诉我,你陪了多久"→"第1天打卡的姐妹,我明天回你" |
+| 收藏率低 | 均1.2 vs 50健康值 | 内容要有"可收藏反复用"的价值,加清单/表格/模板 |
+| 涨粉为0 | 9篇仅涨1粉 | 缺少"关注理由"——每篇结尾加一句"关注我,下周继续聊" |
+
+---
+
+## 23. 本地内容 vs 线上内容核对(2026-07-30)
+
+### 23.1 核对方法
+
+通过小红书创作者中心 API 获取已发布笔记的线上标题和正文,与本地 `运营文案/小红书内容/` 中对应的草稿文件进行对比。
+
+### 23.2 已核对文章
+
+| 编号 | 线上标题 | 本地标题 | 是否一致 |
+|------|---------|---------|---------|
+| D3 | 月入2万的家庭,比想象中穷得更稳 | 购物车里躺着一个三天不会再看的东西 | ❌ 标题不同 |
+| D4 | 通讯录1493人,凌晨两点没人问 | 通讯录里1493人,凌晨两点却没人问 | ✅ 一致 |
+| D5 | 吼完孩子,试试这个情绪开关 | 吼完孩子,试试这个情绪开关 | ✅ 一致 |
+| D7 | 复盘孩子本周3个进步比报班管用100倍 | 复盘孩子本周3个进步比报班管用100倍 | ✅ 一致 |
+| D8 | 每月定投1次,比每天看余额管用100倍 | 每月定投1次比每天看余额管用 | ✅ 一致 |
+| D9 | 老人带娃容易翻脸,分清这3件事就好了 | 老人带娃容易翻脸分清这3件事就好了 | ✅ 一致 |
+| D11 | 睡好两周后脑子真的变快了 | 睡好两周后脑子真的变快了 | ✅ 一致 |
+| D12 | 词穷到会说,只差这14天 | 词穷到会说,只差这14天 | ✅ 一致 |
+
+**结论:D3 标题已更换。** 线上标题为"月入2万的家庭,比想象中穷得更稳",本地仍为"购物车里躺着一个三天不会再看的东西"——说明发布前或发布后人工修改了标题。以线上为准,更新本地文件。
+
+### 23.3 更新操作
+
+以下文件已更新为线上版本(标题+正文以线上发布为准):
+
+| 文件 | 更新项 |
+|------|--------|
+| `运营文案/小红书内容/第三篇-购物车里躺着一个不再看的东西.md` | 标题改为"月入2万的家庭,比想象中穷得更稳" |
+| `README.md` 对照表 | D3 标题更新 |
+
+## 24. 小红书→书 预热策略(2026-08-01)
+
+### 24.1 核心定位
+
+> 小红书不是终点,是书的**选题测试场**和**流量蓄水池**。
+
+每篇小红书文章 = 一个书稿章节的"市场测试"。通过数据验证哪些角度值得在书里放大,哪些角度需要放弃。
+
+### 24.2 数据验证结果(截至2026-08-01)
+
+| 书稿章节 | 对应小红书 | 曝光 | CTR | 验证结论 | 书稿调整建议 |
+|----------|-----------|------|-----|---------|-------------|
+| **第6章 行**(人际和谐) | D9 老人带娃 | **1,645** | **15.0%** | ✅ 家庭关系是最大流量入口 | 第6章增"老人带娃"专题篇幅 |
+| **第7章 心**(大爱相随) | D5 吼完孩子 | 921 | 6.6% | ✅ 情绪管理互动最高 | 第7章"情绪停机坪"详写 |
+| **第5章 富**(利他创富) | D13 存钱第一步 | 608 | 8.2% | ✅ 家庭财务有潜力 | 第5章增"记账→看见"案例 |
+| **第3章 身**(主动健康) | D11 睡好两周 | 531 | 5.7% | ⚠️ 曝光不错但观看仅6s | 开头需更抓人,书稿第3章增"睡眠"开头冲突 |
+| **第4章 智**(赋能未来) | D12 词穷到会说 | 195 | 3.1% | ❌ 词汇类关注度低 | 第4章减少"词汇量"篇幅,聚焦"学习方法" |
+| **第6章 行**(亲子沟通) | D14 对外人客气 | 定时中 | — | ⏳ 待观察 | 反常识标题已验证,书稿第6章增"期待落差"概念 |
+| **第7章 心**(爱的语言) | D15 老人带娃·爱的语言 | 草稿箱 | — | ⏳ 待观察 | 系列化方向验证中 |
+
+### 24.3 五维流量排名(为书排序)
+
+```
+🥇 行(家庭关系)→ 曝光最高,CTR最高 → 书稿第6章应加篇幅
+🥈 心(情绪管理)→ 互动最高,黏性最强 → 书稿第7章应加案例
+🥉 富(家庭财务)→ 新发即冲到第3 → 书稿第5章有潜力
+④ 身(主动健康)→ 有曝光但内容没留住人 → 书稿第3章开头需重写
+⑤ 智(学习能力)→ 关注度最低 → 书稿第4章需调整角度
+```
+
+### 24.4 书稿标题参考(来自小红书标题测试)
+
+| 小红书标题 | CTR | 可迁移到书稿章节标题的公式 |
+|-----------|-----|--------------------------|
+| 老人带娃容易翻脸,分清这3件事就好了 | 15.0% | 场景痛点 + 数字 + 解决方案 |
+| 对外人客气,是因为不在乎 | 定时中 | 反常识 + 认知冲突 |
+| 存钱第一步,不是记账,是看见 | 8.2% | 否定常识 + 新角度 |
+| 吼完孩子,试试这个情绪开关 | 6.6% | 场景 + 动作指令 |
+
+### 24.5 预热节奏建议
+
+```
+出版前6个月:
+  小红书持续发布,重点测试第6章(行)和第7章(心)的不同角度
+  每篇记录数据,建立"数据→书稿"反馈循环
+
+出版前3个月:
+  开始在小红书植入"家的算法"概念(非广告,自然融入)
+  收集高互动评论,作为书稿的读者声音案例
+
+出版时:
+  小红书发布"新书上市"预告
+  利用已积累的粉丝基础做首发转化
+```
+
+| 篇目 | 线上修改时间 | 本地最后修改 | 差异 |
+|------|------------|------------|------|
+| D3 月入2万 | 2026-07-27 | 2026-07-25 | 标题已改 |
+| 其他 | 首次发布 | 与本地一致 | 无差异 |
+
+---
+
+> **版本记录**:v10 → 2026-08-01 书稿预热策略更新:
+> - 更新 §1.1 已发布内容概览(含 D11-D15 草稿箱)
+> - 更新 §5 内容生产节奏(实际进度)
+> - 新增 §19 D11-D14 创作经验沉淀
+> - 新增 §20 反常识标题与情绪驱动(热帖分析+心理学研究)
+> - 新增 §21 内容发布计划更新(含30天路线图)
+> - **新增 §22 运营数据追踪(首次拉取,含9篇曝光/CTR/互动数据)**
+> - **§22.0 核心问题改善方案(4个具体改善项:冲突开头/评论区钩子/可收藏段落/关注理由)**
+> - **新增 §23 本地 vs 线上内容核对(D3 标题已修改,以线上为准)**
+> - **新增 §24 小红书→书 预热策略(含数据验证结果、五维流量排名、书稿标题参考)**
+> - **更新 §18 书稿参考(双向使用:书→小红书素材,小红书→书数据反馈)**
+
 
 
 

+ 0 - 0
运营文案/小红书内容/第三篇-购物车里躺着一个不再看的东西.md → 运营文案/小红书内容/第三篇-月入2万的家庭比想象中穷得更稳.md