feat: matrix status driven by real data + product order status (B2: only show channels with data)
This commit is contained in:
+24
-9
@@ -209,7 +209,8 @@
|
||||
<p class="hint">
|
||||
<span class="badge badge-active">Active</span> 投放中
|
||||
<span class="badge badge-pause">Pause</span> 投过已停
|
||||
空白 = 未投放
|
||||
空白 = 暂无数据(未接入或未投放)<br>
|
||||
状态依据实际投放数据判定:产品订单为 Pause 直接判停;产品在投则看该渠道近期展示趋势(掉到个位数/断更视为已停)。仅显示已接入数据的渠道。
|
||||
</p>
|
||||
<div class="table-wrapper">
|
||||
<table id="matrixTable"><thead></thead><tbody></tbody></table>
|
||||
@@ -251,17 +252,18 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let perfData = [], orderData = [], campaignData = [];
|
||||
let perfData = [], orderData = [], campaignData = [], matrixOverrides = {};
|
||||
let impChart = null;
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const [p, o, c] = await Promise.all([
|
||||
const [p, o, c, m] = await Promise.all([
|
||||
fetch('mtg_data.json?' + Date.now()).then(r => r.json()).catch(() => []),
|
||||
fetch('orders.json?' + Date.now()).then(r => r.json()).catch(() => []),
|
||||
fetch('campaigns.json?' + Date.now()).then(r => r.json()).catch(() => [])
|
||||
fetch('campaigns.json?' + Date.now()).then(r => r.json()).catch(() => []),
|
||||
fetch('matrix_overrides.json?' + Date.now()).then(r => r.json()).catch(() => ({}))
|
||||
]);
|
||||
perfData = p; orderData = o; campaignData = c;
|
||||
perfData = p; orderData = o; campaignData = c; matrixOverrides = m;
|
||||
initTabs();
|
||||
renderPerformance();
|
||||
renderOrders();
|
||||
@@ -401,8 +403,9 @@
|
||||
}
|
||||
|
||||
function renderMatrix() {
|
||||
// 列 = 产品(带 pkg 用于查数据状态)
|
||||
const cols = orderData.map(o => ({
|
||||
label: o.product, sub: o.geo, status: o.status,
|
||||
label: o.product, sub: o.geo, pkg: o.pkg,
|
||||
channels: new Set([...(o.agency_channels||[]), ...(o.self_channels||[])])
|
||||
}));
|
||||
const channels = [];
|
||||
@@ -413,10 +416,22 @@
|
||||
<th style="position:sticky;left:0;background:#f9fafb;z-index:2;">渠道 \\ 产品</th>
|
||||
${cols.map(c => `<th style="text-align:center;min-width:88px;"><div>${c.label}</div><div style="font-weight:400;font-size:10px;color:#9ca3af;">${c.sub}</div></th>`).join('')}
|
||||
</tr>`;
|
||||
|
||||
// 单元格:仅当该「渠道|包名」在 matrixOverrides 有记录时才显示状态(遵从事实:接了数据才判定)
|
||||
// 产品 pkg 可能是 "a / b" 合并形式,任一命中即取用
|
||||
const lookup = (ch, pkg) => {
|
||||
const parts = String(pkg).replace(/\s/g,'').split('/');
|
||||
for (const p of parts) {
|
||||
const k = ch + '|' + p;
|
||||
if (k in matrixOverrides) return matrixOverrides[k];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
const cell = (col, ch) => {
|
||||
if (!col.channels.has(ch)) return '<td></td>';
|
||||
const cls = col.status === 'Active' ? 'badge-active' : 'badge-pause';
|
||||
return `<td style="text-align:center;"><span class="badge ${cls}">${col.status}</span></td>`;
|
||||
const st = lookup(ch, col.pkg);
|
||||
if (st === undefined || st === 'none') return '<td></td>'; // 无数据 / 零曝光 -> 留空
|
||||
const cls = st === 'Active' ? 'badge-active' : 'badge-pause';
|
||||
return `<td style="text-align:center;"><span class="badge ${cls}">${st}</span></td>`;
|
||||
};
|
||||
document.querySelector('#matrixTable tbody').innerHTML = channels.map(ch => `
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user