Browse Source

modified: majiyong/majiyong-closing-report.html
modified: majiyong/majiyong-closing-report.md
modified: majiyong/scripts/gen-majiyong-closing-render.js
modified: majiyong/scripts/gen-majiyong-closing-report.js
modified: shuhua/scripts/gen-shuhua-closing-report.js
modified: shuhua/shuhua-closing-report.html
modified: shuhua/shuhua-closing-report.md

Yi Jiarui 4 months ago
parent
commit
30e685c3c1

File diff suppressed because it is too large
+ 750 - 225
majiyong/majiyong-closing-report.html


+ 19 - 19
majiyong/majiyong-closing-report.md

@@ -1,6 +1,6 @@
 # 马记永 · 四月「新鲜菜」KOL/KOC 宣发结案报告
 
-> **投放期间**: 2026-04 · **生成时间**: 2026-05-14 11:22:23  
+> **投放期间**: 2026-04 · **生成时间**: 2026-05-14 13:10:45  
 > **数据范围**: 293 篇报备笔记 (KOL 12 + KOC 281) + 1682 条公开评论 (覆盖 233/293 篇)
 
 ---
@@ -156,24 +156,24 @@
 | 复购/推荐/回头客 | 11 | 0.7% | [武花追花花@江西] 味道很好 经常去吃[doge] |
 | 竞品提及 | 0 | 0.0% | - |
 
-### 真实评论原声 Top 16 (剔除噪声)
-
-- **[蜡笔小严的手工/手工类]** `-@湖北 · 浙江` *(赞 17)*: 对不起,,,这个盒子真的像二郎神的美瞳盒(
-- **[追更联名鸭(资讯版)/预热资讯]** `-@贵州 · 广东` *(赞 5)*: 好可惜我们这边好像没有😭
-- **[iFeng/美食探店]** `-@上海 · 北京` *(赞 5)*: 看着作者从9000多掉到2000终于接到广子了好开心[完啦R]
-- **[蜡笔小严的手工/手工类]** `蜡笔小严的手工@- · 浙江` *(赞 5)*: 哈哈哈 其实是眼影/口红的分装盒
-- **[追更联名鸭(资讯版)/预热资讯]** `-@广东 · 广东` *(赞 4)*: 速速传下去[派对R][派对R][派对R]
-- **[追更联名鸭(资讯版)/预热资讯]** `星期八联名(资讯版)@- · 广东` *(赞 4)*: 
-- **[追更联名鸭(资讯版)/预热资讯]** `蜡笔小新@- · 广东` *(赞 4)*: 强烈建议也开到我这里来!!!
-- **[武花追花花/美食探店]** `武花追花花@- · 湖北` *(赞 4)*: 马记永
-- **[iFeng/美食探店]** `-@安徽 · 北京` *(赞 3)*: 一看这时间一了,我就说这么便宜[色色R]
-- **[iFeng/美食探店]** `-@浙江 · 北京` *(赞 3)*: 恭喜接广
-- **[iFeng/美食探店]** `iFeng@- · 北京` *(赞 2)*: 太感谢了[飞吻R][飞吻R][飞吻R]
-- **[欣宝儿吃不回本/美食探店]** `-@上海 · 上海` *(赞 2)*: 有具体活动介绍吗?什么报纸都可以?
-- **[啾妈的手工日记/手工]** `-@广东 · 广东` *(赞 2)*: 你好,你的手能借我用用吗?
-- **[武花追花花/美食探店]** `武花追花花@- · 湖北` *(赞 2)*: 没错[笑哭R] 很美味[害羞R]
-- **[武花追花花/美食探店]** `武花追花花@- · 湖北` *(赞 2)*: 是的[笑哭R]
-- **[武花追花花/美食探店]** `-@上海 · 湖北` *(赞 2)*: 吃过很多次,菜都很新鲜[偷笑R]
+### 真实评论原声 Top 16 (产品强相关 · 多主题轮询)
+
+- **[口味体验]** `佳芮@广东`: 小甜水配凉拌菜。不错的活动耶
+- **[产品创新]** `武花追花花@上海`: 吃过很多次,菜都很新鲜[偷笑R]
+- **[门店开店]** `追更联名鸭(资讯版)@贵州`: 好可惜我们这边好像没有😭
+- **[健康营养]** `蜜桃薄荷@陕西`: 好健康啊看着
+- **[价格性价比]** `iFeng@安徽`: 一看这时间一了,我就说这么便宜[色色R]
+- **[活动机制]** `快乐小马寻宝记@广东`: 我看别人用花也换到了,真好啊  下班路上免费吃个菜再回家[萌萌哒R]
+- **[场景外带]** `大Kk@辽宁`: 黄瓜兑换完打包,晚上下🍺[偷笑R]
+- **[复购推荐]** `武花追花花@湖南`: 好好好,我去尝一下
+- **[品牌情感]** `xxxxx@上海`: 马记永这么好啊!
+- **[口味体验]** `蜜桃薄荷@江苏`: 他们家居然出拌菜了!
+- **[产品创新]** `武花追花花@福建`: 感觉很新鲜很美味,下次去尝尝
+- **[门店开店]** `追更联名鸭(资讯版)@-`: 强烈建议也开到我这里来!!!
+- **[健康营养]** `肥猫爱吃草莓🍓@广东`: 外卖也有吗 很健康
+- **[价格性价比]** `checheai@福建`: 这里贵不贵 三个人大概消费多少啊
+- **[活动机制]** `欣宝儿吃不回本@上海`: 有具体活动介绍吗?什么报纸都可以?
+- **[场景外带]** `尝尝玩玩逛逛@上海`: 他家真不错 打工人食堂[笑哭R]
 
 ---
 

+ 154 - 34
majiyong/scripts/gen-majiyong-closing-render.js

@@ -55,10 +55,82 @@ module.exports = function render(M) {
     </tr>`;
     }).join('');
 
-    const realComments = allComments.filter((c) => !/互赞|互助|加油.*互|可以.*点赞|点赞.*返|蹲.*搭子|互粉/.test(c.content));
-    const realCommentList = realComments.sort((a, b) => b.like - a.like).slice(0, 16).map((c) => `
+    // 真实评论筛选 v4: 7 层过滤 + 产品强相关硬约束 + 主题多样性轮询
+    const NOISE_RE = /互赞|互助|加油.*互|可以.*点赞|点赞.*返|蹲.*搭子|互粉/;
+    const OFFTOPIC_RE = /眼影|口红|睫毛|化妆|包包|分装|借我|借用|手能借|护肤|穿搭|开箱|美术生|画的|画得|画风|笔法|插画|手工|盒子.*像/;
+    const PROMO_RE = /推广|求关注|求互|私信|加微|商务合作|接广告|涨粉/;
+    const SHILL_RE = /宝子|亲测|无套路|必.{0,2}冲|绝绝子|拉满|薅羊毛|薅得|放心冲|闭眼冲|爆棚|颜值直接|快冲|姐妹.{0,3}冲|实力宠粉|超(级|绝|香)|爆款|出圈|0元购|0元薅|真香|yyds|YYDS|惊艳到|跺脚/;
+    const META_KOL_RE = /博主|up主|UP主|作者|接广|涨粉|掉粉|播放|粉丝.*多|9000.*掉.*\d|完啦R/;
+    const EMOJI_HEAVY_RE = /(🥬|🥢|🌿|🤩|💯|🔥|💥|✅|💦|📸|🥳|🥞|🛒|🍣|🎉|✨|💚|❗|‼️)/g;
+    const stripDeco = (s) => s.replace(/\[[^\]]+\]/g, '').replace(/[@#][^\s@#]+/g, '').replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '');
+
+    // 产品强相关词典: 9 主题,评论必须命中至少 1 个才算 VOC 有效
+    const PRODUCT_TOPICS = {
+        '口味体验': /好吃|难吃|味道|香|辣|咸|淡|腻|清爽|清甜|甜杆|西兰|拌|脆|嫩|爽口|入味/,
+        '产品创新': /新菜|新鲜|鲜菜|凉拌|凉菜|拌菜|不过夜|当天|现做|现拌|出.{0,3}菜|上.{0,3}菜/,
+        '门店开店': /开店|分店|开到|什么时候.*开|建议.*开|我们这.*没|这边.*没|本地.*有|哪里有店|店在哪/,
+        '健康营养': /健康|减脂|低脂|营养|蔬菜|清淡|0负担|低卡/,
+        '价格性价比': /便宜|划算|实惠|贵|价格|性价比|套餐|¥/,
+        '活动机制': /换菜|换券|换免费|带.*换|带.*能换|花.*换|报纸|活动.*介绍|活动.*在哪|怎么参与|怎么换|领券|领劵/,
+        '场景外带': /外带|打包|下酒|带回家|带走|外卖|食堂|带娃|带朋友/,
+        '复购推荐': /常去|经常.*吃|经常.*去|每次|又来|回头|推荐|尝尝|去试|去尝/,
+        '品牌情感': /马记永.*好|马记永.*爱|爱.*马记永|喜欢.*马记永|马记永.*绝/,
+    };
+    const PRODUCT_RE = new RegExp(Object.values(PRODUCT_TOPICS).map((r) => r.source).join('|'));
+
+    const realComments = allComments.filter((c) => {
+        const txt = c.content || '';
+        if (c.nick && c.koc && c.nick === c.koc) return false; // 博主自评
+        // @ 别人开头的回复 = 缺乏上下文 (除非内容本身够长够独立)
+        if (/^\s*@/.test(txt) && stripDeco(txt.replace(/^\s*@[^\s@#]+/, '')).length < 20) return false;
+        if (NOISE_RE.test(txt) || OFFTOPIC_RE.test(txt) || PROMO_RE.test(txt) || SHILL_RE.test(txt) || META_KOL_RE.test(txt)) return false;
+        const emojis = txt.match(EMOJI_HEAVY_RE) || [];
+        if (emojis.length >= 3) return false;
+        const core = stripDeco(txt);
+        if (core.length < 6) return false;
+        if (core.length > 80 && emojis.length >= 1) return false;
+        if (core.length > 120) return false;
+        if (!PRODUCT_RE.test(txt)) return false; // 硬约束: 必须产品相关
+        return true;
+    });
+
+    // 按主题分桶 (只归首个匹配主题)
+    const buckets = {};
+    for (const tag of Object.keys(PRODUCT_TOPICS)) buckets[tag] = [];
+    for (const c of realComments) {
+        for (const [tag, re] of Object.entries(PRODUCT_TOPICS)) {
+            if (re.test(c.content)) { buckets[tag].push(c); break; }
+        }
+    }
+    // 排序: 点赞降序;同点赞按"信息量"降序 (产品关键词命中数 + 内容长度)
+    const informationScore = (c) => {
+        let hits = 0;
+        for (const re of Object.values(PRODUCT_TOPICS)) if (re.test(c.content)) hits++;
+        const core = stripDeco(c.content);
+        return hits * 20 + core.length;
+    };
+    for (const tag of Object.keys(buckets)) {
+        buckets[tag].sort((a, b) => (b.like - a.like) || (informationScore(b) - informationScore(a)));
+    }
+
+    // 主题轮询: 先每主题 Top 2,补到 16
+    const topPicks = [];
+    const queues = Object.entries(buckets).map(([tag, list]) => ({ tag, list, idx: 0 }));
+    for (let round = 0; round < 4 && topPicks.length < 16; round++) {
+        for (const q of queues) {
+            if (topPicks.length >= 16) break;
+            if (q.idx < q.list.length && q.idx < round + 1) {
+                topPicks.push({ topic: q.tag, c: q.list[q.idx] });
+                q.idx++;
+            }
+        }
+    }
+    realComments.length = 0;
+    realComments.push(...topPicks.map((p) => p.c));
+
+    const realCommentList = topPicks.map(({ topic, c }) => `
 <div class="quote">
-  <div class="quote-meta"><span class="tag">${esc(c.koc)}</span> <span class="text-xs text-3">${esc(c.type || '')} · ${esc(c.ip || '')} · ${esc(String(c.region || '').slice(0, 3))} · 赞 ${c.like}</span></div>
+  <div class="quote-meta"><span class="tag green">${esc(topic)}</span> <span class="tag gray">${esc(c.koc)}</span> <span class="text-xs text-3">${esc(c.ip || '')}</span></div>
   <div class="quote-text">${esc(c.content.replace(/\n/g, ' '))}</div>
 </div>`).join('');
 
@@ -102,17 +174,17 @@ section::before { content: attr(data-num); position: absolute; top: 32px; right:
 .grid { display: grid; gap: 22px; }
 .grid-2 { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }
 .grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
-.grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
+.grid-4 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
 .card { background: linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0.005) 100%), var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 28px; transition: transform 0.3s, border-color 0.3s; }
 .card:hover { transform: translateY(-3px); border-color: var(--border-strong); }
 .card-accent { border-left: 3px solid var(--amber); }
 .card-green { border-left: 3px solid var(--green); }
 .card-rose { border-left: 3px solid var(--rose); }
 .card-blue { border-left: 3px solid var(--blue); }
-.metric { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 28px; position: relative; overflow: hidden; }
+.metric { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 24px; position: relative; overflow: hidden; min-width: 0; }
 .metric::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, var(--amber), transparent); opacity: 0.6; }
 .metric-label { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--text-3); margin-bottom: 10px; }
-.metric-value { font-family: var(--font-head); font-weight: 800; font-size: clamp(2rem, 3.6vw, 3rem); letter-spacing: -0.03em; line-height: 1; }
+.metric-value { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.6rem, 2.6vw, 2.3rem); letter-spacing: -0.03em; line-height: 1.05; word-break: break-all; }
 .metric-unit { font-family: var(--font-mono); font-size: 0.85rem; color: var(--amber); font-weight: 500; margin-left: 4px; }
 .metric-sub { margin-top: 14px; font-size: 0.82rem; color: var(--text-2); line-height: 1.5; }
 .tag { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 4px; font-size: 0.72rem; font-weight: 500; background: rgba(245,166,35,0.1); color: var(--amber); border: 1px solid rgba(245,166,35,0.22); }
@@ -264,8 +336,8 @@ td.sample { color: var(--text-2); font-size: 0.82rem; max-width: 380px; }
       </div>
     </div>
 
-    <h3 class="h2">真实评论原声 (Top 16 by 点赞)</h3>
-    <p class="sub">已剔除互赞互助噪声,展示具有产品对话价值的真实评论。</p>
+    <h3 class="h2">真实评论原声 (Top 16)</h3>
+    <p class="sub">产品强相关 · 多主题轮询 · 已剔除噪声/托式营销/博主自评,展示具有产品对话价值的真实评论。</p>
     <div class="grid grid-2">${realCommentList}</div>
   </div>
 </section>
@@ -368,33 +440,81 @@ td.sample { color: var(--text-2); font-size: 0.82rem; max-width: 380px; }
       }).join('')}
     </div>
 
