09-09 起消耗改从 MIDAS 取(C00000196_TECDO 账户投放中 campaign),09-08 前用冻结表格

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
FANGKK
2026-09-10 18:29:26 +08:00
co-authored by Claude Opus 5
parent f07c872611
commit 44e506ac32
3 changed files with 501 additions and 219 deletions
+4
View File
@@ -1,3 +1,7 @@
push.sh push.sh
build_data.py build_data.py
fetch_midas.js
baseline_sheet.json
midas_latest.json
midas_history.json
.DS_Store .DS_Store
+422 -197
View File
File diff suppressed because it is too large Load Diff
+74 -21
View File
@@ -11,7 +11,7 @@
--page: #f9f9f7; --surface: #fcfcfb; --ink: #0b0b0b; --ink-2: #52514e; --muted: #898781; --page: #f9f9f7; --surface: #fcfcfb; --ink: #0b0b0b; --ink-2: #52514e; --muted: #898781;
--grid: #e1e0d9; --axis: #c3c2b7; --border: rgba(11,11,11,.10); --grid: #e1e0d9; --axis: #c3c2b7; --border: rgba(11,11,11,.10);
--s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --other: #a3a29b; --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --other: #a3a29b;
--warn: #fab219; --crit: #d03b3b; --good: #006300; --warn: #fab219; --crit: #d03b3b;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root:where(:not([data-theme="light"])) { :root:where(:not([data-theme="light"])) {
@@ -19,6 +19,7 @@
--page: #0d0d0d; --surface: #1a1a19; --ink: #ffffff; --ink-2: #c3c2b7; --muted: #898781; --page: #0d0d0d; --surface: #1a1a19; --ink: #ffffff; --ink-2: #c3c2b7; --muted: #898781;
--grid: #2c2c2a; --axis: #383835; --border: rgba(255,255,255,.10); --grid: #2c2c2a; --axis: #383835; --border: rgba(255,255,255,.10);
--s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --other: #6b6a65; --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --other: #6b6a65;
--good: #0ca30c;
} }
} }
:root[data-theme="dark"] { :root[data-theme="dark"] {
@@ -26,6 +27,7 @@
--page: #0d0d0d; --surface: #1a1a19; --ink: #ffffff; --ink-2: #c3c2b7; --muted: #898781; --page: #0d0d0d; --surface: #1a1a19; --ink: #ffffff; --ink-2: #c3c2b7; --muted: #898781;
--grid: #2c2c2a; --axis: #383835; --border: rgba(255,255,255,.10); --grid: #2c2c2a; --axis: #383835; --border: rgba(255,255,255,.10);
--s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --other: #6b6a65; --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --other: #6b6a65;
--good: #0ca30c;
} }
* { box-sizing: border-box; } * { box-sizing: border-box; }
body { margin: 0; background: var(--page); color: var(--ink); font: 14px/1.5 system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; } body { margin: 0; background: var(--page); color: var(--ink); font: 14px/1.5 system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; }
@@ -71,12 +73,14 @@ table { border-collapse: collapse; width: 100%; font-size: 13px; white-space: no
th { text-align: left; color: var(--muted); font-weight: 500; font-size: 12px; padding: 6px 10px; border-bottom: 1px solid var(--axis); } th { text-align: left; color: var(--muted); font-weight: 500; font-size: 12px; padding: 6px 10px; border-bottom: 1px solid var(--axis); }
td { padding: 7px 10px; border-bottom: 1px solid var(--grid); } td { padding: 7px 10px; border-bottom: 1px solid var(--grid); }
th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; } th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; }
td.muted { color: var(--muted); }
tr.sub td { font-weight: 600; border-top: 1px solid var(--axis); } tr.sub td { font-weight: 600; border-top: 1px solid var(--axis); }
tfoot td { font-weight: 600; border-bottom: none; } tfoot td { font-weight: 600; border-bottom: none; }
.badge { display: inline-flex; align-items: center; gap: 5px; color: var(--ink); } .badge { display: inline-flex; align-items: center; gap: 5px; color: var(--ink); }
.badge-icon { display: inline-grid; place-items: center; width: 15px; height: 15px; border-radius: 50%; font-size: 10px; font-weight: 700; color: #0b0b0b; } .badge-icon { display: inline-grid; place-items: center; width: 15px; height: 15px; border-radius: 50%; font-size: 10px; font-weight: 700; color: #0b0b0b; }
.badge.warn .badge-icon { background: var(--warn); } .badge.warn .badge-icon { background: var(--warn); }
.badge.crit .badge-icon { background: var(--crit); color: #fff; } .badge.crit .badge-icon { background: var(--crit); color: #fff; }
.badge.good .badge-icon { background: var(--good); color: #fff; }
footer { color: var(--muted); font-size: 12px; margin-top: 8px; } footer { color: var(--muted); font-size: 12px; margin-top: 8px; }
#err { background: var(--surface); border: 1px solid var(--crit); border-radius: 8px; padding: 14px; margin-top: 20px; } #err { background: var(--surface); border: 1px solid var(--crit); border-radius: 8px; padding: 14px; margin-top: 20px; }
</style> </style>
@@ -95,7 +99,7 @@ footer { color: var(--muted); font-size: 12px; margin-top: 8px; }
<div class="card-head"> <div class="card-head">
<div> <div>
<h2>每日消耗</h2> <h2>每日消耗</h2>
<p class="desc">按包堆叠,悬停查看当天每个包的消耗、注册和首充</p> <p class="desc" id="spend-desc">按包堆叠,悬停查看当天每个包的数据</p>
</div> </div>
<div class="seg" id="range" role="group" aria-label="时间范围"> <div class="seg" id="range" role="group" aria-label="时间范围">
<button type="button" data-range="7" aria-pressed="true">近 7 天</button> <button type="button" data-range="7" aria-pressed="true">近 7 天</button>
@@ -113,9 +117,20 @@ footer { color: var(--muted); font-size: 12px; margin-top: 8px; }
<div class="chart" id="balance-chart"><div class="tip" hidden></div></div> <div class="chart" id="balance-chart"><div class="tip" hidden></div></div>
</section> </section>
<section class="card">
<h2>MIDAS campaign</h2>
<p class="desc" id="camps-desc">账户 C00000196_TECDO HONG KONG LIMITED,DSP投放页状态为「投放中」的 campaign</p>
<div class="table-wrap">
<table id="camps">
<thead><tr><th>广告活动</th><th>ID</th><th>推广包</th><th>状态</th><th class="num">安装</th><th class="num">消耗</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<section class="card"> <section class="card">
<h2>分包汇总</h2> <h2>分包汇总</h2>
<p class="desc">全部历史,按消耗从高到低;成本 = 消耗 ÷ 首充</p> <p class="desc">全部历史,按消耗从高到低;成本 = 消耗 ÷ 首充。MIDAS 没有注册和首充,带 * 的数只统计表格部分</p>
<div class="table-wrap"> <div class="table-wrap">
<table id="pkgs"> <table id="pkgs">
<thead><tr><th>产品名</th><th>投放日期</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead> <thead><tr><th>产品名</th><th>投放日期</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead>
@@ -126,7 +141,7 @@ footer { color: var(--muted); font-size: 12px; margin-top: 8px; }
<section class="card"> <section class="card">
<h2>分月汇总</h2> <h2>分月汇总</h2>
<p class="desc">每月先列合计,再列当月有数据的包</p> <p class="desc">每月先列合计,再列当月有数据的包;带 * 的注册、首充、成本只统计表格部分</p>
<div class="table-wrap"> <div class="table-wrap">
<table id="months"> <table id="months">
<thead><tr><th>月份</th><th>产品名</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead> <thead><tr><th>月份</th><th>产品名</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead>
@@ -139,13 +154,13 @@ footer { color: var(--muted); font-size: 12px; margin-top: 8px; }
<div class="card-head"> <div class="card-head">
<div> <div>
<h2>分天明细</h2> <h2>分天明细</h2>
<p class="desc">按日期倒序</p> <p class="desc">按日期倒序;MIDAS 的天没有注册和首充</p>
</div> </div>
<select id="pkg-filter" aria-label="按包筛选"></select> <select id="pkg-filter" aria-label="按包筛选"></select>
</div> </div>
<div class="table-wrap"> <div class="table-wrap">
<table id="daily"> <table id="daily">
<thead><tr><th>日期</th><th>产品名</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead> <thead><tr><th>日期</th><th>产品名</th><th>来源</th><th class="num">安装</th><th class="num">注册</th><th class="num">首充</th><th class="num">消耗</th><th class="num">成本</th></tr></thead>
<tbody></tbody><tfoot></tfoot> <tbody></tbody><tfoot></tfoot>
</table> </table>
</div> </div>
@@ -173,7 +188,6 @@ const h = (tag, cls, text) => { const e = document.createElement(tag); if (cls)
const r2 = v => Math.round(v * 100) / 100; const r2 = v => Math.round(v * 100) / 100;
const usd = (v, dp = 2) => (v < 0 ? '−$' : '$') + Math.abs(v).toLocaleString('en-US', { minimumFractionDigits: dp, maximumFractionDigits: dp }); const usd = (v, dp = 2) => (v < 0 ? '−$' : '$') + Math.abs(v).toLocaleString('en-US', { minimumFractionDigits: dp, maximumFractionDigits: dp });
const int = v => Number(v || 0).toLocaleString('en-US'); const int = v => Number(v || 0).toLocaleString('en-US');
const costText = (spend, ftd) => ftd ? usd(spend / ftd) : '—';
const shortDate = dt => dt.slice(5).replace('-', '/'); const shortDate = dt => dt.slice(5).replace('-', '/');
const addDays = (s, n) => { const t = new Date(s + 'T00:00:00Z'); t.setUTCDate(t.getUTCDate() + n); return t.toISOString().slice(0, 10); }; const addDays = (s, n) => { const t = new Date(s + 'T00:00:00Z'); t.setUTCDate(t.getUTCDate() + n); return t.toISOString().slice(0, 10); };
const dayRange = (a, b) => { const out = []; for (let s = a; s <= b; s = addDays(s, 1)) out.push(s); return out; }; const dayRange = (a, b) => { const out = []; for (let s = a; s <= b; s = addDays(s, 1)) out.push(s); return out; };
@@ -215,16 +229,30 @@ function tr(cells) {
cells.forEach(c => { cells.forEach(c => {
const td = h('td', c.cls || ''); const td = h('td', c.cls || '');
if (c.color) td.append(swatch(c.color)); if (c.color) td.append(swatch(c.color));
td.append(document.createTextNode(c.text)); if (c.node) td.append(c.node); else td.append(document.createTextNode(c.text));
row.append(td); row.append(td);
}); });
return row; return row;
} }
const sumRows = rows => rows.reduce((a, r) => ({ installs: a.installs + r.installs, reg: a.reg + r.reg, ftd: a.ftd + r.ftd, spend: r2(a.spend + r.spend) }), { installs: 0, reg: 0, ftd: 0, spend: 0 });
const metricCells = t => [ // 注册、首充只有表格部分有(MIDAS 为 null):成本只用有首充数据的那部分消耗来算
{ text: int(t.installs), cls: 'num' }, { text: int(t.reg), cls: 'num' }, { text: int(t.ftd), cls: 'num' }, const sumRows = rows => rows.reduce((a, r) => {
{ text: usd(t.spend), cls: 'num' }, { text: costText(t.spend, t.ftd), cls: 'num' }, a.installs += r.installs;
a.spend = r2(a.spend + r.spend);
if (r.ftd == null) a.unknown++;
else { a.known++; a.reg += r.reg || 0; a.ftd += r.ftd; a.costSpend = r2(a.costSpend + r.spend); }
return a;
}, { installs: 0, reg: 0, ftd: 0, spend: 0, costSpend: 0, known: 0, unknown: 0 });
const metricCells = t => {
const star = t.known && t.unknown ? '*' : '';
return [
{ text: int(t.installs), cls: 'num' },
{ text: t.known ? int(t.reg) + star : '—', cls: 'num' + (t.known ? '' : ' muted') },
{ text: t.known ? int(t.ftd) + star : '—', cls: 'num' + (t.known ? '' : ' muted') },
{ text: usd(t.spend), cls: 'num' },
{ text: t.known && t.ftd ? usd(t.costSpend / t.ftd) + star : '—', cls: 'num' + (t.known && t.ftd ? '' : ' muted') },
]; ];
};
function derive(d) { function derive(d) {
const end = d.range.end; const end = d.range.end;
@@ -242,7 +270,7 @@ function derive(d) {
if (pkgs.length > SLOTS) series.push({ label: `其他 ${pkgs.length - SLOTS} 个包`, color: 'var(--other)', members: pkgs.slice(SLOTS).map(p => p.pkg) }); if (pkgs.length > SLOTS) series.push({ label: `其他 ${pkgs.length - SLOTS} 个包`, color: 'var(--other)', members: pkgs.slice(SLOTS).map(p => p.pkg) });
const seriesOf = {}; const seriesOf = {};
series.forEach((s, i) => s.members.forEach(p => { seriesOf[p] = i; })); series.forEach((s, i) => s.members.forEach(p => { seriesOf[p] = i; }));
const colorOf = pkg => series[seriesOf[pkg]].color; const colorOf = pkg => series[seriesOf[pkg]] ? series[seriesOf[pkg]].color : 'var(--other)';
pkgs.forEach(p => { p.color = colorOf(p.pkg); }); pkgs.forEach(p => { p.color = colorOf(p.pkg); });
const byDate = {}; const byDate = {};
@@ -284,8 +312,8 @@ function renderTiles(S, d) {
else sub = isFinite(days) ? `按近 7 天日均约可用 ${Math.floor(days)} 天` : '近 7 天没有消耗'; else sub = isFinite(days) ? `按近 7 天日均约可用 ${Math.floor(days)} 天` : '近 7 天没有消耗';
add('当前余额', usd(S.balance), sub); add('当前余额', usd(S.balance), sub);
add('近 7 天消耗', usd(S.w7.spend), `${shortDate(addDays(S.end, -6))}–${shortDate(S.end)},日均 ${usd(S.avg7)}`); add('近 7 天消耗', usd(S.w7.spend), `${shortDate(addDays(S.end, -6))}–${shortDate(S.end)},日均 ${usd(S.avg7)}`);
add('近 7 天首充', int(S.w7.ftd), `成本 ${costText(S.w7.spend, S.w7.ftd)} · 注册 ${int(S.w7.reg)}`); add('近 7 天安装', int(S.w7.installs), S.w7.installs ? `eCPI ${usd(S.w7.spend / S.w7.installs)}` : '暂无安装');
add('累计消耗', usd(S.total.spend), `${d.range.start} 起 · 成本 ${costText(S.total.spend, S.total.ftd)}`); add('累计消耗', usd(S.total.spend), `${d.range.start} 起 · 首充成本 ${S.total.ftd ? usd(S.total.costSpend / S.total.ftd) : '—'}(表格部分)`);
add('累计到账', usd(S.received), `打款 ${usd(S.paid, 0)} · 共 ${S.recharges.length} 笔`); add('累计到账', usd(S.received), `打款 ${usd(S.paid, 0)} · 共 ${S.recharges.length} 笔`);
} }
@@ -313,7 +341,7 @@ function drawSpend(S, d) {
return e; return e;
})); }));
const W = Math.max(300, wrap.clientWidth), H = 260, m = { l: 56, r: 14, t: 24, b: 30 }; const W = Math.max(300, wrap.clientWidth), H = 260, m = { l: 56, r: 14, t: 28, b: 30 };
const pw = W - m.l - m.r, ph = H - m.t - m.b; const pw = W - m.l - m.r, ph = H - m.t - m.b;
const sc = scaleY(0, Math.max(...totals, 1)); const sc = scaleY(0, Math.max(...totals, 1));
const y = v => m.t + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph; const y = v => m.t + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph;
@@ -326,6 +354,16 @@ function drawSpend(S, d) {
el('line', { x1: m.l, x2: W - m.r, y1: y(t), y2: y(t), class: t === 0 ? 'axis' : 'grid' }, svg); el('line', { x1: m.l, x2: W - m.r, y1: y(t), y2: y(t), class: t === 0 ? 'axis' : 'grid' }, svg);
el('text', { x: m.l - 8, y: y(t) + 4, 'text-anchor': 'end', class: 'tick' }, svg).textContent = usd(t, sc.dp); el('text', { x: m.l - 8, y: y(t) + 4, 'text-anchor': 'end', class: 'tick' }, svg).textContent = usd(t, sc.dp);
}); });
// 表格数据和 MIDAS 数据的分界线
const k = dates.indexOf(d.midas_from);
if (k > 0) {
const xk = m.l + band * k;
el('line', { x1: xk, x2: xk, y1: m.t - 6, y2: m.t + ph, class: 'axis' }, svg);
el('text', { x: xk + 4, y: m.t - 10, 'text-anchor': 'start', class: 'tick' }, svg).textContent = 'MIDAS →';
el('text', { x: xk - 4, y: m.t - 10, 'text-anchor': 'end', class: 'tick' }, svg).textContent = '← 表格';
}
const step = labelStep(n, pw); const step = labelStep(n, pw);
const maxI = totals.indexOf(Math.max(...totals)), lastI = n - 1; const maxI = totals.indexOf(Math.max(...totals)), lastI = n - 1;
dates.forEach((dt, i) => { dates.forEach((dt, i) => {
@@ -367,7 +405,8 @@ function spendTip(S, dt, total) {
rows.forEach(r => { rows.forEach(r => {
const row = h('div', 'tip-row'); const row = h('div', 'tip-row');
row.append(swatch(S.colorOf(r.pkg)), h('span', 'tip-name', r.pkg), h('span', 'tip-val', usd(r.spend))); row.append(swatch(S.colorOf(r.pkg)), h('span', 'tip-name', r.pkg), h('span', 'tip-val', usd(r.spend)));
f.append(row, h('div', 'tip-sub', `安装 ${int(r.installs)} · 注册 ${int(r.reg)} · 首充 ${int(r.ftd)}`)); const detail = r.ftd == null ? `安装 ${int(r.installs)} · 来自 MIDAS` : `安装 ${int(r.installs)} · 注册 ${int(r.reg)} · 首充 ${int(r.ftd)}`;
f.append(row, h('div', 'tip-sub', detail));
}); });
if (rows.length > 1) { if (rows.length > 1) {
const tot = h('div', 'tip-row tip-total'); const tot = h('div', 'tip-row tip-total');
@@ -427,6 +466,14 @@ function drawBalance(S) {
} }
function renderTables(S, d) { function renderTables(S, d) {
const camps = d.campaigns || [];
$('#camps-desc').textContent = `账户 C00000196_TECDO HONG KONG LIMITED,${shortDate(d.midas_from)} 起的数据;列出状态为「投放中」的 campaign,以及期间内有过消耗、现在已停的`;
$('#camps tbody').replaceChildren(...(camps.length ? camps.map(c => tr([
{ text: c.name }, { text: c.id }, { text: c.pkg || c.app || '—', color: c.pkg ? S.colorOf(c.pkg) : null },
{ node: c.active ? badge('good', '✓', '投放中') : document.createTextNode('已停') },
{ text: int(c.installs), cls: 'num' }, { text: usd(c.spend), cls: 'num' },
])) : [tr([{ text: `还没有 ${d.midas_from} 起的 MIDAS 数据` }, { text: '' }, { text: '' }, { text: '' }, { text: '' }, { text: '' }])]));
$('#pkgs tbody').replaceChildren(...S.pkgs.map(p => tr([{ text: p.pkg, color: p.color }, { text: `${p.first} ~ ${p.last}` }, ...metricCells(p)]))); $('#pkgs tbody').replaceChildren(...S.pkgs.map(p => tr([{ text: p.pkg, color: p.color }, { text: `${p.first} ~ ${p.last}` }, ...metricCells(p)])));
$('#pkgs tfoot').replaceChildren(tr([{ text: '合计' }, { text: `${d.range.start} ~ ${d.range.end}` }, ...metricCells(S.total)])); $('#pkgs tfoot').replaceChildren(tr([{ text: '合计' }, { text: `${d.range.start} ~ ${d.range.end}` }, ...metricCells(S.total)]));
@@ -446,7 +493,9 @@ function renderTables(S, d) {
}); });
const sel = $('#pkg-filter'); const sel = $('#pkg-filter');
const current = sel.value;
sel.replaceChildren(new Option('全部包', ''), ...S.pkgs.map(p => new Option(p.pkg, p.pkg))); sel.replaceChildren(new Option('全部包', ''), ...S.pkgs.map(p => new Option(p.pkg, p.pkg)));
sel.value = current;
sel.onchange = () => renderDaily(S, d); sel.onchange = () => renderDaily(S, d);
renderDaily(S, d); renderDaily(S, d);
@@ -461,8 +510,10 @@ function renderTables(S, d) {
function renderDaily(S, d) { function renderDaily(S, d) {
const f = $('#pkg-filter').value; const f = $('#pkg-filter').value;
const rows = d.daily.filter(r => !f || r.pkg === f).sort((a, b) => b.dt.localeCompare(a.dt) || b.spend - a.spend); const rows = d.daily.filter(r => !f || r.pkg === f).sort((a, b) => b.dt.localeCompare(a.dt) || b.spend - a.spend);
$('#daily tbody').replaceChildren(...rows.map(r => tr([{ text: r.dt }, { text: r.pkg, color: S.colorOf(r.pkg) }, ...metricCells(r)]))); $('#daily tbody').replaceChildren(...rows.map(r => tr([
$('#daily tfoot').replaceChildren(tr([{ text: '合计' }, { text: f || '全部包' }, ...metricCells(sumRows(rows))])); { text: r.dt }, { text: r.pkg, color: S.colorOf(r.pkg) }, { text: r.src === 'midas' ? 'MIDAS' : '表格' }, ...metricCells(sumRows([r])),
])));
$('#daily tfoot').replaceChildren(tr([{ text: '合计' }, { text: f || '全部包' }, { text: '' }, ...metricCells(sumRows(rows))]));
} }
let S, DATA; let S, DATA;
@@ -485,12 +536,14 @@ fetch('data.json', { cache: 'no-store' })
$('#meta').replaceChildren( $('#meta').replaceChildren(
h('span', '', `全账户 ${S.pkgs.length} 个包`), h('span', '', `全账户 ${S.pkgs.length} 个包`),
h('span', '', `数据区间 ${d.range.start} ~ ${d.range.end}`), h('span', '', `数据区间 ${d.range.start} ~ ${d.range.end}`),
h('span', '', `表格更新于 ${updated}`), h('span', '', `${shortDate(d.sheet_until)} 及以前来自表格,${shortDate(d.midas_from)} 起来自 MIDAS`),
h('span', '', `更新于 ${updated}`),
); );
$('#spend-desc').textContent = `按包堆叠,悬停查看当天每个包的数据;竖线右边(${shortDate(d.midas_from)} 起)来自 MIDAS`;
renderTiles(S, d); renderTiles(S, d);
renderTables(S, d); renderTables(S, d);
drawCharts(); drawCharts();
$('#foot').textContent = `数据来源:${d.source}。消耗按表格口径,成本 = 消耗 ÷ 首充,余额按到账金额计算。每天 11:00 检查表格,有更新就自动刷新。`; $('#foot').textContent = `数据来源:${d.sheet_until} 及以前是 tecdo_数据.xlsx(计费口径);${d.midas_from} 起是 MIDAS 账户 C00000196_TECDO HONG KONG LIMITED 的 campaign 消耗(UTC+0,截至前一天),MIDAS 没有注册和首充。充值来自 钛动预付款.xlsx,余额按到账金额计算。每天 11:00 自动刷新。`;
}) })
.catch(e => { .catch(e => {
$('#meta').textContent = ''; $('#meta').textContent = '';