diff --git a/css/pages/stats.css b/css/pages/stats.css index 978c577..9d0e9ab 100644 --- a/css/pages/stats.css +++ b/css/pages/stats.css @@ -418,32 +418,128 @@ display: block; } +/* Item count badge in accordion header */ +.accordion-header .item-count { + font-size: 11px; + font-weight: 500; + color: var(--text-secondary); + background: var(--bg-color); + padding: 2px 8px; + border-radius: 10px; + margin-left: 8px; +} + +.accordion-header.active .item-count { + background: rgba(0, 113, 227, 0.08); + color: var(--accent-color); +} + +/* Search filter inside accordion content */ +.detail-search-wrapper { + position: relative; + margin-bottom: 12px; +} + +.detail-search-wrapper i { + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + color: #c0c0c0; + font-size: 12px; + pointer-events: none; +} + +.detail-search { + width: 100%; + padding: 8px 12px 8px 30px; + border: 1px solid #eee; + border-radius: 8px; + font-size: 13px; + outline: none; + transition: border-color 0.2s, box-shadow 0.2s; + background: #fafafa; +} + +.detail-search:focus { + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(0, 113, 227, 0.08); + background: white; +} + +.detail-no-results { + text-align: center; + color: var(--text-secondary); + font-size: 13px; + padding: 20px 0; + display: none; +} + /* Grid for stats inside accordion */ .detail-stats-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); - gap: 10px; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 8px; } .detail-stat-item { display: flex; - justify-content: space-between; - font-size: 13px; - padding: 4px 0; - border-bottom: 1px dashed #f5f5f5; + flex-direction: column; + background: #fafafa; + border-radius: 8px; + padding: 10px 12px; + border-left: 3px solid transparent; + transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; + cursor: default; +} + +.detail-stat-item:hover { + background: #f0f4ff; + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); +} + +/* Top 3 ranking indicators */ +.detail-stat-item.rank-1 { + border-left-color: #FFD700; + background: linear-gradient(135deg, #fffdf0, #fafafa); +} + +.detail-stat-item.rank-2 { + border-left-color: #C0C0C0; + background: linear-gradient(135deg, #fafafa, #f8f8f8); +} + +.detail-stat-item.rank-3 { + border-left-color: #CD7F32; + background: linear-gradient(135deg, #fdf8f4, #fafafa); +} + +.detail-stat-item.rank-1:hover, +.detail-stat-item.rank-2:hover, +.detail-stat-item.rank-3:hover { + background: #f0f4ff; +} + +.detail-stat-value { + font-size: 15px; + font-weight: 700; + font-family: 'Inter', monospace; + color: var(--text-primary, #1d1d1f); + line-height: 1.3; } .detail-stat-label { - color: #666; - margin-right: 10px; + font-size: 12px; + color: var(--text-secondary); + margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.detail-stat-value { - font-weight: 600; - font-family: monospace; +.detail-stat-item.hidden { + display: none; } /* Mobile Adjustments */ @@ -456,4 +552,17 @@ .stats-list-container.compact-stats { width: 100%; } + + .detail-stats-grid { + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 6px; + } + + .detail-stat-item { + padding: 8px 10px; + } + + .detail-stat-value { + font-size: 14px; + } } diff --git a/js/stats_script.js b/js/stats_script.js index 2cd9f59..470a4b8 100644 --- a/js/stats_script.js +++ b/js/stats_script.js @@ -275,9 +275,13 @@ function renderDetailsAccordion(statsObj) { return a.localeCompare(b); }); + // Threshold for showing search filter + const SEARCH_THRESHOLD = 20; + sortedKeys.forEach(catKey => { const subStats = statsObj[catKey]; - if (Object.keys(subStats).length === 0) return; + const itemCount = Object.keys(subStats).length; + if (itemCount === 0) return; const catInfo = categoryMap[catKey] || { name: formatKey(catKey), icon: 'fa-folder' }; @@ -285,17 +289,37 @@ function renderDetailsAccordion(statsObj) { const item = document.createElement('div'); item.className = 'accordion-item'; - // Header + // Header with item count badge const header = document.createElement('div'); header.className = 'accordion-header'; header.innerHTML = ` - ${catInfo.name} + ${catInfo.name}${itemCount} `; // Content const content = document.createElement('div'); content.className = 'accordion-content'; + + // Search filter for large categories + let searchInput = null; + let noResults = null; + if (itemCount >= SEARCH_THRESHOLD) { + const searchWrapper = document.createElement('div'); + searchWrapper.className = 'detail-search-wrapper'; + searchWrapper.innerHTML = ''; + searchInput = document.createElement('input'); + searchInput.type = 'text'; + searchInput.className = 'detail-search'; + searchInput.placeholder = '搜索条目...'; + searchWrapper.appendChild(searchInput); + content.appendChild(searchWrapper); + + noResults = document.createElement('div'); + noResults.className = 'detail-no-results'; + noResults.textContent = '没有匹配的条目'; + content.appendChild(noResults); + } // Grid for stats const grid = document.createElement('div'); @@ -304,15 +328,13 @@ function renderDetailsAccordion(statsObj) { // Sort sub-items by value descending const subItems = Object.entries(subStats).sort((a, b) => b[1] - a[1]); - subItems.forEach(([k, v]) => { + subItems.forEach(([k, v], index) => { let label = formatKey(k); let val = v.toLocaleString(); // Special formatting for time/distance in 'custom' if (catKey === 'minecraft:custom') { if (k.includes('time') || k.includes('minute')) { - // ticks to hours/min? - // Assuming 'play_time' is ticks (1/20s) if (k.includes('play_time') || k.includes('time_since')) { const sec = v / 20; if (sec > 3600) val = (sec/3600).toFixed(1) + ' h'; @@ -320,22 +342,44 @@ function renderDetailsAccordion(statsObj) { else val = sec.toFixed(0) + ' s'; } } - if (k.includes('cmt') || k.includes('one_cm')) { // one_cm + if (k.includes('cmt') || k.includes('one_cm')) { const m = v / 100; if (m > 1000) val = (m/1000).toFixed(2) + ' km'; else val = m.toFixed(1) + ' m'; } } + // Rank class for top 3 + let rankClass = ''; + if (index === 0) rankClass = ' rank-1'; + else if (index === 1) rankClass = ' rank-2'; + else if (index === 2) rankClass = ' rank-3'; + const statDiv = document.createElement('div'); - statDiv.className = 'detail-stat-item'; + statDiv.className = 'detail-stat-item' + rankClass; + statDiv.dataset.label = label.toLowerCase(); statDiv.innerHTML = ` - ${label} ${val} + ${label} `; grid.appendChild(statDiv); }); + // Wire up search filter + if (searchInput) { + searchInput.addEventListener('input', () => { + const query = searchInput.value.toLowerCase().trim(); + const items = grid.querySelectorAll('.detail-stat-item'); + let visible = 0; + items.forEach(el => { + const match = !query || el.dataset.label.includes(query); + el.classList.toggle('hidden', !match); + if (match) visible++; + }); + noResults.style.display = visible === 0 ? 'block' : 'none'; + }); + } + content.appendChild(grid); item.appendChild(header); item.appendChild(content);