fix(web): 控制台界面细节与 uhd_web 控件规范对齐
- 顶栏搜索移进右侧玻璃胶囊;输入框改淡玻璃(边线 0.46 → 0.16,悬停加深,聚焦 / 出错保留光晕) - 新增 SegmentedControl(滑动 seg-thumb),替换站点、下载、订阅、文件、智能体列表及对话框里的实心选中块;Tabs 改为同一枚滑块 - 开关型按钮统一 outline + aria-pressed 选中外观;页头 / 工具栏次操作描边、图标钮描边圆;文件排序改 Select;下载总速度加标签 - 分页一页放得下时只留总数、空列表不渲染、按容器宽度收起按钮 - 运行状态存储区重排;智能体列表页与会话页共用外壳路由,标题与左栏不再重挂载 - 站点卡片「⋯」不再单独换行;设置导航、状态计数、多选条件改玻璃选中态 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
8ff1817845
commit
c9b4ceb301
32 files changed
+753
-639
No files matched your search
@@ -324,150 +324,146 @@ export function StorageSection({ health }: { health: SystemHealth }) {
|
||||
<BudgetBar label="会话与证据" u={s.sessionsEvidence} />
|
||||
</ul>
|
||||
|
||||
<div className="grid gap-6 xl:grid-cols-2">
|
||||
<TechInfo title={`数据库里最大的 ${TOP_TABLES} 张表`} columns={1}>
|
||||
<Panel title={`体积最大的表(前 ${TOP_TABLES})`} note="含索引与 TOAST">
|
||||
<DataTable<TableRow>
|
||||
rows={s.db.tables.slice(0, TOP_TABLES)}
|
||||
rowKey={(t) => `${t.schema}.${t.name}`}
|
||||
empty={{ title: "取不到表体积" }}
|
||||
columns={[
|
||||
{
|
||||
key: "name",
|
||||
header: "表",
|
||||
cell: (t) => (
|
||||
<span className="font-mono text-caption break-all">
|
||||
{t.schema === "public" ? t.name : `${t.schema}.${t.name}`}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "total",
|
||||
header: "合计",
|
||||
align: "right",
|
||||
cell: (t) => (
|
||||
<span className="whitespace-nowrap tabular-nums">{formatBytes(t.totalBytes, 1)}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "idx",
|
||||
header: "索引",
|
||||
align: "right",
|
||||
hideBelow: "md",
|
||||
cell: (t) => (
|
||||
<span className="whitespace-nowrap tabular-nums text-muted-foreground">
|
||||
{formatBytes(t.indexBytes, 1)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "rows",
|
||||
header: "估算行数",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (t) => (
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{t.rowsEstimate === null ? "—" : t.rowsEstimate.toLocaleString("zh-CN")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "dead",
|
||||
header: "死元组",
|
||||
align: "right",
|
||||
hideBelow: "md",
|
||||
cell: (t) => (
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{t.deadRows === null ? "—" : t.deadRows.toLocaleString("zh-CN")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
</TechInfo>
|
||||
<div className="space-y-6">
|
||||
<Panel title="缓存" note="条数含还没清理的过期条目">
|
||||
<DataTable<KvRow>
|
||||
rows={s.kvCache}
|
||||
rowKey={(r) => r.region}
|
||||
empty={{ title: "缓存为空" }}
|
||||
columns={[
|
||||
{
|
||||
key: "region",
|
||||
header: "类别",
|
||||
cell: (r) => (
|
||||
<span title={r.region}>
|
||||
{REGION_LABEL[r.region] ?? <span className="font-mono text-caption">{r.region}</span>}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "entries",
|
||||
header: "条数",
|
||||
align: "right",
|
||||
cell: (r) => <span className="tabular-nums">{r.entries.toLocaleString("zh-CN")}</span>,
|
||||
},
|
||||
{
|
||||
key: "expired",
|
||||
header: "已过期",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (r) => (
|
||||
<span className="tabular-nums text-muted-foreground">{r.expired.toLocaleString("zh-CN")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "bytes",
|
||||
header: "体积",
|
||||
align: "right",
|
||||
cell: (r) => <span className="whitespace-nowrap tabular-nums">{formatBytes(r.bytes, 1)}</span>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
<Panel title="数据目录" note="DATA_DIR 各子目录">
|
||||
<DataTable<DirRow>
|
||||
rows={s.dataDir}
|
||||
rowKey={(d) => d.path}
|
||||
empty={{ title: "还没有统计", description: "目录用量每 5 分钟统计一次。" }}
|
||||
columns={[
|
||||
{
|
||||
key: "name",
|
||||
header: "目录",
|
||||
cell: (d) => (
|
||||
<div className="min-w-0">
|
||||
<p className="font-medium">{d.name}</p>
|
||||
<p className="truncate font-mono text-meta text-muted-foreground" title={d.path}>
|
||||
{d.path}
|
||||
</p>
|
||||
{d.error ? <p className="text-meta text-destructive">{d.error}</p> : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "files",
|
||||
header: "文件",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (d) => (
|
||||
<span className="tabular-nums text-muted-foreground">{d.files.toLocaleString("zh-CN")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "used",
|
||||
header: "占用",
|
||||
align: "right",
|
||||
cell: (d) => (
|
||||
<span className="whitespace-nowrap tabular-nums">{formatBytes(d.usedBytes, 1)}</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
</div>
|
||||
{/* 缓存与数据目录在宽屏并排;两个折叠区(最大的表、语句统计)整行放在下面,收起时不留空栏 */}
|
||||
<div className="grid items-start gap-6 lg:grid-cols-2">
|
||||
<Panel title="缓存" note="条数含还没清理的过期条目">
|
||||
<DataTable<KvRow>
|
||||
rows={s.kvCache}
|
||||
rowKey={(r) => r.region}
|
||||
empty={{ title: "缓存为空" }}
|
||||
columns={[
|
||||
{
|
||||
key: "region",
|
||||
header: "类别",
|
||||
cell: (r) => (
|
||||
<span title={r.region}>
|
||||
{REGION_LABEL[r.region] ?? <span className="font-mono text-caption">{r.region}</span>}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "entries",
|
||||
header: "条数",
|
||||
align: "right",
|
||||
cell: (r) => <span className="tabular-nums">{r.entries.toLocaleString("zh-CN")}</span>,
|
||||
},
|
||||
{
|
||||
key: "expired",
|
||||
header: "已过期",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (r) => (
|
||||
<span className="tabular-nums text-muted-foreground">{r.expired.toLocaleString("zh-CN")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "bytes",
|
||||
header: "体积",
|
||||
align: "right",
|
||||
cell: (r) => <span className="whitespace-nowrap tabular-nums">{formatBytes(r.bytes, 1)}</span>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
<Panel title="数据目录" note="DATA_DIR 各子目录">
|
||||
<DataTable<DirRow>
|
||||
rows={s.dataDir}
|
||||
rowKey={(d) => d.path}
|
||||
empty={{ title: "还没有统计", description: "目录用量每 5 分钟统计一次。" }}
|
||||
columns={[
|
||||
{
|
||||
key: "name",
|
||||
header: "目录",
|
||||
cell: (d) => (
|
||||
<div className="min-w-0">
|
||||
<p className="font-medium">{d.name}</p>
|
||||
<p className="truncate font-mono text-meta text-muted-foreground" title={d.path}>
|
||||
{d.path}
|
||||
</p>
|
||||
{d.error ? <p className="text-meta text-destructive">{d.error}</p> : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "files",
|
||||
header: "文件",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (d) => (
|
||||
<span className="tabular-nums text-muted-foreground">{d.files.toLocaleString("zh-CN")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "used",
|
||||
header: "占用",
|
||||
align: "right",
|
||||
cell: (d) => <span className="whitespace-nowrap tabular-nums">{formatBytes(d.usedBytes, 1)}</span>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
<TechInfo title={`数据库里最大的 ${TOP_TABLES} 张表`} columns={1}>
|
||||
<Panel title={`体积最大的表(前 ${TOP_TABLES})`} note="含索引与 TOAST">
|
||||
<DataTable<TableRow>
|
||||
rows={s.db.tables.slice(0, TOP_TABLES)}
|
||||
rowKey={(t) => `${t.schema}.${t.name}`}
|
||||
empty={{ title: "取不到表体积" }}
|
||||
columns={[
|
||||
{
|
||||
key: "name",
|
||||
header: "表",
|
||||
cell: (t) => (
|
||||
<span className="font-mono text-caption break-all">
|
||||
{t.schema === "public" ? t.name : `${t.schema}.${t.name}`}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "total",
|
||||
header: "合计",
|
||||
align: "right",
|
||||
cell: (t) => <span className="whitespace-nowrap tabular-nums">{formatBytes(t.totalBytes, 1)}</span>,
|
||||
},
|
||||
{
|
||||
key: "idx",
|
||||
header: "索引",
|
||||
align: "right",
|
||||
hideBelow: "md",
|
||||
cell: (t) => (
|
||||
<span className="whitespace-nowrap tabular-nums text-muted-foreground">
|
||||
{formatBytes(t.indexBytes, 1)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "rows",
|
||||
header: "估算行数",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (t) => (
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{t.rowsEstimate === null ? "—" : t.rowsEstimate.toLocaleString("zh-CN")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "dead",
|
||||
header: "死元组",
|
||||
align: "right",
|
||||
hideBelow: "md",
|
||||
cell: (t) => (
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{t.deadRows === null ? "—" : t.deadRows.toLocaleString("zh-CN")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
</TechInfo>
|
||||
|
||||
<StatementsInfo st={s.db.statements} />
|
||||
|
||||
<Panel title="清理任务" note="立即清理会把维护任务加入队列,结果在运行记录里看">
|
||||
|
||||
Reference in new issue
Block a user