-    <h3 class="h2">完整 ${OPPORTUNITIES.length} 个新机会矩阵</h3>
-    <p class="sub">按 5 大象限分类: <span class="tag" style="margin-right:8px">A 产品卖点</span><span class="tag green" style="margin-right:8px">B 内容形态</span><span class="tag purple" style="margin-right:8px">C 人群渠道</span><span class="tag blue" style="margin-right:8px">D 投放机制</span><span class="tag rose">E 数据机制</span></p>
-
-    <div class="grid grid-2">
-      ${['A · 产品卖点','B · 内容形态','C · 人群渠道','D · 投放机制','E · 数据机制'].map((cat) => {
-          const list = OPPORTUNITIES.filter((o) => o.cat === cat);
-          const colorClass = cat.startsWith('A') ? 'card-accent' : cat.startsWith('B') ? 'card-green' : cat.startsWith('C') ? '' : cat.startsWith('D') ? 'card-blue' : 'card-rose';
-          const tagClass = cat.startsWith('A') ? '' : cat.startsWith('B') ? 'green' : cat.startsWith('C') ? 'purple' : cat.startsWith('D') ? 'blue' : 'rose';
-          return `<div class="card ${colorClass}">
-            <h3 class="h2" style="margin-top:0;margin-bottom:18px">${esc(cat)}</h3>
-            ${list.map((o) => `
-              <div style="padding:14px 0;border-bottom:1px solid var(--border)">
-                <div style="display:flex;gap:8px;align-items:center;margin-bottom:6px;flex-wrap:wrap">
-                  <span class="tag ${tagClass}" style="font-family:var(--font-mono)">${o.id}</span>
-                  <span class="tag ${o.p === 'P0' ? 'rose' : o.p === 'P1' ? '' : 'purple'}">${o.p}</span>
-                  <strong style="font-size:0.96rem">${esc(o.t)}</strong>
-                </div>
-                <p style="color:var(--text-3);font-size:0.74rem;margin-bottom:4px">📍 ${esc(o.signal)}</p>
-                <p style="color:var(--text-2);font-size:0.84rem;line-height:1.6">→ ${esc(o.action)}</p>
-              </div>
-            `).join('')}
-          </div>`;
-      }).join('')}
+    <p class="sub" style="margin-top:32px">完整 ${OPPORTUNITIES.length} 个新机会按 5 大象限分独立章节深度展开,见下方 Section 06.A ~ 06.E。</p>
+    <div class="toc" style="margin-top:24px">
+      <a href="#sec-6a" style="border-color:var(--amber);color:var(--amber)">06.A 产品卖点 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('A')).length})</a>
+      <a href="#sec-6b" style="border-color:var(--green);color:var(--green)">06.B 内容形态 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('B')).length})</a>
+      <a href="#sec-6c" style="border-color:var(--purple);color:var(--purple)">06.C 人群渠道 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('C')).length})</a>
+      <a href="#sec-6d" style="border-color:var(--blue);color:var(--blue)">06.D 投放机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('D')).length})</a>
+      <a href="#sec-6e" style="border-color:var(--rose);color:var(--rose)">06.E 数据机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('E')).length})</a>
     </div>
   </div>
 </section>
 
+${(() => {
+    const QUADRANTS = [
+        { letter: 'A', cat: 'A · 产品卖点', color: 'amber', tagClass: '', accent: 'card-accent', desc: '从用户评论里反推的产品/SKU 级机会 — 把"已经被用户说出口"的需求变成可上架的菜单/套餐/卖点。' },
+        { letter: 'B', cat: 'B · 内容形态', color: 'green', tagClass: 'green', accent: 'card-green', desc: '内容打法升级 — 同样的预算,如何用更高 ROI 的内容形态,把好的东西讲得更让人记得住。' },
+        { letter: 'C', cat: 'C · 人群渠道', color: 'purple', tagClass: 'purple', accent: '', desc: '人群和渠道的二八优化 — 让每一分预算都投在"会真去吃"的人身上,而不是"看了没法吃"的远方观众。' },
+        { letter: 'D', cat: 'D · 投放机制', color: 'blue', tagClass: 'blue', accent: 'card-blue', desc: '投放过程的机制化 — 把"凭感觉发笔记"变成"算法驱动止损/加投/预警",每一轮都比上一轮更聪明。' },
+        { letter: 'E', cat: 'E · 数据机制', color: 'rose', tagClass: 'rose', accent: 'card-rose', desc: '长效数据资产 — 主题词典、竞品对照,这些是可以持续复用 10 轮投放的底层基建。' },
+    ];
+    return QUADRANTS.map((q) => {
+        const list = OPPORTUNITIES.filter((o) => o.cat === q.cat);
+        return `
+<!-- ============= 6.${q.letter} ${q.cat} ============= -->
+<section id="sec-6${q.letter.toLowerCase()}" data-num="06.${q.letter} / ${q.cat.split('·')[1].trim()}" style="justify-content:flex-start">
+  <div class="inner">
+    <div class="eyebrow" style="color:var(--${q.color})">Section 06.${q.letter} · ${q.cat}</div>
+    <h2 class="h1" style="color:var(--${q.color})">${esc(q.cat)} <span style="color:var(--text-3);font-size:0.5em;font-weight:500">${list.length} 个新机会</span></h2>
+    <p class="sub">${esc(q.desc)}</p>
+
+    <div class="grid" style="gap:28px;margin-top:32px">
+      ${list.map((o, idx) => `
+      <div class="card ${q.accent}" style="position:relative">
+        <div style="position:absolute;top:18px;right:24px;font-family:var(--font-mono);font-size:2.4rem;font-weight:800;color:var(--${q.color});opacity:0.15;line-height:1">${o.id}</div>
+        <div style="display:flex;gap:10px;align-items:center;margin-bottom:14px;flex-wrap:wrap">
+          <span class="tag ${q.tagClass}" style="font-family:var(--font-mono);font-size:0.8rem">${o.id}</span>
+          <span class="tag ${o.p === 'P0' ? 'rose' : o.p === 'P1' ? '' : 'purple'}">${o.p}</span>
+          <h3 style="font-family:var(--font-head);font-size:1.4rem;font-weight:700;letter-spacing:-0.01em">${esc(o.t)}</h3>
+        </div>
+
+        <div class="grid grid-3" style="gap:18px;margin-top:18px">
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">📍 信号 / Signal</div>
+            <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.signal)}</p>
+          </div>
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">🎯 行动 / Action</div>
+            <p style="color:var(--text-1);font-size:0.88rem;line-height:1.65;font-weight:500">${esc(o.action)}</p>
+          </div>
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">� 预期 / Outcome</div>
+            <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.outcome || '-')}</p>
+          </div>
+        </div>
+
+        <div style="margin-top:22px;padding:20px;background:var(--bg-0);border-radius:8px">
+          <div class="metric-label" style="margin-bottom:10px">💡 为什么要做 / Why</div>
+          <p style="color:var(--text-2);font-size:0.92rem;line-height:1.75">${esc(o.why || '-')}</p>
+        </div>
+
+        ${Array.isArray(o.how) && o.how.length ? `
+        <div style="margin-top:18px;padding:20px;background:var(--bg-0);border-radius:8px">
+          <div class="metric-label" style="margin-bottom:12px">🛠️ 如何执行 / How (${o.how.length} 步)</div>
+          <ol style="margin:0;padding-left:24px;color:var(--text-2);font-size:0.9rem;line-height:1.85">
+            ${o.how.map((step) => `<li style="margin-bottom:6px">${esc(step)}</li>`).join('')}
+          </ol>
+        </div>
+        ` : ''}
+      </div>
+      `).join('')}
+    </div>
+  </div>
+</section>`;
+    }).join('');
+})()}
+
 <!-- ============= 页脚 ============= -->
 <section style="min-height:auto;padding:60px 24px;background:var(--bg-1)" data-num="END">
   <div class="inner" style="text-align:center">
@@ -575,10 +695,10 @@ initWhenReady();
         W(`| ${t.tag} | ${hits.length} | ${(hits.length / Math.max(allComments.length, 1) * 100).toFixed(1)}% | ${sampleText} |`);
     }
     W('');
-    W('### 真实评论原声 Top 16 (剔除噪声)');
+    W('### 真实评论原声 Top 16 (产品强相关 · 多主题轮询)');
     W('');
