perf: 并行加载首页统计数据

将原来顺序执行的4个API调用改为并行执行(Promise.all),
显著减少首页加载时间。同时提取了渲染函数 renderWeeklyChart、
renderBossRankingPreview、renderPartnerRankingPreview,提高代码复用性。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lizhilun
2026-03-18 09:45:36 +08:00
co-authored by Claude Opus 4.6
parent 4656f3f9ca
commit a03e92d437
+47 -11
View File
@@ -1,8 +1,15 @@
async function loadStats() { async function loadStats() {
try { try {
const res = await fetch(API + '/api/stats/monthly?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }); // 并行加载所有数据
if (!res.ok) return; const [monthlyRes, bossRankRes, partnerRankRes, weeklyRes] = await Promise.all([
const s = await res.json(); fetch(API + '/api/stats/monthly?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }),
fetch(API + '/api/stats/boss-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }),
fetch(API + '/api/stats/partner-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }),
fetch(API + '/api/stats/daily-income', { headers: headers() })
]);
if (monthlyRes.ok) {
const s = await monthlyRes.json();
document.getElementById('takeCount').textContent = s.take_order_count; document.getElementById('takeCount').textContent = s.take_order_count;
document.getElementById('dispatchCount').textContent = s.dispatch_order_count; document.getElementById('dispatchCount').textContent = s.dispatch_order_count;
document.getElementById('takeIncome').textContent = '' + s.take_order_income.toFixed(2); document.getElementById('takeIncome').textContent = '' + s.take_order_income.toFixed(2);
@@ -14,9 +21,22 @@ async function loadStats() {
document.getElementById('totalIncome').textContent = '' + s.total_income.toFixed(2); document.getElementById('totalIncome').textContent = '' + s.total_income.toFixed(2);
document.getElementById('totalExpense').textContent = '' + s.total_expense.toFixed(2); document.getElementById('totalExpense').textContent = '' + s.total_expense.toFixed(2);
document.getElementById('netIncome').textContent = '' + (s.total_income - s.total_expense).toFixed(2); document.getElementById('netIncome').textContent = '' + (s.total_income - s.total_expense).toFixed(2);
loadBossRankingPreview(); }
loadPartnerRankingPreview();
loadWeeklyChart(); if (bossRankRes.ok) {
const data = await bossRankRes.json();
renderBossRankingPreview(data.rows || []);
}
if (partnerRankRes.ok) {
const data = await partnerRankRes.json();
renderPartnerRankingPreview(data.rows || []);
}
if (weeklyRes.ok) {
const days = await weeklyRes.json();
renderWeeklyChart(days);
}
} catch (e) { console.error(e); } } catch (e) { console.error(e); }
} }
@@ -25,7 +45,16 @@ async function loadWeeklyChart() {
const res = await fetch(API + '/api/stats/daily-income', { headers: headers() }); const res = await fetch(API + '/api/stats/daily-income', { headers: headers() });
if (!res.ok) return; if (!res.ok) return;
const days = await res.json(); const days = await res.json();
renderWeeklyChart(days);
} catch (e) { console.error(e); }
}
function renderWeeklyChart(days) {
const container = document.getElementById('weeklyChartBars'); const container = document.getElementById('weeklyChartBars');
if (!days || days.length === 0) {
container.innerHTML = '<div class="ranking-empty">暂无数据</div>';
return;
}
const max = Math.max(...days.map(d => d.income), 1); const max = Math.max(...days.map(d => d.income), 1);
container.innerHTML = days.map(d => { container.innerHTML = days.map(d => {
const pct = Math.max((d.income / max) * 100, 3); const pct = Math.max((d.income / max) * 100, 3);
@@ -37,7 +66,6 @@ async function loadWeeklyChart() {
<span class="weekly-bar-date">${label}</span> <span class="weekly-bar-date">${label}</span>
</div>`; </div>`;
}).join(''); }).join('');
} catch (e) { console.error(e); }
} }
let currentDailyDate = ''; let currentDailyDate = '';
@@ -232,8 +260,13 @@ async function loadBossRankingPreview() {
const res = await fetch(API + '/api/stats/boss-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }); const res = await fetch(API + '/api/stats/boss-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() });
if (!res.ok) return; if (!res.ok) return;
const rows = await res.json(); const rows = await res.json();
renderBossRankingPreview(rows);
} catch (e) { console.error(e); }
}
function renderBossRankingPreview(rows) {
const container = document.getElementById('rankingPreviewList'); const container = document.getElementById('rankingPreviewList');
if (rows.length === 0) { if (!rows || rows.length === 0) {
container.innerHTML = '<div class="ranking-empty">暂无数据</div>'; container.innerHTML = '<div class="ranking-empty">暂无数据</div>';
return; return;
} }
@@ -247,7 +280,6 @@ async function loadBossRankingPreview() {
<div class="hbar-value">${r.total_income.toFixed(2)}</div> <div class="hbar-value">${r.total_income.toFixed(2)}</div>
</div>`; </div>`;
}).join(''); }).join('');
} catch (e) { console.error(e); }
} }
let currentBossName = ''; let currentBossName = '';
@@ -326,8 +358,13 @@ async function loadPartnerRankingPreview() {
const res = await fetch(API + '/api/stats/partner-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() }); const res = await fetch(API + '/api/stats/partner-ranking/preview?year=' + currentYear + '&month=' + currentMonth, { headers: headers() });
if (!res.ok) return; if (!res.ok) return;
const rows = await res.json(); const rows = await res.json();
renderPartnerRankingPreview(rows);
} catch (e) { console.error(e); }
}
function renderPartnerRankingPreview(rows) {
const container = document.getElementById('partnerRankingPreviewList'); const container = document.getElementById('partnerRankingPreviewList');
if (rows.length === 0) { if (!rows || rows.length === 0) {
container.innerHTML = '<div class="ranking-empty">暂无数据</div>'; container.innerHTML = '<div class="ranking-empty">暂无数据</div>';
return; return;
} }
@@ -341,7 +378,6 @@ async function loadPartnerRankingPreview() {
<div class="hbar-value">${r.dispatch_count}单</div> <div class="hbar-value">${r.dispatch_count}单</div>
</div>`; </div>`;
}).join(''); }).join('');
} catch (e) { console.error(e); }
} }
function openPartnerRankingPage() { function openPartnerRankingPage() {