feat: split orders into base info table + channel x product matrix
This commit is contained in:
+80
-11
@@ -403,8 +403,10 @@
|
||||
|
||||
<div class="tab-panel" id="tab-orders">
|
||||
<div class="order-stats" id="orderStats"></div>
|
||||
<div class="table-section">
|
||||
<h2>Moboost广告投放</h2>
|
||||
|
||||
<!-- 模块1:产品订单基础信息 -->
|
||||
<div class="table-section" style="margin-bottom:24px;">
|
||||
<h2>产品订单基础信息</h2>
|
||||
<div class="table-wrapper">
|
||||
<table id="orderTable">
|
||||
<thead>
|
||||
@@ -418,15 +420,28 @@
|
||||
<th>日预算</th>
|
||||
<th>状态</th>
|
||||
<th>MMP</th>
|
||||
<th>代投渠道</th>
|
||||
<th>平台自投渠道</th>
|
||||
<th>数据来源</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 模块2:渠道投放矩阵 -->
|
||||
<div class="table-section">
|
||||
<h2>渠道投放矩阵(渠道 × 产品)</h2>
|
||||
<p style="font-size:12px;color:#94a3b8;margin:-8px 0 14px;">
|
||||
<span class="status-badge status-active" style="padding:1px 8px;">Active</span> 投放中
|
||||
<span class="status-badge status-pause" style="padding:1px 8px;">Pause</span> 投过已停
|
||||
空白 = 未投放
|
||||
</p>
|
||||
<div class="table-wrapper">
|
||||
<table id="matrixTable">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /tab-orders -->
|
||||
|
||||
<div class="updated-time" id="updatedTime"></div>
|
||||
@@ -513,9 +528,6 @@
|
||||
|
||||
// Table
|
||||
const tbody = document.querySelector('#orderTable tbody');
|
||||
const chipList = (arr) => (arr && arr.length)
|
||||
? arr.map(c => `<span class="channel-chip">${c}</span>`).join('')
|
||||
: '<span class="no-channel">—</span>';
|
||||
tbody.innerHTML = orderData.map(o => {
|
||||
const statusClass = o.status === 'Active' ? 'status-active' : 'status-pause';
|
||||
return `
|
||||
@@ -529,12 +541,69 @@
|
||||
<td class="num-cell">${o.budget}</td>
|
||||
<td><span class="status-badge ${statusClass}">${o.status}</span></td>
|
||||
<td>${o.mmp}</td>
|
||||
<td style="max-width:220px;white-space:normal">${chipList(o.agency_channels)}</td>
|
||||
<td style="max-width:180px;white-space:normal">${chipList(o.self_channels)}</td>
|
||||
<td style="font-size:11px;color:#94a3b8">${o.source}</td>
|
||||
</tr>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
renderMatrix();
|
||||
}
|
||||
|
||||
function renderMatrix() {
|
||||
// 列 = 产品(按 pkg 区分,同名产品用地区区分显示);行 = 渠道
|
||||
// 每个订单条目是一列
|
||||
const cols = orderData.map(o => ({
|
||||
key: o.pkg,
|
||||
label: o.product,
|
||||
sub: o.geo,
|
||||
status: o.status,
|
||||
channels: new Set([...(o.agency_channels||[]), ...(o.self_channels||[])])
|
||||
}));
|
||||
|
||||
// 收集所有渠道,分代投 / 自投两组
|
||||
const agencySet = new Set();
|
||||
const selfSet = new Set();
|
||||
orderData.forEach(o => {
|
||||
(o.agency_channels||[]).forEach(c => agencySet.add(c));
|
||||
(o.self_channels||[]).forEach(c => selfSet.add(c));
|
||||
});
|
||||
const agencyChannels = [...agencySet];
|
||||
const selfChannels = [...selfSet];
|
||||
|
||||
// 表头
|
||||
const thead = document.querySelector('#matrixTable thead');
|
||||
thead.innerHTML = `
|
||||
<tr>
|
||||
<th style="position:sticky;left:0;background:#f1f5f9;z-index:2;">渠道 \\ 产品</th>
|
||||
${cols.map(c => `<th style="text-align:center;min-width:90px;">
|
||||
<div>${c.label}</div>
|
||||
<div style="font-weight:400;font-size:10px;color:#94a3b8;">${c.sub}</div>
|
||||
</th>`).join('')}
|
||||
</tr>
|
||||
`;
|
||||
|
||||
// 单元格生成
|
||||
const cell = (col, channel) => {
|
||||
if (!col.channels.has(channel)) return '<td></td>';
|
||||
const cls = col.status === 'Active' ? 'status-active' : 'status-pause';
|
||||
return `<td style="text-align:center;"><span class="status-badge ${cls}" style="padding:2px 8px;font-size:10px;">${col.status}</span></td>`;
|
||||
};
|
||||
|
||||
const groupRows = (title, channels) => {
|
||||
if (!channels.length) return '';
|
||||
let html = `<tr><td colspan="${cols.length+1}" style="background:#eef2ff;font-weight:700;color:#4338ca;font-size:12px;">${title}</td></tr>`;
|
||||
html += channels.map(ch => `
|
||||
<tr>
|
||||
<td style="position:sticky;left:0;background:#fff;font-weight:500;">${ch}</td>
|
||||
${cols.map(col => cell(col, ch)).join('')}
|
||||
</tr>
|
||||
`).join('');
|
||||
return html;
|
||||
};
|
||||
|
||||
const tbody = document.querySelector('#matrixTable tbody');
|
||||
tbody.innerHTML =
|
||||
groupRows('代投渠道', agencyChannels) +
|
||||
groupRows('平台自投渠道', selfChannels);
|
||||
}
|
||||
|
||||
function populateFilters() {
|
||||
|
||||
Reference in New Issue
Block a user