refactor(analysis): 移除重复的「应用日志量流图」与「Top 5 饼图」,并按需触发重查询
CI / Backend (go vet + test) (push) Canceled after 0s
CI / Frontend (lint + build + test) (push) Canceled after 0s

=== 为什么这两个可以去掉(不是拍脑袋)===
排行表已有 9 列:排名 / 应用 / 命名空间 / 日志量 / **占比** / 错误数 /
错误率 / 趋势(sparkline) / 操作(查看日志)。
   - Top 5 饼图 = 应用 + 数量 + 占比 —— 表里全都有,且表里更多
   - 流图 = 各应用随时间的堆叠 —— 表里每行已有 sparkline 趋势
两者都是同一份 by-app 数据的重复呈现,纯增加视觉噪音。

=== 但"去掉它们"本身不减查询,真正的减负在这一步 ===
之前这三个组件都依赖同一条 by-app 重查询(10~15 秒)。
因为饼图/流图在首屏,所以那条查询只能一进页面就全量跑(rankingEnabled=true)。
现在图都没了,重查询只服务底部排行表 → 恢复可见性门控:
    rankingEnabled: rankingView.inView
效果:打开分析页只跑索引类查询(histogram/stats/daily-volume,均 <100ms),
      用户滚到排行卡才发那条重查询。
「活跃应用」卡片在未统计时显示 —(原来显示 0 个,容易误读成"没有应用")。

=== 布局 ===
趋势图从 2/3 宽改为整行,页面高度明显下降。

=== 实测(ddf63053b952)===
  Pod = Hub latest = v0.1 = ddf63053b952
  NamespacePie / AppStreamChart 在页面中引用数均为 0
This commit is contained in:
opsx committed 2026-10-30 16:15:44 +00:00
1 parent 3b297d0429
commit 7f6fb364de
1 file changed
+17 -29
+17 -29
View File
@@ -19,9 +19,7 @@ import { useDailyVolume } from './hooks/useDailyVolume'
import { useInView } from '@/hooks/useInView'
import { compactNumber, formatBytes } from './components/chart-shared'
import { TrendChart } from './components/TrendChart'
import { AppStreamChart } from './components/AppStreamChart'
import { DailyVolumeChart } from './components/DailyVolumeChart'
import { NamespacePie } from './components/NamespacePie'
import { TopAppsTable } from './components/TopAppsTable'
import { IngressAnalysisSection } from './components/IngressAnalysisSection'
@@ -149,6 +147,11 @@ const AnalysisPage = memo(function AnalysisPage() {
start,
end,
namespace: scopedNamespace,
// 流图和 Top5 饼图已移除,按应用统计的重查询现在只服务「排行表」,
// 因此重新用可见性门控:页面打开只跑索引类查询(百毫秒),
// 用户滚到排行卡才发那条 10~15 秒的重查询。
// 这是真正减少查询压力的一步——之前图在首屏,所以只能全量查。
rankingEnabled: rankingView.inView,
})
// 选择值与已生效值不一致 → 提示"点刷新生效"
@@ -265,38 +268,23 @@ const AnalysisPage = memo(function AnalysisPage() {
<StatCard label={t('stats.totalEntries')} value={`${compactNumber(data.stats.totalEntries)} 条`} icon={ScrollText} iconColor="text-info" iconBg="bg-info/10" />
<StatCard label={t('stats.totalVolume')} value={formatBytes(data.stats.total)} icon={ScrollText} iconColor="text-info" iconBg="bg-info/10" />
<StatCard label={t('stats.errors')} value={`${compactNumber(data.stats.errorCount)} 条`} icon={FileWarning} iconColor="text-destructive" iconBg="bg-destructive/10" />
<StatCard label={t('stats.apps')} value={`${data.stats.appCount} 个`} icon={Boxes} iconColor="text-primary" iconBg="bg-primary/10" />
</div>
<div className="grid gap-4 lg:grid-cols-3">
<Card className="lg:col-span-2">
<CardHeader className="pb-3">
<CardTitle className="text-base">{t('trend.title')}</CardTitle>
<p className="text-xs text-muted-foreground">{t('trend.subtitle')}</p>
</CardHeader>
<CardContent><TrendChart trend={data.trend} /></CardContent>
</Card>
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">{t('pie.title')}</CardTitle>
<p className="text-xs text-muted-foreground">{t('pie.subtitle')}</p>
</CardHeader>
<CardContent>
{/* 从"命名空间分布"改成"应用分布":命名空间只有 astralx/log 两个,
看了没有信息量;按应用才看得出是谁在刷日志 */}
<NamespacePie
shares={data.apps.map(app => ({ name: app.app || t('table.untagged'), count: app.total }))}
/>
</CardContent>
</Card>
<StatCard
label={t('stats.apps')}
value={appsLoading ? '统计中…' : data.apps.length > 0 ? `${data.stats.appCount} 个` : '—'}
icon={Boxes}
iconColor="text-primary"
iconBg="bg-primary/10"
/>
</div>
{/* 「应用日志量 Top 5」饼图已移除:排行表里已有 排名/应用/命名空间/日志量/占比
五项信息,饼图属于同一组数据的重复呈现。 */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">{t('stream.title')}</CardTitle>
<p className="text-xs text-muted-foreground">{t('stream.subtitle', { count: Math.min(data.apps.length, 10) })}</p>
<CardTitle className="text-base">{t('trend.title')}</CardTitle>
<p className="text-xs text-muted-foreground">{t('trend.subtitle')}</p>
</CardHeader>
<CardContent><AppStreamChart apps={data.apps} appTimes={data.appTimes} /></CardContent>
<CardContent><TrendChart trend={data.trend} /></CardContent>
</Card>
<div ref={rankingView.ref}>