r111/data.html · 约 7518 字符
1<!DOCTYPE html>2<html lang="zh-CN">3<head>4<meta charset="UTF-8">5<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">6<meta name="theme-color" content="#4263eb">7<title>数据源 · 图表工具大全</title>8<link rel="stylesheet" href="style.css">9</head>10<body data-page="data">11<div class="navbar"><div class="tt" style="padding-left:2px">数据源</div><div class="rt"><a href="#" id="howto">格式说明</a></div></div>12<div class="wrap">13 <div class="kpis4">14 <div class="kc"><b id="s1">0</b><span>JSON 文件</span></div>15 <div class="kc"><b id="s2">0</b><span>数据点</span></div>16 <div class="kc"><b id="s3">0</b><span>结构类型</span></div>17 </div>18 <div class="tk" id="mode">正在探测数据读取方式…</div>19 <div class="chips" id="flt">20 <button class="on" data-v="all">全部</button>21 <button data-v="series">时序型</button>22 <button data-v="items">占比型</button>23 <button data-v="points">坐标型</button>24 <button data-v="radar">多维型</button>25 <button data-v="heat">矩阵型</button>26 </div>27 <div id="list"></div>28 <div style="height:12px"></div>29</div>3031<div class="sheet" id="sjson">32 <div class="sh"><b id="jt">数据预览</b><span class="x">×</span></div>33 <div class="sb">34 <div class="row" style="gap:8px;margin-bottom:10px">35 <a class="btn" id="goview" href="#">去可视化</a>36 <a class="btn o" id="copy" href="#">复制 JSON</a>37 </div>38 <pre class="code" id="jsonbox"></pre>39 </div>40</div>4142<div class="sheet" id="shelp">43 <div class="sh"><b>数据格式说明</b><span class="x">×</span></div>44 <div class="sb">45 <p class="muted" style="font-size:12px;line-height:1.8">所有图表均从 <code>data/*.json</code> 读取,页面本身不内嵌业务数据。替换同名 JSON 即可换成你自己的数据,无需改动任何 JS。</p>46 <div class="gt">1 · 时序型 series</div>47 <pre class="code">{48 "id": "sales", "name": "月度销售额",49 "unit": "万元", "type": "series",50 "cats": ["1月","2月","3月"],51 "series": [52 { "name":"线上", "color":"#4263eb",53 "data":[128, 143, 156] }54 ]55}</pre>56 <div class="gt">2 · 占比型 items</div>57 <pre class="code">{58 "type": "items", "unit": "%",59 "items": [60 { "name":"自然搜索", "value":32.5,61 "color":"#4263eb" }62 ]63}</pre>64 <div class="gt">3 · 坐标型 points</div>65 <pre class="code">{66 "type": "points",67 "series": [68 { "name":"信息流", "color":"#4263eb",69 "points": [[1200, 3.2, 46]] }70 ]71}</pre>72 <div class="muted" style="font-size:11px;margin-top:6px">points 中三个数值依次为 x / y / 气泡权重。</div>73 <div class="gt">4 · 多维型 radar</div>74 <pre class="code">{75 "type": "radar",76 "indicators": [{ "name":"商品力","max":100 }],77 "series": [{ "name":"本店","data":[88] }]78}</pre>79 <div class="gt">5 · 矩阵型 heat</div>80 <pre class="code">{81 "type": "heat", "start": "2026-05-11",82 "weeks": 12, "days": ["一","二","三"],83 "values": [31, 44, 58]84}</pre>85 <div class="tk" style="margin-top:12px">离线兜底:<code>data/fallback.js</code> 内置了一份与 JSON 完全一致的副本。直接双击 index.html 以 file:// 打开时浏览器会拦截 fetch,此时自动回落到该副本,保证页面照常渲染。</div>86 </div>87</div>8889<nav class="tabbar">90<a href="index.html" class=""><span class="ti">🏠</span>看板</a>91<a href="gallery.html" class=""><span class="ti">📊</span>图表库</a>92<a href="data.html" class="on"><span class="ti">🗂</span>数据源</a>93<a href="about.html" class=""><span class="ti">📘</span>文档</a>94</nav>95<div class="mask" id="mask"></div>96<div class="toast" id="toast"></div>97<script src="data/fallback.js"></script>98<script src="chart.js"></script>99<script src="app.js"></script>100<script>101102var LIST=[], flt='all';103var GO={series:'line.html', items:'pie.html', points:'scatter.html', radar:'radar.html', heat:'funnel.html?tab=heat'};104var GO2={sales:'line.html', visits:'line.html', region:'bar.html', traffic:'pie.html', device:'pie.html',105 ad:'scatter.html', ability:'radar.html', funnel:'funnel.html', kpi:'radar.html?tab=gauge', heat:'funnel.html?tab=heat'};106107function count(d){108 if(d.type==='series') return (d.series||[]).reduce(function(a,s){return a+(s.data||[]).length;},0);109 if(d.type==='items') return (d.items||[]).length;110 if(d.type==='points') return (d.series||[]).reduce(function(a,s){return a+(s.points||[]).length;},0);111 if(d.type==='radar') return (d.series||[]).reduce(function(a,s){return a+(s.data||[]).length;},0);112 if(d.type==='heat') return (d.values||[]).length;113 return 0;114}115var TYN={series:'时序型',items:'占比型',points:'坐标型',radar:'多维型',heat:'矩阵型'};116117function render(){118 var arr = LIST.filter(function(d){ return flt==='all' || d.type===flt; });119 if(!arr.length){ $('#list').innerHTML='<div class="tk">该类型下暂无数据集</div>'; return; }120 $('#list').innerHTML = arr.map(function(d){121 return '<div class="card gcard" data-id="'+d.id+'">'+122 '<div class="gh"><div class="ic" style="background:'+(d.tint||'#edf2ff')+'">'+d.icon+'</div>'+123 '<div class="g"><div class="gt">'+d.name+'</div><div class="gd">'+d.desc+'</div></div>'+124 '<span class="tag">'+(TYN[d.type]||d.type)+'</span></div>'+125 '<div class="row" style="justify-content:space-between;margin-top:10px">'+126 '<span class="muted" style="font-size:11px">data/'+d.id+'.json · '+count(d)+' 个数据点 · 单位 '+(d.unit||'-')+'</span>'+127 '<span class="more">查看 ›</span></div></div>';128 }).join('');129 $$('#list .gcard').forEach(function(c){130 c.addEventListener('click', function(){ open(c.dataset.id); });131 });132}133134function open(id){135 var d = LIST.filter(function(x){return x.id===id;})[0];136 if(!d) return;137 $('#jt').textContent = d.name + ' · data/' + id + '.json';138 $('#jsonbox').innerHTML = hlJSON(d);139 $('#goview').href = GO2[id] || GO[d.type] || 'gallery.html';140 openSheet('#sjson');141}142143$('#copy').addEventListener('click', function(e){144 e.preventDefault();145 var t = $('#jsonbox').textContent;146 if(navigator.clipboard && navigator.clipboard.writeText){147 navigator.clipboard.writeText(t).then(function(){ toast('JSON 已复制到剪贴板'); },148 function(){ toast('当前环境不支持复制'); });149 } else { toast('当前环境不支持复制'); }150});151$('#howto').addEventListener('click', function(e){ e.preventDefault(); openSheet('#shelp'); });152segGroup('#flt', function(v){ flt=v; render(); });153154loading($('#list'),'正在加载数据索引');155DS.index().then(function(names){156 return DS.all(names);157}).then(function(all){158 LIST = all;159 $('#s1').textContent = all.length;160 $('#s2').textContent = CH.thousand(all.reduce(function(a,d){return a+count(d);},0));161 var ts={}; all.forEach(function(d){ ts[d.type]=1; });162 $('#s3').textContent = Object.keys(ts).length;163 var json = all.filter(function(d){ return d.__from==='json'; }).length;164 $('#mode').innerHTML = json165 ? '✅ 已通过 <code>fetch()</code> 成功读取 <b>'+json+'</b> 个 JSON 文件,数据与页面完全解耦。'166 : '⚠️ 当前为 <code>file://</code> 本地直开,浏览器拦截了 fetch,已自动回落到 <code>data/fallback.js</code> 离线副本。部署到任意 HTTP 服务后即可走真实 JSON 请求。';167 render();168}).catch(function(e){ failBox($('#list'), e); });169170</script>171</body>172</html>173