feat(web): 运行状态加资源监控(CPU / 内存 / 网络 / 磁盘读写与趋势、进程 CPU),首页换成运行状态简版卡

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 18:09:56 +08:00
1 parent 805ba33ddf
commit a1440401c4
6 files changed
+581 -83

No files matched your search

+3 -3
View File
@@ -28,7 +28,7 @@ import { PageHeader } from "~/components/console/page-header.tsx";
import { AttentionList, attentionRows } from "~/components/dashboard/attention-summary.tsx";
import { HomeRuntime } from "~/components/dashboard/home-runtime.tsx";
import { runTitle } from "~/components/tasks/labels.ts";
import { useLiveTasks } from "~/components/tasks/task-stream.tsx";
import { useLiveTasks } from "~/components/tasks/live.ts";
import { Button } from "~/components/ui/button.tsx";
import { errorMessage } from "~/lib/api.ts";
import { formatRelative } from "~/lib/labels.ts";
@@ -217,7 +217,7 @@ function Busy({ w }: { w: Dashboard["currentWork"] }) {
]);
const empty = !downloads.length && !agents.length && !runs.length;
return (
<Section title="在忙什么" icon={Activity} to="/console/tasks?tab=active">
<Section title="在忙什么" icon={Activity} to="/console/logs?type=task&level=running">
{running.isPending && !downloads.length ? (
<LoadingState rows={3} />
) : empty ? (
@@ -246,7 +246,7 @@ function Busy({ w }: { w: Dashboard["currentWork"] }) {
))}
{runs.slice(0, Math.max(0, 5 - downloads.length - agents.length)).map((r) => (
<Row key={r.id}>
<Link to={`/console/tasks?run=${encodeURIComponent(r.id)}`} className="min-w-0 flex-1 hover:underline">
<Link to={`/console/logs?run=${encodeURIComponent(r.id)}`} className="min-w-0 flex-1 hover:underline">
<span className="block truncate">{runTitle(r)}</span>
</Link>
</Row>
+38 -15
View File
@@ -24,6 +24,7 @@ import { StatusBadge, type StatusTone } from "~/components/console/status-badge.
import { TechInfo } from "~/components/console/tech-info.tsx";
import { AgentSpendCard, AttentionCard } from "~/components/status/attention-cards.tsx";
import { HistoryChart } from "~/components/status/history-chart.tsx";
import { ResourceSection } from "~/components/status/resource-section.tsx";
import { StorageSection } from "~/components/status/storage-section.tsx";
import { Button } from "~/components/ui/button.tsx";
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs.tsx";
@@ -35,6 +36,7 @@ export const meta = () => [{ title: "运行状态 · UHD 媒体自动化控制
// 运行状态(W9-I):进程心跳、事件循环、SSE、DB、磁盘、挂载根、引擎与定时任务;存储节(FIX-5)见 storage-section.tsx。阈值见 docs/runbook/ops.md。
// 2026-10-06:顶部加「需要关注」汇总(系统健康逐条列出,铃铛点进来落到 #attention)与智能体用量。
// 界面第二轮:加「资源」节(CPU / 内存 / 网络 / 磁盘读写与趋势,参考 MP 仪表盘);进程表直接展示并带 CPU 列。
const LEVEL: Record<HealthLevel, { label: string; tone: StatusTone }> = {
ok: { label: "正常", tone: "success" },
@@ -250,10 +252,24 @@ function Processes({ d }: { d: SystemHealth }) {
align: "right",
cell: (p) => <span className="tabular-nums">{p.sseConnections ?? "—"}</span>,
},
{
key: "cpu",
header: "CPU",
hideBelow: "md",
align: "right",
cell: (p) => {
const cpu = p.extra.cpuPercent;
return (
<span className="tabular-nums" title="两次心跳之间本进程占一个核的百分比">
{typeof cpu === "number" ? `${cpu.toFixed(1)}%` : "—"}
</span>
);
},
},
{
key: "mem",
header: "内存",
hideBelow: "lg",
hideBelow: "md",
align: "right",
cell: (p) => {
const rss = p.extra.rssBytes;
@@ -517,6 +533,7 @@ export default function StatusPage() {
<AttentionCard />
<AgentSpendCard />
</div>
<ResourceSection />
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
<Card title="数据库" icon={Database} level={d.db.level}>
{d.db.error ? <p className="mb-2 text-caption text-destructive">{d.db.error}</p> : null}
@@ -542,7 +559,10 @@ export default function StatusPage() {
icon={ListTodo}
level={d.engine.level}
action={
<Link to="/console/tasks?tab=active" className="text-meta text-muted-foreground hover:text-foreground">
<Link
to="/console/logs?type=task&level=running"
className="text-meta text-muted-foreground hover:text-foreground"
>
查看任务
</Link>
}
@@ -567,8 +587,11 @@ export default function StatusPage() {
icon={Timer}
level={d.schedules.level}
action={
<Link to="/console/schedules" className="text-meta text-muted-foreground hover:text-foreground">
查看计划
<Link
to="/console/logs?tab=schedules"
className="text-meta text-muted-foreground hover:text-foreground"
>
查看定时任务
</Link>
}
>
@@ -584,7 +607,7 @@ export default function StatusPage() {
{d.schedules.failing.map((f) => (
<li key={f.id} className="min-w-0 text-caption">
<Link
to={`/console/schedules?job=${encodeURIComponent(f.id)}`}
to={`/console/logs?objectType=scheduled_job&objectId=${encodeURIComponent(f.id)}`}
className="font-medium text-foreground hover:underline"
>
{f.name}
@@ -600,16 +623,16 @@ export default function StatusPage() {
<Mounts d={d} />
</div>
<StorageSection health={d} />
<TechInfo title="进程与趋势" columns={1}>
<section className="min-w-0">
<h2 className="mb-2 flex items-center gap-2 text-body font-semibold text-foreground">
<Cpu className="h-4 w-4 text-muted-foreground" />
进程
<span className="text-meta font-normal text-muted-foreground">SSE 连接合计 {d.sse.connections}</span>
</h2>
<Processes d={d} />
<RetiredProcesses rows={d.retiredProcesses} />
</section>
<section className="min-w-0">
<h2 className="mb-2 flex items-center gap-2 text-body font-semibold text-foreground">
<Cpu className="h-4 w-4 text-muted-foreground" />
进程
<span className="text-meta font-normal text-muted-foreground">SSE 连接合计 {d.sse.connections}</span>
</h2>
<Processes d={d} />
<RetiredProcesses rows={d.retiredProcesses} />
</section>
<TechInfo title="事件循环与 SSE 趋势" columns={1}>
<History />
</TechInfo>
</div>