diff --git a/index.html b/index.html index d0ab1d9..335294b 100755 --- a/index.html +++ b/index.html @@ -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 @@ +
+ + + 无可选 LinkName +
@@ -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();