-    for (const c of realComments.sort((a, b) => b.like - a.like).slice(0, 16)) {
-        W(`- **[${c.koc}/${c.type || '-'}]** \`${c.nick || '-'}@${c.ip || '-'} · ${String(c.region || '').slice(0, 3)}\` *(赞 ${c.like})*: ${c.content.replace(/\n/g, ' ')}`);
+    for (const { topic, c } of topPicks) {
+        W(`- **[${topic}]** \`${c.koc}@${c.ip || '-'}\`: ${c.content.replace(/\n/g, ' ')}`);
     }
     W('');
     W('---');

+ 221 - 17
majiyong/scripts/gen-majiyong-closing-report.js

@@ -187,23 +187,227 @@ const RECS = [
 
 // ---------- 5.5 新机会矩阵 ----------
 const OPPORTUNITIES = [
-    { id: 'A1', cat: 'A · 产品卖点', p: 'P0', t: '"鲜菜可视化"内容必出', signal: '新鲜菜主题命中 ' + newDishHits + ' 条,但探店笔记多停留在"好吃想去"层面', action: '简报必出"摘菜/凉拌/过水"3 选 2 镜头,把"新鲜"从形容词变可见证据,与陈香贵预制感拉开差距' },
-    { id: 'A2', cat: 'A · 产品卖点', p: 'P0', t: '减脂/健康赛道占位', signal: '健康减脂主题已有 ' + topicHits['健康/减脂/营养'].length + ' 条评论自发出现 (蔬菜多/清淡/低卡)', action: '推出"鲜菜套餐 < 600 大卡"标准化菜单,锁定西北菜里的"减脂友好"心智,这是品类空白位' },
-    { id: 'A3', cat: 'A · 产品卖点', p: 'P1', t: '一人食 / 双人套餐显性化', signal: '场景主题命中 ' + topicHits['场景/堂食/外卖'].length + ' 条,堂食/外带/聚餐多场景共存', action: '菜单分场景: 一人食套餐 (拉面+小菜+饮料 39.9) / 双人鲜菜局 / 4 人家庭餐,降低决策摩擦' },
-    { id: 'A4', cat: 'A · 产品卖点', p: 'P1', t: '凉拌菜独立小份 SKU', signal: '凉拌/小菜在评论中高频出现,但用户多吐槽"分量小/想多点几样"', action: '推 9.9 元任选三拼小碟,作为引流爆款 + 拍照 social 货币' },
-    { id: 'B1', cat: 'B · 内容形态', p: 'P0', t: '探店内容差异化 5 赛道', signal: '220+ 探店笔记同质化严重,平均互动衰减', action: '下一轮简报分: 减脂餐 / 早午餐 / 家庭聚餐 / 一人食 / 商务宴请 5 个差异角度,各 15-20 篇' },
-    { id: 'B2', cat: 'B · 内容形态', p: 'P0', t: '二创 KOC 升级为 IP 池', signal: byTier['二创KOC']?.count + ' 篇二创 KOC 互动率最高 (' + ((byTier['二创KOC']?.eng || 0) / Math.max(byTier['二创KOC']?.imp || 1, 1) * 100).toFixed(2) + '%)', action: '搭建"二创素材库" + 月度联名周边激励,把段子/表情包/插画化笔记沉淀为长期 IP 资产' },
-    { id: 'B3', cat: 'B · 内容形态', p: 'P1', t: 'Top KOL 复刻方法论', signal: 'Top 1 KOL 单篇互动 ≈ KOL 中位 4 倍,但属于偶发爆款,未方法化', action: '拆解 Top 5 KOL 笔记的"标题/封面/前 3 秒/CTA",形成《非美食创意 KOL 选号 SOP》' },
-    { id: 'B4', cat: 'B · 内容形态', p: 'P2', t: '直播 + 鲜菜溯源内容', signal: '"新鲜菜"心智已建立,需要 RTB 锚定', action: '邀请 KOL 上门拍"凌晨进货 / 后厨摘菜"溯源内容,纪录片化降低信任成本' },
-    { id: 'C1', cat: 'C · 人群渠道', p: 'P0', t: '"求开店"评论转私域线索', signal: storeHits + ' 条评论提"啥时候开 X 城/求开 XX",这是免费选址 + 高意向用户', action: '统一话术 + 企微留资,把每条求开店评论变成"未来候选店周边的种子用户"私域池' },
-    { id: 'C2', cat: 'C · 人群渠道', p: 'P0', t: '区域分布二八优化', signal: 'Top 区域 ' + topRegions.slice(0, 3).map((r) => r.region).join('/') + ' 占大头,门店空白城市 KOC 浪费', action: '下一轮 KOC 选号必须 80% 落在已开店城市 3km 半径内,提升到店转化' },
-    { id: 'C3', cat: 'C · 人群渠道', p: 'P1', t: '在地达人深耕计划', signal: '一线已开店城市需要"长期到店打卡"用户,而非一次性 KOC', action: '签约 30-50 位一线在地素人做"月度打卡官",月度返券 + 季度活动嘉宾,沉淀长期口碑' },
-    { id: 'C4', cat: 'C · 人群渠道', p: 'P2', t: '小红书"周末饭搭子"群运营', signal: '场景主题里"约/带朋友/聚餐"信号强', action: '城市级"周末饭搭子"群,品牌方半运营半放手,自然带动到店' },
-    { id: 'D1', cat: 'D · 投放机制', p: 'P0', t: 'KOC 长尾自动止损机制', signal: lowEngCnt + '/' + summary.total + ' 篇互动 < 5,长尾零产出占' + (lowEngCnt / summary.total * 100).toFixed(0) + '%', action: '投后 72h 算法判定: 互动 < 5 即冷启动失败,自动追加 ¥30-50 薯条二次抢救;3 次失败即拉黑该号' },
-    { id: 'D2', cat: 'D · 投放机制', p: 'P1', t: 'Top 互动笔记薯条加投', signal: 'Top 5% 笔记贡献 50%+ 互动,但未追加投流', action: '投后 24h 自动识别 Top 5%,统一追加 ¥100-300 薯条 + 评论区置顶引导,放大长尾流量' },
-    { id: 'D3', cat: 'D · 投放机制', p: 'P1', t: '风险词预警 + 24h 介入', signal: negHits + ' 条负面/食安关键词命中,无 SOP', action: '关键词监控 (拉肚子/头发/苍蝇/食物中毒/过期),触发即 24h 内官方私信安抚 + 内部工单同步门店' },
-    { id: 'E1', cat: 'E · 数据机制', p: 'P0', t: '主题词典版本化', signal: '本轮 12 主题命中 ' + Object.values(topicHits).reduce((s, l) => s + l.length, 0) + ' 次,需要持续迭代', action: '把主题词典作为 v1 沉淀,每月增补新词 (新品 / 新场景 / 新竞品),版本化管理' },
-    { id: 'E2', cat: 'E · 数据机制', p: 'P1', t: '竞品评论生态对照基线', signal: '当前只看自己 1612 条评论,缺竞品参照', action: '抓取陈香贵/张拉拉/马富/和府 Top 50 笔记评论 ≥ 1000 条,建立心智份额动态对照,季度复盘' },
+    {
+        id: 'A1', cat: 'A · 产品卖点', p: 'P0', t: '"鲜菜可视化"内容必出',
+        signal: '新鲜菜主题命中 ' + newDishHits + ' 条,但探店笔记多停留在"好吃想去"层面',
+        action: '简报必出"摘菜/凉拌/过水"3 选 2 镜头,把"新鲜"从形容词变可见证据,与陈香贵预制感拉开差距',
+        why: '"新鲜"是西北面馆赛道的最大差异点,但目前 ' + newDishHits + ' 条评论里 80% 仍停留在"好吃/想去试试"这种泛印象,缺少可视化锚点。陈香贵/张拉拉因央厨化被反复质疑预制感,我们如果把"现摘/现拌/不过夜"做成视觉签名,相当于把品类劣势翻转成品牌资产。',
+        how: [
+            '简报硬性规定: 每条笔记至少 1 个"摘菜/洗菜/过水/凉拌"镜头特写 (≥ 3 秒)',
+            '提供官方素材包: 后厨实拍镜头库 + 标准化文案 ("当天摘的 / 不过夜")',
+            '封面强制带"绿叶+水珠"视觉元素,与同行的"红汤大碗"形成视觉差',
+            '高互动笔记复盘: 拍出鲜菜镜头的笔记 vs 没拍的,互动率 / CPE / 评论健康度对比',
+        ],
+        outcome: '预期单月新鲜菜主题命中 +50% (64 → 96 条),CPE 改善 15-25%,"预制感"质疑下降',
+    },
+    {
+        id: 'A2', cat: 'A · 产品卖点', p: 'P0', t: '减脂/健康赛道占位',
+        signal: '健康减脂主题已有 ' + topicHits['健康/减脂/营养'].length + ' 条评论自发出现 (蔬菜多/清淡/低卡)',
+        action: '推出"鲜菜套餐 < 600 大卡"标准化菜单,锁定西北菜里的"减脂友好"心智,这是品类空白位',
+        why: '西北面馆全行业默认"重碳 + 重油 + 大份",几乎没人占"健康"位。但用户已经 60 条评论自发说"好健康/减脂/营养"了,需求已被市场培育起来,差临门一脚的产品承接。先发占位即心智壁垒。',
+        how: [
+            '研发"鲜菜套餐 < 600 大卡": 小份拉面 + 鲜菜双拼 + 酸梅汤',
+            '菜单/包装/线上 SKU 必须标注热量数字 (kcal),做营养可信度',
+            '联动健身/减脂 KOL 测评,锁定 25-35 岁白领女性',
+            '门店摆台增设"今日热量推荐"小卡片,引导点单',
+        ],
+        outcome: '健康/减脂主题评论自发命中 60 → 120,带动减脂场景复购率 +20%,差异化壁垒形成',
+    },
+    {
+        id: 'A3', cat: 'A · 产品卖点', p: 'P1', t: '一人食 / 双人套餐显性化',
+        signal: '场景主题命中 ' + topicHits['场景/堂食/外卖'].length + ' 条,堂食/外带/聚餐多场景共存',
+        action: '菜单分场景: 一人食套餐 (拉面+小菜+饮料 39.9) / 双人鲜菜局 / 4 人家庭餐,降低决策摩擦',
+        why: '"打工人食堂"/"带娃来吃"/"约朋友"等场景评论自然存在,但菜单没有显性套餐承接,用户每次都得自己组合,降低决策效率,损失边际客单。',
+        how: [
+            '一人食套餐 39.9 (拉面 + 小菜 1 + 饮品) — 锁定午餐时段',
+            '双人鲜菜局 78 (面 ×2 + 凉菜 ×3 + 饮品 ×2) — 锁定晚餐约伴',
+            '4 人家庭餐 168 (面 ×2 + 配菜 + 凉菜 ×3 + 甜品) — 锁定家庭聚餐',
+            '菜单首屏左侧 banner 直接展示三档套餐价,引导一键加购',
+        ],
+        outcome: '客单价 +8-15%,套餐 SKU 占总订单 25-35%,降低收银等待时间',
+    },
+    {
+        id: 'A4', cat: 'A · 产品卖点', p: 'P1', t: '凉拌菜独立小份 SKU',
+        signal: '凉拌/小菜在评论中高频出现,但用户多吐槽"分量小/想多点几样"',
+        action: '推 9.9 元任选三拼小碟,作为引流爆款 + 拍照 social 货币',
+        why: '凉拌菜在本次 130 条联名活动评论里被反复提及,是"换菜活动"最成功的产品锚点。但目前 SKU 是大份单点,用户单次只能尝一样;改成小碟三拼能多撬动 SKU 体验深度 + 拍照传播货币。',
+        how: [
+            '推 9.9 元小碟三拼 (任选 3,固定 6-8 种凉拌池)',
+            '提供专门拍照容器 (浅口圆碟,绿色木板托盘)',
+            'KOC 简报新增"凉菜三拼"作为必拍 SKU',
+            '收银端建立"小碟三拼跟单率"指标',
+        ],
+        outcome: '凉拌菜单 SKU 渗透率 ×2,凉菜出现在 70% 的笔记封面,拍照传播货币化',
+    },
+    {
+        id: 'B1', cat: 'B · 内容形态', p: 'P0', t: '探店内容差异化 5 赛道',
+        signal: '220+ 探店笔记同质化严重,平均互动衰减',
+        action: '下一轮简报分: 减脂餐 / 早午餐 / 家庭聚餐 / 一人食 / 商务宴请 5 个差异角度,各 15-20 篇',
+        why: '当前 281 篇 KOC 中绝大多数是"美食探店"形态: 走进店 → 点菜 → 吃 → 出门,内容同质化严重,长尾笔记零互动比例高。差异化角度能撬动不同场景人群心智。',
+        how: [
+            '简报分赛道: 减脂餐 / 早午餐 / 家庭聚餐 / 一人食 / 商务宴请 各 15-20 篇',
+            '每个赛道配独立内容模板 (镜头组合 + 文案话术 + 封面色系)',
+            'KOC 选号按内容历史风格分桶,确保赛道与达人调性匹配',
+            '投后按赛道维度复盘 ROI,沉淀《5 赛道内容打法 SOP》',
+        ],
+        outcome: '同质化笔记占比 90% → 30%,长尾零互动比例从 ~40% 下降到 ~20%,5 类心智同步打透',
+    },
+    {
+        id: 'B2', cat: 'B · 内容形态', p: 'P0', t: '二创 KOC 升级为 IP 池',
+        signal: byTier['二创KOC']?.count + ' 篇二创 KOC 互动率最高 (' + ((byTier['二创KOC']?.eng || 0) / Math.max(byTier['二创KOC']?.imp || 1, 1) * 100).toFixed(2) + '%)',
+        action: '搭建"二创素材库" + 月度联名周边激励,把段子/表情包/插画化笔记沉淀为长期 IP 资产',
+        why: '本期最大惊喜是"蜡笔小严的手工"这类非美食 KOL,单篇互动 2570 ≈ 美食 KOL 中位 4 倍。二创/创意化内容的"反差感"在小红书是稀缺货币,但目前只是偶发,没有机制化。',
+        how: [
+            '建立"二创素材库" (Notion / 飞书云文档),沉淀 50+ 二创案例',
+            '签约 10-15 位插画 / 段子 / 表情包类 KOC 作长期合作',
+            '月度联名周边激励 (帆布袋 / 贴纸 / 表情包),激励 UGC 二创',
+            '把高传播二创内容收纳进"马记永表情包"系列,反哺品牌资产',
+        ],
+        outcome: '二创笔记篇均互动 +50%,品牌进入"年轻人段子库",高互动笔记长尾持续涨粉',
+    },
+    {
+        id: 'B3', cat: 'B · 内容形态', p: 'P1', t: 'Top KOL 复刻方法论',
+        signal: 'Top 1 KOL 单篇互动 ≈ KOL 中位 4 倍,但属于偶发爆款,未方法化',
+        action: '拆解 Top 5 KOL 笔记的"标题/封面/前 3 秒/CTA",形成《非美食创意 KOL 选号 SOP》',
+        why: '本期 KOL 投放 ROI 极度分化: Top 1 单篇互动 2570,KOL 中位 ~600,差异 4 倍,但目前是"押宝式"投放,没有可复制方法论。一旦把爆款公式提炼,下一轮可批量化复刻。',
+        how: [
+            '逆向拆解 Top 5 KOL 笔记: 标题结构 / 封面构图 / 前 3 秒钩子 / CTA 形式',
+            '建立《非美食创意 KOL 选号 SOP》: 粉丝调性 / 历史爆款率 / 内容创意指数',
+            '下一轮 KOL 预算 50% 给 SOP 命中达人,50% 试新',
+            '每月评估 SOP 命中达人 vs 自由探索的 CPE 差',
+        ],
+        outcome: 'KOL 单篇互动均值 +30-50%,降低头部依赖,腰部创意 KOL 池形成',
+    },
+    {
+        id: 'B4', cat: 'B · 内容形态', p: 'P2', t: '直播 + 鲜菜溯源内容',
+        signal: '"新鲜菜"心智已建立,需要 RTB 锚定',
+        action: '邀请 KOL 上门拍"凌晨进货 / 后厨摘菜"溯源内容,纪录片化降低信任成本',
+        why: '"新鲜"是抽象承诺,只有看见才相信。同行靠中央厨房效率竞争,我们如果反向把"凌晨菜场进货"拍成纪录片,本身就是新闻级传播素材,且能持续重复使用作信任资产。',
+        how: [
+            '邀请 3-5 位深度内容 KOL 上门拍"凌晨进货 / 后厨摘菜"纪录片',
+            '剪成 90 秒短片 + 30 秒 reels 两个版本,小红书 + 视频号 + 抖音同步',
+            '门店关键位置 (排队墙 / 餐桌台卡) 二维码引流到该视频',
+            '把内容做成"年度溯源系列",每季度产 1 期,沉淀品牌资产',
+        ],
+        outcome: '建立"新鲜可信"品牌资产,降低用户首次决策门槛,转化漏斗后端友好',
+    },
+    {
+        id: 'C1', cat: 'C · 人群渠道', p: 'P0', t: '"求开店"评论转私域线索',
+        signal: storeHits + ' 条评论提"啥时候开 X 城/求开 XX",这是免费选址 + 高意向用户',
+        action: '统一话术 + 企微留资,把每条求开店评论变成"未来候选店周边的种子用户"私域池',
+        why: storeHits + ' 条求开店评论 = ' + storeHits + ' 个免费选址数据点 + ' + storeHits + ' 个高意向潜在客户,目前 0 承接通道全部流失。把这些用户引导到企微/公众号留资,就是"未来候选门店首日 5 折"的免费种子用户池。',
+        how: [
+            '统一话术: 对每条求开店评论回复"已记录到拓店建议库 + 留邮箱享首店首日 5 折"',
+            '企微/公众号承接,城市标签化运营',
+            '把求开店 IP 数据导出,叠加现有门店地图,输出《潜在外扩城市优先级表》给拓展部',
+            '持续监测求开店主题词,作为月度选址辅助数据',
+        ],
+        outcome: '私域线索 +57 起步,每月新增 ~30,首店开业首周到店率 +20%,选址决策效率提升',
+    },
+    {
+        id: 'C2', cat: 'C · 人群渠道', p: 'P0', t: '区域分布二八优化',
+        signal: 'Top 区域 ' + topRegions.slice(0, 3).map((r) => r.region).join('/') + ' 占大头,门店空白城市 KOC 浪费',
+        action: '下一轮 KOC 选号必须 80% 落在已开店城市 3km 半径内,提升到店转化',
+        why: '本期投放有相当比例 KOC 投在无门店城市,产生"看了没法吃"的损失型曝光。投放本质是"种草 → 拔草"链路,无门店半径内的种草是无效弹药。',
+        how: [
+            'KOC 选号硬性规定: 80% 必须落在已开店城市 3km 内 (IP 验证)',
+            '剩余 20% 投在 C1 求开店数据指向的"未来候选城市"做心智预热',
+            '建立 KOC 地理位置黑/灰/白名单',
+            '投后看"KOC IP 与门店半径匹配度"作为蒲公英结案核心指标',
+        ],
+        outcome: '到店转化率 +30%,曝光 ROI 显著优化,投放预算利用率从 ~70% 提升到 ~90%',
+    },
+    {
+        id: 'C3', cat: 'C · 人群渠道', p: 'P1', t: '在地达人深耕计划',
+        signal: '一线已开店城市需要"长期到店打卡"用户,而非一次性 KOC',
+        action: '签约 30-50 位一线在地素人做"月度打卡官",月度返券 + 季度活动嘉宾,沉淀长期口碑',
+        why: '一次性 KOC 投放是"快闪式种草",在地达人深耕则是"长期口碑发酵"。同样的预算,长期合作 1 个达人 12 个月 > 一次性合作 12 个达人,内容连贯性 + 用户信任度都更高。',
+        how: [
+            '城市级签约 30-50 位在地素人 (粉丝 1k-5k 即可,真实用户优先)',
+            '"月度打卡官"机制: 月度返券 + 季度活动嘉宾 + 年度大使升级',
+            '运营专人对接,提供选题方向 + 灵感库,降低创作门槛',
+            '内容形式不限,鼓励真实日常: 上班路过 / 周末家人 / 雨天慰藉',
+        ],
+        outcome: '在地内容长尾效应 ×3,品牌区域渗透更深,获客成本下降 20-30%',
+    },
+    {
+        id: 'C4', cat: 'C · 人群渠道', p: 'P2', t: '小红书"周末饭搭子"群运营',
+        signal: '场景主题里"约/带朋友/聚餐"信号强',
+        action: '城市级"周末饭搭子"群,品牌方半运营半放手,自然带动到店',
+        why: '"饭搭子"是 2024-2025 小红书一线城市社交关键词,马记永的西北菜 + 适中客单价天然适合 2-4 人小聚。半运营半放手 = 品牌提供场域,用户自发约饭,流量自然到店。',
+        how: [
+            '城市级开"周末饭搭子" 小红书群,管理员协调',
+            '每周一议题: "下班吃面" / "周末减脂局" / "工作日早午餐"',
+            '群专属优惠码 (5% 折扣或免费小菜),低频但稳定',
+            '季度一次线下"饭搭子见面会",带动 UGC 笔记',
+        ],
+        outcome: '城市级私域社群 ×N,自然带动到店 +5-10%,降低长尾投放依赖',
+    },
+    {
+        id: 'D1', cat: 'D · 投放机制', p: 'P0', t: 'KOC 长尾自动止损机制',
+        signal: lowEngCnt + '/' + summary.total + ' 篇互动 < 5,长尾零产出占' + (lowEngCnt / summary.total * 100).toFixed(0) + '%',
+        action: '投后 72h 算法判定: 互动 < 5 即冷启动失败,自动追加 ¥30-50 薯条二次抢救;3 次失败即拉黑该号',
+        why: '本期 ' + lowEngCnt + ' 篇笔记互动 < 5,占总篇数 ' + (lowEngCnt / summary.total * 100).toFixed(0) + '%,这部分预算几乎是"沉没成本"。机制化止损能持续优化每一轮投放 ROI。',
+        how: [
+            '投后 72h 自动检查互动数据 (篇均互动 / 评论 / 收藏)',
+            '互动 < 5: 自动追加 ¥30-50 薯条二次抢救',
+            '抢救后仍 < 10: 标记该 KOC 为低效,3 次失败拉黑',
+            '建立 KOC 历史投放表现数据库,选号时反向参考',
+        ],
+        outcome: '长尾零互动篇数下降 30-50%,投放 ROI 持续优化,KOC 池质量动态净化',
+    },
+    {
+        id: 'D2', cat: 'D · 投放机制', p: 'P1', t: 'Top 互动笔记薯条加投',
+        signal: 'Top 5% 笔记贡献 50%+ 互动,但未追加投流',
+        action: '投后 24h 自动识别 Top 5%,统一追加 ¥100-300 薯条 + 评论区置顶引导,放大长尾流量',
+        why: '互动符合幂律分布: Top 5% 的笔记贡献 50%+ 的总互动量。这部分笔记是"已被算法验证的优质内容",追加投流 ROI 远高于平均。但目前没有自动加投机制,白白错过流量放大窗口。',
+        how: [
+            '投后 24h 自动识别 Top 5% (按互动率排序)',
+            '统一追加 ¥100-300 薯条投流',
+            '评论区置顶引导文案 (CTA 到店 / 私信 / 加群)',
+            '建立"加投后效果归因表",看追加 1 元 → 互动增量多少',
+        ],
+        outcome: 'Top 笔记长尾流量 +50-200%,单条笔记最大互动从 ~2500 突破到 5000+',
+    },
+    {
+        id: 'D3', cat: 'D · 投放机制', p: 'P1', t: '风险词预警 + 24h 介入',
+        signal: negHits + ' 条负面/食安关键词命中,无 SOP',
+        action: '关键词监控 (拉肚子/头发/苍蝇/食物中毒/过期),触发即 24h 内官方私信安抚 + 内部工单同步门店',
+        why: '当前负面评论 ' + negHits + ' 条仅占 0.x%,品牌处于安全期。但餐饮品类一次食安事件就可能造成不可逆品牌损伤,必须在量小阶段就建立 SOP,防患于未然。',
+        how: [
+            '关键词词典: 拉肚子 / 头发 / 苍蝇 / 食物中毒 / 过期 / 不熟 / 难吃 (扩展中)',
+            '小红书 + 微博 + 抖音三端监测,触发即工单',
+            '24h 内官方账号私信安抚 + 内部同步门店核查 + 补偿券',
+            '月度风险评论复盘,迭代关键词词典',
+        ],
+        outcome: '负面舆情发现时间从 ~48h 缩短到 ~6h,处置时效 ×4,品牌信任度兜底',
+    },
+    {
+        id: 'E1', cat: 'E · 数据机制', p: 'P0', t: '主题词典版本化',
+        signal: '本轮 12 主题命中 ' + Object.values(topicHits).reduce((s, l) => s + l.length, 0) + ' 次,需要持续迭代',
+        action: '把主题词典作为 v1 沉淀,每月增补新词 (新品 / 新场景 / 新竞品),版本化管理',
+        why: 'VOC 主题词典是品牌"听用户声音"的眼睛,词典越精准,洞察越精准。当前 v1 词典已能命中 1600+ 评论,但新品新场景新竞品会持续出现,词典必须随时间演化才能保持灵敏度。',
+        how: [
+            '把当前 12 主题词典存入 Git 仓库版本化 (`topics/majiyong-v1.json`)',
+            '每月固定 1 次词典扩充会议: 新增/废弃/合并词',
+            '词典命中变化数据自动出周报,识别"主题异常涨/跌"',
+            '词典开放给业务侧维护,降低数据团队瓶颈',
+        ],
+        outcome: '主题命中率持续 +5-10%/月,新主题发现时效从 ~3 月缩短到 ~2 周',
+    },
+    {
+        id: 'E2', cat: 'E · 数据机制', p: 'P1', t: '竞品评论生态对照基线',
+        signal: '当前只看自己 1612 条评论,缺竞品参照',
+        action: '抓取陈香贵/张拉拉/马富/和府 Top 50 笔记评论 ≥ 1000 条,建立心智份额动态对照,季度复盘',
+        why: '本期评论里 0 条提及竞品,说明马记永品牌护城河深;但反过来,陈香贵/张拉拉的用户是否提到马记永? 这是更重要的"心智份额"指标,目前无数据。',
+        how: [
+            '复用现有 collect-majiyong.js 工作流,抓取竞品 Top 50 笔记',
+            '建立竞品评论数据库,主题词典同样适用',
+            '季度复盘: 心智份额 / 主题分布差 / 用户重叠率',
+            '把"反向心智战"作为下一阶段品牌战略输入',
+        ],
+        outcome: '心智份额数据化,品牌战略决策有竞品参照,识别可挖墙脚人群',
+    },
 ];
 const TOP5 = ['A1', 'B1', 'C1', 'D1', 'E1'];
 

+ 377 - 63
shuhua/scripts/gen-shuhua-closing-report.js

@@ -82,10 +82,77 @@ for (const r of items) {
     }
 }
 
-// 噪声识别
-const noiseRe = /互赞|互助|加油.*互|可以.*点赞|点赞.*返|蹲.*搭子/;
-const noiseComments = allComments.filter((c) => noiseRe.test(c.content));
-const realComments = allComments.filter((c) => !noiseRe.test(c.content));
+// ============== 噪声识别 + 真实评论筛选 v4 ==============
+const NOISE_RE = /互赞|互助|加油.*互|可以.*点赞|点赞.*返|蹲.*搭子|互粉/;
+const OFFTOPIC_RE = /眼影|口红|睫毛|化妆|分装|借我|借用|护肤|穿搭|开箱|美术生|画的|画得|插画|手工/;
+const PROMO_RE = /推广|求关注|求互|私信|加微|商务合作|接广告|涨粉/;
+const SHILL_RE = /宝子|亲测|无套路|必.{0,2}冲|绝绝子|拉满|薅羊毛|放心冲|闭眼冲|爆棚|颜值直接|姐妹.{0,3}冲|实力宠粉|爆款|0元购|yyds|YYDS|惊艳到|跺脚/;
+const META_KOL_RE = /博主|up主|UP主|接广|涨粉|掉粉|播放/;
+const EMOJI_HEAVY_RE = /(🥬|🥢|🌿|🤩|💯|🔥|💥|✅|💦|📸|🥳|🛒|🎉|✨|💚|❗|‼️)/g;
+const stripDeco = (s) => s.replace(/\[[^\]]+\]/g, '').replace(/[@#][^\s@#]+/g, '').replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '');
+
+const noiseComments = allComments.filter((c) => NOISE_RE.test(c.content));
+
+// 跑步机产品强相关词典 - 7 大主题
+const PRODUCT_TOPICS_SHUHUA = {
+    '静音减震': /静音|减震|噪音|噪声|声音|分贝|楼下|楼上|邻居|扰邻|商品房|楼板|响|吵|安静/,
+    '专业参数': /坡度|速度|心率|配速|马达|马力|功率|参数|配置|续航|履带|跑带|尺寸/,
+    '场景体验': /家用|居家|社恐|健身房|减肥|减脂|塑形|课程|训练|跑步|走路|快走/,
+    '购买决策': /购买|入手|考虑|对比|划算|性价比|价格|预算|犹豫|推荐|值得|后悔/,
+    '使用反馈': /好用|不好用|质量|耐用|结实|稳|抖|坏了|售后|故障|包装|物流|安装/,
+    '竞品提及': /易跑|麦瑞克|亿健|岱宇|舒华|小米|华为|keep|Keep/,
+    '复购口碑': /用了.*[年月天]|每天|经常|坚持|续费|又买|回头|二次/,
+};
+const PRODUCT_RE_SHUHUA = new RegExp(Object.values(PRODUCT_TOPICS_SHUHUA).map((r) => r.source).join('|'));
+
+const realCommentsAll = allComments.filter((c) => {
+    const txt = c.content || '';
+    if (c.nick && c.koc && c.nick === c.koc) return false; // 博主自评
+    if (/^\s*@/.test(txt) && stripDeco(txt.replace(/^\s*@[^\s@#]+/, '')).length < 20) return false;
+    if (NOISE_RE.test(txt) || OFFTOPIC_RE.test(txt) || PROMO_RE.test(txt) || SHILL_RE.test(txt) || META_KOL_RE.test(txt)) return false;
+    const emojis = txt.match(EMOJI_HEAVY_RE) || [];
+    if (emojis.length >= 3) return false;
+    const core = stripDeco(txt);
+    if (core.length < 6) return false;
+    if (core.length > 80 && emojis.length >= 1) return false;
+    if (core.length > 120) return false;
+    return true;
+});
+// 产品强相关优先,但样本小不强制 (允许后补)
+const realComments = realCommentsAll.filter((c) => PRODUCT_RE_SHUHUA.test(c.content));
+const realCommentsFallback = realCommentsAll.filter((c) => !PRODUCT_RE_SHUHUA.test(c.content));
+
+// 主题分桶 + 信息量排序 + 轮询
+const informationScore = (c) => {
+    let hits = 0;
+    for (const re of Object.values(PRODUCT_TOPICS_SHUHUA)) if (re.test(c.content)) hits++;
+    return hits * 20 + stripDeco(c.content).length;
+};
+const buckets = {};
+for (const tag of Object.keys(PRODUCT_TOPICS_SHUHUA)) buckets[tag] = [];
+for (const c of realComments) {
+    for (const [tag, re] of Object.entries(PRODUCT_TOPICS_SHUHUA)) {
+        if (re.test(c.content)) { buckets[tag].push(c); break; }
+    }
+}
+for (const tag of Object.keys(buckets)) buckets[tag].sort((a, b) => (b.like - a.like) || (informationScore(b) - informationScore(a)));
+
+const topPicks = [];
+const queues = Object.entries(buckets).map(([tag, list]) => ({ tag, list, idx: 0 }));
+for (let round = 0; round < 4 && topPicks.length < 12; round++) {
+    for (const q of queues) {
+        if (topPicks.length >= 12) break;
+        if (q.idx < q.list.length && q.idx < round + 1) {
+            topPicks.push({ topic: q.tag, c: q.list[q.idx] });
+            q.idx++;
+        }
+    }
+}
+// 不够 12 条用 fallback 补
+for (const c of realCommentsFallback.sort((a, b) => b.like - a.like)) {
+    if (topPicks.length >= 12) break;
+    topPicks.push({ topic: '其他真实声音', c });
+}
 
 // ============== 3. 话题主题分析 ==============
 const TOPICS = [
@@ -185,28 +252,227 @@ const RECS = [
 
 // ============== 5.5 新机会矩阵 (基于评论逐条逆向挖掘) ==============
 const OPPORTUNITIES = [
-    // A. 产品/卖点
-    { id: 'A1', cat: 'A · 产品卖点', p: 'P0', t: '静音减震 RTB 具象化', signal: '沐阳 3 连评论 · 商品房+楼板+邻居', action: '分贝评测 + 楼板自测指南 + 真实邻居访谈视频三件套,把"静音减震"从形容词变成可信证据' },
-    { id: 'A2', cat: 'A · 产品卖点', p: 'P0', t: '坡度参数明牌对比', signal: '木塔塔晒坡度15-20 + 星星不懂星星推易跑"-6到26"', action: '简报必出"舒华 vs 易跑参数对比表",拦截"易跑"搜索流量,直接挖竞品墙脚' },
-    { id: 'A3', cat: 'A · 产品卖点', p: 'P0', t: '社恐居家健身专属内容线', signal: '星星不懂星星/福建: 社恐+不爱挤健身房', action: '5-10 篇专项内容锁定 i 人/社恐/独居场景,占领被易跑先占的细分心智' },
-    { id: 'A4', cat: 'A · 产品卖点', p: 'P1', t: '跑步机 × 课程包绑定', signal: '兔子河南: "第一节课/回放课"', action: '联名 Keep / 帕梅拉 / 刘畊宏,买机送 1 年课程 VIP,客单价翻 2-3 倍' },
-    // B. 内容形态
-    { id: 'B1', cat: 'B · 内容形态', p: 'P1', t: '365 天蜕变长期 IP', signal: '兔子湖南: 一年前奶茶不离手 → 一年后敢露肉了"换头"', action: '招募 100 位真实用户做 1 年期 KOL,送机 + 月度回访,产出对比照,双 11/618 集中释放' },
-    { id: 'B2', cat: 'B · 内容形态', p: 'P0', t: 'UGC 参数交流模板', signal: '木塔塔: 坡度15-20/速度4.2-4.5/心率135-149', action: '简报加入"晒你的训练参数"话题,App 自动生成参数分享卡,自然形成 UGC 素材库' },
-    { id: 'B3', cat: 'B · 内容形态', p: 'P0', t: '泛流量型升级为专业体验型', signal: '形态错配反向信号: 泛流量型互动最低但产生最高质量评论', action: '把"泛流量相关型"重命名为"专业体验交流型",下一轮投入比例从 12% 提到 30%' },
-    { id: 'B4', cat: 'B · 内容形态', p: 'P1', t: '真实邻居访谈视频', signal: '沐阳云南: 跑步机声 + 邻居反馈"没听到"', action: '找 5 位老用户上门,让楼下邻居出镜确认,这是 KOL 软文做不到的真实信任' },
-    // C. 人群渠道
-    { id: 'C1', cat: 'C · 人群渠道', p: 'P0', t: 'KOC 性别/年龄结构调整', signal: '本期 43 位 KOC 全为萌系女性昵称,跑步机决策人群错位', action: '男性 30% + 宝爸宝妈 20% + 30+ 中产女性 10%,等于换一批用户' },
-    { id: 'C2', cat: 'C · 人群渠道', p: 'P1', t: '商品房新业主精准包', signal: '沐阳: "商品房 / 开发商问题"', action: '定向 3 年内交付的高层公寓用户,这是扰邻焦虑最强的目标人群' },
-    { id: 'C3', cat: 'C · 人群渠道', p: 'P1', t: '减肥搭子社交营 (噪声资产化)', signal: '47% 互助互赞噪声实为真实减肥群体寻找搭子', action: '#舒华 30 天减肥搭子营 官方话题 + 企微私域 + 月度 PK 赛事,把噪声变长效资产' },
-    { id: 'C4', cat: 'C · 人群渠道', p: 'P0', t: '一线 + 新一线 IP 占比 ≥ 50%', signal: '本期评论 IP 缺京沪深广杭蓉', action: '跑步机是大件家居,一线城市才有支付力 + 居住空间,选号必须明确 IP 配比' },
-    // D. 投放机制
-    { id: 'D1', cat: 'D · 投放机制', p: 'P0', t: '类目标签从家居/好物迁到健身/减脂', signal: '本期挂"家居 22 + 好物 21",但搜索词是"跑步机推荐/家用跑步机"', action: '简报锁定 SEO 标签 居家健身 / 减脂塑形 / 跑步机推荐 / 健身房替代' },
-    { id: 'D2', cat: 'D · 投放机制', p: 'P1', t: 'MCN 来源审计 + 多源选号', signal: '粉丝量 1k-2k 高度同质,疑似单一 MCN 包号', action: '≥ 3 家 MCN + ≥ 20% 蒲公英直选 + ≥ 10% 自建池 + 粉丝阶梯化金字塔结构' },
-    { id: 'D3', cat: 'D · 投放机制', p: 'P2', t: '7 天上门试驾 O2O', signal: '星星不懂星星山东: "免费体验欢迎来锻炼"', action: '借鉴戴森/特斯拉,跑步机 7 天上门 + 不满意退款,降低决策门槛,KOC 矩阵推广' },
-    // E. 数据机制
-    { id: 'E1', cat: 'E · 数据机制', p: 'P0', t: '投后 24h 抓取 + 博主行为预警', signal: 'xlsx 19 评论 → API 17, 缺失 2 条 (可能博主自删)', action: '24h 内首版数据快照,捕捉删评/删笔记信号,识别评论区翻车风险' },
-    { id: 'E2', cat: 'E · 数据机制', p: 'P1', t: '3 天数据保护期 + 死笔记自动补流', signal: '11/43 篇互动 < 5,33/43 篇产出极差 = ¥7000+ 浪费', action: '投后 3 天数据 < 阈值的笔记,自动触发 ¥30-50 薯条二次投流补救,而非直接放弃' },
+    {
+        id: 'A1', cat: 'A · 产品卖点', p: 'P0', t: '静音减震 RTB 具象化',
+        signal: '沐阳 3 连评论 · 商品房+楼板+邻居',
+        action: '分贝评测 + 楼板自测指南 + 真实邻居访谈视频三件套,把"静音减震"从形容词变成可信证据',
+        why: '"扰邻焦虑"是商品房 / 高层住宅用户购买跑步机最大决策门槛。当前 KOC 笔记停留在"很安静"这种泛形容词,用户依然不敢下单。把抽象承诺翻译成"分贝数 / 楼下邻居反馈视频 / 楼板震动测试"等可见可量化证据,直接拆掉决策最后一道墙。',
+        how: [
+            '分贝评测视频: 不同档位实测 + 同房间对比 (跑步 vs 洗衣机 vs 电视)',
+            '楼板自测指南: 1 张图教用户在自家楼板放杯水/硬币测震动',
+            '真实邻居访谈视频: 找 5 位老用户上门拍楼下邻居反馈 (KOL 软文做不到)',
+            '官方素材包统一分发,KOC 简报硬性引用 1 个静音 RTB 镜头',
+        ],
+        outcome: '"扰邻焦虑"评论占比下降 50%,商品房用户转化率 +20-30%,客户咨询从"声音多大"转为"什么时候发货"',
+    },
+    {
+        id: 'A2', cat: 'A · 产品卖点', p: 'P0', t: '坡度参数明牌对比',
+        signal: '木塔塔晒坡度 15-20 + 星星不懂星星推易跑"-6 到 26"',
+        action: '简报必出"舒华 vs 易跑参数对比表",拦截"易跑"搜索流量,直接挖竞品墙脚',
+        why: '17 条评论里"易跑"被自然提及 1 次 = 用户已在对比阶段。健身硬核用户决策依赖参数,但本期 KOC 笔记几乎不晒参数,白白把这部分流量让给了竞品。明牌参数对比 = 拦截"易跑"搜索流量 + 锁定专业人群。',
+        how: [
+            '简报硬性出"舒华 vs 易跑参数对比表" (坡度/速度/马达/承重/降噪)',
+            'SEO 关键词加投: "易跑跑步机对比" / "易跑值得买吗"',
+            '专业 KOL 1-2 篇深度评测,拍真实使用场景',
+            '在评论区主动应战: 用户提竞品时官方账号给数据回应',
+        ],
+        outcome: '拦截 "易跑" 搜索流量 30%,专业用户决策周期 -50%,品牌专业度认知从 60 → 80 分',
+    },
+    {
+        id: 'A3', cat: 'A · 产品卖点', p: 'P0', t: '社恐居家健身专属内容线',
+        signal: '星星不懂星星/福建: 社恐+不爱挤健身房',
+        action: '5-10 篇专项内容锁定 i 人/社恐/独居场景,占领被易跑先占的细分心智',
+        why: '"社恐 / i 人 / 不去健身房" 是 2024-2025 小红书最大居家心智之一。竞品易跑已抢先占位,但市场远未饱和。舒华本身静音 + 折叠属性天然适合居家,只是没有把这个心智专门讲透。',
+        how: [
+            '5-10 篇专项笔记: 主题"社恐如何在家瘦 30 斤"/"i 人居家健身 30 天"',
+            'KOL 选号偏向"自我表达型 i 人"达人 (粉丝 5k-50k 即可)',
+            '内容必含: 不开摄像头 / 不和教练社交 / 自己节奏 3 个心智锚点',
+            '配套 SOP: 跑步机自动连接耳机 / App 一键开始训练',
+        ],
+        outcome: '社恐/居家细分心智份额建立,从竞品手里挖走 10-15% 用户',
+    },
+    {
+        id: 'A4', cat: 'A · 产品卖点', p: 'P1', t: '跑步机 × 课程包绑定',
+        signal: '兔子河南: "第一节课/回放课"',
+        action: '联名 Keep / 帕梅拉 / 刘畊宏,买机送 1 年课程 VIP,客单价翻 2-3 倍',
+        why: '跑步机是"硬件思维",但用户需要的是"训练效果"。捆绑顶流课程包 = 用软件价值溢价硬件,客单价从 2k 翻到 5-6k 不会让用户感到贵,反而觉得"超值"。',
+        how: [
+            '与 Keep / 帕梅拉 / 刘畊宏 1 家以上签深度合作',
+            '买机送 1 年课程 VIP (单买价值 ¥600-1000)',
+            '入门款机型搭课程版本独立 SKU,锁定首单转化',
+            '蒲公英 KOC 简报必引用"机器+课程"组合卖点',
+        ],
+        outcome: '客单价 ×2-3,首单转化率 +30%,差异化壁垒 (硬件竞品难以复刻)',
+    },
+    {
+        id: 'B1', cat: 'B · 内容形态', p: 'P1', t: '365 天蜕变长期 IP',
+        signal: '兔子湖南: 一年前奶茶不离手 → 一年后敢露肉了"换头"',
+        action: '招募 100 位真实用户做 1 年期 KOL,送机 + 月度回访,产出对比照,双 11/618 集中释放',
+        why: '"用户真实蜕变" 是跑步机最强转化素材,1 张前后对比照 > 100 篇 KOC 探店。但这种内容需要时间沉淀,不能一次性买。先种树,1 年后大丰收。',
+        how: [
+            '招募 100 位真实用户做 1 年期 IP (粉丝 1k-50k 不限)',
+            '免费送机 + 月度回访,内容创作支持',
+            '统一话题 #舒华 365 天蜕变,品牌官方账号集合分发',
+            '双 11/618 节点集中释放对比照,做爆款营销',
+        ],
+        outcome: '1 年后形成 100 个真实蜕变案例,每节点节省广告费 50% 以上,UGC 持续渗透长尾',
+    },
+    {
+        id: 'B2', cat: 'B · 内容形态', p: 'P0', t: 'UGC 参数交流模板',
+        signal: '木塔塔: 坡度 15-20/速度 4.2-4.5/心率 135-149',
+        action: '简报加入"晒你的训练参数"话题,App 自动生成参数分享卡,自然形成 UGC 素材库',
+        why: '"参数交流" 在跑步机社群是最自然的 UGC 形态,但目前几乎没有引导。一条用户晒参数的笔记 = 1 个免费 RTB 锚点,且能引发其他用户参数对比讨论。',
+        how: [
+            '简报加入"晒你的训练参数"话题,作为加分项',
+            'App 端自动生成训练参数分享卡 (1 键导出图片)',
+            '官方账号每周精选"本周最强参数"专题',
+            '建立训练参数排行榜,激励用户晒数据',
+        ],
+        outcome: '免费 UGC 素材库 +50 条/月,品牌专业度持续渗透,长尾 SEO 流量 +20%',
+    },
+    {
+        id: 'B3', cat: 'B · 内容形态', p: 'P0', t: '泛流量型升级为专业体验型',
+        signal: '形态错配反向信号: 泛流量型互动最低但产生最高质量评论',
+        action: '把"泛流量相关型"重命名为"专业体验交流型",下一轮投入比例从 12% 提到 30%',
+        why: '本期最大反直觉信号: "泛流量型" 笔记互动数据最差,但评论区出现的是最专业的用户对话 (参数 / 楼板 / 邻居)。说明这种形态吸引的是"质优"用户而非"量大"用户,只是被低估了。',
+        how: [
+            '把"泛流量相关型"重命名为"专业体验交流型"',
+            '下一轮投入比例从 12% 提到 30%',
+            '简报偏向引导用户参数交流 / 真实使用场景',
+            '考核指标从"互动率"切到"评论质量分" (专业评论占比)',
+        ],
+        outcome: '高质量评论占比 +50%,品牌专业人群心智渗透 ×2,长期复购率 +15%',
+    },
+    {
+        id: 'B4', cat: 'B · 内容形态', p: 'P1', t: '真实邻居访谈视频',
+        signal: '沐阳云南: 跑步机声 + 邻居反馈"没听到"',
+        action: '找 5 位老用户上门,让楼下邻居出镜确认,这是 KOL 软文做不到的真实信任',
+        why: 'KOL 说"很安静"用户半信半疑,KOL 楼下邻居说"没听到"用户立刻信任。第三方背书是降低决策门槛最锋利的内容形式。',
+        how: [
+            '招募 5 位老用户参与"邻居访谈"项目',
+            '上门拍摄: 跑步机使用 + 楼下邻居出镜反馈',
+            '剪成 1 分钟短视频,小红书 + 视频号同步',
+            '门店关键位置二维码引流',
+        ],
+        outcome: '"扰邻焦虑"心理门槛进一步降低,商品房用户决策周期 -30%',
+    },
+    {
+        id: 'C1', cat: 'C · 人群渠道', p: 'P0', t: 'KOC 性别/年龄结构调整',
+        signal: '本期 43 位 KOC 全为萌系女性昵称,跑步机决策人群错位',
+        action: '男性 30% + 宝爸宝妈 20% + 30+ 中产女性 10%,等于换一批用户',
+        why: '跑步机决策人 ≠ 萌系女性。家庭购买决策更多由男性 / 宝爸宝妈 / 30+ 中产驱动。当前 KOC 全为单身年轻女性,看起来"可爱"但不是真实购买人群,转化率天然低。',
+        how: [
+            'KOC 选号比例: 男性 30% + 宝爸宝妈 20% + 30+ 中产女性 10% + 年轻女性 40%',
+            '内容形态适配: 男性偏参数评测 / 宝爸宝妈偏家庭场景 / 中产偏品质生活',
+            '画像审核: 选号时验证粉丝主体年龄性别,避免"号是中产但粉丝是大学生"',
+            '建立 KOC 多维度黑灰白名单',
+        ],
+        outcome: '决策人群错位被纠正,到店/到电商转化率 +30-50%',
+    },
+    {
+        id: 'C2', cat: 'C · 人群渠道', p: 'P1', t: '商品房新业主精准包',
+        signal: '沐阳: "商品房 / 开发商问题"',
+        action: '定向 3 年内交付的高层公寓用户,这是扰邻焦虑最强的目标人群',
+        why: '商品房新业主 = 刚装修完 + 有居家运动需求 + 最在意扰邻 = 跑步机最优潜在客户群。目前没有任何渠道精准触达,纯靠泛流量碰运气。',
+        how: [
+            '与房产 KOC / 装修 KOC 合作,精准触达交付 3 年内业主',
+            '与房地产物业合作: 业主群发"扰邻友好家电推荐"',
+            '小红书"装修笔记"达人投放,植入跑步机',
+            '高层公寓集中区域线下广告 (电梯框架 / 社区入口)',
+        ],
+        outcome: '高意向商品房新业主触达 +1000 起步,客单价高于均值',
+    },
+    {
+        id: 'C3', cat: 'C · 人群渠道', p: 'P1', t: '减肥搭子社交营 (噪声资产化)',
+        signal: '47% 互助互赞噪声实为真实减肥群体寻找搭子',
+        action: '#舒华 30 天减肥搭子营 官方话题 + 企微私域 + 月度 PK 赛事,把噪声变长效资产',
+        why: '本期评论里 47% 互赞互助 "噪声",其实是真实的减肥群体在寻找运动搭子。把"噪声"变成"社群资产" = 把流量变成用户。',
+        how: [
+            '推 #舒华 30 天减肥搭子营 官方话题 (公司账号背书)',
+            '小红书群 + 企微私域承接报名',
+            '月度 PK 赛事 + 实物奖励 (每月轻奢 SKU)',
+            '完赛用户给优惠 / 老带新返利',
+        ],
+        outcome: '私域用户 +5000 起步,长期复购率 ×2,内容生态自循环',
+    },
+    {
+        id: 'C4', cat: 'C · 人群渠道', p: 'P0', t: '一线 + 新一线 IP 占比 ≥ 50%',
+        signal: '本期评论 IP 缺京沪深广杭蓉',
+        action: '跑步机是大件家居,一线城市才有支付力 + 居住空间,选号必须明确 IP 配比',
+        why: '跑步机客单价 2k+ 是大件家居,需要支付力 + 居住空间。一线/新一线人群是核心。本期 IP 严重缺一线,投放打到了价格敏感人群。',
+        how: [
+            'KOC 选号硬性规定: 一线 + 新一线 IP 占比 ≥ 50% (北上广深 + 杭州/成都/武汉)',
+            'IP 验证作为蒲公英结案核心指标',
+            '一线城市同步投放线下广告 (社区/健身房/物业)',
+            '新一线节点城市做品牌活动',
+        ],
+        outcome: '客单价 +15-20%,触达决策人群更精准,品牌势能提升',
+    },
+    {
+        id: 'D1', cat: 'D · 投放机制', p: 'P0', t: '类目标签从家居/好物迁到健身/减脂',
+        signal: '本期挂"家居 22 + 好物 21",但搜索词是"跑步机推荐/家用跑步机"',
+        action: '简报锁定 SEO 标签 居家健身 / 减脂塑形 / 跑步机推荐 / 健身房替代',
+        why: '"家居/好物"标签竞争激烈且与"跑步机"心智弱关联;"健身/减脂/居家健身"才是用户真实搜索路径。换标签 = 换流量池,免费降本。',
+        how: [
+            '简报硬性要求: 标签必含"居家健身/减脂塑形/跑步机推荐/健身房替代"',
+            '禁用"家居好物"等泛标签',
+            '关键词扩展: "家用跑步机选购" / "小户型跑步机" 等长尾词',
+            '考核 SEO 流量入口占比 ≥ 30%',
+        ],
+        outcome: 'SEO 流量入口 +50-100%,搜索流量获客成本下降 30%',
+    },
+    {
+        id: 'D2', cat: 'D · 投放机制', p: 'P1', t: 'MCN 来源审计 + 多源选号',
+        signal: '粉丝量 1k-2k 高度同质,疑似单一 MCN 包号',
+        action: '≥ 3 家 MCN + ≥ 20% 蒲公英直选 + ≥ 10% 自建池 + 粉丝阶梯化金字塔结构',
+        why: '本期 KOC 粉丝量过度集中 1k-2k,疑似单一 MCN 提供"扁平池",这种号有刷数据嫌疑且互动质量低。多 MCN + 直选打散来源,保证内容生态多样性。',
+        how: [
+            '≥ 3 家不同 MCN 提供候选号',
+            '≥ 20% 蒲公英直选 (跳过 MCN)',
+            '≥ 10% 自建 KOC 池 (品牌培育)',
+            '粉丝量阶梯: 头部 5% / 腰部 30% / 尾部 65%',
+        ],
+        outcome: '内容生态多样性提升,刷量风险下降,长尾流量稳定',
+    },
+    {
+        id: 'D3', cat: 'D · 投放机制', p: 'P2', t: '7 天上门试驾 O2O',
+        signal: '星星不懂星星山东: "免费体验欢迎来锻炼"',
+        action: '借鉴戴森/特斯拉,跑步机 7 天上门 + 不满意退款,降低决策门槛,KOC 矩阵推广',
+        why: '跑步机决策成本高 (大件 + 占地 + 长期使用),7 天试驾 = 把决策门槛拆到地板。戴森吸尘器 / 特斯拉试驾都是验证过的成熟模型。',
+        how: [
+            '7 天上门试驾, 不满意 100% 退款',
+            'KOC 矩阵推广"试用日记"内容',
+            '配套售后 SOP: 退货免费上门取',
+            '小红书 / 抖音"7 天试驾打卡"话题运营',
+        ],
+        outcome: '决策门槛大幅降低,转化率 ×1.5-2,试驾用户复购率 +50%',
+    },
+    {
+        id: 'E1', cat: 'E · 数据机制', p: 'P0', t: '投后 24h 抓取 + 博主行为预警',
+        signal: 'xlsx 19 评论 → API 17, 缺失 2 条 (可能博主自删)',
+        action: '24h 内首版数据快照,捕捉删评/删笔记信号,识别评论区翻车风险',
+        why: '本次复盘发现 xlsx 报备 19 条评论 → API 实际抓到 17 条,差额 2 条可能是博主自删。这是评论区出现负面/翻车的强信号,但我们目前无法及时发现。',
+        how: [
+            '采集脚本固化为 24h 自动定时任务',
+            '建立"博主自删评论"预警 (报备 vs 实抓差额 ≥ 3 即告警)',
+            '对应 KOC 客服跟进核实是否有翻车',
+            '建立长期 KOC 风险数据库',
+        ],
+        outcome: '评论区翻车从"事后才知道"变成"6h 内介入",品牌信任度兜底',
+    },
+    {
+        id: 'E2', cat: 'E · 数据机制', p: 'P1', t: '3 天数据保护期 + 死笔记自动补流',
+        signal: '11/43 篇互动 < 5,33/43 篇产出极差 = ¥7000+ 浪费',
+        action: '投后 3 天数据 < 阈值的笔记,自动触发 ¥30-50 薯条二次投流补救,而非直接放弃',
+        why: '本期 11/43 篇互动 < 5,长尾零产出占 26%,这部分预算几乎是沉没成本。机制化止损 + 二次投流 = 把死笔记救回来。',
+        how: [
+            '投后 72h 自动检查互动数据',
+            '互动 < 5: 自动追加 ¥30-50 薯条二次抢救',
+            '抢救后仍 < 10: 标记 KOC 为低效 (3 次失败拉黑)',
+            '建立 KOC 历史投放表现数据库',
+        ],
+        outcome: '长尾零互动篇数下降 30-50%,投放 ROI 持续优化',
+    },
 ];
 
 const TOP5 = ['A1', 'A2', 'C1', 'B3', 'E1'];
@@ -244,9 +510,9 @@ const topicRows = TOPICS.map((t) => {
     </tr>`;
 }).join('');
 
-const realCommentList = realComments.sort((a, b) => b.like - a.like).slice(0, 12).map((c) => `
+const realCommentList = topPicks.map(({ topic, c }) => `
 <div class="quote">
-  <div class="quote-meta"><span class="tag">${esc(c.koc)}</span> <span class="text-xs text-3">${esc(c.type || '')} · ${esc(c.ip || '')} · 赞 ${c.like}</span></div>
+  <div class="quote-meta"><span class="tag green">${esc(topic)}</span> <span class="tag gray">${esc(c.koc)}</span> <span class="text-xs text-3">${esc(c.ip || '')}</span></div>
   <div class="quote-text">${esc(c.content.replace(/\n/g, ' '))}</div>
 </div>`).join('');
 
@@ -296,7 +562,7 @@ section::before { content: attr(data-num); position: absolute; top: 32px; right:
 .grid { display: grid; gap: 22px; }
 .grid-2 { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }
 .grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
-.grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
+.grid-4 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
 
 .card { background: linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0.005) 100%), var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 28px; transition: transform 0.3s, border-color 0.3s; }
 .card:hover { transform: translateY(-3px); border-color: var(--border-strong); }
@@ -305,10 +571,10 @@ section::before { content: attr(data-num); position: absolute; top: 32px; right:
 .card-rose { border-left: 3px solid var(--rose); }
 .card-blue { border-left: 3px solid var(--blue); }
 
-.metric { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 28px; position: relative; overflow: hidden; }
+.metric { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 24px; position: relative; overflow: hidden; min-width: 0; }
 .metric::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, var(--amber), transparent); opacity: 0.6; }
 .metric-label { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--text-3); margin-bottom: 10px; }
-.metric-value { font-family: var(--font-head); font-weight: 800; font-size: clamp(2rem, 3.6vw, 3rem); letter-spacing: -0.03em; line-height: 1; }
+.metric-value { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.6rem, 2.6vw, 2.3rem); letter-spacing: -0.03em; line-height: 1.05; word-break: break-all; }
 .metric-unit { font-family: var(--font-mono); font-size: 0.85rem; color: var(--amber); font-weight: 500; margin-left: 4px; }
 .metric-sub { margin-top: 14px; font-size: 0.82rem; color: var(--text-2); line-height: 1.5; }
 
@@ -456,8 +722,8 @@ td.sample { color: var(--text-2); font-size: 0.82rem; max-width: 380px; }
       </div>
     </div>
 
-    <h3 class="h2">真实评论原声 (Top 12 by 点赞)</h3>
-    <p class="sub">已剔除互赞互助噪声,展示具有产品对话价值的真实评论。</p>
+    <h3 class="h2">真实评论原声 (Top ${topPicks.length})</h3>
+    <p class="sub">产品强相关 · 多主题轮询 · 已剔除噪声/托式营销/博主自评,展示具有产品对话价值的真实评论。</p>
     <div class="grid grid-2">${realCommentList}</div>
   </div>
 </section>
@@ -562,41 +828,89 @@ td.sample { color: var(--text-2); font-size: 0.82rem; max-width: 380px; }
       }).join('')}
     </div>
 
-    <h3 class="h2">完整 ${OPPORTUNITIES.length} 个新机会矩阵</h3>
-    <p class="sub">按 5 大象限分类: <span class="tag" style="margin-right:8px">A 产品卖点</span><span class="tag green" style="margin-right:8px">B 内容形态</span><span class="tag purple" style="margin-right:8px">C 人群渠道</span><span class="tag blue" style="margin-right:8px">D 投放机制</span><span class="tag rose">E 数据机制</span></p>
-
-    <div class="grid grid-2">
-      ${['A · 产品卖点','B · 内容形态','C · 人群渠道','D · 投放机制','E · 数据机制'].map((cat) => {
-          const list = OPPORTUNITIES.filter((o) => o.cat === cat);
-          const colorClass = cat.startsWith('A') ? 'card-accent' : cat.startsWith('B') ? 'card-green' : cat.startsWith('C') ? '' : cat.startsWith('D') ? 'card-blue' : 'card-rose';
-          const tagClass = cat.startsWith('A') ? '' : cat.startsWith('B') ? 'green' : cat.startsWith('C') ? 'purple' : cat.startsWith('D') ? 'blue' : 'rose';
-          return `<div class="card ${colorClass}">
-            <h3 class="h2" style="margin-top:0;margin-bottom:18px">${esc(cat)}</h3>
-            ${list.map((o) => `
-              <div style="padding:14px 0;border-bottom:1px solid var(--border)">
-                <div style="display:flex;gap:8px;align-items:center;margin-bottom:6px;flex-wrap:wrap">
-                  <span class="tag ${tagClass}" style="font-family:var(--font-mono)">${o.id}</span>
-                  <span class="tag ${o.p === 'P0' ? 'rose' : o.p === 'P1' ? '' : 'purple'}">${o.p}</span>
-                  <strong style="font-size:0.96rem">${esc(o.t)}</strong>
-                </div>
-                <p style="color:var(--text-3);font-size:0.74rem;margin-bottom:4px">📍 ${esc(o.signal)}</p>
-                <p style="color:var(--text-2);font-size:0.84rem;line-height:1.6">→ ${esc(o.action)}</p>
-              </div>
-            `).join('')}
-          </div>`;
-      }).join('')}
+    <p class="sub" style="margin-top:32px">完整 ${OPPORTUNITIES.length} 个新机会按 5 大象限分独立章节深度展开,见下方 Section 06.A ~ 06.E。</p>
+    <div class="toc" style="margin-top:24px">
+      <a href="#sec-6a" style="border-color:var(--amber);color:var(--amber)">06.A 产品卖点 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('A')).length})</a>
+      <a href="#sec-6b" style="border-color:var(--green);color:var(--green)">06.B 内容形态 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('B')).length})</a>
+      <a href="#sec-6c" style="border-color:var(--purple);color:var(--purple)">06.C 人群渠道 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('C')).length})</a>
+      <a href="#sec-6d" style="border-color:var(--blue);color:var(--blue)">06.D 投放机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('D')).length})</a>
+      <a href="#sec-6e" style="border-color:var(--rose);color:var(--rose)">06.E 数据机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('E')).length})</a>
     </div>
 
