分类条目数量对比
-比较各主题在当前热榜中的条目数量,识别内容分布重心。
+分类条目分布
+按主题统计上榜条目数量,呈现当前热榜内容覆盖结构。
分类总热度对比
-按主题汇总热度,突出最高热度类目,辅助快速研判舆论集中点。
+分类热度分布
+按主题汇总热度规模,突出当前热榜关注度集中方向。
diff --git a/frontend/zhihu-hotlist-echarts.html b/frontend/zhihu-hotlist-echarts.html index 1a56b4b..bbe0885 100644 --- a/frontend/zhihu-hotlist-echarts.html +++ b/frontend/zhihu-hotlist-echarts.html @@ -171,7 +171,8 @@ height: 100vh; padding: 20px 24px 14px; display: grid; - grid-template-rows: 88px 120px 380px minmax(0, 1fr) 44px; + /* V2 height contract: header / KPI / charts / table / footer */ + grid-template-rows: 92px 140px 380px minmax(0, 1fr) 44px; gap: 14px; } @@ -215,7 +216,7 @@ .screen-header { display: grid; - grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr); + grid-template-columns: minmax(0, 1.35fr) minmax(420px, 1.15fr); gap: 18px; align-items: center; padding: 0 24px; @@ -272,26 +273,115 @@ min-width: 0; } - .header-meta { + .header-chip-row { display: flex; - align-items: center; + align-items: stretch; justify-content: flex-end; - flex-wrap: wrap; - gap: 10px 18px; - font-size: 12px; - color: var(--muted); + flex-wrap: nowrap; + gap: 14px; + width: 100%; + min-width: 0; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + scrollbar-gutter: stable both-edges; + padding-bottom: 4px; } - .header-meta strong { + /* Ensure horizontal scroll works (no forced shrink-to-fit that overflows header). */ + .header-chip-row > * { + flex: 0 0 auto; + min-width: 0; + } + + .chip-group { + display: flex; + align-items: stretch; + gap: 10px; + min-width: 0; + } + + .chip-group-meta { + flex: 1 1 auto; + justify-content: flex-end; + min-width: max-content; + } + + .chip-group-actions { + flex: 0 0 auto; + justify-content: flex-end; + min-width: max-content; + } + + .meta-chip { + display: inline-flex; + align-items: center; + gap: 8px; + min-height: 52px; + padding: 10px 14px; + border-radius: 14px; + border: 1px solid rgba(255, 255, 255, 0.1); + color: var(--muted); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.075) 0%, rgba(255, 255, 255, 0.035) 100%); + font-size: 12px; + min-width: 0; + max-width: 100%; + flex: 0 1 auto; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); + } + + .meta-chip strong { color: var(--text); font-weight: 600; + font-family: var(--font-number); + letter-spacing: 0.02em; + } + + .meta-chip.status-chip { + border-color: rgba(116, 198, 157, 0.32); + color: rgba(234, 244, 255, 0.92); + background: linear-gradient(180deg, rgba(116, 198, 157, 0.16) 0%, rgba(116, 198, 157, 0.08) 100%); + } + + .meta-chip.status-chip strong { + color: var(--success); + font-family: var(--font-main); + letter-spacing: 0; + } + + .status-dot { + width: 9px; + height: 9px; + border-radius: 50%; + background: var(--success); + box-shadow: 0 0 0 4px rgba(116, 198, 157, 0.12), 0 0 10px rgba(116, 198, 157, 0.28); + flex: 0 0 auto; + } + + .meta-chip.action-chip { + padding: 8px 12px; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.065) 0%, rgba(255, 255, 255, 0.028) 100%); + } + + .meta-chip.action-chip .theme-switcher { + gap: 8px; + } + + #snapshotId { + display: inline-block; + min-width: 0; + max-width: 18ch; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } .theme-switcher { display: flex; - flex-wrap: wrap; + flex-wrap: nowrap; justify-content: flex-end; gap: 10px; + min-width: max-content; } .theme-btn, @@ -354,30 +444,99 @@ outline-offset: 2px; } - .kpi-row { + /* + KPI track is fixed (140px) in the V2 screen grid contract, so the KPI layout + must be deterministic and never wrap. + + Spec: 2 large + 3 small cards in one row. + We use a 5-column grid where the first two columns are wider. + */ + .kpi-grid { display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-template-columns: 2fr 2fr 1.2fr 1.2fr 1.2fr; gap: 14px; + align-items: stretch; } .kpi-card { border-radius: 16px; padding: 18px 20px; display: grid; - gap: 8px; + grid-template-columns: minmax(0, 1fr) auto; + grid-template-rows: auto auto auto; + gap: 8px 12px; + min-width: 0; + grid-column: auto; + align-content: start; + } + + /* V2 KPI tiers (kept for typography differences, not layout spans). */ + .kpi-card.kpi-card-large { + min-height: 124px; + align-content: center; + } + + .kpi-card.kpi-card-small { + min-height: 0; + } + + .kpi-label, + .kpi-sub, + .kpi-value { + grid-column: 1 / 2; min-width: 0; } - .kpi-label { - font-size: 12px; + .kpi-badge-slot { + grid-column: 2 / 3; + grid-row: 1 / 2; + justify-self: end; + align-self: start; + min-width: 0; + min-height: 28px; + display: inline-flex; + align-items: center; + justify-content: flex-end; + } + + .kpi-badge { + display: inline-flex; + align-items: center; + gap: 6px; + max-width: 120px; + min-height: 28px; + padding: 0 10px; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(255, 255, 255, 0.05); + color: var(--text); + font-size: 11px; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .kpi-badge.is-muted { color: var(--muted); - letter-spacing: 0.14em; - text-transform: uppercase; + } + + .kpi-badge.has-tone { + border-color: currentColor; + background: transparent; + } + + .kpi-badge-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex: 0 0 auto; + box-shadow: 0 0 10px currentColor; } .kpi-value { font-family: var(--font-number); - font-size: clamp(24px, 2.3vw, 34px); + font-size: clamp(20px, 2vw, 24px); line-height: 1.15; font-weight: 700; color: var(--text); @@ -386,8 +545,18 @@ text-overflow: ellipsis; } - .kpi-value.long { - font-size: clamp(18px, 1.45vw, 24px); + .kpi-card.kpi-card-large .kpi-value { + font-size: clamp(30px, 2.6vw, 36px); + } + + /* 最高热话题:2-line clamp */ + .kpi-card.kpi-card-small .kpi-value.long { + font-size: clamp(20px, 1.75vw, 24px); + white-space: normal; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; } .kpi-sub { @@ -398,6 +567,15 @@ text-overflow: ellipsis; } + .kpi-label { + font-size: 12px; + color: var(--muted); + letter-spacing: 0.14em; + text-transform: uppercase; + } + + /* KPI typography handled by V2 tier rules above. */ + .kpi-status-normal { color: var(--success); } .kpi-status-warning { color: var(--warning); } .kpi-status-danger { color: var(--danger); } @@ -416,17 +594,65 @@ } .panel-head { + position: relative; display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; - margin-bottom: 12px; + margin-bottom: 14px; + padding: 0 0 14px 14px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .panel-head::before { + content: ""; + position: absolute; + left: 0; + top: 2px; + width: 4px; + height: 22px; + border-radius: 999px; + background: linear-gradient(180deg, var(--accent) 0%, var(--accent-2) 100%); + opacity: 0.9; + } + + .panel-head::after { + content: ""; + position: absolute; + right: 0; + top: 0; + width: 84px; + height: 24px; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.06); + background: rgba(255, 255, 255, 0.025); + opacity: 0.85; + pointer-events: none; } .panel-title-wrap { min-width: 0; } + .panel-kicker { + display: inline-flex; + align-items: center; + gap: 8px; + margin-bottom: 6px; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--accent); + } + + .panel-kicker::before { + content: ""; + width: 22px; + height: 1px; + background: linear-gradient(90deg, var(--accent) 0%, rgba(216, 179, 106, 0.08) 100%); + } + .panel-title { margin: 0; font-size: 20px; @@ -461,10 +687,23 @@ } .insight-section { - border: 1px solid rgba(255, 255, 255, 0.06); - background: rgba(255, 255, 255, 0.03); + position: relative; + border: 1px solid rgba(255, 255, 255, 0.07); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.045) 0%, rgba(255, 255, 255, 0.025) 100%); border-radius: 14px; - padding: 14px; + padding: 14px 14px 14px 16px; + } + + .insight-section::before { + content: ""; + position: absolute; + left: 0; + top: 14px; + bottom: 14px; + width: 3px; + border-radius: 999px; + background: linear-gradient(180deg, var(--accent) 0%, rgba(255, 255, 255, 0.1) 100%); + opacity: 0.9; } .insight-section h3 { @@ -538,7 +777,7 @@ height: 6px; border-radius: 50%; background: var(--accent-2); - box-shadow: 0 0 8px rgba(62, 199, 255, 0.35); + box-shadow: none; } .insight-empty, @@ -564,23 +803,28 @@ .category-pills { display: flex; - flex-wrap: wrap; - gap: 8px; + flex-wrap: nowrap; + gap: 10px; + overflow-x: auto; + overflow-y: hidden; + padding-bottom: 4px; + scrollbar-width: thin; } .category-pill, .category-tag { display: inline-flex; align-items: center; - gap: 8px; - min-width: 0; - border-radius: 999px; - padding: 6px 12px; + gap: 10px; + min-width: max-content; + border-radius: 14px; + padding: 10px 14px; font-size: 12px; font-weight: 600; color: var(--text); background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.08); + white-space: nowrap; } .swatch { @@ -588,21 +832,23 @@ height: 10px; border-radius: 50%; flex: 0 0 auto; - box-shadow: 0 0 10px currentColor; + box-shadow: none; } .table-wrap { min-height: 0; overflow: auto; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.09); background: rgba(2, 10, 22, 0.24); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03); } table { width: 100%; min-width: 1020px; - border-collapse: collapse; + border-collapse: separate; + border-spacing: 0; } thead th { @@ -614,10 +860,11 @@ font-size: 12px; color: var(--muted); background: var(--table-header); - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid rgba(255, 255, 255, 0.1); letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap; + backdrop-filter: blur(10px); } tbody td { @@ -631,9 +878,10 @@ background: rgba(255, 255, 255, 0.03); } - tbody tr.top-1 { background: rgba(255, 215, 128, 0.06); } - tbody tr.top-2 { background: rgba(207, 219, 232, 0.05); } - tbody tr.top-3 { background: rgba(201, 145, 89, 0.05); } + /* weak highlight for Top3 only */ + tbody tr.top-1 { background: rgba(255, 215, 128, 0.038); } + tbody tr.top-2 { background: rgba(207, 219, 232, 0.032); } + tbody tr.top-3 { background: rgba(201, 145, 89, 0.032); } .rank-badge { display: inline-flex; @@ -705,6 +953,12 @@ color: var(--muted); } + #footerNote { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .footer-meta { display: flex; gap: 18px; @@ -811,9 +1065,18 @@ } @media (max-width: 1600px) { + body { + height: auto; + min-height: 100%; + overflow-y: auto; + } + .screen { + height: auto; + min-height: 1080px; padding: 16px; gap: 12px; + grid-template-rows: auto auto auto auto auto; } .screen-header { @@ -826,12 +1089,31 @@ justify-items: start; } - .theme-switcher, - .header-meta { + .header-chip-row { + flex-wrap: wrap; + } + + .chip-group { + flex-wrap: wrap; + } + + .header-chip-row, + .chip-group-meta, + .chip-group-actions, + .theme-switcher { justify-content: flex-start; } - .kpi-row, + .kpi-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .kpi-card, + .kpi-card.kpi-card-large, + .kpi-card.kpi-card-small { + grid-column: auto; + } + .main-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } @@ -841,11 +1123,11 @@ } } - @media (max-width: 1280px), (max-height: 900px) { + @media (max-height: 900px) { body { height: auto; min-height: 100%; - overflow: auto; + overflow-y: auto; } .screen { @@ -853,11 +1135,19 @@ min-height: 1080px; grid-template-rows: auto auto auto auto auto; } + } - .kpi-row { + @media (max-width: 1280px), (max-height: 900px) { + .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .kpi-card, + .kpi-card.kpi-card-large, + .kpi-card.kpi-card-small { + grid-column: span 1; + } + .main-grid { grid-template-columns: 1fr; } @@ -878,10 +1168,16 @@ padding: 12px; } - .kpi-row { + .kpi-grid { grid-template-columns: 1fr; } + .kpi-card, + .kpi-card.kpi-card-large, + .kpi-card.kpi-card-small { + grid-column: span 1; + } + .header-title { font-size: 28px; } @@ -895,7 +1191,8 @@ .drawer-actions, .theme-switcher, .footer-meta, - .header-meta { + .header-chip-row, + .chip-group { gap: 8px; } } @@ -910,29 +1207,52 @@
基于知乎热榜快照,按主题分类汇总热度与互动指标,适配国企汇报场景的一页式监测大屏。
比较各主题在当前热榜中的条目数量,识别内容分布重心。
+按主题统计上榜条目数量,呈现当前热榜内容覆盖结构。
按主题汇总热度,突出最高热度类目,辅助快速研判舆论集中点。
+按主题汇总热度规模,突出当前热榜关注度集中方向。