lactic-v2-ch1-adult.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // ==============================================================================
  2. // 乳酸菌 v2 · Ch1 成人乳酸菌素片 · 品类机会(Step 2)
  3. // ==============================================================================
  4. // 1.1 成人乳酸菌素片 VOC 全景 · 平台×情感×主题
  5. // 1.2 成人品类机会点 · 竞品差异化空白
  6. // 1.3 品类核心机会提炼 · 可向儿童迁移的信号
  7. // ==============================================================================
  8. const LA = require('./lactic-analyze.js');
  9. const C = require('./lactic-components.js');
  10. // 去掉 #tag 段,只保留正文文本
  11. const stripTags = s => String(s || '').replace(/#[^\s#]+/g, '').trim();
  12. const { BRAND, esc, renderSectionHead, renderVocCard, renderVocGrid,
  13. renderStatStrip, renderBarChart, renderCompareTable, renderInsightHero,
  14. renderFindingCard, renderDecisionList, renderTagCloud } = C;
  15. // ============================================================
  16. // 1.1 成人 VOC 全景
  17. // ============================================================
  18. function renderSub1({ chapter: c, subIdx, sub, slideNum, slideTotal, data, meta }) {
  19. const items = data?.items || [];
  20. // 筛选成人乳酸菌素片相关 VOC(排除明确儿童关键词)
  21. const childKw = /儿童|宝宝|小孩|婴儿|幼儿|妈咪|3岁|6岁|12岁/i;
  22. const adultKw = /乳酸菌素片|整肠生|培菲康|金双岐|肠炎宁/i;
  23. const adultItems = items.filter(it => {
  24. const txt = `${it.keyword || ''} ${it.product || ''} ${it.content || ''}`;
  25. return adultKw.test(txt) && !childKw.test(it.keyword || '');
  26. });
  27. // 情感分布
  28. const sentiments = {};
  29. adultItems.forEach(it => {
  30. const s = it.sentiment || 'neutral';
  31. sentiments[s] = (sentiments[s] || 0) + 1;
  32. });
  33. // 主题提取
  34. const topicMap = {
  35. '腹泻/拉肚子': /腹泻|拉肚子|拉稀|闹肚子/i,
  36. '便秘/排便': /便秘|排便|通便|大便/i,
  37. '消化不良/胃胀': /消化|胃胀|不消化|积食/i,
  38. '菌群失调': /菌群|微生态|失调|紊乱/i,
  39. '抗生素后调理': /抗生素|消炎药|抗菌/i,
  40. '口味/剂型': /口味|好吃|难吃|咀嚼|奶片/i,
  41. '安全性/副作用': /安全|副作用|无害|放心/i,
  42. '效果/见效': /有效|管用|见效|好转|没用|没效/i,
  43. };
  44. const topicStats = Object.entries(topicMap).map(([name, re]) => ({
  45. label: name,
  46. value: adultItems.filter(it => re.test(it.content || '')).length,
  47. color: BRAND.WARM_ORANGE,
  48. })).sort((a, b) => b.value - a.value);
  49. // 成人 VOC 证据卡(stripTags 去掉 #tag 后再匹配,避免纯 hashtag 帖入选)
  50. const probioticRe = /益生菌|乳酸菌|肠道|便秘|腹泻|消化|菌群|活菌|拉肚子|肠胃|调理|双歧|鼠李糖/i;
  51. const substantiveAdult = adultItems.filter(it => stripTags(it.content).length >= 30 && probioticRe.test(stripTags(it.content)));
  52. const adultEvidence = LA.getEvidence(substantiveAdult, { top: 4, seed: 11, minChars: 20 });
  53. return `<section class="report-section" id="${c.key}-${subIdx}" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  54. <div class="section-inner">
  55. ${renderSectionHead({
  56. eyebrow: `${c.num}.${subIdx} · ADULT VOC LANDSCAPE`,
  57. title: sub,
  58. subtitle: '王总要求:"先看一下这些成人整个乳酸菌素片用药的 VOC"',
  59. color: c.color,
  60. })}
  61. ${renderStatStrip([
  62. { num: adultItems.length, label: '成人相关 VOC', color: c.color },
  63. { num: sentiments.positive || 0, label: '好评', color: BRAND.JIANG_GREEN },
  64. { num: sentiments.negative || 0, label: '差评', color: BRAND.CORAL },
  65. { num: sentiments.conflicted || 0, label: '矛盾', color: BRAND.WARM_ORANGE },
  66. ])}
  67. <div style="margin-top:24px;">
  68. ${renderBarChart(topicStats.slice(0, 8), { accent: c.color, title: '成人乳酸菌素片 VOC 主题分布', height: 280 })}
  69. </div>
  70. <div style="margin-top:24px;">
  71. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:14px; font-weight:700;">成人 VOC 原声卡片</div>
  72. ${renderVocGrid(adultEvidence, { columns: 2, accent: c.color })}
  73. </div>
  74. ${renderFindingCard({
  75. icon: '💡',
  76. title: '成人 VOC 全景:腹泻和消化不良是两大核心痛点',
  77. body: '成人乳酸菌素片的使用场景集中在 <strong>腹泻调理</strong> 和 <strong>消化不良</strong>,其次是抗生素后的菌群恢复。这些需求在儿童场景中同样存在——为 Step 3 的机会迁移奠定基础。',
  78. accent: c.color,
  79. })}
  80. </div>
  81. </section>`;
  82. }
  83. // ============================================================
  84. // 1.2 成人品类机会点 · 竞品差异化空白
  85. // ============================================================
  86. function renderSub2({ chapter: c, subIdx, sub, slideNum, slideTotal, data, meta }) {
  87. const items = data?.items || [];
  88. // 竞品对比数据
  89. const competitors = [
  90. { name: '整肠生(地衣芽孢杆菌)', type: '药品', strength: '医生信任高', weakness: '胶囊剂型、儿童难用', opportunity: '成人主战场,儿童缺位' },
  91. { name: '培菲康(双歧杆菌三联活菌)', type: '药品', strength: '三菌协同', weakness: '需冷链、价格高', opportunity: '冷链痛点可突破' },
  92. { name: '金双岐(双歧杆菌)', type: '药品', strength: '品牌老、渠道广', weakness: '剂型老旧', opportunity: '品牌老化留出空间' },
  93. { name: '妈咪爱(枯草杆菌+肠球菌)', type: '药品', strength: '儿童第一心智', weakness: '散剂喂药难', opportunity: '剂型可突破' },
  94. { name: '合生元益生菌', type: '食品', strength: '营销强、口碑好', weakness: '非药品无功效背书', opportunity: 'OTC 身份差异化' },
  95. { name: '万益蓝益生菌', type: '食品', strength: '网红种草', weakness: '价格贵、效果争议', opportunity: '性价比空间' },
  96. ];
  97. return `<section class="report-section" id="${c.key}-${subIdx}" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  98. <div class="section-inner">
  99. ${renderSectionHead({
  100. eyebrow: `${c.num}.${subIdx} · COMPETITOR GAP`,
  101. title: sub,
  102. subtitle: '成人市场竞品格局 × 差异化空白分析',
  103. color: c.color,
  104. })}
  105. ${renderCompareTable({
  106. title: '成人肠道微生态竞品矩阵',
  107. headers: ['产品', '身份', '核心优势', '核心弱点', '乳酸菌素片机会'],
  108. rows: competitors.map(cp => [
  109. { html: `<strong>${esc(cp.name)}</strong>`, bold: true },
  110. cp.type,
  111. cp.strength,
  112. { html: `<span style="color:${BRAND.CORAL};">${esc(cp.weakness)}</span>`, color: BRAND.CORAL },
  113. { html: `<span style="color:${BRAND.JIANG_GREEN};">${esc(cp.opportunity)}</span>`, color: BRAND.JIANG_GREEN },
  114. ]),
  115. accent: c.color,
  116. })}
  117. ${renderInsightHero({
  118. eyebrow: 'GAP ANALYSIS',
  119. title: '成人市场三大差异化空白',
  120. subtitle: `
  121. <strong style="color:${BRAND.JIANG_GREEN};">① 非冷链便携</strong>:培菲康/亿活需冷链,乳酸菌素片常温保存(王总纠正:妈咪爱也不用冷链,25°C 以下即可)<br/>
  122. <strong style="color:${BRAND.JIANG_GREEN};">② OTC 药品信任 + 食品级体验</strong>:合生元/万益蓝是食品无功效背书,整肠生是药品但体验差——乳酸菌素片可以两头占<br/>
  123. <strong style="color:${BRAND.JIANG_GREEN};">③ 咀嚼片剂型</strong>:奶片口感 + 不用水 + 孩子爱吃——这是从成人向儿童迁移的核心武器
  124. `,
  125. color: c.color,
  126. })}
  127. ${renderDecisionList([
  128. '乳酸菌素片的核心差异化 = <strong>OTC 药品身份 + 咀嚼片剂型 + 常温保存</strong>',
  129. '成人市场竞争激烈但格局分散——没有绝对龙头',
  130. '成人→儿童的迁移桥梁:咀嚼片剂型天然适配儿童',
  131. '关注妈咪爱"不用冷链"这个特性——不是我们的独有优势',
  132. ], { accent: c.color, title: 'DECISION · 品类机会判断' })}
  133. </div>
  134. </section>`;
  135. }
  136. // ============================================================
  137. // 1.3 品类核心机会提炼
  138. // ============================================================
  139. function renderSub3({ chapter: c, subIdx, sub, slideNum, slideTotal, data, meta }) {
  140. const items = data?.items || [];
  141. // 找成人 VOC 中暗含儿童信号的
  142. const childSignal = items.filter(it => {
  143. const kw = it.keyword || '';
  144. const childKw = /儿童|宝宝|小孩|妈咪/i;
  145. if (childKw.test(kw)) return false; // 排除本身就是儿童关键词的
  146. const content = it.content || '';
  147. return /小孩|宝宝|孩子|女儿|儿子|闺女|给娃/i.test(content);
  148. });
  149. const childProbRe = /益生菌|乳酸菌|肠|便秘|消化|积食|拉肚|吸收|喂药|抗生素/i;
  150. const substSignal = (childSignal.length > 0 ? childSignal : items)
  151. .filter(it => stripTags(it.content).length >= 30 && childProbRe.test(stripTags(it.content)));
  152. const signalEvidence = LA.getEvidence(substSignal, { top: 3, seed: 17, minChars: 20 });
  153. return `<section class="report-section" id="${c.key}-${subIdx}" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  154. <div class="section-inner">
  155. ${renderSectionHead({
  156. eyebrow: `${c.num}.${subIdx} · OPPORTUNITY DISTILL`,
  157. title: sub,
  158. subtitle: '从成人品类机会中提炼可向儿童迁移的核心信号',
  159. color: c.color,
  160. })}
  161. <div style="display:grid; grid-template-columns:repeat(3, 1fr); gap:18px;">
  162. ${[
  163. { title: '肠道日常调理', desc: '成人市场最大需求:腹泻/便秘/消化不良的日常调理。儿童同样存在,且家长更焦虑。', migrable: true, color: BRAND.JIANG_GREEN },
  164. { title: '抗生素后恢复', desc: '成人用抗生素后补菌群。儿童生病用抗生素更频繁,家长更担心副作用。', migrable: true, color: BRAND.LACTIC_MINT },
  165. { title: '口味/便携需求', desc: '成人对口味不太在意,但咀嚼片"像奶片"的特性天然适合儿童。', migrable: true, color: BRAND.SKY_BLUE },
  166. ].map(item => `
  167. <div style="padding:22px; background:${item.color}08; border:1px solid ${item.color}33; border-radius:var(--radius-md);">
  168. <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
  169. <div class="text-mono text-xs" style="color:${item.color}; font-weight:700;">${esc(item.title)}</div>
  170. ${item.migrable ? `<span style="padding:2px 8px; background:${BRAND.JIANG_GREEN}15; color:${BRAND.JIANG_GREEN}; border-radius:10px; font-size:0.66rem; font-weight:700;">✓ 可迁移</span>` : ''}
  171. </div>
  172. <div style="color:var(--text-1); font-size:0.86rem; line-height:1.65;">${esc(item.desc)}</div>
  173. </div>`).join('')}
  174. </div>
  175. ${childSignal.length > 0 ? `
  176. <div style="margin-top:24px;">
  177. <div class="text-mono text-xs" style="color:${BRAND.BERRY_PINK}; letter-spacing:0.15em; margin-bottom:14px; font-weight:700;">
  178. 成人 VOC 中的儿童信号 · ${childSignal.length} 条含"孩子/宝宝/女儿/儿子"
  179. </div>
  180. ${renderVocGrid(signalEvidence, { columns: 3, accent: BRAND.BERRY_PINK, compact: true })}
  181. </div>` : `
  182. <div style="margin-top:24px; padding:20px; background:${BRAND.BERRY_PINK}08; border:1px dashed ${BRAND.BERRY_PINK}44; border-radius:var(--radius-md); text-align:center;">
  183. <div style="color:${BRAND.BERRY_PINK}; font-size:0.88rem;">成人 VOC 中儿童信号较少——这将在 Ch2 通过专门的儿童 VOC 补充</div>
  184. </div>`}
  185. ${renderFindingCard({
  186. icon: '🔄',
  187. title: '向 Ch2 传递:三条可迁移机会',
  188. body: '① <strong>肠道日常调理</strong>(最大需求·直接可迁移)→ ② <strong>抗生素后恢复</strong>(儿童更高频)→ ③ <strong>咀嚼片剂型优势</strong>(天然适配儿童)。Ch2 将验证这些机会在儿童端的真实需求强度。',
  189. accent: BRAND.BERRY_PINK,
  190. })}
  191. </div>
  192. </section>`;
  193. }
  194. module.exports = { renderSub1, renderSub2, renderSub3 };