Files
amazon-za-delivery/index.html
T

37 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. 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">
<meta name="color-scheme" content="light dark">
<title>Amazon ZA 每日交付报告</title>
<style>
:root{--bg:#f4f7fb;--panel:#fff;--ink:#162033;--muted:#667085;--line:#dce3ec;--blue:#2f6fed;--gold:#d79b24;--orange:#e56d35;--soft:#eaf1ff;--shadow:0 8px 28px rgba(23,43,77,.08)}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.55 Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}main{max-width:1180px;margin:auto;padding:42px 24px 64px}.eyebrow{color:var(--blue);font-weight:700;letter-spacing:.08em;text-transform:uppercase}.hero h1{font-size:clamp(28px,4vw,46px);line-height:1.1;margin:8px 0 12px}.hero p{color:var(--muted);font-size:16px;margin:0;max-width:800px}.status{display:inline-flex;align-items:center;gap:8px;margin-top:18px;padding:7px 11px;border:1px solid var(--line);border-radius:999px;background:var(--panel);color:var(--muted)}.dot{width:8px;height:8px;border-radius:50%;background:var(--blue)}section{margin-top:30px}h2{font-size:22px;margin:0 0 12px}.summary{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}.card,.panel{background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow)}.card{padding:18px}.card .label{color:var(--muted);font-weight:600}.card .value{font-size:28px;font-weight:750;margin-top:6px;font-variant-numeric:tabular-nums}.card .note{color:var(--muted);font-size:12px;margin-top:3px}.panel{padding:22px;margin-top:14px}.takeaway{border-left:4px solid var(--blue);padding-left:14px;color:var(--muted)}.takeaway strong{color:var(--ink)}.charts{display:grid;grid-template-columns:1fr 1fr;gap:14px}.chart{min-height:300px}.chart-head{margin-bottom:16px}.chart-title{font-weight:750;font-size:16px}.chart-sub{color:var(--muted);font-size:12px}.bars{height:220px;display:flex;align-items:end;gap:14px;padding:20px 10px 28px;border-bottom:1px solid var(--line);position:relative}.bar-group{flex:1;height:100%;display:flex;align-items:end;justify-content:center;gap:6px;position:relative}.bar{min-width:16px;max-width:34px;width:33%;border-radius:6px 6px 0 0;position:relative}.bar span{position:absolute;top:-21px;left:50%;transform:translateX(-50%);font-size:11px;font-weight:700;white-space:nowrap}.bar-label{position:absolute;bottom:-25px;left:50%;transform:translateX(-50%);color:var(--muted);font-size:11px}.legend{display:flex;gap:14px;margin-top:13px;color:var(--muted);font-size:12px}.swatch{width:9px;height:9px;border-radius:2px;display:inline-block;margin-right:5px}.rate-bars .bar{width:52%;background:var(--orange)}table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}th,td{padding:12px 10px;border-bottom:1px solid var(--line);text-align:right;white-space:nowrap}th:first-child,td:first-child{text-align:left}th{color:var(--muted);font-size:12px}tbody tr:hover{background:var(--soft)}.footer-note{color:var(--muted);font-size:12px;margin-top:18px}.error{padding:18px;border:1px solid #f0b7b7;background:#fff2f2;color:#912b2b;border-radius:12px}@media(max-width:850px){.summary{grid-template-columns:1fr 1fr}.charts{grid-template-columns:1fr}}@media(max-width:520px){main{padding:26px 14px}.summary{grid-template-columns:1fr}.panel{padding:16px;overflow:auto}.card .value{font-size:24px}}
@media(prefers-color-scheme:dark){:root{--bg:#0c1220;--panel:#121a2a;--ink:#eef3fb;--muted:#9ba9bd;--line:#28354a;--soft:#182743;--shadow:none}}
</style>
</head>
<body><main>
<header class="hero"><div class="eyebrow">Daily Delivery · ZA</div><h1>Amazon ZA 每日交付报告</h1><p>包名:com.amazon.mShop.android.shopping。聚焦 repostback 交付、E1+E2 转化与 Midas / Payable spend。</p><div class="status"><span class="dot"></span><span id="range">正在载入数据…</span></div></header>
<section><h2>Executive Summary</h2><div id="summaryText" class="panel takeaway">载入中…</div></section>
<section><h2>核心指标</h2><div class="summary" id="cards"></div></section>
<section><h2>每日交付与转化</h2><div class="takeaway"><strong>如何阅读:</strong>先看每日 Install 与 E1/E2 的规模,再结合 E1+E2% 判断转化效率;仅有 3 个日期,因此使用离散柱状图,避免把短窗口误读为长期趋势。</div><div class="charts"><div class="panel chart"><div class="chart-head"><div class="chart-title">每日 Install、Event1 与 Event2</div><div class="chart-sub">均取 repostback;按 ZA 日期汇总</div></div><div id="deliveryChart" class="bars"></div><div class="legend"><span><i class="swatch" style="background:var(--blue)"></i>Install</span><span><i class="swatch" style="background:var(--gold)"></i>Event1</span><span><i class="swatch" style="background:var(--orange)"></i>Event2</span></div></div><div class="panel chart"><div class="chart-head"><div class="chart-title">每日 E1+E2%</div><div class="chart-sub">(Event1 + Event2) ÷ Install</div></div><div id="rateChart" class="bars rate-bars"></div></div></div></section>
<section><h2>消耗对比</h2><div id="spendText" class="takeaway"></div><div class="panel chart"><div class="chart-head"><div class="chart-title">Midas spend 与 Payable spend</div><div class="chart-sub">USD;Payable spend = (E1 + E2) × $3</div></div><div id="spendChart" class="bars"></div><div class="legend"><span><i class="swatch" style="background:var(--blue)"></i>Midas spend</span><span><i class="swatch" style="background:var(--gold)"></i>Payable spend</span></div></div></section>
<section><h2>每日明细</h2><div class="panel"><table><thead><tr><th>日期</th><th>Install</th><th>Event1</th><th>Event2</th><th>E1+E2%</th><th>Midas spend</th><th>Payable spend</th></tr></thead><tbody id="rows"></tbody></table><div class="footer-note">口径:Install、Event1、Event2 均取 repostback;金额为 USD。源文件更新后,update.sh 会重新生成 data.json。</div></div></section>
<section><h2>建议关注</h2><div class="panel"><ul><li>继续监控 E1+E2% 是否在更长日期窗口内稳定,当前 3 天样本不宜外推长期趋势。</li><li>对比 Payable spend 与 Midas spend 的日级差额,优先排查差额扩大日期的事件质量和计费口径。</li><li>若要实现新增日期自动进入报告,需要让 update.sh 能访问持续更新的数据源;当前版本自动重算仓库内两份 CSV 快照。</li></ul></div></section>
</main><script>
const fmt=n=>new Intl.NumberFormat('en-US').format(n), money=n=>'$'+new Intl.NumberFormat('en-US',{minimumFractionDigits:2,maximumFractionDigits:2}).format(n), pct=n=>n==null?'—':n.toFixed(2)+'%';
const label=d=>d.slice(5).replace('-','/');
function bars(el,data,series,max){el.innerHTML=data.map(d=>`<div class="bar-group">${series.map(s=>`<div class="bar" style="height:${Math.max(2,d[s.key]/max*100)}%;background:${s.color}"><span>${s.format(d[s.key])}</span></div>`).join('')}<div class="bar-label">${label(d.date)}</div></div>`).join('')}
fetch('data.json',{cache:'no-store'}).then(r=>{if(!r.ok)throw Error('data.json '+r.status);return r.json()}).then(data=>{
const t=data.totals,d=data.daily,latest=d[d.length-1],first=d[0];document.getElementById('range').textContent=`${data.meta.date_start} 至 ${data.meta.date_end} · 每日快照`;
const delta=first&&latest?latest.e1e2_rate-first.e1e2_rate:0;document.getElementById('summaryText').innerHTML=`<strong>${d.length} 天累计 ${fmt(t.install)} Install,产生 ${fmt(t.e1e2)} 个 E1+E2,整体转化率 ${pct(t.e1e2_rate)}。</strong> Midas spend 为 ${money(t.midas_spend)},按每个 E1/E2 事件 $3 计算的 Payable spend 为 ${money(t.payable_spend)}。窗口首尾 E1+E2% ${delta>=0?'上升':'下降'} ${Math.abs(delta).toFixed(2)} 个百分点;由于仅有 ${d.length} 天数据,应作为短期交付快照解读。`;
const cards=[['Install',fmt(t.install),'af_app_opened repostback'],['E1 + E2',fmt(t.e1e2),`${fmt(t.event1)} E1 · ${fmt(t.event2)} E2`],['E1+E2%',pct(t.e1e2_rate),'累计 E1+E2 ÷ 累计 Install'],['Payable spend',money(t.payable_spend),`Midas spend ${money(t.midas_spend)}`]];document.getElementById('cards').innerHTML=cards.map(x=>`<div class="card"><div class="label">${x[0]}</div><div class="value">${x[1]}</div><div class="note">${x[2]}</div></div>`).join('');
bars(document.getElementById('deliveryChart'),d,[{key:'install',color:'var(--blue)',format:fmt},{key:'event1',color:'var(--gold)',format:fmt},{key:'event2',color:'var(--orange)',format:fmt}],Math.max(...d.flatMap(x=>[x.install,x.event1,x.event2]),1));
bars(document.getElementById('rateChart'),d,[{key:'e1e2_rate',color:'var(--orange)',format:pct}],Math.max(...d.map(x=>x.e1e2_rate||0),1));
bars(document.getElementById('spendChart'),d,[{key:'midas_spend',color:'var(--blue)',format:money},{key:'payable_spend',color:'var(--gold)',format:money}],Math.max(...d.flatMap(x=>[x.midas_spend,x.payable_spend]),1));
const gap=t.payable_spend-t.midas_spend;document.getElementById('spendText').innerHTML=`<strong>累计 Payable spend ${gap>=0?'高于':'低于'} Midas spend ${money(Math.abs(gap))}。</strong> 该差额来自约定的事件计费公式与平台实际消耗之间的口径差异,不应直接解读为利润。`;
document.getElementById('rows').innerHTML=d.slice().reverse().map(x=>`<tr><td>${x.date}</td><td>${fmt(x.install)}</td><td>${fmt(x.event1)}</td><td>${fmt(x.event2)}</td><td>${pct(x.e1e2_rate)}</td><td>${money(x.midas_spend)}</td><td>${money(x.payable_spend)}</td></tr>`).join('');
}).catch(e=>{document.getElementById('summaryText').className='error';document.getElementById('summaryText').textContent='数据载入失败:'+e.message});
</script></body></html>