Add LinkName dashboard filter
This commit is contained in:
+62
-3
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user