-    <h3 class="h2">方法论 — 4 条挖掘原则</h3>
+    <h3 class="h2" style="margin-top:48px">方法论 — 4 条挖掘原则</h3>
     <div class="grid grid-4">
-      <div class="card"><div class="tag">原则 1</div><h4 style="margin:10px 0">小样本不影响信号方向</h4><p style="color:var(--text-2);font-size:0.84rem">1 条专业参数评论 = 1 个产品价值锚点,**信号密度** > 统计显著性</p></div>
-      <div class="card"><div class="tag green">原则 2</div><h4 style="margin:10px 0">每条评论都是潜在购买者</h4><p style="color:var(--text-2);font-size:0.84rem">不是数据,是真人,值得**逐字解读** — 词序、表情、IP 全有意义</p></div>
+      <div class="card"><div class="tag">原则 1</div><h4 style="margin:10px 0">小样本不影响信号方向</h4><p style="color:var(--text-2);font-size:0.84rem">1 条专业参数评论 = 1 个产品价值锚点,<strong>信号密度</strong> > 统计显著性</p></div>
+      <div class="card"><div class="tag green">原则 2</div><h4 style="margin:10px 0">每条评论都是潜在购买者</h4><p style="color:var(--text-2);font-size:0.84rem">不是数据,是真人,值得<strong>逐字解读</strong> — 词序、表情、IP 全有意义</p></div>
       <div class="card"><div class="tag purple">原则 3</div><h4 style="margin:10px 0">反直觉信号 > 平均值</h4><p style="color:var(--text-2);font-size:0.84rem">"泛流量型"互动最低却产生最高质量对话 — 这就是被低估的机会</p></div>
