perf: load dashboard data by date range
This commit is contained in:
+6
-3
@@ -27,7 +27,8 @@ body{font:14px system-ui,sans-serif;margin:2rem;color:#223}label{margin-right:1r
|
||||
<script>
|
||||
(() => {"use strict";
|
||||
const columns=["dt","attr_platform","pkg_name","shareit_clicks","af_clicks","installs_ua","clicks_diff","clicks_diff_rate"];
|
||||
const pageSize=200;let rows=[],failed=[],page=1,sort={key:"dt",direction:-1};
|
||||
const pageSize=200,maxConcurrent=6;let rows=[],failed=[],page=1,sort={key:"dt",direction:-1},files=[],loadVersion=0;
|
||||
const dataCache=new Map();
|
||||
const $=id=>document.getElementById(id),status=$("status");
|
||||
function text(value){return value===null||value===undefined?"—":String(value)}
|
||||
function validDate(value){return /^\d{4}-\d{2}-\d{2}$/.test(value)&&!Number.isNaN(Date.parse(value))}
|
||||
@@ -49,7 +50,9 @@ function setupHeaders(){const header=$("head");header.replaceChildren();columns.
|
||||
function resetPage(){page=1;show()}
|
||||
function setDefaultDates(){const yesterday=new Date();yesterday.setDate(yesterday.getDate()-1);const date=localDate(yesterday);$("start").value=date;$("end").value=date}
|
||||
function downloadRaw(){const blob=new Blob([JSON.stringify(rows,null,2)],{type:"application/json;charset=utf-8"}),url=URL.createObjectURL(blob),link=document.createElement("a"),stamp=new Date().toISOString().replaceAll(/[:.]/g,"-");link.href=url;link.download=`af-click-gap-raw-${stamp}.json`;link.click();URL.revokeObjectURL(url)}
|
||||
async function load(){setupHeaders();try{const response=await fetch("data/index.json",{cache:"no-store"});if(!response.ok)throw Error("index.json 加载失败");const index=await response.json();if(!Array.isArray(index.files))throw Error("数据清单格式错误");const safe=index.files.filter(file=>/^\d{8}$/.test(file.date)&&file.path===`data/${file.date}.json`);failed=safe.length===index.files.length?[]:["清单路径"];const loaded=await Promise.all(safe.map(async file=>{try{const response=await fetch(file.path,{cache:"no-store"});if(!response.ok)throw Error("HTTP");const data=await response.json();if(!Array.isArray(data)||data.some(row=>!row||typeof row!=="object"||row.dt!==file.date))throw Error("格式");return data}catch(error){failed.push(file.date);return []}}));rows=loaded.flat();setDefaultDates();renderPackageOptions();$("pkgTrigger").textContent=packageLabel();if(rows.length)show();else{status.textContent="暂无数据。";updatePagination(0)}}catch(error){status.textContent=`无法加载数据:${error.message}`;status.className="status error"}}
|
||||
$("pkgTrigger").addEventListener("click",()=>$("pkgPanel").hidden?openPackages():closePackages());$("pkgSearch").addEventListener("input",renderPackageOptions);$("selectAllPkg").addEventListener("click",()=>{[...new Set(rows.map(row=>row.pkg_name).filter(Boolean))].forEach(pkg=>draftPackages.add(pkg));renderPackageOptions()});$("clearPkg").addEventListener("click",()=>{draftPackages.clear();renderPackageOptions()});$("confirmPkg").addEventListener("click",()=>{appliedPackages=new Set(draftPackages);$("pkgTrigger").textContent=packageLabel();closePackages();resetPage()});document.addEventListener("click",event=>{if(!$("pkgFilter").contains(event.target)&&!$("pkgPanel").hidden)closePackages()});document.addEventListener("keydown",event=>{if(event.key==="Escape"&&!$("pkgPanel").hidden)closePackages()});$("apply").addEventListener("click",resetPage);$("start").addEventListener("change",resetPage);$("end").addEventListener("change",resetPage);$("reset").addEventListener("click",()=>{if(rows.length){appliedPackages.clear();$("pkgTrigger").textContent=packageLabel();setDefaultDates();resetPage()}});$("previous").addEventListener("click",()=>{if(page>1){page--;show()}});$("next").addEventListener("click",()=>{if(page<Math.ceil(filteredRows().length/pageSize)){page++;show()}});$("download").addEventListener("click",downloadRaw);load();
|
||||
async function fetchDate(file){if(dataCache.has(file.path))return {date:file.date,data:dataCache.get(file.path)};try{const response=await fetch(file.path,{cache:"no-store"});if(!response.ok)throw Error("HTTP");const data=await response.json();if(!Array.isArray(data)||data.some(row=>!row||typeof row!=="object"||row.dt!==file.date))throw Error("格式");dataCache.set(file.path,data);return {date:file.date,data}}catch(error){return {date:file.date,data:null}}}
|
||||
async function loadRange(){const version=++loadVersion,start=$("start").value,end=$("end").value;if(!validDate(start)||!validDate(end)||start>end){show();return}const selected=files.filter(file=>file.date>=date8(start)&&file.date<=date8(end));rows=[];failed=[];page=1;status.textContent=selected.length?`正在加载 ${selected.length} 个日期文件…`:`所选日期范围暂无数据文件。`;status.className="status";if(!selected.length){renderPackageOptions();show();return}for(let offset=0;offset<selected.length;offset+=maxConcurrent){const batch=selected.slice(offset,offset+maxConcurrent),loaded=await Promise.all(batch.map(fetchDate));if(version!==loadVersion)return;loaded.forEach(item=>{if(item.data)rows.push(...item.data);else failed.push(item.date)});renderPackageOptions();$("pkgTrigger").textContent=packageLabel();show();if(offset+batch.length<selected.length)status.textContent=`已加载 ${Math.min(offset+batch.length,selected.length)} / ${selected.length} 个日期文件…`}if(failed.length)status.textContent=`数据不完整:跳过 ${failed.length} 个文件。 ${status.textContent}`}
|
||||
async function load(){setupHeaders();setDefaultDates();try{const response=await fetch("data/index.json",{cache:"no-store"});if(!response.ok)throw Error("index.json 加载失败");const index=await response.json();if(!Array.isArray(index.files))throw Error("数据清单格式错误");files=index.files.filter(file=>/^\d{8}$/.test(file.date)&&file.path===`data/${file.date}.json`);await loadRange()}catch(error){status.textContent=`无法加载数据:${error.message}`;status.className="status error"}}
|
||||
$("pkgTrigger").addEventListener("click",()=>$("pkgPanel").hidden?openPackages():closePackages());$("pkgSearch").addEventListener("input",renderPackageOptions);$("selectAllPkg").addEventListener("click",()=>{[...new Set(rows.map(row=>row.pkg_name).filter(Boolean))].forEach(pkg=>draftPackages.add(pkg));renderPackageOptions()});$("clearPkg").addEventListener("click",()=>{draftPackages.clear();renderPackageOptions()});$("confirmPkg").addEventListener("click",()=>{appliedPackages=new Set(draftPackages);$("pkgTrigger").textContent=packageLabel();closePackages();resetPage()});document.addEventListener("click",event=>{if(!$("pkgFilter").contains(event.target)&&!$("pkgPanel").hidden)closePackages()});document.addEventListener("keydown",event=>{if(event.key==="Escape"&&!$("pkgPanel").hidden)closePackages()});$("apply").addEventListener("click",loadRange);$("start").addEventListener("change",loadRange);$("end").addEventListener("change",loadRange);$("reset").addEventListener("click",()=>{appliedPackages.clear();$("pkgTrigger").textContent=packageLabel();setDefaultDates();loadRange()});$("previous").addEventListener("click",()=>{if(page>1){page--;show()}});$("next").addEventListener("click",()=>{if(page<Math.ceil(filteredRows().length/pageSize)){page++;show()}});$("download").addEventListener("click",downloadRaw);load();
|
||||
})();
|
||||
</script></body></html>
|
||||
|
||||
Reference in New Issue
Block a user