| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- // ==============================================================================
- // 精美 HTML 报告 · 视觉模式库(20+ copy-paste 小组件)
- // ==============================================================================
- // 使用方法:
- // 1. 不要整文件 require,而是查阅 → 复制对应 pattern 到你的 <品类>-components.js
- // 2. 每个 pattern 都有:① 适用场景 ② 输入参数 ③ HTML 范式 ④ 变体
- // 3. 所有 pattern 都假设 BRAND.MAIN 是品类主色
- // ==============================================================================
- // 公共依赖(你需要在实际 components.js 里定义)
- const BRAND_STUB = {
- MAIN: '#4A90E2',
- CORAL: '#FF6B6B',
- GOLD: '#D4AF37',
- JIANG_GREEN: '#1A7C5F',
- };
- function esc(s) {
- return String(s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
- }
- function fmtLikes(n) {
- if (!n) return '0';
- if (n >= 10000) return (n / 10000).toFixed(1) + 'w';
- if (n >= 1000) return (n / 1000).toFixed(1) + 'k';
- return String(n);
- }
- // ============================================================
- // P01 · Eyebrow · 小标签(所有 section head 开头必有)
- // ============================================================
- // 适用:section head / insight / decision list 前的小标签
- // 输入:text, color, letterSpacing
- function renderEyebrow({ text, color = BRAND_STUB.MAIN, letterSpacing = '0.2em' }) {
- return `<div class="text-mono text-xs"
- style="color:${color}; letter-spacing:${letterSpacing}; font-weight:700; margin-bottom:10px;">
- ${esc(text)}
- </div>`;
- }
- // ============================================================
- // P02 · Section Head · 三段式标题(eyebrow + title + subtitle)
- // ============================================================
- // 适用:每子章节开头
- // 输入:eyebrow, title(带 HTML, 允许 <strong>), subtitle, color
- function renderSectionHead({ eyebrow, title, subtitle, color = BRAND_STUB.MAIN }) {
- return `<div style="margin-bottom:20px;">
- ${eyebrow ? renderEyebrow({ text: eyebrow, color }) : ''}
- <h2 style="font-family:var(--font-head); font-weight:800; font-size:1.9rem; line-height:1.3;
- color:var(--text-1); margin:0 0 12px 0;">${title || ''}</h2>
- ${subtitle ? `<div style="color:var(--text-2); font-size:0.95rem; line-height:1.75; max-width:900px;">${subtitle}</div>` : ''}
- </div>`;
- }
- // ============================================================
- // P03 · VOC Card · 证据卡(核心组件 · 全报告贯穿)
- // ============================================================
- // 适用:所有子章节 ≥ 3 张
- // 输入:item { platform, nickname, ip, content, likes }, accent, maxChars
- function renderVocCard(item, opts = {}) {
- if (!item) return '';
- const accent = opts.accent || BRAND_STUB.MAIN;
- const maxChars = opts.maxChars || 200;
- const content = String(item.content || '').slice(0, maxChars);
- const more = (item.content || '').length > maxChars ? '…' : '';
- return `<div style="padding:14px 16px; background:var(--bg-1); border:1px solid var(--border);
- border-left:3px solid ${accent}; border-radius:6px;">
- <div style="display:flex; justify-content:space-between; gap:10px; margin-bottom:8px; font-size:0.78rem;">
- <div style="flex:1; min-width:0;">
- <span class="text-mono" style="color:${accent}; font-weight:700; letter-spacing:0.1em;">
- ${(item.platform || 'XHS').toUpperCase()}
- </span>
- <span style="color:var(--text-3);"> · ${esc(item.nickname || '匿名')}</span>
- ${item.ip ? `<span style="color:var(--text-3);"> · ${esc(item.ip)}</span>` : ''}
- </div>
- <div style="color:${accent}; font-family:var(--font-mono); font-weight:700; white-space:nowrap;">
- ♥${fmtLikes(item.likes)}
- </div>
- </div>
- <div style="color:var(--text-1); font-size:0.88rem; line-height:1.7;">
- 「${esc(content)}${more}」
- </div>
- </div>`;
- }
- // ============================================================
- // P04 · VOC Card Compact · 紧凑证据卡(3 列布局用)
- // ============================================================
- function renderVocCardCompact(item, opts = {}) {
- if (!item) return '';
- const accent = opts.accent || BRAND_STUB.MAIN;
- const maxChars = opts.maxChars || 120;
- const content = String(item.content || '').slice(0, maxChars);
- const more = (item.content || '').length > maxChars ? '…' : '';
- return `<div style="padding:10px 12px; background:var(--bg-1); border-left:3px solid ${accent}; border-radius:4px;">
- <div style="font-size:0.72rem; color:var(--text-3); margin-bottom:6px;">
- <span class="text-mono" style="color:${accent}; font-weight:700;">${(item.platform || 'XHS').toUpperCase()}</span>
- · ${esc(item.nickname || '匿名')} · ♥${fmtLikes(item.likes)}
- </div>
- <div style="color:var(--text-1); font-size:0.82rem; line-height:1.6;">「${esc(content)}${more}」</div>
- </div>`;
- }
- // ============================================================
- // P05 · StatStrip · KPI 数字条(4-6 个并列数字)
- // ============================================================
- // 适用:Cover / 章节 hero / 章末总结
- // 输入:stats = [{ num, label, delta, color }]
- function renderStatStrip(stats, opts = {}) {
- const accent = opts.accent || BRAND_STUB.MAIN;
- const cols = stats.length;
- return `<div class="grid" style="grid-template-columns:repeat(${cols},1fr); gap:12px; margin:20px 0;">
- ${stats.map((s) => `
- <div style="padding:18px; background:${s.color || accent}0C; border:1px solid ${s.color || accent}33; border-radius:8px; text-align:center;">
- <div style="color:${s.color || accent}; font-family:var(--font-head); font-weight:900; font-size:2rem; line-height:1;">${esc(s.num)}</div>
- <div style="color:var(--text-2); font-size:0.82rem; margin-top:6px;">${esc(s.label)}</div>
- ${s.delta ? `<div style="color:${s.color || accent}; font-size:0.72rem; font-family:var(--font-mono); margin-top:4px;">${esc(s.delta)}</div>` : ''}
- </div>`).join('')}
- </div>`;
- }
- // ============================================================
- // P06 · Single Big Stat · 巨型单数字(镇场)
- // ============================================================
- // 适用:Cover 核心数字 / 章节 hero 唯一金句数字
- function renderBigStat({ num, label, delta, color = BRAND_STUB.MAIN }) {
- return `<div style="padding:32px 40px; background:${color}0C; border:1px solid ${color}33; border-radius:12px; text-align:center; margin:24px 0;">
- <div style="color:${color}; font-family:var(--font-head); font-weight:900; font-size:4rem; line-height:1; letter-spacing:-0.02em;">${esc(num)}</div>
- <div style="color:var(--text-1); font-size:1rem; margin-top:12px; font-weight:600;">${esc(label)}</div>
- ${delta ? `<div style="color:${color}; font-size:0.82rem; font-family:var(--font-mono); margin-top:6px;">${esc(delta)}</div>` : ''}
- </div>`;
- }
- // ============================================================
- // P07 · Insight Hero · 金句观点卡(渐变背景)
- // ============================================================
- // 适用:章节核心洞察 · 每章 1-2 处
- function renderInsightHero({ eyebrow, title, subtitle, color = BRAND_STUB.MAIN }) {
- return `<div style="padding:24px 28px; background:linear-gradient(135deg, ${color}14, ${color}04);
- border:2px solid ${color}44; border-radius:12px; margin:20px 0;">
- ${eyebrow ? `<div class="text-mono text-xs" style="color:${color}; letter-spacing:0.2em; margin-bottom:12px; font-weight:700;">${esc(eyebrow)}</div>` : ''}
- <div style="color:var(--text-1); font-size:1.1rem; line-height:1.8;">${title || ''}</div>
- ${subtitle ? `<div style="color:var(--text-2); font-size:0.9rem; line-height:1.7; margin-top:10px;">${subtitle}</div>` : ''}
- </div>`;
- }
- // ============================================================
- // P08 · Decision List · 落地决策列表(每子章收尾)
- // ============================================================
- // 适用:每子章节最后 · 2 列 grid
- // 输入:items = ['<strong>P0 · 动词</strong>:具体动作', ...]
- function renderDecisionList(items, opts = {}) {
- const accent = opts.accent || BRAND_STUB.MAIN;
- const title = opts.title || '落地决策';
- const columns = opts.columns || 2;
- return `<div style="margin-top:24px; padding:20px 24px; background:${accent}08; border:1px solid ${accent}33; border-radius:8px;">
- <div class="text-mono text-xs" style="color:${accent}; letter-spacing:0.18em; margin-bottom:14px; font-weight:700;">🎯 ${esc(title)}</div>
- <div class="grid" style="grid-template-columns:repeat(${columns},1fr); gap:10px;">
- ${items.map((x) => `
- <div style="padding:10px 14px; background:var(--bg-1); border-left:3px solid ${accent}; border-radius:4px; color:var(--text-1); font-size:0.86rem; line-height:1.65;">
- ${x}
- </div>`).join('')}
- </div>
- </div>`;
- }
- // ============================================================
- // P09 · Compare Table · 对比表格
- // ============================================================
- // 适用:竞品 / 本品 vs 竞品矩阵
- // 输入:headers = [], rows = [[cell, cell, ...], ...]
- // cell = string | { html, color, bold }
- function renderCompareTable({ title, headers = [], rows = [], accent = BRAND_STUB.MAIN }) {
- return `<div style="margin:20px 0;">
- ${title ? `<div class="text-mono text-xs" style="color:${accent}; letter-spacing:0.18em; margin-bottom:12px; font-weight:700;">${esc(title)}</div>` : ''}
- <div style="overflow-x:auto;">
- <table style="width:100%; border-collapse:collapse; font-size:0.86rem;">
- <thead>
- <tr style="border-bottom:2px solid ${accent}44;">
- ${headers.map((h) => `<th style="text-align:left; padding:10px 12px; color:var(--text-3); font-weight:700; font-size:0.78rem; letter-spacing:0.05em;">${esc(h)}</th>`).join('')}
- </tr>
- </thead>
- <tbody>
- ${rows.map((row) => `
- <tr style="border-bottom:1px solid var(--border);">
- ${row.map((cell) => {
- const c = typeof cell === 'object' ? cell : { html: cell };
- return `<td style="padding:10px 12px; color:${c.color || 'var(--text-1)'}; ${c.bold ? 'font-weight:700;' : ''}">${c.html || c}</td>`;
- }).join('')}
- </tr>`).join('')}
- </tbody>
- </table>
- </div>
- </div>`;
- }
- // ============================================================
- // P10 · Matrix 2x2 · 无人地带四象限
- // ============================================================
- // 适用:Ch6 竞品 × 无人地带定位
- // 关键纪律:第 4 象限(本品独占)必须品类色高亮
- function renderMatrix2x2({ xLabel, yLabel, xLow, xHigh, yLow, yHigh, quadrants = {}, accent = BRAND_STUB.MAIN }) {
- const renderQ = (q) => {
- if (!q) return '<div></div>';
- return `<div style="padding:16px; background:${(q.color || accent)}0C; border:1px solid ${(q.color || accent)}33; border-radius:6px;">
- <div class="text-mono text-xs" style="color:${q.color || accent}; font-weight:700; margin-bottom:8px;">${q.title || ''}</div>
- <ul style="margin:0; padding-left:18px; color:var(--text-1); font-size:0.82rem; line-height:1.7;">
- ${(q.items || []).map((i) => `<li>${i}</li>`).join('')}
- </ul>
- ${q.note ? `<div style="color:var(--text-3); font-size:0.76rem; margin-top:8px; font-style:italic;">${esc(q.note)}</div>` : ''}
- </div>`;
- };
- return `<div style="margin:24px 0;">
- <div style="display:grid; grid-template-columns:auto 1fr 1fr; gap:12px; align-items:stretch;">
- <div></div>
- <div style="text-align:center; color:var(--text-3); font-size:0.78rem; font-weight:700;">${esc(xLow || '')}</div>
- <div style="text-align:center; color:var(--text-3); font-size:0.78rem; font-weight:700;">${esc(xHigh || '')}</div>
- <div style="writing-mode:vertical-rl; text-align:center; color:var(--text-3); font-size:0.78rem; font-weight:700; padding:8px 0;">${esc(yHigh || '')}</div>
- ${renderQ(quadrants.q2)}
- ${renderQ(quadrants.q1)}
- <div style="writing-mode:vertical-rl; text-align:center; color:var(--text-3); font-size:0.78rem; font-weight:700; padding:8px 0;">${esc(yLow || '')}</div>
- ${renderQ(quadrants.q3)}
- ${renderQ(quadrants.q4)}
- </div>
- <div style="text-align:center; color:${accent}; font-family:var(--font-mono); font-size:0.82rem; letter-spacing:0.12em; margin-top:8px;">
- ← ${esc(xLabel || '')} → ${yLabel ? '· Y: ' + esc(yLabel) : ''}
- </div>
- </div>`;
- }
- // ============================================================
- // P11 · Theory Box · 理论映射盒(KANO / JTBD / 3C)
- // ============================================================
- function renderTheoryBox({ theory, mapping, accent = BRAND_STUB.MAIN }) {
- return `<div style="padding:16px 18px; background:${accent}08; border-left:3px solid ${accent}; border-radius:8px;">
- ${theory ? `<div class="text-mono text-xs" style="color:${accent}; letter-spacing:0.15em; font-weight:700; margin-bottom:10px;">${esc(theory)}</div>` : ''}
- ${mapping || ''}
- </div>`;
- }
- // ============================================================
- // P12 · Finding Card · 发现洞察卡(icon + 标题 + 正文)
- // ============================================================
- // 适用:3-4 列并排的小发现
- function renderFindingCard({ icon, title, body, accent = BRAND_STUB.MAIN }) {
- return `<div style="padding:16px 18px; background:var(--bg-1); border:1px solid ${accent}33; border-left:4px solid ${accent}; border-radius:8px;">
- <div style="display:flex; align-items:flex-start; gap:12px;">
- ${icon ? `<div style="font-size:1.6rem; line-height:1;">${icon}</div>` : ''}
- <div style="flex:1;">
- ${title ? `<div style="color:var(--text-1); font-weight:700; font-size:0.95rem; margin-bottom:6px;">${title}</div>` : ''}
- <div style="color:var(--text-2); font-size:0.84rem; line-height:1.7;">${body || ''}</div>
- </div>
- </div>
- </div>`;
- }
- // ============================================================
- // P13 · Progress Bar · 横向比例条(单维度对比)
- // ============================================================
- // 适用:竞品市占 / 假设覆盖率 / 渠道占比
- function renderProgressBar({ label, value, max = 100, accent = BRAND_STUB.MAIN, suffix = '%' }) {
- const pct = Math.min(100, (value / max) * 100);
- return `<div style="margin:8px 0;">
- <div style="display:flex; justify-content:space-between; font-size:0.78rem; margin-bottom:4px;">
- <span style="color:var(--text-2);">${esc(label)}</span>
- <span class="text-mono" style="color:${accent}; font-weight:700;">${value}${suffix}</span>
- </div>
- <div style="height:6px; background:var(--bg-2); border-radius:3px; overflow:hidden;">
- <div style="height:100%; width:${pct}%; background:linear-gradient(90deg, ${accent}, ${accent}cc);"></div>
- </div>
- </div>`;
- }
- // ============================================================
- // P14 · Inline Bar Chart · 小柱图(纯 div · 无依赖)
- // ============================================================
- // 适用:多项对比 5-10 个
- function renderInlineBars({ items, max, accent = BRAND_STUB.MAIN, height = 80 }) {
- const maxVal = max || Math.max(...items.map((i) => i.value));
- return `<div style="display:flex; align-items:flex-end; gap:6px; height:${height}px; margin:16px 0;">
- ${items.map((i) => {
- const pct = Math.max(4, (i.value / maxVal) * 100);
- return `<div style="flex:1; text-align:center;">
- <div style="height:${pct}%; background:${i.color || accent}; border-radius:2px 2px 0 0; margin-top:auto; position:relative;">
- <div class="text-mono" style="position:absolute; top:-18px; left:50%; transform:translateX(-50%); font-size:0.72rem; color:${i.color || accent}; white-space:nowrap;">${i.value}</div>
- </div>
- <div style="font-size:0.72rem; color:var(--text-3); margin-top:6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${esc(i.label)}</div>
- </div>`;
- }).join('')}
- </div>`;
- }
- // ============================================================
- // P15 · Tag Cloud · 标签云(高频词)
- // ============================================================
- function renderTagCloud({ tags, accent = BRAND_STUB.MAIN }) {
- return `<div style="display:flex; flex-wrap:wrap; gap:8px; margin:16px 0;">
- ${tags.map((t) => {
- const size = t.count ? Math.min(1.1, 0.78 + Math.log10(t.count) * 0.1) : 0.82;
- const alpha = t.count ? Math.min(44, 14 + t.count) : 28;
- return `<span class="text-mono" style="padding:4px 10px; background:${accent}${alpha.toString(16).padStart(2, '0')}; border:1px solid ${accent}44; border-radius:12px; font-size:${size}rem; color:${accent};">#${esc(t.label)}${t.count ? ` · ${t.count}` : ''}</span>`;
- }).join('')}
- </div>`;
- }
- // ============================================================
- // P16 · Flow Diagram · 决策链流程图(纯 div + Unicode 箭头)
- // ============================================================
- function renderFlow({ steps, accent = BRAND_STUB.MAIN }) {
- return `<div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:20px 0;">
- ${steps.map((s, i) => {
- const box = `<div style="padding:8px 14px; background:${accent}14; border:1px solid ${accent}; border-radius:6px; color:var(--text-1); font-size:0.86rem; white-space:nowrap;">${esc(s)}</div>`;
- const arrow = i < steps.length - 1 ? `<div style="color:${accent}; font-size:1.2rem; font-weight:700;">→</div>` : '';
- return box + arrow;
- }).join('')}
- </div>`;
- }
- // ============================================================
- // P17 · Platform Badge · 平台徽章(带图标)
- // ============================================================
- function renderPlatformBadge(platform, count, color) {
- const icons = { xhs: '📕', douyin: '🎵', weibo: '📱', jd: '🛒', tmall: '🛍', amazon: '📦' };
- const labels = { xhs: 'XHS', douyin: 'DOUYIN', weibo: 'WEIBO', jd: 'JD', tmall: 'TMALL', amazon: 'AMZN' };
- return `<span class="text-mono"
- style="padding:4px 10px; background:var(--bg-2); border:1px solid ${color || 'var(--border)'};
- border-radius:4px; font-size:0.78rem; color:${color || 'var(--text-2)'};
- letter-spacing:0.08em; font-weight:700;">
- ${icons[platform] || '📊'} ${labels[platform] || platform.toUpperCase()}${count !== undefined ? ` · ${count}` : ''}
- </span>`;
- }
- // ============================================================
- // P18 · Hypothesis Tag · 假设标签(H1-H8)
- // ============================================================
- function renderHypothesisTag(h, desc, color) {
- return `<div style="display:inline-flex; align-items:center; gap:8px; padding:6px 12px; background:${color || BRAND_STUB.MAIN}14; border:1px solid ${color || BRAND_STUB.MAIN}44; border-radius:4px; margin:4px 4px 4px 0;">
- <span class="text-mono" style="color:${color || BRAND_STUB.MAIN}; font-weight:800; font-size:0.78rem;">${h}</span>
- <span style="color:var(--text-2); font-size:0.82rem;">${esc(desc || '')}</span>
- </div>`;
- }
- // ============================================================
- // P19 · Page Indicator · 右下角页码(固定定位)
- // ============================================================
- // 使用:作为独立 HTML 节点放在 body 末尾,配合 JS 更新
- function renderPageIndicator() {
- return `<div id="page-indicator"
- style="position:fixed; right:20px; bottom:20px; padding:6px 12px;
- background:var(--bg-2); border:1px solid var(--border); border-radius:4px;
- font-family:var(--font-mono); font-size:0.78rem; color:var(--text-3); z-index:50;">
- 1 / 1
- </div>`;
- }
- // 配套 JS · 嵌到 NAV_JS 末尾
- const PAGE_INDICATOR_JS = `
- (function(){
- const indicator = document.getElementById('page-indicator');
- const sections = document.querySelectorAll('.report-section');
- if (!indicator || !sections.length) return;
- indicator.textContent = '1 / ' + sections.length;
- const observer = new IntersectionObserver((entries) => {
- for (const e of entries) {
- if (e.isIntersecting && e.intersectionRatio > 0.5) {
- const idx = [...sections].indexOf(e.target) + 1;
- indicator.textContent = idx + ' / ' + sections.length;
- break;
- }
- }
- }, { threshold: [0.5] });
- sections.forEach((s) => observer.observe(s));
- })();
- `;
- // ============================================================
- // P20 · Nav JS · 键盘导航(标配)
- // ============================================================
- // 嵌到 render.js 的 NAV_JS 常量里
- const NAV_JS = `
- (function() {
- const sections = document.querySelectorAll('.report-section');
- let idx = 0;
- function go(i) {
- idx = Math.max(0, Math.min(sections.length - 1, i));
- sections[idx].scrollIntoView({ behavior: 'smooth' });
- if (sections[idx].id) history.replaceState(null, '', '#' + sections[idx].id);
- }
- document.addEventListener('keydown', (e) => {
- if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'PageDown') { e.preventDefault(); go(idx + 1); }
- if (e.key === 'ArrowLeft' || e.key === 'PageUp') { e.preventDefault(); go(idx - 1); }
- if (e.key === 'Home') go(0);
- if (e.key === 'End') go(sections.length - 1);
- });
- if (location.hash) {
- const i = [...sections].findIndex((s) => '#' + s.id === location.hash);
- if (i >= 0) idx = i;
- }
- })();
- `;
- // ============================================================
- // P21 · Gradient Cover Background(Cover 专用)
- // ============================================================
- const COVER_STYLE = `
- .cover {
- background: linear-gradient(180deg, #0A0A0A 0%, #111 100%);
- position: relative;
- overflow: hidden;
- }
- .cover::before {
- content: '';
- position: absolute;
- top: -50%;
- right: -10%;
- width: 60%;
- height: 200%;
- background: radial-gradient(circle, BRAND_MAIN_ALPHA 0%, transparent 70%);
- opacity: 0.3;
- pointer-events: none;
- }
- `;
- // ============================================================
- // P22 · Print Friendly · 打印友好
- // ============================================================
- const PRINT_CSS = `
- @media print {
- .report-section {
- min-height: auto;
- page-break-after: always;
- padding: 20px;
- border: none;
- }
- body { background: white; color: black; }
- .report-section, .section-inner { background: white !important; }
- [style*="color:var(--text-1)"] { color: black !important; }
- [style*="color:var(--text-2)"] { color: #333 !important; }
- [style*="color:var(--text-3)"] { color: #666 !important; }
- #page-indicator { display: none; }
- }
- `;
- // ============================================================
- // P23 · Mobile Degradation · 移动端降级
- // ============================================================
- const MOBILE_CSS = `
- @media (max-width: 768px) {
- .report-section { padding: 24px 16px; }
- .section-inner { max-width: 100%; }
- .grid { grid-template-columns: 1fr !important; gap: 10px !important; }
- .cover h1 { font-size: 2rem !important; }
- .divider h1 { font-size: 2.8rem !important; }
- h2 { font-size: 1.4rem !important; }
- [style*="font-size:4rem"] { font-size: 2.4rem !important; }
- [style*="font-size:5rem"] { font-size: 2.8rem !important; }
- [style*="font-size:3.6rem"] { font-size: 2rem !important; }
- }
- `;
- // ============================================================
- // 导出(只是作为参考,实际使用时 copy-paste 到你的 components.js)
- // ============================================================
- module.exports = {
- // 基础工具
- esc,
- fmtLikes,
- // P01-P23 视觉模式
- renderEyebrow, // P01
- renderSectionHead, // P02
- renderVocCard, // P03
- renderVocCardCompact, // P04
- renderStatStrip, // P05
- renderBigStat, // P06
- renderInsightHero, // P07
- renderDecisionList, // P08
- renderCompareTable, // P09
- renderMatrix2x2, // P10
- renderTheoryBox, // P11
- renderFindingCard, // P12
- renderProgressBar, // P13
- renderInlineBars, // P14
- renderTagCloud, // P15
- renderFlow, // P16
- renderPlatformBadge, // P17
- renderHypothesisTag, // P18
- renderPageIndicator, // P19
- NAV_JS, // P20
- PAGE_INDICATOR_JS,
- COVER_STYLE, // P21
- PRINT_CSS, // P22
- MOBILE_CSS, // P23
- };
|