Add LinkName dashboard filter

This commit is contained in:
liuji
2026-10-10 18:14:17 +08:00
parent 73774e6c2e
commit 3a15bb8352
+62 -3
View File
@@ -49,7 +49,9 @@
.filter-group { display: grid; gap: 5px; }
.filter-group > span, .filter-group > label { color: var(--muted); font-size: 13px; }
.filter-group input, .filter-group select { min-height: 36px; padding: 6px 9px; border: 1px solid var(--border); border-radius: 8px; background: #fff; color: var(--text); font: inherit; }
.filter-group select[multiple] { min-width: 220px; min-height: 96px; }
.filter-group select:disabled { background: #f1f4f8; color: var(--muted); }
.filter-help { color: var(--muted); font-size: 12px; }
.range-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.range-button { min-height: 36px; padding: 6px 11px; border: 1px solid var(--border); border-radius: 8px; background: #fff; color: var(--text); cursor: pointer; font: inherit; }
.range-button:hover, .range-button:focus, .range-button[data-active="true"] { border-color: var(--primary); color: var(--primary); }
@@ -123,6 +125,11 @@
<label for="end-date">结束日期</label>
<input id="end-date" type="date">
</div>
<div class="filter-group">
<label for="link-name-select">LinkName</label>
<select id="link-name-select" multiple size="4" disabled aria-describedby="link-name-summary"></select>
<span class="filter-help" id="link-name-summary" aria-live="polite">无可选 LinkName</span>
</div>
<div class="currency-help" id="currency-help"></div>
</div>
<div class="rate-info" id="rate-info">
@@ -188,6 +195,8 @@
currencyHelp: document.getElementById('currency-help'),
startDate: document.getElementById('start-date'),
endDate: document.getElementById('end-date'),
linkName: document.getElementById('link-name-select'),
linkNameSummary: document.getElementById('link-name-summary'),
rangeButtons: Array.from(document.querySelectorAll('[data-range]')),
rateStatus: document.getElementById('rate-status'),
metrics: document.getElementById('metrics'),
@@ -213,7 +222,8 @@
dateOnlyRows: 0,
invalidCurrencyRows: 0,
syncLog: null,
syncLogUnavailable: false
syncLogUnavailable: false,
selectedLinkNames: new Set()
};
function setStatus(message, status) {
@@ -414,6 +424,43 @@
return { start: start.time, end: end.time };
}
function updateLinkNameSummary() {
var total = elements.linkName.options.length;
var selected = elements.linkName.selectedOptions.length;
if (!total) {
elements.linkNameSummary.textContent = '无可选 LinkName';
} else if (selected === total) {
elements.linkNameSummary.textContent = '全部 LinkName(' + formatNumber(total) + ')';
} else {
elements.linkNameSummary.textContent = '已选 ' + formatNumber(selected) + ' / ' + formatNumber(total) + ' 个 LinkName';
}
}
function updateLinkNameOptions() {
var available = [];
try {
var range = currentRange();
available = Array.from(new Set(state.rawRecords.filter(function (record) {
return record.date.time >= range.start && record.date.time <= range.end;
}).map(function (record) { return record.linkName; }))).sort(function (a, b) {
return a.localeCompare(b);
});
} catch (error) {
available = [];
}
elements.linkName.replaceChildren();
available.forEach(function (linkName) {
var option = document.createElement('option');
option.value = linkName;
option.textContent = linkName;
option.selected = true;
elements.linkName.appendChild(option);
});
state.selectedLinkNames = new Set(available);
elements.linkName.disabled = available.length === 0;
updateLinkNameSummary();
}
function needsRates() {
return state.rawRecords.some(function (record) { return record.currency !== state.selectedCurrency; });
}
@@ -599,7 +646,9 @@
setStatus(needsRates() ? '正在准备汇率与图表…' : '正在准备图表…', 'loading');
convertedRecords().then(function (records) {
if (token !== renderToken) return;
var filtered = records.filter(function (record) { return record.date.time >= range.start && record.date.time <= range.end; });
var filtered = records.filter(function (record) {
return record.date.time >= range.start && record.date.time <= range.end && state.selectedLinkNames.has(record.linkName);
});
updateSummary(filtered);
elements.error.hidden = true;
elements.metrics.hidden = false;
@@ -637,6 +686,7 @@
elements.filters.hidden = false;
updateCurrencyOptions();
updateRangeInputs();
updateLinkNameOptions();
if (!state.rawRecords.length) { showEmpty('没有可展示的有效数据。'); return; }
renderCurrentView();
}).catch(showError);
@@ -646,16 +696,25 @@
state.selectedCurrency = elements.currency.value;
renderCurrentView();
});
elements.linkName.addEventListener('change', function () {
state.selectedLinkNames = new Set(Array.from(elements.linkName.selectedOptions).map(function (option) {
return option.value;
}));
updateLinkNameSummary();
renderCurrentView();
});
elements.startDate.addEventListener('change', function () {
elements.rangeButtons.forEach(function (button) { button.dataset.active = 'false'; });
updateLinkNameOptions();
renderCurrentView();
});
elements.endDate.addEventListener('change', function () {
elements.rangeButtons.forEach(function (button) { button.dataset.active = 'false'; });
updateLinkNameOptions();
renderCurrentView();
});
elements.rangeButtons.forEach(function (button) {
button.addEventListener('click', function () { setRange(button.dataset.range); renderCurrentView(); });
button.addEventListener('click', function () { setRange(button.dataset.range); updateLinkNameOptions(); renderCurrentView(); });
});
window.addEventListener('resize', function () { charts.forEach(function (chart) { chart.resize(); }); });
loadData();