监测明细表表头支持点击升序/降序排序

This commit is contained in:
2026-09-10 18:27:45 +08:00
parent f23e8d0acc
commit 936e2ae40a
+53 -16
View File
@@ -36,6 +36,11 @@
.sum-metric{color:var(--accent);font-weight:600;} .sum-metric{color:var(--accent);font-weight:600;}
.total-row td{position:sticky;top:33px;background:#eef2f7;font-weight:700;color:var(--head);border-top:2px solid #cbd5e1;z-index:1;} .total-row td{position:sticky;top:33px;background:#eef2f7;font-weight:700;color:var(--head);border-top:2px solid #cbd5e1;z-index:1;}
.total-row td.txt{text-align:left;} .total-row td.txt{text-align:left;}
th.sortable{cursor:pointer;user-select:none;}
th.sortable:hover{background:#374151;}
th .arrow{display:inline-block;width:10px;margin-left:3px;font-size:10px;color:#93c5fd;}
th.sort-asc .arrow::after{content:"\25B2";}
th.sort-desc .arrow::after{content:"\25BC";}
</style> </style>
</head> </head>
<body> <body>
@@ -75,20 +80,20 @@
<table id="detailTable"> <table id="detailTable">
<thead> <thead>
<tr> <tr>
<th>dt</th> <th class="sortable" data-key="dt" data-type="dt">dt<span class="arrow"></span></th>
<th>融合后campaign id</th> <th class="sortable" data-key="routing_campaign_id" data-type="str">融合后campaign id<span class="arrow"></span></th>
<th>融合前campaign id</th> <th class="sortable" data-key="campaign_id" data-type="str">融合前campaign id<span class="arrow"></span></th>
<th>adping_id</th> <th class="sortable" data-key="adping_id" data-type="num">adping_id<span class="arrow"></span></th>
<th>second_channel</th> <th class="sortable" data-key="second_channel" data-type="str">second_channel<span class="arrow"></span></th>
<th>account</th> <th class="sortable" data-key="account" data-type="str">account<span class="arrow"></span></th>
<th>pkg</th> <th class="sortable" data-key="pkg" data-type="str">pkg<span class="arrow"></span></th>
<th>clicks</th> <th class="sortable" data-key="clicks" data-type="num">clicks<span class="arrow"></span></th>
<th>conversion</th> <th class="sortable" data-key="conversion" data-type="num">conversion<span class="arrow"></span></th>
<th>cvr</th> <th class="sortable" data-key="cvr" data-type="num">cvr<span class="arrow"></span></th>
<th>revenue</th> <th class="sortable" data-key="revenue" data-type="num">revenue<span class="arrow"></span></th>
<th>cost</th> <th class="sortable" data-key="cost" data-type="num">cost<span class="arrow"></span></th>
<th>GP</th> <th class="sortable" data-key="gp" data-type="num">GP<span class="arrow"></span></th>
<th>ecpc</th> <th class="sortable" data-key="ecpc" data-type="num">ecpc<span class="arrow"></span></th>
</tr> </tr>
<tr id="totalRow" class="total-row"> <tr id="totalRow" class="total-row">
<td colspan="7" class="txt">Total</td> <td colspan="7" class="txt">Total</td>
@@ -160,10 +165,32 @@ function currentFilter(d){
return true; return true;
} }
function renderDetail(){ var SORT_KEY='clicks', SORT_TYPE='num', SORT_DIR='desc';
var rows = ALL.filter(currentFilter).sort(function(a,b){
function sortRows(rows){
var k=SORT_KEY, type=SORT_TYPE, dir=(SORT_DIR==='asc'?1:-1);
return rows.sort(function(a,b){
var va,vb;
if(type==='dt'){ va=dtKey(a.dt); vb=dtKey(b.dt); }
else if(type==='num'){ va=Number(a[k])||0; vb=Number(b[k])||0; }
else { va=String(a[k]||''); vb=String(b[k]||''); return dir*va.localeCompare(vb); }
if(va<vb) return -1*dir; if(va>vb) return 1*dir;
// 次级排序:dt 降序、clicks 降序,保持稳定观感
return dtKey(b.dt)-dtKey(a.dt) || (b.clicks-a.clicks); return dtKey(b.dt)-dtKey(a.dt) || (b.clicks-a.clicks);
}); });
}
function updateSortArrows(){
document.querySelectorAll('#detailTable th.sortable').forEach(function(th){
th.classList.remove('sort-asc','sort-desc');
if(th.getAttribute('data-key')===SORT_KEY){
th.classList.add(SORT_DIR==='asc'?'sort-asc':'sort-desc');
}
});
}
function renderDetail(){
var rows = sortRows(ALL.filter(currentFilter));
var tb=document.querySelector('#detailTable tbody'); var tb=document.querySelector('#detailTable tbody');
if(!rows.length){ tb.innerHTML='<tr><td colspan="14" class="empty">无匹配数据</td></tr>'; } if(!rows.length){ tb.innerHTML='<tr><td colspan="14" class="empty">无匹配数据</td></tr>'; }
else { else {
@@ -189,6 +216,7 @@ function renderDetail(){
} }
document.getElementById('detailNote').textContent='显示 '+rows.length+' / '+ALL.length+' 行'; document.getElementById('detailNote').textContent='显示 '+rows.length+' / '+ALL.length+' 行';
renderTotal(rows); renderTotal(rows);
updateSortArrows();
} }
function renderTotal(rows){ function renderTotal(rows){
@@ -207,6 +235,15 @@ function renderTotal(rows){
document.getElementById('tEcpc').textContent=dec(ecpc,4); document.getElementById('tEcpc').textContent=dec(ecpc,4);
} }
document.querySelectorAll('#detailTable th.sortable').forEach(function(th){
th.addEventListener('click',function(){
var k=th.getAttribute('data-key'), type=th.getAttribute('data-type');
if(SORT_KEY===k){ SORT_DIR=(SORT_DIR==='asc'?'desc':'asc'); }
else { SORT_KEY=k; SORT_TYPE=type; SORT_DIR='desc'; }
renderDetail();
});
});
document.getElementById('applyBtn').onclick=renderDetail; document.getElementById('applyBtn').onclick=renderDetail;
document.getElementById('resetBtn').onclick=function(){ document.getElementById('resetBtn').onclick=function(){
['fDtFrom','fDtTo','fRc','fCid'].forEach(function(id){document.getElementById(id).value='';}); ['fDtFrom','fDtTo','fRc','fCid'].forEach(function(id){document.getElementById(id).value='';});