-      <div class="card"><div class="tag rose">原则 4</div><h4 style="margin:10px 0">缺席与出现同等重要</h4><p style="color:var(--text-2);font-size:0.84rem">一线 IP 缺席、男性 KOC 缺席、品牌词命中 0 — **"没有"才是最大的机会**</p></div>
+      <div class="card"><div class="tag rose">原则 4</div><h4 style="margin:10px 0">缺席与出现同等重要</h4><p style="color:var(--text-2);font-size:0.84rem">一线 IP 缺席、男性 KOC 缺席、品牌词命中 0 — <strong>"没有"才是最大的机会</strong></p></div>
     </div>
   </div>
 </section>
 
+${(() => {
+    const QUADRANTS = [
+        { letter: 'A', cat: 'A · 产品卖点', color: 'amber', tagClass: '', accent: 'card-accent', desc: '从用户评论里反推的产品/卖点级机会 — 把"用户已经说出口"的需求变成可执行的内容指引/SKU/卖点。' },
+        { letter: 'B', cat: 'B · 内容形态', color: 'green', tagClass: 'green', accent: 'card-green', desc: '内容打法升级 — 同样的预算,如何把"被低估的内容形态"翻转成主战场。' },
+        { letter: 'C', cat: 'C · 人群渠道', color: 'purple', tagClass: 'purple', accent: '', desc: '人群和渠道的二八优化 — 让每一分预算都投在"会真买跑步机"的人身上,而不是看了不下单的远方观众。' },
+        { letter: 'D', cat: 'D · 投放机制', color: 'blue', tagClass: 'blue', accent: 'card-blue', desc: '投放过程的机制化 — 把"凭感觉发笔记"变成"算法驱动止损/加投/预警",每轮都比上轮更聪明。' },
+        { letter: 'E', cat: 'E · 数据机制', color: 'rose', tagClass: 'rose', accent: 'card-rose', desc: '长效数据资产 — 投后快照、博主行为预警,这是可以持续复用 N 轮投放的底层基建。' },
+    ];
+    return QUADRANTS.map((q) => {
+        const list = OPPORTUNITIES.filter((o) => o.cat === q.cat);
+        return `
+<!-- ============= 6.${q.letter} ${q.cat} ============= -->
+<section id="sec-6${q.letter.toLowerCase()}" data-num="06.${q.letter} / ${q.cat.split('·')[1].trim()}" style="justify-content:flex-start">
+  <div class="inner">
+    <div class="eyebrow" style="color:var(--${q.color})">Section 06.${q.letter} · ${q.cat}</div>
+    <h2 class="h1" style="color:var(--${q.color})">${esc(q.cat)} <span style="color:var(--text-3);font-size:0.5em;font-weight:500">${list.length} 个新机会</span></h2>
+    <p class="sub">${esc(q.desc)}</p>
+
+    <div class="grid" style="gap:28px;margin-top:32px">
+      ${list.map((o) => `
+      <div class="card ${q.accent}" style="position:relative">
+        <div style="position:absolute;top:18px;right:24px;font-family:var(--font-mono);font-size:2.4rem;font-weight:800;color:var(--${q.color});opacity:0.15;line-height:1">${o.id}</div>
+        <div style="display:flex;gap:10px;align-items:center;margin-bottom:14px;flex-wrap:wrap">
+          <span class="tag ${q.tagClass}" style="font-family:var(--font-mono);font-size:0.8rem">${o.id}</span>
+          <span class="tag ${o.p === 'P0' ? 'rose' : o.p === 'P1' ? '' : 'purple'}">${o.p}</span>
+          <h3 style="font-family:var(--font-head);font-size:1.4rem;font-weight:700;letter-spacing:-0.01em">${esc(o.t)}</h3>
+        </div>
+
+        <div class="grid grid-3" style="gap:18px;margin-top:18px">
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">📍 信号 / Signal</div>
+            <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.signal)}</p>
+          </div>
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">🎯 行动 / Action</div>
+            <p style="color:var(--text-1);font-size:0.88rem;line-height:1.65;font-weight:500">${esc(o.action)}</p>
+          </div>
+          <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
+            <div class="metric-label" style="margin-bottom:8px">📈 预期 / Outcome</div>
+            <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.outcome || '-')}</p>
+          </div>
+        </div>
+
+        <div style="margin-top:22px;padding:20px;background:var(--bg-0);border-radius:8px">
+          <div class="metric-label" style="margin-bottom:10px">💡 为什么要做 / Why</div>
+          <p style="color:var(--text-2);font-size:0.92rem;line-height:1.75">${esc(o.why || '-')}</p>
+        </div>
+
+        ${Array.isArray(o.how) && o.how.length ? `
+        <div style="margin-top:18px;padding:20px;background:var(--bg-0);border-radius:8px">
+          <div class="metric-label" style="margin-bottom:12px">🛠️ 如何执行 / How (${o.how.length} 步)</div>
+          <ol style="margin:0;padding-left:24px;color:var(--text-2);font-size:0.9rem;line-height:1.85">
+            ${o.how.map((step) => `<li style="margin-bottom:6px">${esc(step)}</li>`).join('')}
+          </ol>
+        </div>
+        ` : ''}
+      </div>
+      `).join('')}
+    </div>
+  </div>
+</section>`;
+    }).join('');
+})()}
+
 <!-- ============= 页脚 ============= -->
 <section style="min-height:auto;padding:60px 24px;background:var(--bg-1)" data-num="END">
   <div class="inner" style="text-align:center">
