Files
mediabuy-wh/index.html
T

66 lines
5.5 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>武汉自投 · 投手投放花费报告</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<style>
:root{--bg:#ffffff;--card:#f4f8ff;--line:#d6e2f5;--txt:#111111;--sub:#5b6472;--accent:#2f6bff;--accent2:#ff9f5b;}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--txt);font-family:"PingFang SC","PingFang TC","Apple LiGothic","STHeiti","Hiragino Sans GB",-apple-system,BlinkMacSystemFont,"Microsoft YaHei",sans-serif;line-height:1.5}
.wrap{max-width:1080px;margin:0 auto;padding:28px 20px 60px}
h1{font-size:24px;margin:0 0 4px}
.sub{color:var(--sub);font-size:13px;margin-bottom:22px}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:26px}
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
.card .k{color:var(--sub);font-size:12px}
.card .v{font-size:22px;font-weight:600;margin-top:6px}
.panel{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:18px;margin-bottom:22px}
.panel h2{font-size:16px;margin:0 0 14px}
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{padding:9px 10px;text-align:left;border-bottom:1px solid var(--line)}
th{color:var(--sub);font-weight:500;font-size:12px}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
.pkg{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;color:#333a45}
.buyer-name{font-weight:600}
details{margin-top:6px}
summary{cursor:pointer;color:var(--accent);font-size:12px}
.foot{color:var(--sub);font-size:12px;margin-top:30px;border-top:1px solid var(--line);padding-top:14px}
.badge{display:inline-block;background:#e6eefc;color:var(--sub);border-radius:6px;padding:2px 8px;font-size:11px;margin-left:8px}
.chartbox{position:relative;height:300px}
</style>
</head>
<body>
<div class="wrap">
<h1>武汉自投 · 投手投放花费报告 <span class="badge" id="weekBadge"></span></h1>
<div class="sub" id="metaLine">加载中…</div>
<div class="cards" id="cards"></div>
<div class="panel"><h2>各投手 Week 投放花费</h2><div class="chartbox"><canvas id="spendChart"></canvas></div></div>
<div class="panel"><h2>各投手主要订单 Package(花费最高)</h2><div class="chartbox"><canvas id="pkgChart"></canvas></div></div>
<div class="panel"><h2>投手明细</h2><div id="tables"></div></div>
<div class="panel" id="unmatchedPanel" style="display:none"><h2>未匹配到投手的 Adpingid</h2><div id="unmatched"></div></div>
<div class="foot" id="foot"></div>
</div>
<script>
const fmt=n=>n.toLocaleString('en-US',{minimumFractionDigits:2,maximumFractionDigits:2});
fetch('data.json?t='+Date.now()).then(r=>r.json()).then(d=>render(d)).catch(e=>{document.getElementById('metaLine').textContent='数据加载失败:'+e.message;});
function render(d){
document.getElementById('weekBadge').textContent=d.meta.week||'';
document.getElementById('metaLine').textContent='数据来源:'+d.meta.source+' · 生成时间:'+new Date(d.meta.generated_at).toLocaleString('zh-CN');
const buyers=d.buyers.slice().sort((a,b)=>b.total-a.total);
const cards=[['投手数',buyers.length],['投放花费合计',fmt(d.grand_total)],['覆盖 Adpingid 数',d.week34_id_count],['花费最高投手',buyers[0].name]];
document.getElementById('cards').innerHTML=cards.map(c=>'<div class="card"><div class="k">'+c[0]+'</div><div class="v">'+c[1]+'</div></div>').join('');
const palette=['#5b8cff','#ff9f5b','#4dd6a8','#c78bff','#ff6b81','#f5c451'];
new Chart(document.getElementById('spendChart'),{type:'bar',data:{labels:buyers.map(b=>b.name),datasets:[{label:'投放花费',data:buyers.map(b=>b.total),backgroundColor:buyers.map((b,i)=>palette[i%palette.length])}]},options:{indexAxis:'y',plugins:{legend:{display:false}},scales:{x:{ticks:{color:'#5b6472'},grid:{color:'#d6e2f5'}},y:{ticks:{color:'#111111'},grid:{display:false}}}}});
new Chart(document.getElementById('pkgChart'),{type:'bar',data:{labels:buyers.map(b=>b.name),datasets:[{label:'主要Package花费',data:buyers.map(b=>b.pkgs[0].spend),backgroundColor:'#4dd6a8'}]},options:{plugins:{legend:{display:false},tooltip:{callbacks:{afterLabel:(ctx)=>buyers[ctx.dataIndex].pkgs[0].pkg}}},scales:{x:{ticks:{color:'#111111'},grid:{display:false}},y:{ticks:{color:'#5b6472'},grid:{color:'#d6e2f5'}}}}});
document.getElementById('tables').innerHTML=buyers.map(b=>{
const rows=b.pkgs.map(p=>'<tr><td class="pkg">'+p.pkg+'</td><td class="num">'+fmt(p.spend)+'</td></tr>').join('');
return '<div style="margin-bottom:18px"><div class="buyer-name">'+b.name+' <span style="color:var(--sub);font-weight:400">合计 '+fmt(b.total)+' · 主要订单 '+b.pkgs[0].pkg+'</span></div><details><summary>展开 '+b.pkgs.length+' 个 Package 明细</summary><table><thead><tr><th>Package</th><th class="num">花费</th></tr></thead><tbody>'+rows+'</tbody></table></details></div>';
}).join('');
if(d.unmatched&&d.unmatched.length){document.getElementById('unmatchedPanel').style.display='';document.getElementById('unmatched').innerHTML='<table><thead><tr><th>Adpingid</th><th>Package</th><th class="num">花费</th></tr></thead><tbody>'+d.unmatched.map(u=>'<tr><td>'+u.id+'</td><td class="pkg">'+u.pkg+'</td><td class="num">'+fmt(u.spend)+'</td></tr>').join('')+'</tbody></table>';}
document.getElementById('foot').textContent=d.meta.note;
}
</script>
</body>
</html>