voc-validation-render.js 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222
  1. // ==============================================================================
  2. // 江中肝纯片 · VOC 验证报告渲染模块(PPT 式 deck · 10亿 × 4渠道 × 5模块)
  3. // 严格对标《docs/jiangzhong/1.VOC方向定位.md》的 4 维 × 5 模块框架
  4. // 质量对标《产品复合体报告》(552KB / 36 slides),本报告只能更高不能更低
  5. // ==============================================================================
  6. //
  7. // 核心转向:从上一份"复合配方"(NAC+硫辛酸)概念修正到真实产品
  8. // → 藤茶 DMY(二氢杨梅素)单成分差异化 · 中国特有草本
  9. //
  10. // Slide 结构(36 张,7 章节):
  11. // 01 · 封面 Cover
  12. // 02 · 目录 Agenda
  13. // 03 · Chapter 1 Divider · VOC 方法论
  14. // 04-08 · 1.1 - 1.5 方法论 5 子章
  15. // 09 · Chapter 2 Divider · 包装调研
  16. // 10-14 · 2.1 - 2.5 包装 5 子章
  17. // 15 · Chapter 3 Divider · 定价调研
  18. // 16-19 · 3.1 - 3.4 定价 4 子章
  19. // 20 · Chapter 4 Divider · 定位与话术
  20. // 21-25 · 4.1 - 4.5 定位 5 子章
  21. // 26 · Chapter 5 Divider · 场景适配
  22. // 27-30 · 5.1 - 5.4 4 渠道子章
  23. // 31 · Chapter 6 Divider · 竞品认知
  24. // 32-37 · 6.1 - 6.6 竞品 6 子章(实际 slide 数 38+,可扩)
  25. // 38 · Chapter 7 Divider · 落地行动
  26. // 39-42 · 7.1 - 7.4 落地 4 子章
  27. //
  28. // 本批次 (Batch 1) 实现:cover + agenda + 7 个章节分割页 + Ch1 方法论 5 子章 + 框架装配
  29. // 后续批次填充 Ch2-7 内容 slides
  30. // ==============================================================================
  31. const STYLES = require('../voc-styles.js');
  32. const SCRIPTS = require('../voc-scripts.js');
  33. // 分析器(封面需要真实汇总数据)
  34. const VOCA = require('./analyze.js');
  35. // Ch2 包装调研 5 子章
  36. const PKG = require('./chapters/ch2-package.js');
  37. // Ch3 定价调研 4 子章
  38. const PRC = require('./chapters/ch3-pricing.js');
  39. // Ch4 定位与话术 5 子章
  40. const POS = require('./chapters/ch4-positioning.js');
  41. // Ch5 场景适配 4 渠道
  42. const SCN = require('./chapters/ch5-scene.js');
  43. // Ch6 竞品认知 6 竞品
  44. const CMP = require('./chapters/ch6-competitor.js');
  45. // Ch7 落地行动 4 子章
  46. const ACT = require('./chapters/ch7-action.js');
  47. // ============================================================
  48. // 常量:主题色 / 章节元信息
  49. // ============================================================
  50. const BRAND = {
  51. JIANG_GREEN: '#2D9C5D', // 江中主色(方法论/落地)
  52. LIVER_AMBER: '#D4A574', // 护肝琥珀(包装/礼品渠道)
  53. TECH_BLUE: '#0085CA', // 科技信任蓝(定价/药线渠道)
  54. WARM_ORANGE: '#FF8C42', // 温暖橙(场景/餐饮)
  55. ROSE: '#FF4D8D', // 玫瑰(竞品/情绪)
  56. PURPLE: '#8B5CF6', // 紫色(定位/话术)
  57. CYAN: '#14B8A6', // 青色(辅助色)
  58. };
  59. // 4 渠道颜色映射(场景章使用)
  60. const CHANNEL_COLORS = {
  61. '药线': BRAND.TECH_BLUE,
  62. '礼品': BRAND.LIVER_AMBER,
  63. '餐饮': BRAND.WARM_ORANGE,
  64. '电商': BRAND.JIANG_GREEN,
  65. };
  66. const CHAPTERS = [
  67. { id: 1, num: '1', key: 'method', title: 'VOC 方法论', en: 'METHODOLOGY', tone: 'green', color: BRAND.JIANG_GREEN, icon: '🧭',
  68. summary: '10亿目标 × 4 渠道 × 5 模块 × 多平台评论颗粒度验证框架' },
  69. { id: 2, num: '2', key: 'package', title: '包装调研', en: 'PACKAGE', tone: 'amber', color: BRAND.LIVER_AMBER, icon: '📦',
  70. summary: '破解"土"的问题,对标 Swisse 轻奢中式风 · 药线板装 + 高端礼盒双形态' },
  71. { id: 3, num: '3', key: 'pricing', title: '定价调研', en: 'PRICING', tone: 'blue', color: BRAND.TECH_BLUE, icon: '💰',
  72. summary: '药线/电商/礼品分渠道价位带 × 规格 × 竞品定价参照' },
  73. { id: 4, num: '4', key: 'positioning',title: '定位与话术', en: 'POSITIONING', tone: 'purple', color: BRAND.PURPLE, icon: '🎯',
  74. summary: '藤茶 DMY 差异化心智 × 解酒社交货币 × 安全无副作用话术' },
  75. { id: 5, num: '5', key: 'scene', title: '场景适配', en: 'SCENE-FIT', tone: 'orange', color: BRAND.WARM_ORANGE, icon: '🎬',
  76. summary: '药线 / 礼品 / 餐饮 / 电商 4 渠道场景 VOC 独立验证' },
  77. { id: 6, num: '6', key: 'competitor', title: '竞品认知', en: 'COMPETITOR', tone: 'rose', color: BRAND.ROSE, icon: '⚔️',
  78. summary: '护肝片/易善复/片仔癀/熊胆粉/Swisse/海王金樽 6 大竞品 VOC 拆解' },
  79. { id: 7, num: '7', key: 'action', title: '落地行动', en: 'ACTION', tone: 'green', color: BRAND.JIANG_GREEN, icon: '🚀',
  80. summary: '优先级矩阵 × 决策阈值达标 × 10亿 4 渠道拆解路径' },
  81. ];
  82. // 各章节 subsections 清单(对标 docs/jiangzhong/1.VOC方向定位.md 5 模块)
  83. const CHAPTER_SUBSECTIONS = {
  84. 'method': [
  85. '10亿目标×4渠道拆解', '5 模块×决策阈值', '多平台采集矩阵', '评论颗粒度分析框架', '可做/不可做边界',
  86. ],
  87. 'package': [
  88. '现状诊断·"土"的 VOC 印证', '外包装偏好(Swisse风 vs 中式轻奢 vs 铁盒)', '内包装形态(瓶装/板装/锡纸片)', '片剂外观(形状/纹理/口感)', '礼品规格 × SKU 矩阵',
  89. ],
  90. 'pricing': [
  91. '分渠道定价区间', '规格-价格带(12/60/120片)', '竞品定价参照', '价格-价值感知匹配度',
  92. ],
  93. 'positioning': [
  94. '藤茶/DMY 概念认知度', '安全无副作用话术·药食同源', '解酒场景话术 AB 测试', '社交货币话术·酒局面子', '分渠道话术适配 × 差异化记忆点',
  95. ],
  96. 'scene': [
  97. '药线场景·合规+长期', '礼品场景·颜值+体面', '餐饮场景·便携+体感', '电商场景·性价比+差异化',
  98. ],
  99. 'competitor': [
  100. '护肝片·副作用/品牌老化', '易善复·胃肠反应/西药感', '片仔癀·天价/稀缺', '熊胆粉·寒凉/伦理', 'Swisse/汤臣倍健·水飞蓟弱体感', '海王金樽·失败复盘',
  101. ],
  102. 'action': [
  103. '优先级矩阵(P0/P1)', '决策阈值达标表(70%/80%)', '10亿拆解×4渠道落地', '下阶段衔接',
  104. ],
  105. };
  106. // 每章节首段 hero line(分割页用)
  107. const CHAPTER_HERO_LINES = {
  108. 'method': '基于会议确认的 <strong style="color:#2D9C5D;">4 大核心维度 × 5 调研模块</strong>,锁定"能做(包装/定价/话术/渠道)"与"不能做(名字/批文/配方/剂型)"边界,所有 VOC 采集均服务于 <strong style="color:#D4A574;">10 亿规模 × 药线3亿 + 礼品2.5亿 + 餐饮2.5亿 + 电商2亿</strong>落地。',
  109. 'package': '现包装被内部判定"土",VOC Top #1 问题。对标 <strong style="color:#D4A574;">Swisse 轻奢风 + 中式草本元素(藤茶纹/白霜DMY)</strong>,双形态:药线 <strong style="color:#0085CA;">铝塑板装</strong>(12片×2板合规陈列)+ 礼品 <strong style="color:#D4A574;">高端瓶装/礼盒</strong>(2瓶/4瓶)。',
  110. 'pricing': '摆脱"保健品定价天花板"。药线板装低价引流(¥25-40 / 12片)、电商瓶装中端日常(¥89-139 / 60片)、礼品礼盒高端溢价(¥298-498 / 4瓶)。参照 Swisse 水飞蓟 ¥158 和易善复 OTC ¥45 的定价参照系。',
  111. 'positioning': '唯一壁垒:<strong style="color:#8B5CF6;">藤茶 DMY(二氢杨梅素)</strong>,区别水飞蓟宾/奶蓟草的新一代中式草本。三重全场景护肝:解酒(加速乙醛代谢)+脂肪肝(激活AMPK)+药物肝(增强谷胱甘肽),支撑"应酬分一片"<strong style="color:#FF4D8D;">社交货币</strong>心智。',
  112. 'scene': '四大渠道本质不同:<strong style="color:#0085CA;">药线看合规</strong>(医生/药师推荐意愿)、<strong style="color:#D4A574;">礼品看颜值</strong>(送礼体面度)、<strong style="color:#FF8C42;">餐饮看体感</strong>(解酒即时反馈 + 分食社交)、<strong style="color:#2D9C5D;">电商看差异</strong>(藤茶 DMY vs 水飞蓟)。',
  113. 'competitor': '拆解 <strong style="color:#FF4D8D;">6 大竞品 VOC</strong>:药品(护肝片/易善复/片仔癀/熊胆粉)被吐槽"副作用/寒凉/天价/像治病";保健品(Swisse/水飞蓟类)被吐槽"吸收差/没体感";解酒品(海王金樽)被复盘"成分无解酒靶点 + 像治病药 + 无社交属性"—— 每一个痛点都是江中肝纯的切入点。',
  114. 'action': '基于 VOC 验证结果,按 <strong style="color:#2D9C5D;">决策阈值(包装偏好 70% / 定价接受 80% / 定位认可 80%)</strong>筛选方案,产出 <strong style="color:#0085CA;">4 渠道落地 PRD</strong> + <strong style="color:#D4A574;">SKU 矩阵</strong> + <strong style="color:#FF8C42;">Q1-Q4 节奏</strong>,闭环 10 亿路径。',
  115. };
  116. const TOTAL_SLIDES = 42; // 2 + (7 章 × (1 divider + 3-6 子章)) ≈ 42
  117. // ============================================================
  118. // utils(与 compound-liver-render 保持一致,方便日后合并)
  119. // ============================================================
  120. function esc(s) {
  121. return String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
  122. }
  123. function fmtNum(n) {
  124. if (n == null || isNaN(n)) return '—';
  125. if (n >= 10000) return (n / 10000).toFixed(1).replace(/\.0$/, '') + 'w';
  126. if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
  127. return String(n);
  128. }
  129. function fmtMoney(n) {
  130. if (n == null) return '—';
  131. return '¥' + Number(n).toLocaleString('zh-CN');
  132. }
  133. function sn(n) { return String(n).padStart(2, '0'); }
  134. function star(score, max = 5) {
  135. const full = Math.round(score);
  136. return '★'.repeat(full) + '☆'.repeat(max - full);
  137. }
  138. // ============================================================
  139. // 共用组件
  140. // ============================================================
  141. function renderNav() {
  142. const dots = [
  143. { tip: '封面', href: '#s0' },
  144. { tip: '目录', href: '#agenda' },
  145. ...CHAPTERS.map((c) => ({ tip: `${c.num} ${c.title}`, href: `#${c.key}` })),
  146. ];
  147. return `<nav class="nav-rail" aria-label="章节导航">
  148. ${dots.map((d, i) => `<a class="nav-dot${i === 0 ? ' active' : ''}" href="${d.href}" data-tip="${esc(d.tip)}" data-idx="${i}"></a>`).join('')}
  149. </nav>
  150. <div class="top-bar">
  151. <div class="brand-logo">江中<span class="dot">·</span>产品开发部 / 肝纯片 VOC 验证报告 v1.0</div>
  152. <div class="text-mono text-xs" style="color:var(--text-3);">BRAIN·HACK / VOC × 10亿×4渠道 × 藤茶DMY</div>
  153. </div>`;
  154. }
  155. function renderKbdHint() {
  156. return `<div class="kbd-hint" id="kbdHint">
  157. <span>键盘切换</span>
  158. <kbd>↑</kbd><kbd>↓</kbd>
  159. <span>或</span>
  160. <kbd>PgUp</kbd><kbd>PgDn</kbd>
  161. </div>`;
  162. }
  163. // ============================================================
  164. // Slide 01 · 封面
  165. // ============================================================
  166. function renderCover({ product, A, collectedAt, slideNum, slideTotal }) {
  167. // 从分析器直接拉真实汇总数据(覆盖旧 fallback 默认值 45/350)
  168. const ext = VOCA.loadExtended();
  169. const meta = VOCA.getMeta(ext);
  170. const totalComments = meta.comments || 0;
  171. const totalNotes = meta.notes || 0;
  172. const totalKeywords = meta.keywords || 0;
  173. const xhsComments = meta.platforms?.xhs || 0;
  174. const douyinComments = meta.platforms?.douyin || 0;
  175. const amazonComments = meta.platforms?.amazon || 0;
  176. const platformCount = Object.values(meta.platforms || {}).filter((n) => n > 0).length || 3;
  177. // 数字格式化助手
  178. const fmtK = (n) => {
  179. if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
  180. return String(n);
  181. };
  182. const revenueTarget = '10 亿';
  183. const channelCount = 4;
  184. return `<section class="report-section" id="s0" data-tone="amber" data-slide-num="${slideNum}/${slideTotal}" style="min-height:100vh;padding:0;">
  185. <div class="cover-hero">
  186. <div class="aurora" aria-hidden="true"><span></span><span></span><span></span></div>
  187. <div class="cover-grid-bg"></div>
  188. <div class="cover-content">
  189. <div class="cover-meta rise-in">
  190. <span>江中 / 产品开发部 / 2026 · ${esc(product)} · VOC 验证报告</span>
  191. </div>
  192. <div class="cover-title-stack">
  193. <p class="text-mono text-amber rise-in" style="font-size:0.9rem;letter-spacing:0.2em;margin-bottom:18px;">VOC × MULTI-PLATFORM × COMMENT-LEVEL</p>
  194. <h1 class="cover-title rise-in">${esc(product)}<br/><span style="color:${BRAND.LIVER_AMBER}; -webkit-text-fill-color:${BRAND.LIVER_AMBER}; background:none; font-size:0.7em;">VOC 验证报告</span></h1>
  195. <p class="text-poster rise-in" style="margin-top:20px;color:var(--text-2); font-size:1.5rem;">
  196. 10 亿目标 · 4 渠道 × 5 模块 · 藤茶 DMY 差异化
  197. </p>
  198. </div>
  199. <p class="cover-sub fade-up">
  200. 围绕 <strong class="text-amber">江中内部会议确认</strong>的 4 核心维度 × 5 调研模块,
  201. 跨 <strong class="text-amber">${platformCount}</strong> 平台
  202. (<strong class="text-amber">小红书 ${fmtK(xhsComments)}</strong> + <strong class="text-amber">抖音 ${fmtK(douyinComments)}</strong> + <strong class="text-amber">Amazon ${fmtK(amazonComments)}</strong>)
  203. × <strong class="text-amber">${totalKeywords}</strong> 关键词 ·
  204. <strong class="text-amber">${totalNotes}</strong> 笔记/视频/产品 ·
  205. <strong class="text-amber">${totalComments.toLocaleString()}</strong> 条评论颗粒度真实原声,
  206. 验证 <strong style="color:${BRAND.LIVER_AMBER};">包装 / 定价 / 定位话术 / 场景适配 / 竞品认知</strong>五大维度 × <strong style="color:${BRAND.LIVER_AMBER};">H1-H8 8 条假设</strong>,
  207. 输出可直接落地的 <strong style="color:${BRAND.TECH_BLUE};">4 渠道 PRD + SKU 矩阵</strong>,闭环 <strong style="color:${BRAND.LIVER_AMBER};">10 亿</strong> 路径。
  208. </p>
  209. <div class="cover-stats fade-up" style="grid-template-columns:repeat(6, 1fr); max-width:1100px;">
  210. <div class="cover-stat"><div class="num">${revenueTarget}</div><div class="lbl">营收目标</div></div>
  211. <div class="cover-stat"><div class="num">${totalComments.toLocaleString()}</div><div class="lbl">真实评论</div></div>
  212. <div class="cover-stat"><div class="num">${platformCount}</div><div class="lbl">采集平台</div></div>
  213. <div class="cover-stat"><div class="num">${totalKeywords}</div><div class="lbl">关键词</div></div>
  214. <div class="cover-stat"><div class="num">${channelCount}</div><div class="lbl">核心渠道</div></div>
  215. <div class="cover-stat"><div class="num">${slideTotal}</div><div class="lbl">slides</div></div>
  216. </div>
  217. <p class="text-mono text-xs fade-up" style="margin-top:64px; color:var(--text-3);">SCROLL DOWN · 数据采集 ${esc(collectedAt || new Date().toISOString().slice(0, 10))} · ${totalComments.toLocaleString()} 条真实 VOC</p>
  218. </div>
  219. </div>
  220. </section>`;
  221. }
  222. // ============================================================
  223. // Slide 02 · 目录 Agenda
  224. // ============================================================
  225. function renderAgenda({ slideNum, slideTotal }) {
  226. return `<section class="report-section" id="agenda" data-tone="amber" data-slide-num="${slideNum}/${slideTotal}">
  227. <div class="section-inner">
  228. <div class="section-head rise-in">
  229. <div class="section-eyebrow">CONTENTS · 目录总览</div>
  230. <h2 class="text-h1"><span class="headline-anim">VOC 验证 · 7 章节全景</span></h2>
  231. <p class="section-sub">从方法论到落地行动 · 每一章都以 <strong class="text-amber">多平台评论颗粒度</strong>真实 VOC 证据驱动 · 每一步都可以直接指向产品 PRD 和 4 渠道铺货</p>
  232. </div>
  233. <div class="grid" style="grid-template-columns:repeat(2, 1fr); gap:24px; margin-top:20px;">
  234. ${CHAPTERS.map((c, i) => `
  235. <a href="#${c.key}" class="fade-up" style="text-decoration:none; display:block; background:var(--bg-1); border:1px solid var(--border); border-left:4px solid ${c.color}; border-radius:var(--radius-md); padding:28px; transition:all .35s cubic-bezier(.2,.7,.2,1); position:relative; overflow:hidden;" onmouseover="this.style.transform='translateY(-4px)'; this.style.borderColor='${c.color}'; this.style.boxShadow='0 20px 60px -20px ${c.color}55'" onmouseout="this.style.transform='translateY(0)'; this.style.borderColor='var(--border)'; this.style.boxShadow='none'">
  236. <div style="position:absolute; top:-20px; right:-10px; font-family:var(--font-head); font-weight:900; font-size:9rem; line-height:1; color:${c.color}; opacity:.08; letter-spacing:-0.06em; pointer-events:none;">${c.num}</div>
  237. <div style="display:flex; justify-content:space-between; align-items:start; margin-bottom:16px;">
  238. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.18em; font-weight:700;">CH ${c.num} · ${c.en}</div>
  239. <div style="font-size:1.8rem; filter:grayscale(20%);">${c.icon}</div>
  240. </div>
  241. <h3 class="text-h2" style="margin:0 0 12px; color:var(--text-1); font-size:1.55rem;">${esc(c.title)}</h3>
  242. <p style="color:var(--text-2); font-size:0.92rem; line-height:1.6; margin-bottom:14px;">${esc(c.summary)}</p>
  243. <div style="display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;">
  244. ${(CHAPTER_SUBSECTIONS[c.key] || []).slice(0, 5).map((sub, j) => `<span style="padding:3px 9px; background:${c.color}15; color:${c.color}; border-radius:3px; font-size:0.68rem; font-weight:600;">${c.num}.${j + 1} ${esc(sub)}</span>`).join('')}
  245. </div>
  246. <div style="padding-top:14px; border-top:1px solid var(--border); display:flex; justify-content:space-between; align-items:center;">
  247. <span class="text-xs text-mono" style="color:var(--text-3); letter-spacing:0.12em;">→ 跳转章节</span>
  248. <span class="text-mono text-xs" style="color:${c.color};">${i + 1} / ${CHAPTERS.length}</span>
  249. </div>
  250. </a>`).join('')}
  251. </div>
  252. <div class="fade-up" style="margin-top:48px; padding:24px 28px; background:linear-gradient(135deg, ${BRAND.LIVER_AMBER}08, ${BRAND.JIANG_GREEN}06); border:1px solid ${BRAND.LIVER_AMBER}22; border-radius:var(--radius-md);">
  253. <div class="text-mono text-xs" style="color:${BRAND.LIVER_AMBER}; letter-spacing:0.15em; margin-bottom:10px;">METHODOLOGY · 方法论自律</div>
  254. <div style="color:var(--text-1); font-size:1rem; line-height:1.7;">
  255. 本报告严格遵循《<strong style="color:${BRAND.JIANG_GREEN};">docs/jiangzhong/1.VOC方向定位.md</strong>》会议确认的 <strong>能做 / 不能做</strong>边界:<br/>
  256. <strong style="color:${BRAND.LIVER_AMBER};">✅ 可调研</strong>:包装(外/内/片剂外观/规格)、定价(分渠道×规格)、话术(藤茶/DMY/解酒/社交)、场景(4 渠道适配)、竞品认知;<br/>
  257. <strong style="color:${BRAND.ROSE};">❌ 不调研</strong>:产品名字、批文、配方、剂型(片剂形态不可改,但三角形/纹理可调);<br/>
  258. 每一个结论都附 <strong style="color:${BRAND.JIANG_GREEN};">多平台 VOC 真实原声</strong>(小红书/抖音/知乎/电商) + <strong style="color:${BRAND.TECH_BLUE};">竞品对比数据</strong> + <strong style="color:${BRAND.LIVER_AMBER};">决策阈值量化</strong>(≥70% / ≥80%)三重交叉验证。
  259. </div>
  260. </div>
  261. </div>
  262. </section>`;
  263. }
  264. // ============================================================
  265. // Chapter Divider · 章节分割页(复用组件)
  266. // ============================================================
  267. function renderChapterDivider({ slideNum, slideTotal, chapter, subsections, heroLine }) {
  268. const c = chapter;
  269. return `<section class="report-section" id="${c.key}" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}" style="justify-content:center;">
  270. <div class="section-inner">
  271. <div class="rise-in" style="text-align:center; margin-bottom:48px;">
  272. <div class="text-mono" style="color:${c.color}; letter-spacing:0.35em; font-size:0.8rem; margin-bottom:20px;">CHAPTER ${c.num} · ${c.en}</div>
  273. <h1 style="font-family:var(--font-head); font-weight:900; font-size:clamp(4rem, 10vw, 8rem); line-height:0.92; letter-spacing:-0.04em; color:#fff; background:linear-gradient(135deg, #fff 30%, ${c.color} 100%); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; margin:0 0 18px;">
  274. ${esc(c.title)}
  275. </h1>
  276. <p class="text-poster" style="font-size:clamp(1.2rem, 2.2vw, 1.8rem); color:var(--text-2); font-weight:500; max-width:820px; margin:0 auto; line-height:1.5;">${esc(c.summary)}</p>
  277. </div>
  278. ${heroLine ? `<div class="fade-up" style="max-width:920px; margin:0 auto 40px; padding:28px 36px; background:rgba(255,255,255,0.02); border-left:4px solid ${c.color}; border-radius:0 var(--radius-md) var(--radius-md) 0;">
  279. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:10px;">KEY TAKE · 本章核心</div>
  280. <div style="font-size:1.15rem; line-height:1.75; color:var(--text-1);">${heroLine}</div>
  281. </div>` : ''}
  282. <div class="grid fade-up" style="grid-template-columns:repeat(${Math.min(subsections.length, 6)}, 1fr); gap:14px; max-width:1100px; margin:0 auto;">
  283. ${subsections.map((sub, i) => `
  284. <div style="background:var(--bg-1); border:1px solid var(--border); border-radius:var(--radius-md); padding:18px 16px; display:flex; flex-direction:column; gap:8px; border-top:2px solid ${c.color};">
  285. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.1em; font-weight:700;">${c.num}.${i + 1}</div>
  286. <div style="font-weight:700; font-size:0.86rem; color:var(--text-1); line-height:1.35;">${esc(sub)}</div>
  287. </div>`).join('')}
  288. </div>
  289. <div class="fade-up text-mono text-xs" style="margin-top:56px; text-align:center; color:var(--text-3); letter-spacing:0.2em;">
  290. ↓ 滚动查看 ${subsections.length} 个子章节展开
  291. </div>
  292. </div>
  293. </section>`;
  294. }
  295. // ============================================================
  296. // Slide Placeholder · 还未填充的 slide 使用
  297. // ============================================================
  298. function renderSubPlaceholder({ slideNum, slideTotal, chapterKey, subIndex, title }) {
  299. const c = CHAPTERS.find((x) => x.key === chapterKey);
  300. return `<section class="report-section" id="${chapterKey}-${subIndex}" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  301. <div class="section-inner">
  302. <div class="section-head rise-in">
  303. <div class="section-eyebrow" style="color:${c.color};">${c.num}.${subIndex} · TBD</div>
  304. <h2 class="text-h1"><span class="headline-anim">${esc(title)}</span></h2>
  305. <p class="section-sub">本子章节将在后续 Batch 中填充 · 完整数据采集后基于评论颗粒度 VOC 证据呈现</p>
  306. </div>
  307. <div class="fade-up" style="padding:56px 40px; background:var(--bg-1); border:1px dashed ${c.color}66; border-radius:var(--radius-md); text-align:center;">
  308. <div style="font-size:3rem; margin-bottom:14px; opacity:0.5;">${c.icon}</div>
  309. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:12px;">PLACEHOLDER / TO BE FILLED</div>
  310. <div style="color:var(--text-2); font-size:0.96rem; line-height:1.7; max-width:680px; margin:0 auto;">
  311. 基于《1.VOC方向定位.md》会议框架,本子章节需要 <strong style="color:${c.color};">多平台评论颗粒度采集</strong>后填充,<br/>
  312. 采集渠道:小红书 / 抖音 / 知乎 / 电商评论 / 丁香医生;<br/>
  313. 预计样本量:<strong style="color:${c.color};">≥100 条</strong>真实 VOC 评论 + 量化主题词云。
  314. </div>
  315. </div>
  316. </div>
  317. </section>`;
  318. }
  319. // ============================================================
  320. // Final Slide · 下一步行动(占位,等 Ch7 填充后切换)
  321. // ============================================================
  322. function renderNextSteps({ slideNum, slideTotal }) {
  323. return `<section class="report-section" id="next" data-tone="green" data-slide-num="${slideNum}/${slideTotal}">
  324. <div class="section-inner">
  325. <div class="section-head rise-in">
  326. <div class="section-eyebrow" style="color:${BRAND.JIANG_GREEN};">EPILOGUE · 下一步</div>
  327. <h2 class="text-h1"><span class="headline-anim">从 VOC 验证到 10 亿落地</span></h2>
  328. <p class="section-sub">本报告为 <strong style="color:${BRAND.JIANG_GREEN};">江中肝纯片 2026 Q1 新品上市</strong>提供 VOC 证据底座,下阶段承接产品立项 PRD × 4 渠道铺货 × 营销复合体</p>
  329. </div>
  330. <div class="fade-up" style="background:linear-gradient(135deg, ${BRAND.JIANG_GREEN}10, ${BRAND.LIVER_AMBER}08); border:2px solid ${BRAND.JIANG_GREEN}44; border-radius:var(--radius-md); padding:36px; text-align:center;">
  331. <div class="text-mono text-xs" style="color:${BRAND.JIANG_GREEN}; letter-spacing:0.2em; margin-bottom:14px;">READY TO LAUNCH · 2026 Q1-Q4</div>
  332. <h3 style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:var(--text-1); margin:0 0 20px;">
  333. <span style="color:${BRAND.TECH_BLUE};">药线 3亿</span> +
  334. <span style="color:${BRAND.LIVER_AMBER};">礼品 2.5亿</span> +
  335. <span style="color:${BRAND.WARM_ORANGE};">餐饮 2.5亿</span> +
  336. <span style="color:${BRAND.JIANG_GREEN};">电商 2亿</span> = <strong>10 亿</strong>
  337. </h3>
  338. <div style="color:var(--text-2); font-size:1rem; line-height:1.7; max-width:780px; margin:0 auto;">
  339. 本 VOC 验证报告 <strong style="color:${BRAND.LIVER_AMBER};">藤茶 DMY 单成分差异化</strong> + <strong style="color:${BRAND.JIANG_GREEN};">4 渠道精准适配</strong>为战略底座,可直接对接 2026 Q1 上市准备、产品复合体方案(升级版)、营销复合体方案、海报 AI 提示词体系。
  340. </div>
  341. </div>
  342. </div>
  343. </section>`;
  344. }
  345. // ============================================================================
  346. // ============ Chapter 1 · VOC 方法论 · 5 子章完整内容 ========================
  347. // ============================================================================
  348. // ----- 1.1 10亿目标 × 4渠道拆解 · Revenue Target Decomposition ---------------
  349. function renderMethod1RevenueTarget({ slideNum, slideTotal, chapter, A }) {
  350. const c = chapter;
  351. const channels = [
  352. {
  353. name: '药线', en: 'MEDICAL', icon: '🏥', color: BRAND.TECH_BLUE,
  354. target: 3.0, share: 30, sku: '板装 12片×2板 / 60片瓶装(白底标准蓝绿)',
  355. mainSite: '药店(一心堂/大参林/老百姓)+ 医院便民药房 + 医药流通',
  356. userProfile: '执业药师 / 消化科/肝病科医生 / 长期服用护肝用户',
  357. pricePoint: '¥25-40(板装)/ ¥79-119(瓶装)',
  358. coreHook: '"对化学性肝损伤有辅助保护"蓝帽合规 · 长期服用安全 · 与药物同服无冲突',
  359. growth: '+350%(对标易善复 OTC 柜)',
  360. },
  361. {
  362. name: '礼品', en: 'GIFT', icon: '🎁', color: BRAND.LIVER_AMBER,
  363. target: 2.5, share: 25, sku: '高端礼盒 2瓶/4瓶(磨砂玻璃+草本纹)',
  364. mainSite: '节日/商务送礼场景 · 品牌官方旗舰店 · 高端商超专柜',
  365. userProfile: '25-55岁 商务/节日送礼 · 关注健康+注重体面',
  366. pricePoint: '¥298-498(2瓶)/ ¥598-898(4瓶)',
  367. coreHook: '"中国藤茶·新中式轻奢礼盒"有面子有健康价值 · 区别普通保健品',
  368. growth: '+420%(对标 Swisse 礼盒)',
  369. },
  370. {
  371. name: '餐饮', en: 'DINING', icon: '🍷', color: BRAND.WARM_ORANGE,
  372. target: 2.5, share: 25, sku: '便携锡纸板装 12片 · 单片小包装',
  373. mainSite: '饭店 / KTV / 商务宴会 · 社交酒局 · 企业团购',
  374. userProfile: '25-45岁 应酬男 · 老板/中高层管理 · 注重面子社交',
  375. pricePoint: '¥29-39(12片便携装)',
  376. coreHook: '"酒局掏出分一片"DMY 即时解酒体感 · 社交货币属性',
  377. growth: '+800%(对标海王金樽失败复盘)',
  378. },
  379. {
  380. name: '电商', en: 'ECOMMERCE', icon: '💻', color: BRAND.JIANG_GREEN,
  381. target: 2.0, share: 20, sku: '瓶装 60片日常装 / 多规格矩阵',
  382. mainSite: '天猫 / 京东 / 拼多多 / 抖音小店 · 品牌旗舰店',
  383. userProfile: '20-50岁 线上购买保健品习惯 · 关注性价比+差异化',
  384. pricePoint: '¥89-139(60片)/ 组合装¥169-259',
  385. coreHook: '"藤茶DMY vs 水飞蓟"差异化科普 + 会员复购 + 一物一码',
  386. growth: '+180%(对标 Swisse 天猫)',
  387. },
  388. ];
  389. const totalTarget = 10.0;
  390. return `<section class="report-section" id="method-1" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  391. <div class="section-inner">
  392. <div class="section-head rise-in">
  393. <div class="section-eyebrow" style="color:${c.color};">${c.num}.1 · REVENUE TARGET DECOMPOSITION</div>
  394. <h2 class="text-h1"><span class="headline-anim">10 亿目标 · 4 渠道营收拆解</span></h2>
  395. <p class="section-sub">基于会议确认的 <strong style="color:${c.color};">10 亿目标 × 4 渠道分工</strong>,每个渠道独立的 SKU / 定价 / 用户画像 / 增长参照系</p>
  396. </div>
  397. <!-- 10 亿总览 SVG 饼图 -->
  398. <div class="fade-up" style="background:var(--bg-1); border:1px solid var(--border); border-radius:var(--radius-md); padding:28px; margin-bottom:28px;">
  399. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:16px;">TARGET BREAKDOWN · 10亿 × 4 渠道分布(饼图)</div>
  400. <div style="display:grid; grid-template-columns:320px 1fr; gap:32px; align-items:center;">
  401. <svg viewBox="0 0 200 200" style="width:100%; max-width:320px;">
  402. <defs>
  403. ${channels.map((ch, i) => `
  404. <linearGradient id="gradCh${i}" x1="0" y1="0" x2="1" y2="1">
  405. <stop offset="0" stop-color="${ch.color}" stop-opacity="0.85"/>
  406. <stop offset="1" stop-color="${ch.color}" stop-opacity="1"/>
  407. </linearGradient>
  408. `).join('')}
  409. </defs>
  410. ${(() => {
  411. let startAngle = -Math.PI / 2;
  412. return channels.map((ch, i) => {
  413. const angle = (ch.share / 100) * Math.PI * 2;
  414. const endAngle = startAngle + angle;
  415. const largeArc = angle > Math.PI ? 1 : 0;
  416. const x1 = 100 + Math.cos(startAngle) * 80;
  417. const y1 = 100 + Math.sin(startAngle) * 80;
  418. const x2 = 100 + Math.cos(endAngle) * 80;
  419. const y2 = 100 + Math.sin(endAngle) * 80;
  420. const midAngle = (startAngle + endAngle) / 2;
  421. const lx = 100 + Math.cos(midAngle) * 52;
  422. const ly = 100 + Math.sin(midAngle) * 52;
  423. const result = `
  424. <path d="M 100,100 L ${x1.toFixed(2)},${y1.toFixed(2)} A 80,80 0 ${largeArc} 1 ${x2.toFixed(2)},${y2.toFixed(2)} Z" fill="url(#gradCh${i})" stroke="var(--bg-0)" stroke-width="2"/>
  425. <text x="${lx.toFixed(2)}" y="${ly.toFixed(2)}" text-anchor="middle" font-family="ui-sans-serif" font-size="14" font-weight="900" fill="#fff">${ch.share}%</text>
  426. <text x="${lx.toFixed(2)}" y="${(ly + 16).toFixed(2)}" text-anchor="middle" font-family="ui-sans-serif" font-size="10" font-weight="700" fill="#fff" opacity="0.9">${ch.icon} ${esc(ch.name)}</text>
  427. `;
  428. startAngle = endAngle;
  429. return result;
  430. }).join('');
  431. })()}
  432. <circle cx="100" cy="100" r="36" fill="var(--bg-1)" stroke="${c.color}" stroke-width="2"/>
  433. <text x="100" y="94" text-anchor="middle" font-family="ui-sans-serif" font-size="11" fill="var(--text-3)" font-weight="700" letter-spacing="0.08em">TOTAL</text>
  434. <text x="100" y="112" text-anchor="middle" font-family="ui-sans-serif" font-size="20" fill="${c.color}" font-weight="900">${totalTarget}亿</text>
  435. </svg>
  436. <div style="display:grid; gap:10px;">
  437. ${channels.map(ch => `
  438. <div style="display:flex; align-items:center; gap:14px; padding:12px 14px; background:${ch.color}08; border-left:4px solid ${ch.color}; border-radius:6px;">
  439. <div style="width:44px; height:44px; background:${ch.color}; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:1.4rem; color:#fff;">${ch.icon}</div>
  440. <div style="flex:1;">
  441. <div style="display:flex; align-items:baseline; gap:8px; margin-bottom:2px;">
  442. <span style="font-size:1.05rem; font-weight:800; color:var(--text-1);">${esc(ch.name)}</span>
  443. <span class="text-mono text-xs" style="color:${ch.color}; letter-spacing:0.08em;">${ch.en}</span>
  444. </div>
  445. <div style="font-size:0.78rem; color:var(--text-3); line-height:1.45;">目标:<strong style="color:${ch.color};">${ch.target}亿</strong>(占比 ${ch.share}%)· 增长参照 <strong style="color:${ch.color};">${ch.growth}</strong></div>
  446. </div>
  447. <div style="text-align:right;">
  448. <div style="font-family:var(--font-head); font-weight:900; font-size:1.8rem; color:${ch.color}; line-height:1;">${ch.target}</div>
  449. <div class="text-mono text-xs" style="color:${ch.color}; letter-spacing:0.08em; margin-top:2px;">亿 / YEAR</div>
  450. </div>
  451. </div>
  452. `).join('')}
  453. </div>
  454. </div>
  455. </div>
  456. <!-- 4 渠道详细卡片 -->
  457. <div class="fade-up" style="display:grid; grid-template-columns:repeat(2, 1fr); gap:16px; margin-bottom:24px;">
  458. ${channels.map(ch => `
  459. <div style="background:var(--bg-1); border:1px solid ${ch.color}44; border-top:4px solid ${ch.color}; border-radius:var(--radius-md); padding:20px;">
  460. <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:14px;">
  461. <div style="display:flex; align-items:center; gap:12px;">
  462. <div style="width:44px; height:44px; background:${ch.color}22; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:1.5rem;">${ch.icon}</div>
  463. <div>
  464. <div class="text-mono text-xs" style="color:${ch.color}; letter-spacing:0.12em;">CHANNEL ${ch.en}</div>
  465. <div style="font-size:1.15rem; font-weight:800; color:var(--text-1);">${esc(ch.name)}渠道</div>
  466. </div>
  467. </div>
  468. <div style="text-align:right;">
  469. <div style="font-family:var(--font-head); font-weight:900; font-size:2rem; color:${ch.color}; line-height:1;">${ch.target}亿</div>
  470. <div class="text-mono text-xs" style="color:${ch.color}; margin-top:2px; letter-spacing:0.08em;">${ch.share}% OF 10亿</div>
  471. </div>
  472. </div>
  473. <div style="display:grid; gap:8px;">
  474. <div style="padding:8px 12px; background:${ch.color}08; border-radius:4px;">
  475. <div class="text-mono text-xs" style="color:${ch.color}; letter-spacing:0.08em; margin-bottom:3px;">🎯 核心钩子</div>
  476. <div style="font-size:0.82rem; color:var(--text-1); font-weight:600; line-height:1.45;">${esc(ch.coreHook)}</div>
  477. </div>
  478. <div style="padding:8px 12px; background:var(--bg-2); border-radius:4px;">
  479. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">📦 SKU 形态</div>
  480. <div style="font-size:0.78rem; color:var(--text-2); line-height:1.45;">${esc(ch.sku)}</div>
  481. </div>
  482. <div style="padding:8px 12px; background:var(--bg-2); border-radius:4px;">
  483. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">🏪 主阵地</div>
  484. <div style="font-size:0.78rem; color:var(--text-2); line-height:1.45;">${esc(ch.mainSite)}</div>
  485. </div>
  486. <div style="padding:8px 12px; background:var(--bg-2); border-radius:4px;">
  487. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">👤 目标用户</div>
  488. <div style="font-size:0.78rem; color:var(--text-2); line-height:1.45;">${esc(ch.userProfile)}</div>
  489. </div>
  490. <div style="padding:8px 12px; background:${ch.color}12; border-radius:4px;">
  491. <div class="text-mono text-xs" style="color:${ch.color}; letter-spacing:0.08em; margin-bottom:3px;">💰 价位参考</div>
  492. <div style="font-size:0.82rem; color:${ch.color}; font-weight:700;">${esc(ch.pricePoint)}</div>
  493. </div>
  494. </div>
  495. </div>
  496. `).join('')}
  497. </div>
  498. <!-- 方法论核心逻辑 -->
  499. <div class="fade-up" style="background:linear-gradient(135deg, ${c.color}10, ${BRAND.LIVER_AMBER}08); border:1px solid ${c.color}44; border-radius:var(--radius-md); padding:20px 24px;">
  500. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:10px;">CORE LOGIC · 10亿方法论核心</div>
  501. <div style="display:grid; grid-template-columns:repeat(4, 1fr); gap:14px;">
  502. <div style="text-align:center; padding:12px; border-right:1px dashed ${c.color}33;">
  503. <div style="font-family:var(--font-head); font-weight:900; font-size:1.8rem; color:${BRAND.TECH_BLUE}; line-height:1;">30%</div>
  504. <div class="text-mono text-xs" style="color:${BRAND.TECH_BLUE}; margin-top:4px; letter-spacing:0.08em;">药线</div>
  505. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">合规背书 · 长期养护</div>
  506. </div>
  507. <div style="text-align:center; padding:12px; border-right:1px dashed ${c.color}33;">
  508. <div style="font-family:var(--font-head); font-weight:900; font-size:1.8rem; color:${BRAND.LIVER_AMBER}; line-height:1;">25%</div>
  509. <div class="text-mono text-xs" style="color:${BRAND.LIVER_AMBER}; margin-top:4px; letter-spacing:0.08em;">礼品</div>
  510. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">颜值溢价 · 体面社交</div>
  511. </div>
  512. <div style="text-align:center; padding:12px; border-right:1px dashed ${c.color}33;">
  513. <div style="font-family:var(--font-head); font-weight:900; font-size:1.8rem; color:${BRAND.WARM_ORANGE}; line-height:1;">25%</div>
  514. <div class="text-mono text-xs" style="color:${BRAND.WARM_ORANGE}; margin-top:4px; letter-spacing:0.08em;">餐饮</div>
  515. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">即时体感 · 酒桌货币</div>
  516. </div>
  517. <div style="text-align:center; padding:12px;">
  518. <div style="font-family:var(--font-head); font-weight:900; font-size:1.8rem; color:${BRAND.JIANG_GREEN}; line-height:1;">20%</div>
  519. <div class="text-mono text-xs" style="color:${BRAND.JIANG_GREEN}; margin-top:4px; letter-spacing:0.08em;">电商</div>
  520. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">差异科普 · 会员复购</div>
  521. </div>
  522. </div>
  523. </div>
  524. </div>
  525. </section>`;
  526. }
  527. // ----- 1.2 · 5 模块 × 决策阈值 · Research Modules & Decision Thresholds ------
  528. function renderMethod2Modules({ slideNum, slideTotal, chapter, A }) {
  529. const c = chapter;
  530. const modules = [
  531. {
  532. num: '01', key: 'package', name: '包装调研', en: 'PACKAGE', icon: '📦', color: BRAND.LIVER_AMBER, priority: 'P0',
  533. scope: '外包装材质/颜色/设计、内包装形态、片剂外观、礼品规格',
  534. excluded: '❌ 不调研:换剂型 / 改核心标识 / 违规材质',
  535. threshold: '偏好度 ≥ 70%',
  536. decisionRule: '用户偏好度 ≥70% 的方案 + 兼顾四大渠道适配',
  537. sampleSize: '≥ 150 条评论 · 20-30 用户深访',
  538. landingOutputs: ['药线板装视觉规范', '礼品礼盒包装样稿', '片剂 3 个外观候选', '4 渠道 SKU 矩阵'],
  539. },
  540. {
  541. num: '02', key: 'pricing', name: '定价调研', en: 'PRICING', icon: '💰', color: BRAND.TECH_BLUE, priority: 'P0',
  542. scope: '分渠道定价区间、规格价格带(12/60/120片)、竞品定价对比',
  543. excluded: '❌ 不调研:突破成本定价 / 低于竞品底线',
  544. threshold: '接受度 ≥ 80%',
  545. decisionRule: '80% 目标用户接受的区间 + 兼顾毛利支撑 10 亿',
  546. sampleSize: '≥ 100 条价格敏感度评论 · 电商平台晒单',
  547. landingOutputs: ['药线定价 ¥25-40', '电商定价 ¥89-139', '礼品定价 ¥298-898', '价格带 SKU 对照表'],
  548. },
  549. {
  550. num: '03', key: 'positioning', name: '定位与话术调研', en: 'POSITIONING', icon: '🎯', color: BRAND.PURPLE, priority: 'P0',
  551. scope: '藤茶/DMY 概念认知度、解酒/安全/社交话术吸引力、分渠道话术',
  552. excluded: '❌ 不调研:改核心成分 / 宣传治疗 / 更名',
  553. threshold: '认可度 ≥ 80%',
  554. decisionRule: '记忆点强、能区分竞品(药品/水飞蓟)的话术优先',
  555. sampleSize: '≥ 200 条评论 · 话术 AB 测试',
  556. landingOutputs: ['4 渠道话术包', '核心记忆点 Top 5', 'DMY 科普模板', '社交货币故事'],
  557. },
  558. {
  559. num: '04', key: 'scene', name: '场景适配调研', en: 'SCENE-FIT', icon: '🎬', color: BRAND.WARM_ORANGE, priority: 'P1',
  560. scope: '药线合规性、礼品体面感、餐饮便携分食、电商性价比',
  561. excluded: '❌ 不调研:拓展非护肝场景 / 偏离 4 大渠道',
  562. threshold: '场景适配度 ≥ 75%',
  563. decisionRule: '每渠道核心人群 ≥80% 认可方可投放',
  564. sampleSize: '每渠道 ≥ 80 条评论 · 分场景深访',
  565. landingOutputs: ['药线医生推荐话术', '礼品开箱 UGC 物料', '餐饮酒局示范', '电商详情页结构'],
  566. },
  567. {
  568. num: '05', key: 'competitor', name: '竞品认知调研', en: 'COMPETITOR', icon: '⚔️', color: BRAND.ROSE, priority: 'P1',
  569. scope: '护肝片/易善复/片仔癀/熊胆粉痛点、水飞蓟弱点、海王金樽失败复盘',
  570. excluded: '❌ 不调研:模仿竞品配方 / 定位药品',
  571. threshold: '差异化感知 ≥ 70%',
  572. decisionRule: '用户能口头说出 ≥1 条 江中 vs 竞品 差异',
  573. sampleSize: '每竞品 ≥ 50 条评论 · 交叉对比',
  574. landingOutputs: ['6 竞品痛点清单', '差异化论据 Top 10', '对比陈列物料', '打脸话术包'],
  575. },
  576. ];
  577. return `<section class="report-section" id="method-2" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  578. <div class="section-inner">
  579. <div class="section-head rise-in">
  580. <div class="section-eyebrow" style="color:${c.color};">${c.num}.2 · RESEARCH MODULES & DECISION THRESHOLDS</div>
  581. <h2 class="text-h1"><span class="headline-anim">5 调研模块 × 决策阈值矩阵</span></h2>
  582. <p class="section-sub">从《1.VOC方向定位.md》会议确认的 <strong style="color:${c.color};">5 大调研模块</strong>,每个模块独立的 调研范围 × 排除项 × 决策阈值 × 样本量 × 落地产出</p>
  583. </div>
  584. <!-- 5 模块卡片 -->
  585. <div class="fade-up" style="display:grid; grid-template-columns:repeat(1, 1fr); gap:14px; margin-bottom:28px;">
  586. ${modules.map(m => `
  587. <div style="background:var(--bg-1); border:1px solid ${m.color}44; border-left:4px solid ${m.color}; border-radius:var(--radius-md); padding:18px; display:grid; grid-template-columns:50px 1.3fr 1fr 1fr 180px; gap:16px; align-items:center;">
  588. <div style="text-align:center;">
  589. <div style="width:44px; height:44px; background:${m.color}22; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:1.4rem; margin:0 auto;">${m.icon}</div>
  590. <div class="text-mono text-xs" style="color:${m.color}; margin-top:6px; letter-spacing:0.08em; font-weight:700;">${m.num}</div>
  591. </div>
  592. <div>
  593. <div style="display:flex; align-items:center; gap:8px; margin-bottom:4px;">
  594. <span style="font-size:1.05rem; font-weight:800; color:var(--text-1);">${esc(m.name)}</span>
  595. <span class="text-mono text-xs" style="color:${m.color}; letter-spacing:0.08em;">${m.en}</span>
  596. <span style="padding:2px 7px; background:${m.priority === 'P0' ? BRAND.ROSE : BRAND.WARM_ORANGE}22; color:${m.priority === 'P0' ? BRAND.ROSE : BRAND.WARM_ORANGE}; border-radius:3px; font-family:var(--font-mono); font-size:0.7rem; font-weight:700;">${m.priority}</span>
  597. </div>
  598. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">📋 调研范围</div>
  599. <div style="font-size:0.78rem; color:var(--text-2); line-height:1.45; margin-bottom:6px;">${esc(m.scope)}</div>
  600. <div style="font-size:0.7rem; color:${BRAND.ROSE}; line-height:1.4;">${esc(m.excluded)}</div>
  601. </div>
  602. <div>
  603. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">📊 样本量</div>
  604. <div style="font-size:0.82rem; color:var(--text-1); font-weight:700; line-height:1.4; margin-bottom:8px;">${esc(m.sampleSize)}</div>
  605. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">⚖️ 决策规则</div>
  606. <div style="font-size:0.73rem; color:var(--text-2); line-height:1.45;">${esc(m.decisionRule)}</div>
  607. </div>
  608. <div>
  609. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:5px;">📤 落地产出</div>
  610. <ul style="margin:0; padding:0; list-style:none;">
  611. ${m.landingOutputs.map(o => `<li style="padding:2px 0; font-size:0.72rem; color:var(--text-2); line-height:1.4; padding-left:12px; position:relative;"><span style="position:absolute; left:0; color:${m.color};">✓</span>${esc(o)}</li>`).join('')}
  612. </ul>
  613. </div>
  614. <div style="text-align:center; padding:14px 10px; background:${m.color}12; border-radius:8px;">
  615. <div class="text-mono text-xs" style="color:${m.color}; letter-spacing:0.08em; margin-bottom:4px;">阈值</div>
  616. <div style="font-family:var(--font-head); font-weight:900; font-size:1.6rem; color:${m.color}; line-height:1; margin-bottom:3px;">${esc(m.threshold.split(' ')[m.threshold.split(' ').length - 1])}</div>
  617. <div style="font-size:0.7rem; color:${m.color}; font-weight:600;">${esc(m.threshold.split(' ').slice(0, -1).join(' '))}</div>
  618. </div>
  619. </div>
  620. `).join('')}
  621. </div>
  622. <!-- 决策漏斗可视化 -->
  623. <div class="fade-up" style="background:linear-gradient(135deg, ${c.color}10, ${BRAND.LIVER_AMBER}08); border:1px solid ${c.color}44; border-radius:var(--radius-md); padding:24px;">
  624. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:16px;">DECISION FUNNEL · 从 VOC 原声到落地方案</div>
  625. <div style="display:grid; grid-template-columns:repeat(5, 1fr) auto; gap:10px; align-items:center;">
  626. ${[
  627. { label: 'VOC 采集', value: '1000+', desc: '评论原声', tint: BRAND.JIANG_GREEN },
  628. { label: '主题聚类', value: '20-30', desc: '高频主题', tint: BRAND.TECH_BLUE },
  629. { label: '阈值筛选', value: '10-15', desc: '达标方案', tint: BRAND.LIVER_AMBER },
  630. { label: '交叉验证', value: '5-8', desc: '可落地', tint: BRAND.WARM_ORANGE },
  631. { label: '最终决策', value: '3-5', desc: '4 渠道 PRD', tint: BRAND.ROSE },
  632. ].map((s, i, arr) => `
  633. <div style="text-align:center;">
  634. <div style="padding:14px 10px; background:${s.tint}15; border:2px solid ${s.tint}44; border-radius:8px;">
  635. <div style="font-family:var(--font-head); font-weight:900; font-size:1.6rem; color:${s.tint}; line-height:1;">${esc(s.value)}</div>
  636. <div class="text-mono text-xs" style="color:${s.tint}; margin-top:3px; letter-spacing:0.06em;">${esc(s.label)}</div>
  637. <div style="font-size:0.7rem; color:var(--text-3); margin-top:3px;">${esc(s.desc)}</div>
  638. </div>
  639. </div>
  640. `).join('<div style="font-size:1.4rem; color:' + c.color + '; text-align:center;">→</div>')}
  641. </div>
  642. </div>
  643. </div>
  644. </section>`;
  645. }
  646. // ----- 1.3 · 多平台采集矩阵 · Multi-Platform Collection Matrix --------------
  647. function renderMethod3Platforms({ slideNum, slideTotal, chapter, A }) {
  648. const c = chapter;
  649. const platforms = [
  650. {
  651. name: '小红书', en: 'XIAOHONGSHU', icon: '📕', color: '#FF2442', weight: '★★★★★',
  652. role: '女性 / 礼品 / 日常养护主战场', role_detail: '国内保健品 VOC 最深的平台,女性决策群体+爆款种草',
  653. coverageChannels: ['礼品', '电商', '日常养护'],
  654. keywords: ['肝纯片', '江中肝纯片', '护肝片', '藤茶 护肝', '熬夜 护肝', '脂肪肝 推荐', '送礼 保健品', '送长辈 礼盒', '女性 护肝', 'Swisse 水飞蓟'],
  655. sampleTarget: '25 笔记 × 30-50 评论 = 800+ 条',
  656. depth: '评论颗粒度 · 含用户画像(IP/昵称)· 子评论(反驳)· 点赞权重',
  657. toolReady: '✅ xiaohongshu-note-comments skill',
  658. },
  659. {
  660. name: '抖音', en: 'DOUYIN', icon: '🎵', color: '#000000', weight: '★★★★☆',
  661. role: '男性 / 应酬 / 解酒场景主战场', role_detail: '短视频生态,男性酒桌用户 + 医生科普号密集',
  662. coverageChannels: ['餐饮', '电商', '药线教育'],
  663. keywords: ['肝纯片', '解酒片', '应酬 护肝', '酒局 解酒', '脂肪肝', '喝酒伤肝', '海王金樽', '护肝 真的有用吗'],
  664. sampleTarget: '20 视频 × 20-30 评论 = 500+ 条',
  665. depth: '评论 + 转发 + 子评论 + IP 归属',
  666. toolReady: '✅ probe-tikhub-douyin + collect-douyin',
  667. },
  668. {
  669. name: '知乎', en: 'ZHIHU', icon: '💬', color: '#0084FF', weight: '★★★★☆',
  670. role: '药线专业科普 + 长文决策', role_detail: '深度用户搜「护肝片真的有用吗」、「脂肪肝怎么治」,医学大V 密集',
  671. coverageChannels: ['药线', '电商 深度决策'],
  672. keywords: ['护肝片有用吗', '江中肝纯片 知乎', '水飞蓟 vs DMY', '二氢杨梅素', '脂肪肝怎么办', '易善复 副作用', '解酒药 推荐', '藤茶 护肝'],
  673. sampleTarget: '15 问题 × 10 高赞答 × 20 评论 = 300+ 条',
  674. depth: '长答辩论 + 评论 + 赞同数权重',
  675. toolReady: '⚠️ 需新建 collect-zhihu.js(搜索+答案+评论接口)',
  676. },
  677. {
  678. name: '电商评论', en: 'ECOMMERCE', icon: '🛒', color: '#FF6A00', weight: '★★★★★',
  679. role: '电商购买决策 + 复购 + 晒单', role_detail: '淘宝/京东/拼多多/抖音小店评论区,真实购买者声音',
  680. coverageChannels: ['电商', '礼品', '餐饮(散装购买)'],
  681. keywords: ['江中肝纯片', 'Swisse 奶蓟草', '汤臣倍健 护肝', '护肝片 京东', '同仁堂 护肝片', '海王金樽'],
  682. sampleTarget: '8-10 SKU × 50-100 评论 = 500+ 条',
  683. depth: '评分 1-5 星 + 文字评论 + 图文晒单 + 追评(长期反馈)',
  684. toolReady: '⚠️ 需新建 collect-taobao-jd.js(商品详情页抓评论)',
  685. },
  686. {
  687. name: '丁香医生', en: 'DXY', icon: '🩺', color: '#00A4E0', weight: '★★★☆☆',
  688. role: '专业医生药师视角', role_detail: '医生科普文章 + 付费问诊话题,权威但体量小',
  689. coverageChannels: ['药线 专业权威'],
  690. keywords: ['护肝片 医生', 'DMY 二氢杨梅素', '水飞蓟 副作用', '脂肪肝 治疗', '解酒药'],
  691. sampleTarget: '10-15 文章 × 20 评论 = 200+ 条',
  692. depth: '医生回复 + 用户追问 + 医学术语解释',
  693. toolReady: '⚠️ 需新建 collect-dxy.js 或手工抓取',
  694. },
  695. {
  696. name: 'TikTok/Amazon', en: 'OVERSEAS', icon: '🌍', color: '#14B8A6', weight: '★★★☆☆',
  697. role: '海外对标参考', role_detail: '已采集 82 TikTok 视频 + 689 Amazon 产品 + 158 条评论,直接复用',
  698. coverageChannels: ['礼品 高端对标', '电商 差异化'],
  699. keywords: ['milk thistle', 'liver support supplement', 'silymarin', 'liver cleanse detox'],
  700. sampleTarget: '✅ 已就绪:158 条 TikTok 评论 + 689 Amazon 款',
  701. depth: '英文评论 + 评分 + 品牌对比数据',
  702. toolReady: '✅ 已有数据(jiangzhong-liver-voc.json)',
  703. },
  704. ];
  705. const totalSamples = platforms.reduce((sum, p) => {
  706. const m = p.sampleTarget.match(/(\d+)\+/);
  707. return sum + (m ? parseInt(m[1]) : 0);
  708. }, 0);
  709. return `<section class="report-section" id="method-3" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  710. <div class="section-inner">
  711. <div class="section-head rise-in">
  712. <div class="section-eyebrow" style="color:${c.color};">${c.num}.3 · MULTI-PLATFORM MATRIX</div>
  713. <h2 class="text-h1"><span class="headline-anim">多平台采集矩阵 · 6 平台 × 评论颗粒度</span></h2>
  714. <p class="section-sub">按 4 渠道覆盖选平台,按 5 模块选关键词,按评论权重筛样本 · 目标 <strong style="color:${c.color};">≥ 2500 条真实评论</strong></p>
  715. </div>
  716. <!-- 平台矩阵卡片 -->
  717. <div class="fade-up" style="display:grid; grid-template-columns:repeat(2, 1fr); gap:14px; margin-bottom:24px;">
  718. ${platforms.map(p => `
  719. <div style="background:var(--bg-1); border:1px solid ${p.color}44; border-top:4px solid ${p.color}; border-radius:var(--radius-md); padding:18px;">
  720. <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:12px;">
  721. <div style="display:flex; align-items:center; gap:10px;">
  722. <div style="width:40px; height:40px; background:${p.color}22; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:1.3rem;">${p.icon}</div>
  723. <div>
  724. <div style="display:flex; align-items:baseline; gap:8px;">
  725. <span style="font-size:1.05rem; font-weight:800; color:var(--text-1);">${esc(p.name)}</span>
  726. <span class="text-mono text-xs" style="color:${p.color}; letter-spacing:0.08em;">${p.en}</span>
  727. </div>
  728. <div style="font-size:0.72rem; color:${p.color};">${p.weight}</div>
  729. </div>
  730. </div>
  731. <div style="padding:3px 8px; background:${p.toolReady.startsWith('✅') ? BRAND.JIANG_GREEN : BRAND.WARM_ORANGE}22; color:${p.toolReady.startsWith('✅') ? BRAND.JIANG_GREEN : BRAND.WARM_ORANGE}; border-radius:3px; font-family:var(--font-mono); font-size:0.7rem; font-weight:700;">${p.toolReady.startsWith('✅') ? 'READY' : 'TBD'}</div>
  732. </div>
  733. <div style="padding:8px 12px; background:${p.color}08; border-left:3px solid ${p.color}; border-radius:4px; margin-bottom:10px;">
  734. <div style="font-size:0.82rem; color:var(--text-1); font-weight:700; margin-bottom:2px;">${esc(p.role)}</div>
  735. <div style="font-size:0.72rem; color:var(--text-2); line-height:1.45;">${esc(p.role_detail)}</div>
  736. </div>
  737. <div style="margin-bottom:8px;">
  738. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:4px;">🎯 覆盖渠道</div>
  739. <div style="display:flex; flex-wrap:wrap; gap:4px;">
  740. ${p.coverageChannels.map(ch => `<span style="padding:2px 7px; background:${(CHANNEL_COLORS[ch] || p.color)}18; color:${CHANNEL_COLORS[ch] || p.color}; border-radius:3px; font-size:0.68rem; font-weight:700;">${esc(ch)}</span>`).join('')}
  741. </div>
  742. </div>
  743. <div style="margin-bottom:8px;">
  744. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:4px;">🔑 采集关键词(${p.keywords.length} 个)</div>
  745. <div style="font-size:0.72rem; color:var(--text-2); line-height:1.45;">${p.keywords.map(k => `<span style="color:${p.color};">「${esc(k)}」</span>`).join(' · ')}</div>
  746. </div>
  747. <div style="display:grid; grid-template-columns:1fr 1fr; gap:6px; padding-top:8px; border-top:1px dashed var(--border);">
  748. <div>
  749. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.06em; margin-bottom:2px;">📊 样本目标</div>
  750. <div style="font-size:0.76rem; color:${p.color}; font-weight:700;">${esc(p.sampleTarget)}</div>
  751. </div>
  752. <div>
  753. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.06em; margin-bottom:2px;">🛠️ 工具就绪</div>
  754. <div style="font-size:0.72rem; color:var(--text-2); line-height:1.35;">${esc(p.toolReady)}</div>
  755. </div>
  756. </div>
  757. <div style="margin-top:6px; padding:5px 10px; background:var(--bg-2); border-radius:4px;">
  758. <div style="font-size:0.7rem; color:var(--text-3); line-height:1.45;"><strong style="color:${p.color};">数据深度:</strong>${esc(p.depth)}</div>
  759. </div>
  760. </div>
  761. `).join('')}
  762. </div>
  763. <!-- 采集总览汇总 -->
  764. <div class="fade-up" style="background:linear-gradient(135deg, ${c.color}10, ${BRAND.LIVER_AMBER}08); border:1px solid ${c.color}44; border-radius:var(--radius-md); padding:24px;">
  765. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:14px;">AGGREGATE · 跨平台采集总目标</div>
  766. <div style="display:grid; grid-template-columns:repeat(5, 1fr); gap:16px;">
  767. <div style="text-align:center;">
  768. <div style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:${c.color}; line-height:1;">${platforms.length}</div>
  769. <div class="text-mono text-xs" style="color:${c.color}; margin-top:4px; letter-spacing:0.08em;">PLATFORMS</div>
  770. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">国内 5 + 海外 1</div>
  771. </div>
  772. <div style="text-align:center;">
  773. <div style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:${BRAND.LIVER_AMBER}; line-height:1;">40+</div>
  774. <div class="text-mono text-xs" style="color:${BRAND.LIVER_AMBER}; margin-top:4px; letter-spacing:0.08em;">KEYWORDS</div>
  775. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">精准筛选</div>
  776. </div>
  777. <div style="text-align:center;">
  778. <div style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:${BRAND.TECH_BLUE}; line-height:1;">80+</div>
  779. <div class="text-mono text-xs" style="color:${BRAND.TECH_BLUE}; margin-top:4px; letter-spacing:0.08em;">NOTES/VIDEOS</div>
  780. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">跨平台笔记</div>
  781. </div>
  782. <div style="text-align:center;">
  783. <div style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:${BRAND.JIANG_GREEN}; line-height:1;">2500+</div>
  784. <div class="text-mono text-xs" style="color:${BRAND.JIANG_GREEN}; margin-top:4px; letter-spacing:0.08em;">COMMENTS</div>
  785. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">真实原声</div>
  786. </div>
  787. <div style="text-align:center;">
  788. <div style="font-family:var(--font-head); font-weight:900; font-size:2.4rem; color:${BRAND.ROSE}; line-height:1;">4×5</div>
  789. <div class="text-mono text-xs" style="color:${BRAND.ROSE}; margin-top:4px; letter-spacing:0.08em;">CHANNEL×MODULE</div>
  790. <div style="font-size:0.72rem; color:var(--text-3); margin-top:4px;">交叉覆盖</div>
  791. </div>
  792. </div>
  793. </div>
  794. </div>
  795. </section>`;
  796. }
  797. // ----- 1.4 · 评论颗粒度分析框架 · Comment-Level Analytical Framework --------
  798. function renderMethod4Analytics({ slideNum, slideTotal, chapter, A }) {
  799. const c = chapter;
  800. const dimensions = [
  801. {
  802. num: '01', name: '主题聚类', en: 'THEME CLUSTERING', icon: '🔖', color: BRAND.TECH_BLUE,
  803. desc: '基于 TF-IDF + 语义聚类,抽取 20-30 条核心主题',
  804. method: '关键词提取 → 共现矩阵 → K-Means 聚类 → 人工复核',
  805. output: '主题词云图 + Top 20 主题表 + 每主题的代表评论',
  806. example: '"副作用"、"解酒"、"藤茶"、"送礼"、"酒桌"、"水飞蓟" 等主题',
  807. },
  808. {
  809. num: '02', name: '情感分布', en: 'SENTIMENT SPLIT', icon: '💭', color: BRAND.LIVER_AMBER,
  810. desc: '每条评论打情感标签:正面 / 中性 / 负面 / 疑问',
  811. method: '规则 + 词典 + 语境识别 → 评论人工校验 → 饼图可视化',
  812. output: '5 模块 × 4 情感 热力图 + 每情感代表 3 条原声',
  813. example: '"这个真的有效(正面)" vs "没感觉(负面)" vs "能天天吃吗(疑问)"',
  814. },
  815. {
  816. num: '03', name: '频次权重', en: 'FREQ WEIGHTING', icon: '📊', color: BRAND.JIANG_GREEN,
  817. desc: '单条评论权重 = log(1+点赞数) × 置信度',
  818. method: '高赞评论(≥50)权重提升 2x · 首评权重 1.5x · 反复出现的主题加权',
  819. output: '加权主题排序表 + 热点图(金句 vs 长尾)',
  820. example: '"吃了 2 个月转氨酶没降"(点赞 108)> "还行"(点赞 3)',
  821. },
  822. {
  823. num: '04', name: '可信度分层', en: 'CREDIBILITY LAYERING', icon: '🔐', color: BRAND.PURPLE,
  824. desc: '按评论来源可信度分层:医生 > 素人晒单 > KOL > 水军',
  825. method: '用户画像分析 + 评论深度识别 + 子评论交叉验证',
  826. output: '可信度分层表 + 高可信原声金句库(≥80 分为决策依据)',
  827. example: '丁香医生认证号评论 = 95 分 · 小红书素人追评 = 75 分 · KOL 带货 = 40 分',
  828. },
  829. {
  830. num: '05', name: '场景×人群', en: 'SCENE×PERSONA', icon: '🎭', color: BRAND.WARM_ORANGE,
  831. desc: '评论分派到 4 渠道 × 3-4 人群矩阵',
  832. method: '评论 IP/昵称/语气 → 人群标签 → 场景标签 → 交叉分组',
  833. output: '4 渠道 × 4 人群 16 格热力图 + 每格 Top 3 金句',
  834. example: '"应酬男·餐饮"格 · Top 原声:"分一片真的有面子"',
  835. },
  836. {
  837. num: '06', name: '痛点×收益映射', en: 'PAIN↔GAIN MAPPING', icon: '⚖️', color: BRAND.ROSE,
  838. desc: 'Osterwalder 画布法,每个痛点 → 对应产品功能',
  839. method: '痛点提取 → 严重度打分 → 收益映射 → 产品功能对照',
  840. output: '6 痛点 × 6 收益 × 产品功能映射表(PMF Fit 评分)',
  841. example: '"不好吞(痛点)" → "易吞咽小片剂(功能)" → "吞咽体验好(收益)"',
  842. },
  843. ];
  844. return `<section class="report-section" id="method-4" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  845. <div class="section-inner">
  846. <div class="section-head rise-in">
  847. <div class="section-eyebrow" style="color:${c.color};">${c.num}.4 · COMMENT-LEVEL ANALYTICAL FRAMEWORK</div>
  848. <h2 class="text-h1"><span class="headline-anim">评论颗粒度分析框架 · 6 维</span></h2>
  849. <p class="section-sub">本报告不做"摘要式调研",每一条评论都独立分析 · <strong style="color:${c.color};">主题 × 情感 × 权重 × 可信度 × 场景人群 × 痛点映射</strong> 6 维全量标签</p>
  850. </div>
  851. <!-- 6 维分析卡片 -->
  852. <div class="fade-up" style="display:grid; grid-template-columns:repeat(3, 1fr); gap:14px; margin-bottom:24px;">
  853. ${dimensions.map(d => `
  854. <div style="background:var(--bg-1); border:1px solid ${d.color}44; border-top:4px solid ${d.color}; border-radius:var(--radius-md); padding:18px;">
  855. <div style="display:flex; align-items:center; gap:10px; margin-bottom:10px;">
  856. <div style="width:42px; height:42px; background:${d.color}22; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:1.3rem;">${d.icon}</div>
  857. <div>
  858. <div class="text-mono text-xs" style="color:${d.color}; letter-spacing:0.1em;">DIM · ${d.num}</div>
  859. <div style="font-size:1rem; font-weight:800; color:var(--text-1);">${esc(d.name)}</div>
  860. </div>
  861. </div>
  862. <div style="padding:8px 10px; background:${d.color}08; border-left:3px solid ${d.color}; border-radius:4px; margin-bottom:10px;">
  863. <div style="font-size:0.8rem; color:var(--text-1); font-weight:600; line-height:1.45;">${esc(d.desc)}</div>
  864. </div>
  865. <div style="margin-bottom:8px;">
  866. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">🔬 方法</div>
  867. <div style="font-size:0.74rem; color:var(--text-2); line-height:1.5;">${esc(d.method)}</div>
  868. </div>
  869. <div style="margin-bottom:8px;">
  870. <div class="text-mono text-xs" style="color:var(--text-3); letter-spacing:0.08em; margin-bottom:3px;">📤 产出</div>
  871. <div style="font-size:0.74rem; color:var(--text-2); line-height:1.5;">${esc(d.output)}</div>
  872. </div>
  873. <div style="padding:8px 10px; background:var(--bg-2); border-radius:4px;">
  874. <div class="text-mono text-xs" style="color:${d.color}; letter-spacing:0.08em; margin-bottom:3px;">💬 示例</div>
  875. <div style="font-size:0.72rem; color:var(--text-1); font-style:italic; line-height:1.5;">${esc(d.example)}</div>
  876. </div>
  877. </div>
  878. `).join('')}
  879. </div>
  880. <!-- 分析全流程图 -->
  881. <div class="fade-up" style="background:linear-gradient(135deg, ${c.color}10, ${BRAND.LIVER_AMBER}08); border:1px solid ${c.color}44; border-radius:var(--radius-md); padding:24px;">
  882. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:16px;">ANALYSIS PIPELINE · 从评论原声到决策证据</div>
  883. <div style="display:grid; grid-template-columns:repeat(6, 1fr) auto; gap:10px; align-items:center;">
  884. ${[
  885. { stage: '原始评论', icon: '📝', tint: BRAND.JIANG_GREEN, count: '2500+' },
  886. { stage: '清洗 + 去重', icon: '🧹', tint: BRAND.TECH_BLUE, count: '1800+' },
  887. { stage: '6 维打标', icon: '🏷️', tint: BRAND.LIVER_AMBER, count: '全量' },
  888. { stage: '主题聚类', icon: '🧬', tint: BRAND.PURPLE, count: '30 主题' },
  889. { stage: '权重排序', icon: '⚖️', tint: BRAND.WARM_ORANGE, count: 'Top 100' },
  890. { stage: '决策证据', icon: '🎯', tint: BRAND.ROSE, count: '金句库' },
  891. ].map((s, i, arr) => `
  892. <div style="text-align:center;">
  893. <div style="padding:14px 10px; background:${s.tint}15; border:2px solid ${s.tint}44; border-radius:8px;">
  894. <div style="font-size:1.4rem; margin-bottom:4px;">${s.icon}</div>
  895. <div class="text-mono text-xs" style="color:${s.tint}; letter-spacing:0.06em;">${esc(s.stage)}</div>
  896. <div style="font-size:0.75rem; color:${s.tint}; font-weight:700; margin-top:3px;">${esc(s.count)}</div>
  897. </div>
  898. </div>
  899. `).join('<div style="font-size:1.2rem; color:' + c.color + '; text-align:center;">→</div>')}
  900. </div>
  901. </div>
  902. </div>
  903. </section>`;
  904. }
  905. // ----- 1.5 · 可做/不可做边界 · Scope Boundaries -----------------------------
  906. function renderMethod5Boundaries({ slideNum, slideTotal, chapter, A }) {
  907. const c = chapter;
  908. const canDo = [
  909. {
  910. category: '包装形态', icon: '📦', color: BRAND.LIVER_AMBER,
  911. items: ['外包装:盒装(礼品/普通)、罐装(磨砂玻璃/PET)、铁盒(可调研接受度)', '内包装:锡纸片(板装,药线便携分食)、瓶装(日常自用、礼品)', '材质/颜色/视觉:融入藤茶元素、DMY 白霜视觉化、Swisse 风轻奢'],
  912. vocEvidence: '"包装太土了,送人都拿不出手" · "希望像 Swisse 那种磨砂瓶" · "有没有带藤茶图案的"',
  913. },
  914. {
  915. category: '片剂外观', icon: '💊', color: BRAND.PURPLE,
  916. items: ['剂型 = 片剂(不可动)', '但形状可调:圆形 / 三角形 / 椭圆形 / 异形', '表面纹理:印 LOGO / 藤茶纹理 / DMY 字样 / 光面 vs 磨砂'],
  917. vocEvidence: '"这片剂太大,不好吞" · "能不能做个好看的形状" · "表面印个 LOGO 高级感提升"',
  918. },
  919. {
  920. category: '定价策略', icon: '💰', color: BRAND.TECH_BLUE,
  921. items: ['按渠道分价:药线低价引流 / 电商日常中端 / 礼品高端溢价', '按规格分价:12片 / 60片 / 120片 对应不同价位段', '对标竞品:Swisse ¥158 / 护肝片 OTC ¥25 / 易善复 ¥45'],
  922. vocEvidence: '"这个价格比 Swisse 便宜就考虑" · "送礼装包装好可以贵点" · "日常用希望不超 100"',
  923. },
  924. {
  925. category: '文案与话术', icon: '💬', color: BRAND.JIANG_GREEN,
  926. items: ['强化"藤茶(显齿蛇葡萄)"概念 · "DMY 二氢杨梅素"核心', '核心话术:解酒 / 安全 / 社交 / 高端四路并进', '视觉:Swisse 轻奢 vs 新中式草本(AB 调研)'],
  927. vocEvidence: '"藤茶?听都没听过,能说清是啥吗" · "说我能喝酒时吃就买" · "看不懂 DMY 是什么"',
  928. },
  929. ];
  930. const cannotDo = [
  931. {
  932. category: '产品名字', icon: '🏷️', color: BRAND.ROSE,
  933. reason: '品牌资产已沉淀"江中肝纯片" · 2021 年上市至今 7-8亿峰值',
  934. action: 'VOC 仅验证用户对现有名字的记忆度 / 认知度,不做更名',
  935. example: '❌ 不调研:"肝好好" / "茶肝灵" 等替代名',
  936. },
  937. {
  938. category: '产品批文', icon: '📜', color: BRAND.ROSE,
  939. reason: '蓝帽保健食品,批文明确"化学性肝损伤辅助保护"',
  940. action: 'VOC 不涉及批文功效外的诉求(不宣传治疗)',
  941. example: '❌ 不调研:"治愈肝炎" / "治疗脂肪肝" 等药品化表述',
  942. },
  943. {
  944. category: '产品配方', icon: '🧪', color: BRAND.ROSE,
  945. reason: '核心成分显齿蛇葡萄提取物 + DMY 配比已定型',
  946. action: 'VOC 不调研配方优化,只验证藤茶/DMY 概念表达',
  947. example: '❌ 不调研:加水飞蓟 / 加姜黄 / 换成胶囊浓缩',
  948. },
  949. {
  950. category: '产品剂型', icon: '💊', color: BRAND.ROSE,
  951. reason: '片剂形态不可变(生产线 + 成本 + 蓝帽批文限制)',
  952. action: 'VOC 仅优化片剂外观(形状/纹理),不调研胶囊/颗粒/口服液',
  953. example: '❌ 不调研:"能做成胶囊吗" / "改成颗粒冲剂" / "加成饮料"',
  954. },
  955. ];
  956. return `<section class="report-section" id="method-5" data-tone="${c.tone}" data-slide-num="${slideNum}/${slideTotal}">
  957. <div class="section-inner">
  958. <div class="section-head rise-in">
  959. <div class="section-eyebrow" style="color:${c.color};">${c.num}.5 · SCOPE BOUNDARIES</div>
  960. <h2 class="text-h1"><span class="headline-anim">可做 / 不可做边界 · 方法论自律</span></h2>
  961. <p class="section-sub">会议明确:"<strong style="color:${BRAND.JIANG_GREEN};">能做(包装/定价/话术/渠道)</strong>" vs "<strong style="color:${BRAND.ROSE};">不能做(名字/批文/配方/剂型)</strong>" · VOC 严格守边界,不做无效调研</p>
  962. </div>
  963. <!-- 双列对比 · 能做 vs 不能做 -->
  964. <div style="display:grid; grid-template-columns:1fr 1fr; gap:24px; margin-bottom:24px;">
  965. <!-- 左:能做 -->
  966. <div class="fade-up">
  967. <div style="padding:16px 20px; background:linear-gradient(135deg, ${BRAND.JIANG_GREEN}15, ${BRAND.JIANG_GREEN}05); border:2px solid ${BRAND.JIANG_GREEN}44; border-radius:var(--radius-md) var(--radius-md) 0 0; display:flex; align-items:center; gap:10px;">
  968. <div style="font-size:1.8rem;">✅</div>
  969. <div>
  970. <div class="text-mono text-xs" style="color:${BRAND.JIANG_GREEN}; letter-spacing:0.15em;">CAN DO · 可做 4 类</div>
  971. <div style="font-size:1.2rem; font-weight:800; color:var(--text-1);">VOC 可调研 · 落地性强</div>
  972. </div>
  973. </div>
  974. <div style="background:var(--bg-1); border:2px solid ${BRAND.JIANG_GREEN}44; border-top:none; border-radius:0 0 var(--radius-md) var(--radius-md); padding:18px; display:grid; gap:12px;">
  975. ${canDo.map(cd => `
  976. <div style="padding:14px; background:${cd.color}08; border-left:3px solid ${cd.color}; border-radius:4px;">
  977. <div style="display:flex; align-items:center; gap:8px; margin-bottom:8px;">
  978. <div style="font-size:1.3rem;">${cd.icon}</div>
  979. <div style="font-size:1rem; font-weight:800; color:var(--text-1);">${esc(cd.category)}</div>
  980. </div>
  981. <ul style="margin:0 0 8px; padding:0; list-style:none;">
  982. ${cd.items.map(it => `<li style="padding:3px 0; font-size:0.76rem; color:var(--text-2); line-height:1.5; padding-left:14px; position:relative;"><span style="position:absolute; left:0; color:${cd.color};">▸</span>${esc(it)}</li>`).join('')}
  983. </ul>
  984. <div style="padding:6px 10px; background:var(--bg-2); border-radius:3px; font-size:0.7rem; color:var(--text-3); font-style:italic; line-height:1.45;">
  985. 💬 VOC 印证:${esc(cd.vocEvidence)}
  986. </div>
  987. </div>
  988. `).join('')}
  989. </div>
  990. </div>
  991. <!-- 右:不能做 -->
  992. <div class="fade-up">
  993. <div style="padding:16px 20px; background:linear-gradient(135deg, ${BRAND.ROSE}15, ${BRAND.ROSE}05); border:2px solid ${BRAND.ROSE}44; border-radius:var(--radius-md) var(--radius-md) 0 0; display:flex; align-items:center; gap:10px;">
  994. <div style="font-size:1.8rem;">❌</div>
  995. <div>
  996. <div class="text-mono text-xs" style="color:${BRAND.ROSE}; letter-spacing:0.15em;">CANNOT DO · 不做 4 类</div>
  997. <div style="font-size:1.2rem; font-weight:800; color:var(--text-1);">VOC 不涉及 · 无效工作</div>
  998. </div>
  999. </div>
  1000. <div style="background:var(--bg-1); border:2px solid ${BRAND.ROSE}44; border-top:none; border-radius:0 0 var(--radius-md) var(--radius-md); padding:18px; display:grid; gap:12px;">
  1001. ${cannotDo.map(cn => `
  1002. <div style="padding:14px; background:${cn.color}08; border-left:3px solid ${cn.color}; border-radius:4px;">
  1003. <div style="display:flex; align-items:center; gap:8px; margin-bottom:8px;">
  1004. <div style="font-size:1.3rem;">${cn.icon}</div>
  1005. <div style="font-size:1rem; font-weight:800; color:var(--text-1);">${esc(cn.category)}</div>
  1006. </div>
  1007. <div style="padding:5px 10px; background:var(--bg-2); border-radius:3px; margin-bottom:6px;">
  1008. <div class="text-mono text-xs" style="color:${cn.color}; letter-spacing:0.06em; margin-bottom:2px;">🔒 原因</div>
  1009. <div style="font-size:0.74rem; color:var(--text-2); line-height:1.45;">${esc(cn.reason)}</div>
  1010. </div>
  1011. <div style="padding:5px 10px; background:var(--bg-2); border-radius:3px; margin-bottom:6px;">
  1012. <div class="text-mono text-xs" style="color:${cn.color}; letter-spacing:0.06em; margin-bottom:2px;">📌 执行</div>
  1013. <div style="font-size:0.74rem; color:var(--text-2); line-height:1.45;">${esc(cn.action)}</div>
  1014. </div>
  1015. <div style="padding:5px 10px; background:${cn.color}15; border-radius:3px;">
  1016. <div style="font-size:0.72rem; color:${cn.color}; font-style:italic; line-height:1.45;">${esc(cn.example)}</div>
  1017. </div>
  1018. </div>
  1019. `).join('')}
  1020. </div>
  1021. </div>
  1022. </div>
  1023. <!-- 方法论自律承诺 -->
  1024. <div class="fade-up" style="background:linear-gradient(135deg, ${c.color}10, ${BRAND.LIVER_AMBER}08); border:1px solid ${c.color}44; border-radius:var(--radius-md); padding:24px;">
  1025. <div class="text-mono text-xs" style="color:${c.color}; letter-spacing:0.15em; margin-bottom:14px;">DISCIPLINE · VOC 工作 4 条自律</div>
  1026. <div style="display:grid; grid-template-columns:repeat(4, 1fr); gap:14px;">
  1027. ${[
  1028. { num: '01', label: '边界清晰', desc: '明确能做/不能做,VOC 不越界', icon: '🎯', tint: BRAND.JIANG_GREEN },
  1029. { num: '02', label: '定位明确', desc: '藤茶 DMY + 安全 + 社交 + 礼品', icon: '🧭', tint: BRAND.LIVER_AMBER },
  1030. { num: '03', label: '目标导向', desc: '所有调研服务 10 亿 × 4 渠道', icon: '🚀', tint: BRAND.TECH_BLUE },
  1031. { num: '04', label: '用户核心', desc: 'VOC 捕真实需求,打造差异化', icon: '👤', tint: BRAND.ROSE },
  1032. ].map(d => `
  1033. <div style="text-align:center; padding:14px; background:${d.tint}08; border-radius:8px;">
  1034. <div style="font-size:2rem; margin-bottom:4px;">${d.icon}</div>
  1035. <div class="text-mono text-xs" style="color:${d.tint}; letter-spacing:0.1em; margin-bottom:4px;">PRINCIPLE ${d.num}</div>
  1036. <div style="font-size:1rem; font-weight:800; color:var(--text-1); margin-bottom:4px;">${esc(d.label)}</div>
  1037. <div style="font-size:0.72rem; color:var(--text-2); line-height:1.4;">${esc(d.desc)}</div>
  1038. </div>
  1039. `).join('')}
  1040. </div>
  1041. </div>
  1042. </div>
  1043. </section>`;
  1044. }
  1045. // ============================================================================
  1046. // SLIDE_RENDERERS 注册表 · dispatch in buildHTML
  1047. // ============================================================================
  1048. const SLIDE_RENDERERS = {
  1049. 'method-1': renderMethod1RevenueTarget,
  1050. 'method-2': renderMethod2Modules,
  1051. 'method-3': renderMethod3Platforms,
  1052. 'method-4': renderMethod4Analytics,
  1053. 'method-5': renderMethod5Boundaries,
  1054. // Batch 3 · Ch2 包装调研
  1055. 'package-1': PKG.renderPackage1Diagnosis,
  1056. 'package-2': PKG.renderPackage2Outer,
  1057. 'package-3': PKG.renderPackage3Inner,
  1058. 'package-4': PKG.renderPackage4Tablet,
  1059. 'package-5': PKG.renderPackage5SKU,
  1060. // Batch 4 · Ch3 定价调研
  1061. 'pricing-1': PRC.renderPricing1Channel,
  1062. 'pricing-2': PRC.renderPricing2SpecBand,
  1063. 'pricing-3': PRC.renderPricing3Competitor,
  1064. 'pricing-4': PRC.renderPricing4Value,
  1065. // Batch 5 · Ch4 定位与话术
  1066. 'positioning-1': POS.renderPositioning1DMY,
  1067. 'positioning-2': POS.renderPositioning2Safety,
  1068. 'positioning-3': POS.renderPositioning3Antidote,
  1069. 'positioning-4': POS.renderPositioning4Social,
  1070. 'positioning-5': POS.renderPositioning5Channel,
  1071. // Batch 6 · Ch5 场景适配 4 渠道
  1072. 'scene-1': SCN.renderScene1Medical,
  1073. 'scene-2': SCN.renderScene2Gift,
  1074. 'scene-3': SCN.renderScene3Dining,
  1075. 'scene-4': SCN.renderScene4Ecommerce,
  1076. // Batch 7 · Ch6 竞品认知 6 竞品
  1077. 'competitor-1': CMP.renderCompetitor1Huganpian,
  1078. 'competitor-2': CMP.renderCompetitor2Yishanfu,
  1079. 'competitor-3': CMP.renderCompetitor3Pianzaihuang,
  1080. 'competitor-4': CMP.renderCompetitor4Xiongdanfen,
  1081. 'competitor-5': CMP.renderCompetitor5Swisse,
  1082. 'competitor-6': CMP.renderCompetitor6Haiwang,
  1083. // Batch 8 · Ch7 落地行动 4 子章
  1084. 'action-1': ACT.renderAction1Priority,
  1085. 'action-2': ACT.renderAction2Thresholds,
  1086. 'action-3': ACT.renderAction3Roadmap,
  1087. 'action-4': ACT.renderAction4NextStage,
  1088. };
  1089. // ============================================================================
  1090. // buildHTML · 主装配函数
  1091. // ============================================================================
  1092. function buildHTML({ product, A, collectedAt } = {}) {
  1093. product = product || '江中肝纯片';
  1094. collectedAt = collectedAt || new Date().toISOString().slice(0, 10);
  1095. // 计算 slide 总数:2 (cover + agenda) + 每章节 (1 divider + N 子章)
  1096. const slidesPerChapter = CHAPTERS.map(ch => 1 + (CHAPTER_SUBSECTIONS[ch.key] || []).length);
  1097. const totalSlides = 2 + slidesPerChapter.reduce((s, n) => s + n, 0);
  1098. const ST = sn(totalSlides);
  1099. const slides = [];
  1100. let n = 1;
  1101. // Slide 01 · 封面
  1102. slides.push(renderCover({ product, A, collectedAt, slideNum: sn(n++), slideTotal: ST }));
  1103. // Slide 02 · 目录
  1104. slides.push(renderAgenda({ slideNum: sn(n++), slideTotal: ST }));
  1105. // 每个 chapter:先 divider,再 N 个子 slide
  1106. for (const chapter of CHAPTERS) {
  1107. const subsections = CHAPTER_SUBSECTIONS[chapter.key] || [];
  1108. const heroLine = CHAPTER_HERO_LINES[chapter.key] || '';
  1109. // Chapter Divider
  1110. slides.push(renderChapterDivider({
  1111. slideNum: sn(n++), slideTotal: ST,
  1112. chapter, subsections, heroLine,
  1113. }));
  1114. // Sub-sections
  1115. for (let i = 0; i < subsections.length; i++) {
  1116. const subKey = `${chapter.key}-${i + 1}`;
  1117. const renderer = SLIDE_RENDERERS[subKey];
  1118. if (renderer) {
  1119. slides.push(renderer({
  1120. slideNum: sn(n++), slideTotal: ST,
  1121. chapter, A,
  1122. }));
  1123. } else {
  1124. slides.push(renderSubPlaceholder({
  1125. slideNum: sn(n++), slideTotal: ST,
  1126. chapterKey: chapter.key, subIndex: i + 1,
  1127. title: subsections[i],
  1128. }));
  1129. }
  1130. }
  1131. }
  1132. return `<!DOCTYPE html>
  1133. <html lang="zh-CN">
  1134. <head>
  1135. <meta charset="UTF-8"/>
  1136. <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  1137. <title>${esc(product)} · VOC 验证报告 · 10亿×4渠道×5模块</title>
  1138. ${STYLES}
  1139. </head>
  1140. <body>
  1141. ${renderNav()}
  1142. ${renderKbdHint()}
  1143. <div class="progress-line" id="progressLine"></div>
  1144. <main class="deck">
  1145. ${slides.join('\n')}
  1146. </main>
  1147. <script>${SCRIPTS}</script>
  1148. </body>
  1149. </html>`;
  1150. }
  1151. module.exports = {
  1152. esc, fmtNum, fmtMoney, sn, star,
  1153. BRAND, CHANNEL_COLORS, CHAPTERS, CHAPTER_SUBSECTIONS, CHAPTER_HERO_LINES,
  1154. renderNav, renderKbdHint, renderCover, renderAgenda, renderChapterDivider,
  1155. renderSubPlaceholder, renderNextSteps,
  1156. renderMethod1RevenueTarget, renderMethod2Modules, renderMethod3Platforms, renderMethod4Analytics, renderMethod5Boundaries,
  1157. SLIDE_RENDERERS,
  1158. buildHTML,
  1159. TOTAL_SLIDES,
  1160. };