@@ -771,10 +1085,10 @@ for (const t of TOPICS) {
 }
 M('');
 
-M('### 真实评论原声 Top 12 (剔除噪声)');
+M(`### 真实评论原声 Top ${topPicks.length} (产品强相关 · 多主题轮询)`);
 M('');
-for (const c of realComments.sort((a,b)=>b.like-a.like).slice(0,12)) {
-    M(`- **[${c.koc}/${c.type||'-'}]** \`${c.nick||'-'}@${c.ip||'-'}\` *(赞 ${c.like})*: ${c.content.replace(/\n/g,' ')}`);
+for (const { topic, c } of topPicks) {
+    M(`- **[${topic}]** \`${c.koc}@${c.ip||'-'}\`: ${c.content.replace(/\n/g,' ')}`);
 }
 M('');
 M('---');

File diff suppressed because it is too large
+ 739 - 218
shuhua/shuhua-closing-report.html


+ 11 - 12
shuhua/shuhua-closing-report.md

@@ -1,6 +1,6 @@
 # 舒华跑步机 · 四月小红书 KOC 宣发 结案报告
 
-> **投放期间**: 2026-04 · **生成时间**: 2026-05-14 11:21:33  
+> **投放期间**: 2026-04 · **生成时间**: 2026-05-14 13:23:59  
 > **数据范围**: 43 位 KOC + 17 条公开评论 (覆盖 7/43 篇笔记)
 
 ---
@@ -97,17 +97,16 @@
 | 竞品提及 | 1 | 5.9% | [星星不懂星星@福建] 我买易跑,坡度-6到26爬坡跑步都很爽,再也不用去健身房和人挤了,对于我这种社恐的人很适合 |
 | 效果/见证/打卡 | 1 | 5.9% | [兔子@湖南] 救命!谁能看出这是同一个人啊?! <2025.05.01-2026.05.01,365> 一年前:走路都嫌累,奶茶不离手 一年后:健身房常客,拍照敢露肉了 说真 |
 
-### 真实评论原声 Top 12 (剔除噪声)
-
-- **[兔子/效果展示型]** `-@湖南` *(赞 0)*: 救命!谁能看出这是同一个人啊?! <2025.05.01-2026.05.01,365> 一年前:走路都嫌累,奶茶不离手 一年后:健身房常客,拍照敢露肉了 说真的,健身真的能让人“换头”(物理+精神双重意义上) ​[派对R][派对R][派对R]
-- **[兔子/效果展示型]** `-@河南` *(赞 0)*: 还在拉伸,第一节课还是回放课[捂脸R][捂脸R]
-- **[木塔塔/泛流量相关型]** `-@浙江` *(赞 0)*: 坡度15-20,速度4.2-4.5,心率135-149,我觉得还不错
-- **[沐阳/泛流量相关型]** `-@湖南` *(赞 0)*: 吵的都是商品房[偷笑R]开发商的问题
-- **[沐阳/泛流量相关型]** `-@江苏` *(赞 0)*: 其实跑步机减震可以没有这个问题
-- **[沐阳/泛流量相关型]** `-@云南` *(赞 0)*: 只爬坡,遇到楼下邻居就问能不能听到我们跑步机声,问了几次他们都说没听到,不过我们房子楼板非常扎实,白天在家光脚追猫跑都不会有“咚咚咚”的回声
-- **[到了/疑问互动型]** `-@-` *(赞 0)*: 111互
-- **[星星不懂星星/踩坑反转种草型]** `-@福建` *(赞 0)*: 我买易跑,坡度-6到26爬坡跑步都很爽,再也不用去健身房和人挤了,对于我这种社恐的人很适合
-- **[星星不懂星星/踩坑反转种草型]** `-@山东` *(赞 0)*: dd我免费体验哦欢迎大家来来锻炼[赞R]
+### 真实评论原声 Top 8 (产品强相关 · 多主题轮询)
+
+- **[静音减震]** `沐阳@云南`: 只爬坡,遇到楼下邻居就问能不能听到我们跑步机声,问了几次他们都说没听到,不过我们房子楼板非常扎实,白天在家光脚追猫跑都不会有“咚咚咚”的回声
+- **[专业参数]** `星星不懂星星@福建`: 我买易跑,坡度-6到26爬坡跑步都很爽,再也不用去健身房和人挤了,对于我这种社恐的人很适合
+- **[场景体验]** `兔子@湖南`: 救命!谁能看出这是同一个人啊?! <2025.05.01-2026.05.01,365> 一年前:走路都嫌累,奶茶不离手 一年后:健身房常客,拍照敢露肉了 说真的,健身真的能让人“换头”(物理+精神双重意义上) ​[派对R][派对R][派对R]
+- **[静音减震]** `沐阳@江苏`: 其实跑步机减震可以没有这个问题
+- **[专业参数]** `木塔塔@浙江`: 坡度15-20,速度4.2-4.5,心率135-149,我觉得还不错
+- **[静音减震]** `沐阳@湖南`: 吵的都是商品房[偷笑R]开发商的问题
+- **[其他真实声音]** `兔子@河南`: 还在拉伸,第一节课还是回放课[捂脸R][捂脸R]
+- **[其他真实声音]** `星星不懂星星@山东`: dd我免费体验哦欢迎大家来来锻炼[赞R]
 
 ---
 

Some files were not shown because too many files changed in this diff