板块2/3互换(客户分类前移为2.x,PKG波动后移为3.x); 3.2客户明细改为多天并列; DoD说明移至标题下
This commit is contained in:
+67
-50
@@ -51,8 +51,8 @@
|
||||
<div class="meta" id="meta">加载中…</div>
|
||||
<div class="tabs">
|
||||
<div class="tab active" data-tab="overview">总日报</div>
|
||||
<div class="tab" data-tab="pkg">PKG 收入波动</div>
|
||||
<div class="tab" data-tab="cust">客户分类</div>
|
||||
<div class="tab" data-tab="pkg">PKG 收入波动</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 总日报 ===== -->
|
||||
@@ -74,40 +74,16 @@
|
||||
</div>
|
||||
|
||||
<!-- ===== PKG 收入波动 ===== -->
|
||||
<div id="tab-pkg" class="hide">
|
||||
<div class="card">
|
||||
<h2>2.1 PKG 收入波动 - Midas <span class="tag">保留14天</span></h2>
|
||||
<div class="ctrl">
|
||||
<label><input type="checkbox" class="m-pkg" data-t="midas" checked> 按 pkg</label>
|
||||
<label><input type="checkbox" class="m-acc" data-t="midas"> 按 account</label>
|
||||
<input type="text" class="f-pkg" data-t="midas" placeholder="筛选 pkg">
|
||||
<input type="text" class="f-acc" data-t="midas" placeholder="筛选 account">
|
||||
<span class="sub-note" style="margin:0;">|DoD|>100 标注(+绿−红);表头点击排序;波动原因暂存本浏览器</span>
|
||||
</div>
|
||||
<div class="scroll"><table id="tPkgMidas"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>2.2 PKG 收入波动 - MS <span class="tag">保留14天</span></h2>
|
||||
<div class="ctrl">
|
||||
<label><input type="checkbox" class="m-pkg" data-t="ms" checked> 按 pkg</label>
|
||||
<label><input type="checkbox" class="m-acc" data-t="ms"> 按 account</label>
|
||||
<input type="text" class="f-pkg" data-t="ms" placeholder="筛选 pkg">
|
||||
<input type="text" class="f-acc" data-t="ms" placeholder="筛选 account">
|
||||
<span class="sub-note" style="margin:0;">|DoD|>100 标注(+绿−红);表头点击排序;波动原因暂存本浏览器</span>
|
||||
</div>
|
||||
<div class="scroll"><table id="tPkgMS"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 客户分类 ===== -->
|
||||
<!-- ===== 客户分类(板块2) ===== -->
|
||||
<div id="tab-cust" class="hide">
|
||||
<div class="card">
|
||||
<h2>3.1 客户分类日报</h2>
|
||||
<div class="sub-note">DoD=T-1−T-2,DoD%=T-1/T-2−1。波动原因可编辑(暂存本浏览器)。</div>
|
||||
<h2>2.1 客户分类日报</h2>
|
||||
<div class="sub-note">日期列为各日收入;DoD=最新日−前一日,DoD%=最新日/前一日−1。波动原因可编辑(暂存本浏览器)。</div>
|
||||
<div class="scroll"><table id="tCustDaily"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>3.2 客户明细 <span class="tag">保留14天</span></h2>
|
||||
<h2>2.2 客户明细 <span class="tag">保留14天</span></h2>
|
||||
<div class="sub-note">日期列为各客户各日收入;DoD=最新日−前一日。</div>
|
||||
<div class="ctrl">
|
||||
<label>客户分类 <select id="deCat"><option value="">全部</option></select></label>
|
||||
<input type="text" id="deAcc" placeholder="筛选客户">
|
||||
@@ -115,6 +91,32 @@
|
||||
<div class="scroll"><table id="tCustDetail"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== PKG 收入波动(板块3) ===== -->
|
||||
<div id="tab-pkg" class="hide">
|
||||
<div class="card">
|
||||
<h2>3.1 PKG 收入波动 - Midas <span class="tag">保留14天</span></h2>
|
||||
<div class="sub-note">|DoD|>100 标注(+绿−红);表头点击排序;波动原因暂存本浏览器。</div>
|
||||
<div class="ctrl">
|
||||
<label><input type="checkbox" class="m-pkg" data-t="midas" checked> 按 pkg</label>
|
||||
<label><input type="checkbox" class="m-acc" data-t="midas"> 按 account</label>
|
||||
<input type="text" class="f-pkg" data-t="midas" placeholder="筛选 pkg">
|
||||
<input type="text" class="f-acc" data-t="midas" placeholder="筛选 account">
|
||||
</div>
|
||||
<div class="scroll"><table id="tPkgMidas"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>3.2 PKG 收入波动 - MS <span class="tag">保留14天</span></h2>
|
||||
<div class="sub-note">|DoD|>100 标注(+绿−红);表头点击排序;波动原因暂存本浏览器。</div>
|
||||
<div class="ctrl">
|
||||
<label><input type="checkbox" class="m-pkg" data-t="ms" checked> 按 pkg</label>
|
||||
<label><input type="checkbox" class="m-acc" data-t="ms"> 按 account</label>
|
||||
<input type="text" class="f-pkg" data-t="ms" placeholder="筛选 pkg">
|
||||
<input type="text" class="f-acc" data-t="ms" placeholder="筛选 account">
|
||||
</div>
|
||||
<div class="scroll"><table id="tPkgMS"><thead></thead><tbody></tbody></table></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -381,44 +383,59 @@ function renderCustDaily(){
|
||||
// ===== 3.2 客户明细 =====
|
||||
var DE_SORT={k:null,ty:'num',dir:'desc'};
|
||||
function renderCustDetail(){
|
||||
var dts=sortedDates(D.cust_detail);
|
||||
var t1=dts[dts.length-1], t2=dts[dts.length-2];
|
||||
var t1list=D.cust_detail[t1]||[];
|
||||
var t2map={};
|
||||
(D.cust_detail[t2]||[]).forEach(function(x){ t2map[x.cat+'||'+x.acc]=x.t1; });
|
||||
var dts=sortedDates(D.cust_detail).slice(-14); // 升序, 最近14天
|
||||
var latest=dts[dts.length-1], prev=dts[dts.length-2];
|
||||
// 按 (cat,acc) 聚合各天收入 + base
|
||||
var map={}; // key -> {cat,acc,base,byDt:{}}
|
||||
dts.forEach(function(dt){
|
||||
(D.cust_detail[dt]||[]).forEach(function(x){
|
||||
var k=x.cat+'||'+x.acc;
|
||||
if(!map[k]) map[k]={cat:x.cat,acc:x.acc,base:x.base,byDt:{}};
|
||||
map[k].byDt[dt]=x.t1;
|
||||
if(x.base!=null) map[k].base=x.base;
|
||||
});
|
||||
});
|
||||
var fCat=(document.getElementById('deCat')||{}).value||'';
|
||||
var fAcc=((document.getElementById('deAcc')||{}).value||'').trim().toLowerCase();
|
||||
var rows=t1list.map(function(r){
|
||||
var prev=t2map[r.cat+'||'+r.acc];
|
||||
return {cat:r.cat,acc:r.acc,base:r.base,t1:r.t1,dod:(prev!=null?r.t1-prev:null)};
|
||||
var rows=Object.keys(map).map(function(k){
|
||||
var r=map[k];
|
||||
var lv=r.byDt[latest], pv=prev?r.byDt[prev]:null;
|
||||
r.dod=(lv!=null&&pv!=null)?lv-pv:(lv!=null?lv:null);
|
||||
r.latest=lv;
|
||||
return r;
|
||||
}).filter(function(r){
|
||||
if(fCat && r.cat!==fCat) return false;
|
||||
if(fAcc && String(r.acc).toLowerCase().indexOf(fAcc)<0) return false;
|
||||
return true;
|
||||
});
|
||||
// 排序
|
||||
if(DE_SORT.k){
|
||||
var dir=DE_SORT.dir==='asc'?1:-1;
|
||||
rows.sort(function(a,b){
|
||||
if(DE_SORT.ty==='str') return dir*String(a[DE_SORT.k]).localeCompare(String(b[DE_SORT.k]));
|
||||
var va=a[DE_SORT.k]==null?-Infinity:a[DE_SORT.k], vb=b[DE_SORT.k]==null?-Infinity:b[DE_SORT.k];
|
||||
var va,vb;
|
||||
if(DE_SORT.k==='cat'||DE_SORT.k==='acc'){ return dir*String(a[DE_SORT.k]).localeCompare(String(b[DE_SORT.k])); }
|
||||
if(DE_SORT.k==='base'){ va=a.base||0; vb=b.base||0; }
|
||||
else if(DE_SORT.k==='dod'){ va=a.dod==null?-Infinity:a.dod; vb=b.dod==null?-Infinity:b.dod; }
|
||||
else { va=a.byDt[DE_SORT.k]==null?-Infinity:a.byDt[DE_SORT.k]; vb=b.byDt[DE_SORT.k]==null?-Infinity:b.byDt[DE_SORT.k]; } // 某日期列
|
||||
return (va<vb?-1:va>vb?1:0)*dir;
|
||||
});
|
||||
} else {
|
||||
rows.sort(function(a,b){ return a.cat<b.cat?-1:a.cat>b.cat?1:(b.t1-a.t1); });
|
||||
rows.sort(function(a,b){ return a.cat<b.cat?-1:a.cat>b.cat?1:((b.latest||0)-(a.latest||0)); });
|
||||
}
|
||||
// 动态表头:用实际日期替代 T-1
|
||||
// 动态表头:客户分类 | 客户 | base | 各日期列 | DoD
|
||||
var thead=document.querySelector('#tCustDetail thead');
|
||||
thead.innerHTML='<tr>'
|
||||
+'<th class="txt de-sort" data-k="cat" data-ty="str">客户分类<span class="arw"></span></th>'
|
||||
var th='<tr><th class="txt de-sort" data-k="cat" data-ty="str">客户分类<span class="arw"></span></th>'
|
||||
+'<th class="txt de-sort" data-k="acc" data-ty="str">客户<span class="arw"></span></th>'
|
||||
+'<th class="de-sort" data-k="base" data-ty="num">base收入<span class="arw"></span></th>'
|
||||
+'<th class="de-sort" data-k="t1" data-ty="num">'+(t1||'—')+'收入<span class="arw"></span></th>'
|
||||
+'<th class="de-sort" data-k="dod" data-ty="num">DoD('+(t1||'—')+'−'+(t2||'—')+')<span class="arw"></span></th>'
|
||||
+'</tr>';
|
||||
+'<th class="de-sort" data-k="base" data-ty="num">base收入<span class="arw"></span></th>';
|
||||
dts.forEach(function(dt){ th+='<th class="de-sort" data-k="'+dt+'" data-ty="num">'+dt+'<span class="arw"></span></th>'; });
|
||||
th+='<th class="de-sort" data-k="dod" data-ty="num">DoD<span class="arw"></span></th></tr>';
|
||||
thead.innerHTML=th;
|
||||
var body=rows.map(function(r){
|
||||
var s='<tr><td class="txt">'+r.cat+'</td><td class="txt">'+r.acc+'</td><td>'+n2(r.base)+'</td>';
|
||||
dts.forEach(function(dt){ var v=r.byDt[dt]; s+='<td>'+(v==null?'':n2(v))+'</td>'; });
|
||||
var dc=r.dod==null?'':(r.dod>=0?'pos':'neg');
|
||||
return '<tr><td class="txt">'+r.cat+'</td><td class="txt">'+r.acc+'</td><td>'+n2(r.base)+'</td>'
|
||||
+'<td>'+n2(r.t1)+'</td><td class="'+dc+'">'+(r.dod==null?'':n2(r.dod))+'</td></tr>';
|
||||
s+='<td class="'+dc+'">'+(r.dod==null?'':n2(r.dod))+'</td></tr>';
|
||||
return s;
|
||||
}).join('');
|
||||
document.querySelector('#tCustDetail tbody').innerHTML=body;
|
||||
document.querySelectorAll('#tCustDetail th.de-sort').forEach(function(th){
|
||||
|
||||
Reference in New Issue
Block a user