refactor(web): 技术信息折叠铺到媒体库 / 审计 / 运行状态,清理正常态徽章与解释型页描述(DEAI-2)

- 媒体库详情:作品 UUID 进技术信息;「实际路径与库根」改「文件位置」,正常态(已核验、
  可访问、主位置)不加徽章;外部身份显示「TMDB 90228 · 你确认的 / 自动匹配」,修订号进悬停;
  元数据字段来源默认收起(「显示来源」,跟随界面设置);别名默认只列中英文与手动加的;
  「内容单元」→「季与集」,「临时单元」→「编号待确认」;侧栏与页标题统一「媒体库」
- 审计:动作列不再重复英文码,对象列显示中文类型 / 能力名,ID 只在详情;补 capability.denied
- 运行状态:进程、已下线实例、趋势图与最大表收进折叠区;图例同名序列加序号,不再拼接
- 站点卡:账号正常与登录方式不加徽章,健康不显示毫秒,限流移出卡片
- 文件管理:目录「正常」徽章与重复的剩余空间去掉;已登记 → 已入库,临时文件 → 未完成
- 规则:「修订」列改「最后修改」;不支持的关键字合成一行;页签改「默认规则 / 自动收新作品 / 已忽略」;
  默认规则说明去掉「带层」等算法描述
- 站点 Passkey 与登录用通行密钥区分命名;命令面板提示去重
- 删解释型页描述(审计、搜索、下载、下载计划、RSS、规则、媒体库、运行状态、站点、任务、计划、整理)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 20:58:38 +08:00
1 parent 5a717e414c
commit 57ce40168d
31 files changed
+253 -209

No files matched your search

@@ -48,6 +48,16 @@ export function HistoryChart({
return [...m.values()].sort((a, b) => String(a.at).localeCompare(String(b.at)));
}, [series, metric]);
// 同名序列(容器重建后 pid 相同)加序号区分,图例不再重复拼接
const labels = new Map<string, string>();
const seen = new Map<string, number>();
for (const s of series) {
const base = seriesLabel(s);
const n = (seen.get(base) ?? 0) + 1;
seen.set(base, n);
labels.set(s.instanceId, n > 1 ? `${base}(${n})` : base);
}
if (rows.length === 0) return <EmptyState plain title="这段时间没有采样" className="py-8" />;
return (
@@ -80,13 +90,19 @@ export function HistoryChart({
}}
cursor={{ stroke: "var(--color-muted-foreground)", strokeDasharray: "3 3" }}
/>
{series.length > 1 ? <Legend iconType="plainline" wrapperStyle={{ fontSize: 12 }} /> : null}
{series.length > 1 ? (
<Legend
iconType="plainline"
wrapperStyle={{ fontSize: 12, paddingTop: 4 }}
formatter={(v) => <span className="mr-3 text-muted-foreground">{String(v)}</span>}
/>
) : null}
{series.map((s, i) => (
<Line
key={s.instanceId}
type="monotone"
dataKey={s.instanceId}
name={seriesLabel(s)}
name={labels.get(s.instanceId) ?? seriesLabel(s)}
stroke="var(--color-foreground)"
strokeOpacity={OPACITY[i % OPACITY.length]}
strokeDasharray={DASH[i % DASH.length]}
@@ -12,6 +12,7 @@ import { useStorageCleanup, useSystemStorage } from "~/api/system.ts";
import { DataTable } from "~/components/console/data-table.tsx";
import { ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
import { StatusBadge, type StatusTone } from "~/components/console/status-badge.tsx";
import { TechInfo } from "~/components/console/tech-info.tsx";
import { Button } from "~/components/ui/button.tsx";
import { errorMessage } from "~/lib/api.ts";
import { formatRelative } from "~/lib/labels.ts";
@@ -257,52 +258,56 @@ export function StorageSection({ health }: { health: SystemHealth }) {
</ul>
<div className="grid gap-6 xl:grid-cols-2">
<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>
),
},
]}
/>
</Panel>
<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>
),
},
]}
/>
</Panel>
</TechInfo>
<div className="space-y-6">
<Panel title="缓存" note="条数含尚未清理的过期条目">
<DataTable<KvRow>