|
|
@@ -0,0 +1,930 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+<meta charset="UTF-8">
|
|
|
+<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
|
+<title>{{industryName}}行业竞品与B端线索分析报告</title>
|
|
|
+<!-- ===== Chart.js CDN ===== -->
|
|
|
+<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
|
+<style>
|
|
|
+/* ============================================================
|
|
|
+ 全局变量 & 色彩体系 — 轻奢深棕 + 暖金莫兰迪
|
|
|
+ ============================================================ */
|
|
|
+:root{
|
|
|
+ --bg-deep:#1A110B;
|
|
|
+ --bg-dark:#2D1810;
|
|
|
+ --bg-mid:#3E2518;
|
|
|
+ --brown:#5C3D2E;
|
|
|
+ --brown-light:#8B6F47;
|
|
|
+ --gold:#C5A55A;
|
|
|
+ --gold-light:#D4B978;
|
|
|
+ --cream:#FFF8F0;
|
|
|
+ --cream-dim:#F5E6D3;
|
|
|
+ --accent-rose:#C4868B;
|
|
|
+ --accent-sage:#8FA68A;
|
|
|
+ --accent-blue:#7E9BB5;
|
|
|
+ --glass:rgba(255,248,240,0.06);
|
|
|
+ --glass-border:rgba(197,165,90,0.18);
|
|
|
+ --glass-hover:rgba(255,248,240,0.12);
|
|
|
+ --shadow:0 8px 32px rgba(0,0,0,0.35);
|
|
|
+ --radius:16px;
|
|
|
+ --transition:all .4s cubic-bezier(.4,0,.2,1);
|
|
|
+ --font:'Segoe UI','PingFang SC','Microsoft YaHei','Helvetica Neue',system-ui,sans-serif;
|
|
|
+}
|
|
|
+/* ============================================================
|
|
|
+ Reset & 基础排版
|
|
|
+ ============================================================ */
|
|
|
+*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
|
|
|
+html{font-size:16px;scroll-behavior:smooth;overflow:hidden}
|
|
|
+body{font-family:var(--font);background:var(--bg-deep);color:var(--cream);line-height:1.7;overflow:hidden;-webkit-font-smoothing:antialiased}
|
|
|
+h1{font-size:clamp(2rem,5vw,3.6rem);font-weight:800;letter-spacing:-.02em;line-height:1.15}
|
|
|
+h2{font-size:clamp(1.5rem,3.5vw,2.4rem);font-weight:700;letter-spacing:-.01em}
|
|
|
+h3{font-size:clamp(1.1rem,2vw,1.5rem);font-weight:600}
|
|
|
+a{color:var(--gold);text-decoration:none}
|
|
|
+/* ============================================================
|
|
|
+ 幻灯片容器
|
|
|
+ ============================================================ */
|
|
|
+#slides-wrapper{position:relative;width:100vw;height:100vh;overflow:hidden}
|
|
|
+.slide{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:clamp(24px,4vw,60px);opacity:0;visibility:hidden;transform:translateY(30px);transition:opacity .7s ease,transform .7s ease,visibility 0s .7s;z-index:0;overflow-y:auto}
|
|
|
+.slide.active{opacity:1;visibility:visible;transform:translateY(0);transition:opacity .7s ease,transform .7s ease,visibility 0s 0s;z-index:1}
|
|
|
+.slide-inner{width:100%;max-width:1200px;position:relative}
|
|
|
+/* ============================================================
|
|
|
+ 页眉 & 页脚
|
|
|
+ ============================================================ */
|
|
|
+.slide-header{position:absolute;top:0;left:0;right:0;display:flex;justify-content:space-between;align-items:center;padding:18px clamp(24px,4vw,60px);font-size:.8rem;color:var(--brown-light);letter-spacing:.05em;z-index:10;pointer-events:none}
|
|
|
+.slide-footer{position:absolute;bottom:0;left:0;right:0;display:flex;justify-content:space-between;align-items:center;padding:14px clamp(24px,4vw,60px);font-size:.75rem;color:rgba(139,111,71,.6);z-index:10;pointer-events:none}
|
|
|
+.page-num{font-weight:600;color:var(--gold)}
|
|
|
+/* ============================================================
|
|
|
+ 毛玻璃卡片(Glassmorphism)
|
|
|
+ ============================================================ */
|
|
|
+.glass-card{background:var(--glass);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius);padding:clamp(18px,2.5vw,32px);transition:var(--transition);position:relative;overflow:hidden}
|
|
|
+.glass-card::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(197,165,90,.08) 0%,transparent 60%);pointer-events:none;border-radius:inherit}
|
|
|
+.glass-card:hover{background:var(--glass-hover);border-color:rgba(197,165,90,.35);transform:translateY(-2px);box-shadow:var(--shadow)}
|
|
|
+/* ============================================================
|
|
|
+ 数据指标卡片
|
|
|
+ ============================================================ */
|
|
|
+.metric-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:clamp(12px,2vw,24px);width:100%}
|
|
|
+.metric-card{text-align:center;padding:clamp(16px,2vw,28px)}
|
|
|
+.metric-value{font-size:clamp(1.8rem,4vw,2.8rem);font-weight:800;color:var(--gold);margin-bottom:4px}
|
|
|
+.metric-label{font-size:.85rem;color:var(--cream-dim);font-weight:400}
|
|
|
+.metric-sub{font-size:.75rem;color:var(--brown-light);margin-top:2px}
|
|
|
+/* ============================================================
|
|
|
+ 数据表格
|
|
|
+ ============================================================ */
|
|
|
+.data-table{width:100%;border-collapse:separate;border-spacing:0;font-size:clamp(.75rem,1.4vw,.9rem)}
|
|
|
+.data-table thead th{background:rgba(197,165,90,.15);color:var(--gold-light);font-weight:600;padding:12px 14px;text-align:left;border-bottom:2px solid var(--gold);white-space:nowrap}
|
|
|
+.data-table thead th:first-child{border-radius:var(--radius) 0 0 0}
|
|
|
+.data-table thead th:last-child{border-radius:0 var(--radius) 0 0}
|
|
|
+.data-table tbody td{padding:10px 14px;border-bottom:1px solid rgba(139,111,71,.15);transition:background .3s}
|
|
|
+.data-table tbody tr:hover td{background:rgba(197,165,90,.06)}
|
|
|
+.data-table tbody tr:last-child td:first-child{border-radius:0 0 0 var(--radius)}
|
|
|
+.data-table tbody tr:last-child td:last-child{border-radius:0 0 var(--radius) 0}
|
|
|
+/* ============================================================
|
|
|
+ 标签 / 徽章
|
|
|
+ ============================================================ */
|
|
|
+.badge{display:inline-block;padding:3px 10px;border-radius:20px;font-size:.72rem;font-weight:600;letter-spacing:.03em}
|
|
|
+.badge-gold{background:rgba(197,165,90,.2);color:var(--gold-light);border:1px solid rgba(197,165,90,.3)}
|
|
|
+.badge-rose{background:rgba(196,134,139,.15);color:var(--accent-rose);border:1px solid rgba(196,134,139,.25)}
|
|
|
+.badge-sage{background:rgba(143,166,138,.15);color:var(--accent-sage);border:1px solid rgba(143,166,138,.25)}
|
|
|
+.badge-blue{background:rgba(126,155,181,.15);color:var(--accent-blue);border:1px solid rgba(126,155,181,.25)}
|
|
|
+/* ============================================================
|
|
|
+ 进度条 / 比例条
|
|
|
+ ============================================================ */
|
|
|
+.bar-row{display:flex;align-items:center;gap:12px;margin-bottom:10px}
|
|
|
+.bar-label{min-width:140px;font-size:.82rem;text-align:right;color:var(--cream-dim)}
|
|
|
+.bar-track{flex:1;height:22px;background:rgba(255,248,240,.06);border-radius:11px;overflow:hidden;position:relative}
|
|
|
+.bar-fill{height:100%;border-radius:11px;transition:width 1.5s cubic-bezier(.4,0,.2,1);position:relative}
|
|
|
+.bar-fill::after{content:attr(data-value);position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:.7rem;font-weight:700;color:var(--bg-dark)}
|
|
|
+/* ============================================================
|
|
|
+ 侧边导航
|
|
|
+ ============================================================ */
|
|
|
+#side-nav{position:fixed;right:clamp(10px,2vw,24px);top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:12px;z-index:1000}
|
|
|
+.nav-dot{width:12px;height:12px;border-radius:50%;border:2px solid var(--brown-light);background:transparent;cursor:pointer;transition:var(--transition);position:relative}
|
|
|
+.nav-dot.active{background:var(--gold);border-color:var(--gold);box-shadow:0 0 12px rgba(197,165,90,.5)}
|
|
|
+.nav-dot::after{content:attr(data-tip);position:absolute;right:22px;top:50%;transform:translateY(-50%);background:var(--bg-mid);color:var(--cream);padding:4px 12px;border-radius:8px;font-size:.72rem;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .3s}
|
|
|
+.nav-dot:hover::after{opacity:1}
|
|
|
+/* ============================================================
|
|
|
+ 全屏按钮
|
|
|
+ ============================================================ */
|
|
|
+#fs-btn{position:fixed;top:18px;right:clamp(10px,2vw,24px);z-index:1001;background:var(--glass);backdrop-filter:blur(10px);border:1px solid var(--glass-border);color:var(--gold);padding:6px 14px;border-radius:8px;cursor:pointer;font-size:.78rem;transition:var(--transition)}
|
|
|
+#fs-btn:hover{background:var(--glass-hover);border-color:var(--gold)}
|
|
|
+/* ============================================================
|
|
|
+ 封面粒子画布
|
|
|
+ ============================================================ */
|
|
|
+#particles-canvas{position:absolute;inset:0;z-index:0;pointer-events:none}
|
|
|
+/* ============================================================
|
|
|
+ 图表容器
|
|
|
+ ============================================================ */
|
|
|
+.chart-wrap{position:relative;width:100%;max-height:320px;margin:12px 0}
|
|
|
+.chart-wrap canvas{max-height:320px}
|
|
|
+/* ============================================================
|
|
|
+ 两栏/三栏布局
|
|
|
+ ============================================================ */
|
|
|
+.cols-2{display:grid;grid-template-columns:1fr 1fr;gap:clamp(14px,2vw,28px)}
|
|
|
+.cols-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:clamp(14px,2vw,24px)}
|
|
|
+/* ============================================================
|
|
|
+ 分隔线 & 间距工具
|
|
|
+ ============================================================ */
|
|
|
+.divider{width:60px;height:3px;background:linear-gradient(90deg,var(--gold),transparent);border-radius:2px;margin:16px 0}
|
|
|
+.mt-sm{margin-top:12px}.mt-md{margin-top:24px}.mt-lg{margin-top:36px}
|
|
|
+.mb-sm{margin-bottom:12px}.mb-md{margin-bottom:24px}
|
|
|
+.text-gold{color:var(--gold)}.text-rose{color:var(--accent-rose)}.text-sage{color:var(--accent-sage)}.text-blue{color:var(--accent-blue)}
|
|
|
+.text-dim{color:var(--brown-light)}.text-sm{font-size:.82rem}.text-xs{font-size:.72rem}
|
|
|
+.fw-700{font-weight:700}.fw-600{font-weight:600}
|
|
|
+/* ============================================================
|
|
|
+ 封面页特殊样式
|
|
|
+ ============================================================ */
|
|
|
+.cover-content{position:relative;z-index:1;text-align:center}
|
|
|
+.cover-brand{font-size:clamp(.9rem,1.8vw,1.2rem);color:var(--gold);letter-spacing:.3em;text-transform:uppercase;margin-bottom:16px;font-weight:600}
|
|
|
+.cover-title{background:linear-gradient(135deg,var(--cream) 0%,var(--gold-light) 50%,var(--gold) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:20px}
|
|
|
+.cover-sub{font-size:clamp(.9rem,1.6vw,1.15rem);color:var(--cream-dim);max-width:640px;margin:0 auto 32px}
|
|
|
+.cover-date{font-size:.85rem;color:var(--brown-light);letter-spacing:.1em}
|
|
|
+.cover-line{width:80px;height:1px;background:var(--gold);margin:24px auto}
|
|
|
+/* ============================================================
|
|
|
+ 目录页
|
|
|
+ ============================================================ */
|
|
|
+.toc-list{list-style:none;counter-reset:toc}
|
|
|
+.toc-item{counter-increment:toc;padding:14px 20px;border-bottom:1px solid rgba(139,111,71,.12);cursor:pointer;display:flex;align-items:center;gap:16px;transition:var(--transition);border-radius:8px}
|
|
|
+.toc-item:hover{background:var(--glass-hover);padding-left:28px}
|
|
|
+.toc-item::before{content:counter(toc,decimal-leading-zero);font-size:1.6rem;font-weight:800;color:var(--gold);min-width:40px}
|
|
|
+.toc-item .toc-title{font-size:1.05rem;font-weight:600;color:var(--cream)}
|
|
|
+.toc-item .toc-desc{font-size:.78rem;color:var(--brown-light);margin-top:2px}
|
|
|
+/* ============================================================
|
|
|
+ 竞品卡片
|
|
|
+ ============================================================ */
|
|
|
+.competitor-card{padding:clamp(18px,2vw,28px)}
|
|
|
+.competitor-card h3{color:var(--gold-light);margin-bottom:8px}
|
|
|
+.comp-stat{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(139,111,71,.1);font-size:.85rem}
|
|
|
+/* ============================================================
|
|
|
+ 时间轴
|
|
|
+ ============================================================ */
|
|
|
+.timeline{position:relative;padding-left:28px}
|
|
|
+.timeline::before{content:'';position:absolute;left:8px;top:0;bottom:0;width:2px;background:linear-gradient(180deg,var(--gold),var(--brown-light),transparent)}
|
|
|
+.timeline-item{position:relative;margin-bottom:24px;padding-left:20px}
|
|
|
+.timeline-item::before{content:'';position:absolute;left:-24px;top:6px;width:12px;height:12px;border-radius:50%;background:var(--gold);border:2px solid var(--bg-dark);box-shadow:0 0 8px rgba(197,165,90,.4)}
|
|
|
+.timeline-item h4{color:var(--gold-light);font-size:.95rem;margin-bottom:4px}
|
|
|
+.timeline-item p{font-size:.82rem;color:var(--cream-dim)}
|
|
|
+/* ============================================================
|
|
|
+ VOC 痛点条
|
|
|
+ ============================================================ */
|
|
|
+.pain-bar{display:flex;align-items:center;gap:12px;margin-bottom:14px}
|
|
|
+.pain-icon{font-size:1.1rem;min-width:24px;text-align:center}
|
|
|
+.pain-info{flex:1}
|
|
|
+.pain-name{font-size:.85rem;font-weight:600;color:var(--cream);margin-bottom:3px}
|
|
|
+.pain-pct{font-size:.75rem;color:var(--brown-light)}
|
|
|
+.pain-track{width:100%;height:8px;background:rgba(255,248,240,.06);border-radius:4px;overflow:hidden}
|
|
|
+.pain-fill{height:100%;border-radius:4px;transition:width 1.5s ease}
|
|
|
+/* ============================================================
|
|
|
+ 动画关键帧
|
|
|
+ ============================================================ */
|
|
|
+@keyframes fadeInUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}
|
|
|
+@keyframes fadeIn{from{opacity:0}to{opacity:1}}
|
|
|
+@keyframes shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}
|
|
|
+@keyframes pulse{0%,100%{opacity:1}50%{opacity:.6}}
|
|
|
+.anim-up{animation:fadeInUp .8s ease both}
|
|
|
+.anim-delay-1{animation-delay:.15s}.anim-delay-2{animation-delay:.3s}.anim-delay-3{animation-delay:.45s}.anim-delay-4{animation-delay:.6s}
|
|
|
+/* 入场动画 */
|
|
|
+.anim-enter{opacity:0;transform:translateY(24px);transition:opacity .7s ease,transform .7s ease}
|
|
|
+.slide.active .anim-enter{opacity:1;transform:translateY(0)}
|
|
|
+.slide.active .anim-enter.d1{transition-delay:.1s}
|
|
|
+.slide.active .anim-enter.d2{transition-delay:.2s}
|
|
|
+.slide.active .anim-enter.d3{transition-delay:.3s}
|
|
|
+.slide.active .anim-enter.d4{transition-delay:.4s}
|
|
|
+.slide.active .anim-enter.d5{transition-delay:.5s}
|
|
|
+.slide.active .anim-enter.d6{transition-delay:.6s}
|
|
|
+/* ============================================================
|
|
|
+ Modal弹窗
|
|
|
+ ============================================================ */
|
|
|
+.modal-overlay{position:fixed;inset:0;background:rgba(10,6,3,.85);backdrop-filter:blur(12px);z-index:2000;display:none;align-items:center;justify-content:center;opacity:0;transition:opacity .4s ease}
|
|
|
+.modal-overlay.show{display:flex;opacity:1}
|
|
|
+.modal-box{background:linear-gradient(135deg,#1a110b,#0d0a08);border:1px solid rgba(197,165,90,.25);border-radius:16px;width:92vw;max-width:960px;max-height:88vh;overflow-y:auto;box-shadow:0 8px 48px rgba(0,0,0,.7);position:relative;animation:modalIn .4s ease}
|
|
|
+@keyframes modalIn{from{opacity:0;transform:translateY(30px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}
|
|
|
+.modal-close{position:absolute;top:12px;right:16px;background:none;border:none;color:var(--cream-dim);font-size:1.4rem;cursor:pointer;z-index:10;transition:color .3s}
|
|
|
+.modal-close:hover{color:var(--gold)}
|
|
|
+.modal-header{padding:24px 28px 16px;border-bottom:1px solid rgba(197,165,90,.15)}
|
|
|
+.modal-header h2{font-size:1.15rem;color:var(--gold);margin:0 0 6px}
|
|
|
+.modal-header p{font-size:.8rem;color:var(--cream-dim);margin:0}
|
|
|
+.modal-body{padding:20px 28px 28px}
|
|
|
+/* ============================================================
|
|
|
+ 响应式
|
|
|
+ ============================================================ */
|
|
|
+@media(max-width:900px){
|
|
|
+ .cols-2,.cols-3{grid-template-columns:1fr}
|
|
|
+ .metric-grid{grid-template-columns:repeat(2,1fr)}
|
|
|
+ #side-nav{right:6px;gap:8px}
|
|
|
+ .nav-dot{width:9px;height:9px}
|
|
|
+ .bar-label{min-width:100px;font-size:.75rem}
|
|
|
+}
|
|
|
+@media(max-width:600px){
|
|
|
+ .metric-grid{grid-template-columns:1fr}
|
|
|
+ .slide{padding:16px}
|
|
|
+}
|
|
|
+</style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+
|
|
|
+<!-- ===== 全屏按钮 ===== -->
|
|
|
+<button id="fs-btn" title="全屏切换">⛶ 全屏</button>
|
|
|
+
|
|
|
+<!-- ===== 侧边导航(由 JS 自动生成) ===== -->
|
|
|
+<nav id="side-nav"></nav>
|
|
|
+
|
|
|
+<!-- ===== 幻灯片容器 ===== -->
|
|
|
+<div id="slides-wrapper">
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 0 — 封面
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide active" id="slide-0">
|
|
|
+ <canvas id="particles-canvas"></canvas>
|
|
|
+ <div class="cover-content">
|
|
|
+ <p class="cover-brand">{{coverBrandEnglish}}</p>
|
|
|
+ <h1 class="cover-title">{{industryName}}行业竞品与<br>B端线索分析报告</h1>
|
|
|
+ <div class="cover-line"></div>
|
|
|
+ <p class="cover-sub">基于Amazon电商数据 · TikTok/Instagram社媒数据 · {{totalReviews}}条用户评论VOC分析<br>覆盖{{categoryCount}}大核心品类 · {{competitorCount}}大竞品品牌深度对标</p>
|
|
|
+ <p class="cover-date">{{reportDate}} · AI Data Intelligence</p>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span></span><span class="text-xs" style="opacity:.4">按 → 或滚轮翻页</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 1 — 目录
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-1">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>目录</span></div>
|
|
|
+ <div class="slide-inner" style="max-width:720px">
|
|
|
+ <h2 class="text-gold mb-md" style="text-align:center">报告目录</h2>
|
|
|
+ <div class="divider" style="margin:0 auto 28px"></div>
|
|
|
+ <ul class="toc-list">
|
|
|
+ <li class="toc-item" onclick="goSlide(2)"><div><div class="toc-title">核心执行摘要</div><div class="toc-desc">关键数据 · 核心结论 · 核心价值</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(3)"><div><div class="toc-title">{{industryName}}品类市场全景分析</div><div class="toc-desc">{{categoryCount}}大品类规模 · 增长趋势 · 价格带 · 品牌分布</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(4)"><div><div class="toc-title">核心竞品深度对标分析</div><div class="toc-desc">{{competitorNames}} 品牌拆解</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(5)"><div><div class="toc-title">全渠道用户VOC与需求洞察</div><div class="toc-desc">{{totalReviews}}条评论 · 痛点 · 喜爱点 · 使用场景</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(6)"><div><div class="toc-title">B端高价值线索与品类矩阵</div><div class="toc-desc">品类机会评估 · 社媒热度 · 优先级排序</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(7)"><div><div class="toc-title">市场拓展与落地执行建议</div><div class="toc-desc">短期·中期·长期分阶段策略</div></div></li>
|
|
|
+ <li class="toc-item" onclick="goSlide(8)"><div><div class="toc-title">总结与展望</div><div class="toc-desc">核心机会点 · 行动优先级</div></div></li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">01</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 2 — 执行摘要
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-2">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>执行摘要</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">核心执行摘要</h2>
|
|
|
+ <div class="divider"></div>
|
|
|
+ <!-- 核心数据指标卡片 — 由 REPORT_DATA.metrics 注入 -->
|
|
|
+ <div class="metric-grid mt-md mb-md" id="exec-metrics"></div>
|
|
|
+ <!-- 核心结论 — 由 REPORT_DATA.coreFindings / coreValues 注入 -->
|
|
|
+ <div class="cols-2">
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-gold mb-sm">📊 核心发现</h3>
|
|
|
+ <ul id="core-findings" style="list-style:none;font-size:.85rem;color:var(--cream-dim)"></ul>
|
|
|
+ </div>
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-gold mb-sm">💡 核心价值</h3>
|
|
|
+ <ul id="core-values" style="list-style:none;font-size:.85rem;color:var(--cream-dim)"></ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">02</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 3 — 市场全景
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-3">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>市场全景</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">{{industryName}}品类市场全景分析</h2>
|
|
|
+ <div class="divider mb-md"></div>
|
|
|
+ <div class="cols-2">
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">Top100 周均销售额(美元)</h3>
|
|
|
+ <div class="chart-wrap"><canvas id="chart-revenue"></canvas></div>
|
|
|
+ </div>
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">品类增长率(同比)</h3>
|
|
|
+ <div class="chart-wrap"><canvas id="chart-growth"></canvas></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 数据表格 — 由 REPORT_DATA.categoryTable 注入 -->
|
|
|
+ <div class="glass-card mt-md" style="overflow-x:auto">
|
|
|
+ <table class="data-table">
|
|
|
+ <thead><tr>
|
|
|
+ <th>品类</th><th>周均销量</th><th>周均销售额</th><th>均价</th><th>品牌数</th><th>增长率</th><th>中国卖家</th>
|
|
|
+ </tr></thead>
|
|
|
+ <tbody id="market-table-body"></tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">03</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 4 — 竞品对标
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-4">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>竞品对标</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">核心竞品深度对标分析</h2>
|
|
|
+ <div class="divider mb-md"></div>
|
|
|
+ <!-- 竞品卡片 — 由 REPORT_DATA.competitors 注入 -->
|
|
|
+ <div class="cols-3" id="competitor-cards"></div>
|
|
|
+ <!-- 雷达图 -->
|
|
|
+ <div class="glass-card mt-md" style="max-width:480px;margin-left:auto;margin-right:auto">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm" style="text-align:center">竞品综合能力雷达图</h3>
|
|
|
+ <div class="chart-wrap" style="max-height:260px"><canvas id="chart-radar"></canvas></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">04</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 5 — VOC 用户洞察
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-5">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>用户VOC</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">全渠道用户VOC与需求洞察</h2>
|
|
|
+ <p class="text-dim text-sm mb-md">基于品类 Top 畅销产品 <strong class="text-gold" id="voc-review-count">0</strong> 条真实用户评论深度分析</p>
|
|
|
+ <div class="cols-2">
|
|
|
+ <!-- 左:痛点分析 -->
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-rose text-sm fw-600 mb-sm">🔴 用户核心痛点(差评Top5)</h3>
|
|
|
+ <div id="pain-points-container"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 右:喜爱点 + 场景 -->
|
|
|
+ <div>
|
|
|
+ <div class="glass-card mb-sm">
|
|
|
+ <h3 class="text-sage text-sm fw-600 mb-sm">🟢 用户最爱亮点(好评Top5)</h3>
|
|
|
+ <div id="highlights-container"></div>
|
|
|
+ </div>
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">📍 使用场景分布</h3>
|
|
|
+ <div class="chart-wrap" style="max-height:180px"><canvas id="chart-scenes"></canvas></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">05</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 6 — B端线索 & 品类矩阵
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-6">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>线索清单</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">B端高价值线索与品类机会矩阵</h2>
|
|
|
+ <div class="divider mb-md"></div>
|
|
|
+ <!-- 品类机会矩阵 — 由 REPORT_DATA.categoryMatrix 注入 -->
|
|
|
+ <div class="glass-card mb-md" style="overflow-x:auto">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">品类综合机会评估</h3>
|
|
|
+ <table class="data-table">
|
|
|
+ <thead><tr><th>品类</th><th>市场规模</th><th>增长性</th><th>社媒热度</th><th>竞争强度</th><th>中国卖家</th><th>综合推荐</th></tr></thead>
|
|
|
+ <tbody id="matrix-table-body"></tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ <div class="cols-2">
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">TikTok 社媒热度排名</h3>
|
|
|
+ <div class="chart-wrap"><canvas id="chart-tiktok"></canvas></div>
|
|
|
+ </div>
|
|
|
+ <div class="glass-card">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">季节性与要点</h3>
|
|
|
+ <div id="seasonality-notes" style="font-size:.85rem;color:var(--cream-dim)"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">06</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 7 — 执行策略
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-7">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>执行策略</span></div>
|
|
|
+ <div class="slide-inner">
|
|
|
+ <h2 class="text-gold mb-sm">市场拓展与落地执行建议</h2>
|
|
|
+ <div class="divider mb-md"></div>
|
|
|
+ <!-- 短中长期策略 — 由 REPORT_DATA.strategy 注入 -->
|
|
|
+ <div class="cols-3" id="strategy-columns"></div>
|
|
|
+ <!-- VOC驱动的产品策略 -->
|
|
|
+ <div class="glass-card mt-md">
|
|
|
+ <h3 class="text-sm fw-600 mb-sm">🔬 VOC驱动的产品开发优先级</h3>
|
|
|
+ <div id="voc-priorities" style="display:flex;flex-wrap:wrap;gap:12px;font-size:.82rem"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">07</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 8 — 总结与展望
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-8">
|
|
|
+ <div class="slide-header"><span>{{industryName}}行业竞品分析报告</span><span>总结展望</span></div>
|
|
|
+ <div class="slide-inner" style="max-width:900px">
|
|
|
+ <h2 class="text-gold mb-sm" style="text-align:center">总结与展望</h2>
|
|
|
+ <div class="divider" style="margin:0 auto 32px"></div>
|
|
|
+ <!-- 由 REPORT_DATA.conclusion 注入 -->
|
|
|
+ <div class="cols-2 mb-md" id="conclusion-top-cards"></div>
|
|
|
+ <div class="glass-card mb-md" id="conclusion-differentiator" style="text-align:center;padding:28px"></div>
|
|
|
+ <div class="glass-card" id="conclusion-actions" style="background:linear-gradient(135deg,rgba(197,165,90,.1),rgba(143,166,138,.08));border-color:rgba(197,165,90,.25)"></div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">08</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+<!-- ════════════════════════════════════════════
|
|
|
+ SLIDE 9 — 致谢
|
|
|
+ ════════════════════════════════════════════ -->
|
|
|
+<section class="slide" id="slide-9">
|
|
|
+ <div class="cover-content">
|
|
|
+ <div class="cover-line" style="margin-bottom:32px"></div>
|
|
|
+ <h2 style="font-size:clamp(1.6rem,3.5vw,2.6rem);background:linear-gradient(135deg,var(--cream),var(--gold-light));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:16px">感谢您的关注</h2>
|
|
|
+ <p class="text-dim" style="font-size:1rem;max-width:520px;margin:0 auto 28px">期待与您携手,用AI-VOC系统共同开拓{{industryName}}市场新蓝海</p>
|
|
|
+ <div class="cover-line"></div>
|
|
|
+ <div style="margin-top:32px;font-size:.85rem;color:var(--brown-light)">
|
|
|
+ <p>报告编制:AI-VOC 智能数据分析系统</p>
|
|
|
+ <p>数据来源:Amazon Sorftime API · TikHub (TikTok & Instagram) · AI-VOC Engine</p>
|
|
|
+ <p>数据时效:截至 {{reportDate}}</p>
|
|
|
+ <p style="margin-top:16px;font-size:.82rem;color:var(--gold)">📧 联系我们,获取专属VOC系统试用</p>
|
|
|
+ <p style="margin-top:12px;font-size:.75rem;opacity:.6">本报告数据来自第三方API,仅供商业决策参考</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="slide-footer"><span>{{industryName}}行业竞品分析报告</span><span class="page-num">09</span></div>
|
|
|
+</section>
|
|
|
+
|
|
|
+</div><!-- /slides-wrapper -->
|
|
|
+
|
|
|
+<!-- ===== Modal弹窗容器 ===== -->
|
|
|
+<div class="modal-overlay" id="modal-overlay">
|
|
|
+ <div class="modal-box">
|
|
|
+ <button class="modal-close" id="modal-close">×</button>
|
|
|
+ <div class="modal-header" id="modal-header"></div>
|
|
|
+ <div class="modal-body" id="modal-body"></div>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<!-- ============================================================
|
|
|
+ REPORT DATA — 由编排引擎注入
|
|
|
+ ============================================================ -->
|
|
|
+<script>
|
|
|
+/**
|
|
|
+ * REPORT_DATA: 所有报告数据由 workflow Stage 7 组装后注入到此对象。
|
|
|
+ * 模板中所有 DOM 操作均基于此数据驱动渲染。
|
|
|
+ *
|
|
|
+ * 结构说明:
|
|
|
+ * - meta: 报告元信息
|
|
|
+ * - metrics: 执行摘要指标卡片 [{value, prefix, suffix, label, sub}]
|
|
|
+ * - coreFindings: 核心发现列表 [{text, highlight, highlightClass}]
|
|
|
+ * - coreValues: 核心价值列表 [string]
|
|
|
+ * - categories: 品类市场数据 [{name, weeklySales, weeklyRevenue, avgPrice, brands, growth, chinaRatio, highlight, revenueNum, growthNum}]
|
|
|
+ * - competitors: 竞品数据 [{name, positioning, positionBadge, priceRange, igFollowers, tiktokFollowers, skuNote, strategyNote, pros, cons, radarData:[5]}]
|
|
|
+ * - vocAnalysis: VOC分析 {totalReviews, painPoints:[{icon, name, pct, gradient, quote}], highlights:[{name, pct, color}], scenes:[{name, pct}]}
|
|
|
+ * - categoryMatrix: 品类机会矩阵 [{name, marketSize, growth, socialHeat, competition, chinaRatio, recommendation, badgeClass}]
|
|
|
+ * - tiktokHeat: TikTok热度 [{name, plays}]
|
|
|
+ * - seasonalNotes: 季节性要点 [{icon, title, desc}]
|
|
|
+ * - strategy: 执行策略 {shortTerm:[{title, desc}], midTerm:[{title, desc}], longTerm:[{title, desc}]}
|
|
|
+ * - vocPriorities: VOC驱动优先级 [{text, badgeClass}]
|
|
|
+ * - conclusion: 总结 {topCategory:{emoji, title, name, desc}, socialDividend:{emoji, title, name, desc}, differentiator:{title, subtitle, desc}, keyActions:[{emoji, title, desc}]}
|
|
|
+ * - trendData: 趋势数据 {weeks:[], datasets:[{label, data, borderColor}]}
|
|
|
+ */
|
|
|
+const REPORT_DATA = /*{{REPORT_DATA_JSON}}*/ {};
|
|
|
+</script>
|
|
|
+
|
|
|
+<!-- ============================================================
|
|
|
+ JavaScript — 导航 · 动画 · 数据驱动渲染 · 图表
|
|
|
+ ============================================================ -->
|
|
|
+<script>
|
|
|
+/* ===== 全局状态 ===== */
|
|
|
+let currentSlide = 0;
|
|
|
+const totalSlides = document.querySelectorAll('.slide').length;
|
|
|
+let isTransitioning = false;
|
|
|
+
|
|
|
+/* ===== 自动生成侧边导航 ===== */
|
|
|
+(function buildNav(){
|
|
|
+ const tips = ['封面','目录','执行摘要','市场全景','竞品对标','用户VOC','线索清单','执行策略','总结展望','致谢'];
|
|
|
+ const nav = document.getElementById('side-nav');
|
|
|
+ tips.forEach((tip,i) => {
|
|
|
+ const d = document.createElement('div');
|
|
|
+ d.className = 'nav-dot' + (i===0?' active':'');
|
|
|
+ d.dataset.tip = tip;
|
|
|
+ d.dataset.slide = i;
|
|
|
+ d.addEventListener('click', () => goSlide(i));
|
|
|
+ nav.appendChild(d);
|
|
|
+ });
|
|
|
+})();
|
|
|
+const dots = document.querySelectorAll('.nav-dot');
|
|
|
+
|
|
|
+/* ===== 幻灯片切换 ===== */
|
|
|
+function goSlide(n) {
|
|
|
+ if (isTransitioning || n === currentSlide || n < 0 || n >= totalSlides) return;
|
|
|
+ isTransitioning = true;
|
|
|
+ const slides = document.querySelectorAll('.slide');
|
|
|
+ slides[currentSlide].classList.remove('active');
|
|
|
+ slides[n].classList.add('active');
|
|
|
+ dots.forEach((d, i) => d.classList.toggle('active', i === n));
|
|
|
+ currentSlide = n;
|
|
|
+ triggerSlideAnimations(n);
|
|
|
+ setTimeout(() => { isTransitioning = false; }, 750);
|
|
|
+}
|
|
|
+function nextSlide() { goSlide(currentSlide + 1); }
|
|
|
+function prevSlide() { goSlide(currentSlide - 1); }
|
|
|
+
|
|
|
+/* ===== 弹窗检测 ===== */
|
|
|
+function isModalOpen() { return document.getElementById('modal-overlay').classList.contains('show'); }
|
|
|
+
|
|
|
+/* ===== 键盘事件 ===== */
|
|
|
+document.addEventListener('keydown', e => {
|
|
|
+ if (isModalOpen()) return;
|
|
|
+ if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'PageDown') { e.preventDefault(); nextSlide(); }
|
|
|
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { e.preventDefault(); prevSlide(); }
|
|
|
+ else if (e.key === 'Home') { e.preventDefault(); goSlide(0); }
|
|
|
+ else if (e.key === 'End') { e.preventDefault(); goSlide(totalSlides - 1); }
|
|
|
+});
|
|
|
+
|
|
|
+/* ===== 鼠标滚轮 ===== */
|
|
|
+let wheelTimeout = 0;
|
|
|
+document.addEventListener('wheel', e => {
|
|
|
+ if (isModalOpen()) return;
|
|
|
+ e.preventDefault();
|
|
|
+ const now = Date.now();
|
|
|
+ if (now - wheelTimeout < 800) return;
|
|
|
+ wheelTimeout = now;
|
|
|
+ e.deltaY > 0 ? nextSlide() : prevSlide();
|
|
|
+}, { passive: false });
|
|
|
+
|
|
|
+/* ===== 触屏滑动 ===== */
|
|
|
+let touchStartY = 0, touchStartX = 0;
|
|
|
+document.addEventListener('touchstart', e => { touchStartY = e.touches[0].clientY; touchStartX = e.touches[0].clientX; });
|
|
|
+document.addEventListener('touchend', e => {
|
|
|
+ if (isModalOpen()) return;
|
|
|
+ const dy = e.changedTouches[0].clientY - touchStartY;
|
|
|
+ const dx = e.changedTouches[0].clientX - touchStartX;
|
|
|
+ if (Math.abs(dy) > Math.abs(dx) && Math.abs(dy) > 50) { dy < 0 ? nextSlide() : prevSlide(); }
|
|
|
+ else if (Math.abs(dx) > 50) { dx < 0 ? nextSlide() : prevSlide(); }
|
|
|
+});
|
|
|
+
|
|
|
+/* ===== 全屏 ===== */
|
|
|
+document.getElementById('fs-btn').addEventListener('click', () => {
|
|
|
+ if (!document.fullscreenElement) document.documentElement.requestFullscreen().catch(() => {});
|
|
|
+ else document.exitFullscreen();
|
|
|
+});
|
|
|
+
|
|
|
+/* ===== 数字递增动画 ===== */
|
|
|
+function animateCounters(slideEl) {
|
|
|
+ slideEl.querySelectorAll('.metric-value[data-count]').forEach(el => {
|
|
|
+ const target = +el.dataset.count;
|
|
|
+ const prefix = el.dataset.prefix || '';
|
|
|
+ const suffix = el.dataset.suffix || '';
|
|
|
+ const duration = 1800;
|
|
|
+ const start = performance.now();
|
|
|
+ const format = n => {
|
|
|
+ if (n >= 1e6) return (n / 1e6).toFixed(1) + 'M';
|
|
|
+ if (n >= 1e3) return (n / 1e3).toFixed(n >= 1e4 ? 0 : 1) + 'K';
|
|
|
+ return n.toLocaleString();
|
|
|
+ };
|
|
|
+ function step(now) {
|
|
|
+ const p = Math.min((now - start) / duration, 1);
|
|
|
+ const ease = 1 - Math.pow(1 - p, 3);
|
|
|
+ el.textContent = prefix + format(Math.round(target * ease)) + suffix;
|
|
|
+ if (p < 1) requestAnimationFrame(step);
|
|
|
+ }
|
|
|
+ requestAnimationFrame(step);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* ===== 进度条动画 ===== */
|
|
|
+function animateBars(slideEl) {
|
|
|
+ slideEl.querySelectorAll('.bar-fill[data-target]').forEach(el => {
|
|
|
+ setTimeout(() => { el.style.width = el.dataset.target + '%'; }, 200);
|
|
|
+ });
|
|
|
+ slideEl.querySelectorAll('.pain-fill[data-target]').forEach(el => {
|
|
|
+ setTimeout(() => {
|
|
|
+ el.style.width = (el.dataset.target / 35 * 100) + '%';
|
|
|
+ if (el.dataset.bg) el.style.background = el.dataset.bg;
|
|
|
+ }, 200);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* ===== 页面动画触发器 ===== */
|
|
|
+const animatedSlides = new Set();
|
|
|
+function triggerSlideAnimations(n) {
|
|
|
+ const slideEl = document.getElementById('slide-' + n);
|
|
|
+ if (!slideEl) return;
|
|
|
+ if (!animatedSlides.has(n)) {
|
|
|
+ animatedSlides.add(n);
|
|
|
+ animateCounters(slideEl);
|
|
|
+ animateBars(slideEl);
|
|
|
+ initChartsForSlide(n);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* ============================================================
|
|
|
+ Chart.js 全局配置
|
|
|
+ ============================================================ */
|
|
|
+const chartInstances = {};
|
|
|
+const chartFontColor = '#F5E6D3';
|
|
|
+const chartGridColor = 'rgba(139,111,71,0.15)';
|
|
|
+const PALETTE = ['rgba(197,165,90,0.7)','rgba(143,166,138,0.65)','rgba(196,134,139,0.6)','rgba(126,155,181,0.55)','rgba(212,185,120,0.5)','rgba(139,111,71,0.4)'];
|
|
|
+const PALETTE_BORDER = ['#C5A55A','#8FA68A','#C4868B','#7E9BB5','#D4B978','#8B6F47'];
|
|
|
+
|
|
|
+Chart.defaults.color = chartFontColor;
|
|
|
+Chart.defaults.font.family = "'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif";
|
|
|
+Chart.defaults.font.size = 12;
|
|
|
+
|
|
|
+function initChartsForSlide(n) {
|
|
|
+ if (n === 3) initMarketCharts();
|
|
|
+ if (n === 4) initRadarChart();
|
|
|
+ if (n === 5) initScenesChart();
|
|
|
+ if (n === 6) initTiktokChart();
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 市场全景图表 --- */
|
|
|
+function initMarketCharts() {
|
|
|
+ if (chartInstances.revenue || !REPORT_DATA.categories) return;
|
|
|
+ const cats = REPORT_DATA.categories;
|
|
|
+ const labels = cats.map(c => c.name);
|
|
|
+ const revenueData = cats.map(c => c.revenueNum);
|
|
|
+ chartInstances.revenue = new Chart(document.getElementById('chart-revenue'), {
|
|
|
+ type: 'bar',
|
|
|
+ data: { labels, datasets: [{ data: revenueData, backgroundColor: PALETTE.slice(0, cats.length), borderColor: PALETTE_BORDER.slice(0, cats.length), borderWidth: 1, borderRadius: 6, maxBarThickness: 52 }] },
|
|
|
+ options: {
|
|
|
+ responsive: true, maintainAspectRatio: false,
|
|
|
+ plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => '$' + (ctx.raw / 1e6).toFixed(1) + 'M / 周' } } },
|
|
|
+ scales: { y: { ticks: { callback: v => '$' + (v/1e6).toFixed(0) + 'M' }, grid: { color: chartGridColor } }, x: { grid: { display: false } } },
|
|
|
+ animation: { duration: 1200, easing: 'easeOutQuart' }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const growthSorted = [...cats].sort((a,b) => b.growthNum - a.growthNum);
|
|
|
+ chartInstances.growth = new Chart(document.getElementById('chart-growth'), {
|
|
|
+ type: 'bar',
|
|
|
+ data: {
|
|
|
+ labels: growthSorted.map(c => c.name),
|
|
|
+ datasets: [{ data: growthSorted.map(c => c.growthNum),
|
|
|
+ backgroundColor: growthSorted.map(c => c.growthNum > 50 ? 'rgba(143,166,138,0.7)' : c.growthNum > 0 ? 'rgba(197,165,90,0.6)' : 'rgba(196,134,139,0.5)'),
|
|
|
+ borderColor: growthSorted.map(c => c.growthNum > 50 ? '#8FA68A' : c.growthNum > 0 ? '#C5A55A' : '#C4868B'),
|
|
|
+ borderWidth: 1, borderRadius: 6, maxBarThickness: 52 }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ indexAxis: 'y', responsive: true, maintainAspectRatio: false,
|
|
|
+ plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => (ctx.raw > 0 ? '+' : '') + ctx.raw + '%' } } },
|
|
|
+ scales: { x: { ticks: { callback: v => (v > 0 ? '+' : '') + v + '%' }, grid: { color: chartGridColor } }, y: { grid: { display: false } } },
|
|
|
+ animation: { duration: 1200, easing: 'easeOutQuart' }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 竞品雷达图 --- */
|
|
|
+function initRadarChart() {
|
|
|
+ if (chartInstances.radar || !REPORT_DATA.competitors) return;
|
|
|
+ const comps = REPORT_DATA.competitors;
|
|
|
+ const radarLabels = ['品牌知名度','社媒粉丝','内容质量','产品线宽度','价格竞争力'];
|
|
|
+ const colors = ['#C5A55A','#8FA68A','#C4868B','#7E9BB5','#D4B978'];
|
|
|
+ const bgColors = ['rgba(197,165,90,0.15)','rgba(143,166,138,0.12)','rgba(196,134,139,0.1)','rgba(126,155,181,0.1)','rgba(212,185,120,0.1)'];
|
|
|
+ chartInstances.radar = new Chart(document.getElementById('chart-radar'), {
|
|
|
+ type: 'radar',
|
|
|
+ data: {
|
|
|
+ labels: radarLabels,
|
|
|
+ datasets: comps.map((c,i) => ({
|
|
|
+ label: c.name, data: c.radarData || [50,50,50,50,50],
|
|
|
+ borderColor: colors[i%colors.length], backgroundColor: bgColors[i%bgColors.length],
|
|
|
+ pointBackgroundColor: colors[i%colors.length], borderWidth: 2
|
|
|
+ }))
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ responsive: true, maintainAspectRatio: false,
|
|
|
+ scales: { r: { min: 0, max: 100, ticks: { stepSize: 25, display: false }, grid: { color: chartGridColor }, pointLabels: { font: { size: 11 } }, angleLines: { color: chartGridColor } } },
|
|
|
+ plugins: { legend: { position: 'bottom', labels: { boxWidth: 12, padding: 14, font: { size: 11 } } } },
|
|
|
+ animation: { duration: 1200 }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 使用场景饼图 --- */
|
|
|
+function initScenesChart() {
|
|
|
+ if (chartInstances.scenes || !REPORT_DATA.vocAnalysis) return;
|
|
|
+ const scenes = REPORT_DATA.vocAnalysis.scenes;
|
|
|
+ chartInstances.scenes = new Chart(document.getElementById('chart-scenes'), {
|
|
|
+ type: 'doughnut',
|
|
|
+ data: {
|
|
|
+ labels: scenes.map(s => s.name + ' ' + s.pct + '%'),
|
|
|
+ datasets: [{ data: scenes.map(s => s.pct), backgroundColor: PALETTE.slice(0, scenes.length), borderColor: 'rgba(26,17,11,0.6)', borderWidth: 2 }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ responsive: true, maintainAspectRatio: false, cutout: '55%',
|
|
|
+ plugins: { legend: { position: 'right', labels: { boxWidth: 10, padding: 8, font: { size: 10 } } } },
|
|
|
+ animation: { duration: 1200 }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* --- TikTok热度图表 --- */
|
|
|
+function initTiktokChart() {
|
|
|
+ if (chartInstances.tiktok || !REPORT_DATA.tiktokHeat) return;
|
|
|
+ const tt = REPORT_DATA.tiktokHeat;
|
|
|
+ chartInstances.tiktok = new Chart(document.getElementById('chart-tiktok'), {
|
|
|
+ type: 'bar',
|
|
|
+ data: {
|
|
|
+ labels: tt.map(t => t.name),
|
|
|
+ datasets: [{ label: '播放量', data: tt.map(t => t.plays),
|
|
|
+ backgroundColor: PALETTE.slice(0, tt.length), borderColor: PALETTE_BORDER.slice(0, tt.length),
|
|
|
+ borderWidth: 1, borderRadius: 6, maxBarThickness: 48 }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ responsive: true, maintainAspectRatio: false,
|
|
|
+ plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => (ctx.raw / 1e6).toFixed(1) + 'M 播放' } } },
|
|
|
+ scales: { y: { ticks: { callback: v => (v/1e6).toFixed(0) + 'M' }, grid: { color: chartGridColor } }, x: { grid: { display: false } } },
|
|
|
+ animation: { duration: 1200, easing: 'easeOutQuart' }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/* ============================================================
|
|
|
+ 数据驱动 DOM 渲染
|
|
|
+ ============================================================ */
|
|
|
+function renderReport() {
|
|
|
+ const D = REPORT_DATA;
|
|
|
+ if (!D || !D.categories) { console.warn('REPORT_DATA 未注入'); return; }
|
|
|
+
|
|
|
+ // --- Slide 2: 执行摘要 ---
|
|
|
+ if (D.metrics) {
|
|
|
+ document.getElementById('exec-metrics').innerHTML = D.metrics.map(m =>
|
|
|
+ `<div class="glass-card metric-card"><div class="metric-value" data-count="${m.value}" data-prefix="${m.prefix||''}" data-suffix="${m.suffix||''}">${m.prefix||''}0${m.suffix||''}</div><div class="metric-label">${m.label}</div><div class="metric-sub">${m.sub}</div></div>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+ if (D.coreFindings) {
|
|
|
+ document.getElementById('core-findings').innerHTML = D.coreFindings.map(f =>
|
|
|
+ `<li style="margin-bottom:8px">• <strong class="${f.highlightClass||'text-gold'}">${f.highlight||''}</strong> ${f.text}</li>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+ if (D.coreValues) {
|
|
|
+ document.getElementById('core-values').innerHTML = D.coreValues.map(v =>
|
|
|
+ `<li style="margin-bottom:8px">• ${v}</li>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 3: 市场全景表格 ---
|
|
|
+ if (D.categories) {
|
|
|
+ document.getElementById('market-table-body').innerHTML = D.categories.map(c => {
|
|
|
+ const growthClass = c.growthNum > 30 ? 'text-sage fw-700' : c.growthNum > 0 ? 'text-sage' : 'text-rose';
|
|
|
+ const chinaClass = c.chinaRatioNum > 70 ? 'text-rose fw-600' : '';
|
|
|
+ return `<tr><td class="fw-600 ${c.highlight?'text-gold':''}">${c.name}${c.highlight?' ⭐':''}</td><td>${c.weeklySales}</td><td>${c.weeklyRevenue}</td><td>${c.avgPrice}</td><td>${c.brands}</td><td class="${growthClass}">${c.growth}</td><td class="${chinaClass}">${c.chinaRatio}</td></tr>`;
|
|
|
+ }).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 4: 竞品卡片 ---
|
|
|
+ if (D.competitors) {
|
|
|
+ document.getElementById('competitor-cards').innerHTML = D.competitors.map(c => `
|
|
|
+ <div class="glass-card competitor-card">
|
|
|
+ <span class="badge ${c.positionBadge||'badge-gold'} mb-sm" style="display:inline-block">${c.positioning}</span>
|
|
|
+ <h3>${c.name}</h3>
|
|
|
+ <p class="text-xs text-dim mb-sm">${c.priceRange||''}</p>
|
|
|
+ <div class="comp-stat"><span>Instagram</span><span class="fw-700 text-gold">${c.igFollowers||'—'}</span></div>
|
|
|
+ <div class="comp-stat"><span>TikTok</span><span class="fw-600">${c.tiktokFollowers||'—'}</span></div>
|
|
|
+ <div class="comp-stat"><span>Amazon SKU</span><span>${c.skuNote||'—'}</span></div>
|
|
|
+ <div class="comp-stat"><span>策略</span><span class="text-xs">${c.strategyNote||'—'}</span></div>
|
|
|
+ <p class="text-xs mt-sm text-dim">${c.pros||''}<br>${c.cons||''}</p>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 5: VOC ---
|
|
|
+ if (D.vocAnalysis) {
|
|
|
+ const voc = D.vocAnalysis;
|
|
|
+ document.getElementById('voc-review-count').textContent = voc.totalReviews + '条';
|
|
|
+ document.getElementById('pain-points-container').innerHTML = voc.painPoints.map(p =>
|
|
|
+ `<div class="pain-bar"><div class="pain-icon">${p.icon}</div><div class="pain-info"><div class="pain-name">${p.name} <span class="badge badge-rose">${p.pct}%</span></div><div class="pain-track"><div class="pain-fill" style="width:0%" data-target="${p.pct}" data-bg="${p.gradient}"></div></div>${p.quote?`<div class="pain-pct">"${p.quote}"</div>`:''}</div></div>`
|
|
|
+ ).join('');
|
|
|
+ document.getElementById('highlights-container').innerHTML = voc.highlights.map(h =>
|
|
|
+ `<div class="bar-row"><span class="bar-label">${h.name}</span><div class="bar-track"><div class="bar-fill" style="width:0%;background:${h.color}" data-target="${h.pct}" data-value="${h.pct}%"></div></div></div>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 6: 品类矩阵 ---
|
|
|
+ if (D.categoryMatrix) {
|
|
|
+ document.getElementById('matrix-table-body').innerHTML = D.categoryMatrix.map(c =>
|
|
|
+ `<tr><td class="fw-600 ${c.highlight?'text-gold':''}">${c.name}</td><td>${c.marketSize}</td><td>${c.growth}</td><td>${c.socialHeat}</td><td>${c.competition}</td><td>${c.chinaRatio}</td><td><span class="badge ${c.badgeClass||'badge-gold'}">${c.recommendation}</span></td></tr>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+ if (D.seasonalNotes) {
|
|
|
+ document.getElementById('seasonality-notes').innerHTML = D.seasonalNotes.map(s =>
|
|
|
+ `<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><span style="font-size:1.4rem">${s.icon}</span><div><strong class="text-gold">${s.title}</strong><br>${s.desc}</div></div>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 7: 执行策略 ---
|
|
|
+ if (D.strategy) {
|
|
|
+ const phases = [
|
|
|
+ { key: 'shortTerm', label: '短期 1-3个月', badge: 'badge-sage' },
|
|
|
+ { key: 'midTerm', label: '中期 3-6个月', badge: 'badge-gold' },
|
|
|
+ { key: 'longTerm', label: '长期 6-12个月', badge: 'badge-blue' }
|
|
|
+ ];
|
|
|
+ document.getElementById('strategy-columns').innerHTML = phases.map(p => `
|
|
|
+ <div class="glass-card">
|
|
|
+ <span class="badge ${p.badge} mb-sm" style="display:inline-block">${p.label}</span>
|
|
|
+ <div class="timeline mt-sm">
|
|
|
+ ${(D.strategy[p.key]||[]).map(item => `<div class="timeline-item"><h4>${item.title}</h4><p>${item.desc}</p></div>`).join('')}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+ }
|
|
|
+ if (D.vocPriorities) {
|
|
|
+ document.getElementById('voc-priorities').innerHTML = D.vocPriorities.map(p =>
|
|
|
+ `<span class="badge ${p.badgeClass||'badge-rose'}">${p.text}</span>`
|
|
|
+ ).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- Slide 8: 总结 ---
|
|
|
+ if (D.conclusion) {
|
|
|
+ const con = D.conclusion;
|
|
|
+ document.getElementById('conclusion-top-cards').innerHTML = `
|
|
|
+ <div class="glass-card" style="text-align:center;padding:32px 24px"><div style="font-size:2.4rem;margin-bottom:8px">${con.topCategory.emoji}</div><h3 class="text-gold mb-sm">${con.topCategory.title}</h3><p class="text-sm"><strong>${con.topCategory.name}</strong></p><p class="text-xs text-dim mt-sm">${con.topCategory.desc}</p></div>
|
|
|
+ <div class="glass-card" style="text-align:center;padding:32px 24px"><div style="font-size:2.4rem;margin-bottom:8px">${con.socialDividend.emoji}</div><h3 class="text-gold mb-sm">${con.socialDividend.title}</h3><p class="text-sm"><strong>${con.socialDividend.name}</strong></p><p class="text-xs text-dim mt-sm">${con.socialDividend.desc}</p></div>`;
|
|
|
+ document.getElementById('conclusion-differentiator').innerHTML =
|
|
|
+ `<h3 class="text-gold mb-sm">${con.differentiator.title}</h3><p style="font-size:1.15rem;font-weight:600;color:var(--cream)">${con.differentiator.subtitle}</p><p class="text-sm text-dim mt-sm">${con.differentiator.desc}</p>`;
|
|
|
+ document.getElementById('conclusion-actions').innerHTML =
|
|
|
+ `<h3 class="text-sm fw-600 mb-sm" style="text-align:center">✅ 三大关键行动</h3><div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;text-align:center;font-size:.85rem">${con.keyActions.map(a => `<div><div style="font-size:1.6rem;margin-bottom:4px">${a.emoji}</div><strong>${a.title}</strong><br><span class="text-xs text-dim">${a.desc}</span></div>`).join('')}</div>`;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* ============================================================
|
|
|
+ 封面粒子效果
|
|
|
+ ============================================================ */
|
|
|
+function initParticles() {
|
|
|
+ const canvas = document.getElementById('particles-canvas');
|
|
|
+ if (!canvas) return;
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+ let w, h, particles = [];
|
|
|
+ function resize() { w = canvas.width = window.innerWidth; h = canvas.height = window.innerHeight; }
|
|
|
+ resize();
|
|
|
+ window.addEventListener('resize', resize);
|
|
|
+ for (let i = 0; i < 60; i++) {
|
|
|
+ particles.push({
|
|
|
+ x: Math.random() * w, y: Math.random() * h,
|
|
|
+ r: Math.random() * 2 + 0.5,
|
|
|
+ dx: (Math.random() - 0.5) * 0.3, dy: (Math.random() - 0.5) * 0.2,
|
|
|
+ alpha: Math.random() * 0.4 + 0.1,
|
|
|
+ color: Math.random() > 0.5 ? '197,165,90' : '212,185,120'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ function draw() {
|
|
|
+ ctx.clearRect(0, 0, w, h);
|
|
|
+ const grd = ctx.createRadialGradient(w*.5, h*.4, 0, w*.5, h*.4, w*.6);
|
|
|
+ grd.addColorStop(0, 'rgba(92,61,46,0.12)');
|
|
|
+ grd.addColorStop(0.5, 'rgba(45,24,16,0.06)');
|
|
|
+ grd.addColorStop(1, 'transparent');
|
|
|
+ ctx.fillStyle = grd; ctx.fillRect(0, 0, w, h);
|
|
|
+ particles.forEach(p => {
|
|
|
+ ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI*2);
|
|
|
+ ctx.fillStyle = `rgba(${p.color},${p.alpha})`; ctx.fill();
|
|
|
+ p.x += p.dx; p.y += p.dy;
|
|
|
+ if (p.x<0||p.x>w) p.dx *= -1;
|
|
|
+ if (p.y<0||p.y>h) p.dy *= -1;
|
|
|
+ p.alpha += (Math.random()-.5)*.01;
|
|
|
+ p.alpha = Math.max(.05, Math.min(.5, p.alpha));
|
|
|
+ });
|
|
|
+ for (let i=0; i<particles.length; i++) {
|
|
|
+ for (let j=i+1; j<particles.length; j++) {
|
|
|
+ const dx=particles[i].x-particles[j].x, dy=particles[i].y-particles[j].y;
|
|
|
+ const dist = Math.sqrt(dx*dx+dy*dy);
|
|
|
+ if (dist<150) { ctx.beginPath(); ctx.moveTo(particles[i].x,particles[i].y); ctx.lineTo(particles[j].x,particles[j].y); ctx.strokeStyle=`rgba(197,165,90,${.06*(1-dist/150)})`; ctx.lineWidth=.5; ctx.stroke(); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ requestAnimationFrame(draw);
|
|
|
+ }
|
|
|
+ draw();
|
|
|
+}
|
|
|
+
|
|
|
+/* ============================================================
|
|
|
+ Modal 弹窗系统
|
|
|
+ ============================================================ */
|
|
|
+const modalOverlay = document.getElementById('modal-overlay');
|
|
|
+const modalHeader = document.getElementById('modal-header');
|
|
|
+const modalBody = document.getElementById('modal-body');
|
|
|
+function openModal(headerHTML, bodyHTML) {
|
|
|
+ modalHeader.innerHTML = headerHTML;
|
|
|
+ modalBody.innerHTML = bodyHTML;
|
|
|
+ modalOverlay.style.display = 'flex';
|
|
|
+ requestAnimationFrame(() => modalOverlay.classList.add('show'));
|
|
|
+}
|
|
|
+function closeModal() {
|
|
|
+ modalOverlay.classList.remove('show');
|
|
|
+ setTimeout(() => { modalOverlay.style.display = 'none'; }, 350);
|
|
|
+}
|
|
|
+document.getElementById('modal-close').addEventListener('click', closeModal);
|
|
|
+modalOverlay.addEventListener('click', e => { if(e.target===modalOverlay) closeModal(); });
|
|
|
+document.addEventListener('keydown', e => { if(e.key==='Escape' && modalOverlay.classList.contains('show')) closeModal(); });
|
|
|
+
|
|
|
+/* ===== 初始化 ===== */
|
|
|
+renderReport();
|
|
|
+initParticles();
|
|
|
+triggerSlideAnimations(0);
|
|
|
+</script>
|
|
|
+</body>
|
|
|
+</html>
|