perf: 收斂商品看板前端事件與圖表載入
All checks were successful
CD Pipeline / deploy (push) Successful in 1m2s

This commit is contained in:
OoO
2026-05-18 10:29:01 +08:00
parent 4e71ed9ecd
commit d1ff323e50
4 changed files with 71 additions and 34 deletions

View File

@@ -389,6 +389,13 @@
flex-wrap: wrap;
}
.dashboard-section-index {
color: var(--momo-text-tertiary);
font-size: 11px;
font-weight: 800;
letter-spacing: 0.08em;
}
.dashboard-table-title {
color: var(--momo-text-primary);
font-size: 14px;
@@ -596,6 +603,14 @@
font-size: 10px;
}
.dashboard-muted {
color: var(--momo-text-tertiary);
}
.dashboard-table-time {
color: var(--momo-text-secondary);
}
.dashboard-pchome-price {
color: var(--momo-accent-strong);
font-size: 16px;

View File

@@ -30,17 +30,27 @@ let priceChartInstance = null;
}
function ensureDashboardChart() {
if (window.EwoooCChartTheme && window.EwoooCChartTheme.loadChartJs) {
return window.EwoooCChartTheme.loadChartJs();
}
if (typeof Chart !== 'undefined') {
return Promise.resolve();
return Promise.resolve(window.Chart);
}
if (dashboardChartLoader) {
return dashboardChartLoader;
}
dashboardChartLoader = new Promise((resolve, reject) => {
const existing = document.querySelector('script[data-chartjs-loader="dashboard"]');
if (existing) {
existing.addEventListener('load', () => resolve(window.Chart), { once: true });
existing.addEventListener('error', () => reject(new Error('Chart.js 載入失敗')), { once: true });
return;
}
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/chart.js';
script.src = 'https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js';
script.async = true;
script.onload = resolve;
script.dataset.chartjsLoader = 'dashboard';
script.onload = () => resolve(window.Chart);
script.onerror = () => reject(new Error('Chart.js 載入失敗'));
document.head.appendChild(script);
});
@@ -235,29 +245,40 @@ let priceChartInstance = null;
});
});
function triggerTask() {
if (confirm('確定要手動執行全站爬蟲嗎?可能需要一段時間。')) {
fetch('/api/run_task', {
method: 'POST',
headers: { 'X-CSRFToken': getCSRFToken() }
})
.then(response => response.json())
.then(data => alert(data.message))
.catch(error => alert('錯誤: ' + error));
document.querySelectorAll('[data-dashboard-auto-submit]').forEach(select => {
select.addEventListener('change', () => {
if (select.form) {
select.form.submit();
}
});
});
const dashboardTaskMap = {
crawler: {
confirmText: '確定要手動執行全站爬蟲嗎?可能需要一段時間。',
url: '/api/run_task'
},
notification: {
confirmText: '確定要發送今日商品異動通知嗎?',
url: '/api/trigger_momo_notification'
}
};
function runDashboardTask(taskName) {
const task = dashboardTaskMap[taskName];
if (!task || !confirm(task.confirmText)) return;
fetch(task.url, {
method: 'POST',
headers: { 'X-CSRFToken': getCSRFToken() }
})
.then(response => response.json())
.then(data => alert(data.message))
.catch(error => alert('錯誤: ' + error));
}
function triggerNotification() {
if (confirm('確定要發送今日商品異動通知嗎?')) {
fetch('/api/trigger_momo_notification', {
method: 'POST',
headers: { 'X-CSRFToken': getCSRFToken() }
})
.then(response => response.json())
.then(data => alert(data.message))
.catch(error => alert('錯誤: ' + error));
}
}
document.querySelectorAll('[data-dashboard-task]').forEach(button => {
button.addEventListener('click', () => runDashboardTask(button.dataset.dashboardTask));
});
function trackMomoLinkClick(event) {
const link = event.target.closest('.momo-tracked-link');