[feat]:[FL-208][优化worker监控页面]
1. 预取配置硬编码显示为1 2. 移除自动刷新功能,刷新按钮改为主题色 3. 移除"生成时间、执行节点、在线、离线"统计信息展示 4. 修复队列列"默认队列"重复显示问题 5. 修复执行节点列内容超长时的溢出问题 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
|||||||
getQueueDisplayName,
|
getQueueDisplayName,
|
||||||
getTaskSourceDisplay,
|
getTaskSourceDisplay,
|
||||||
getTaskStateDisplay,
|
getTaskStateDisplay,
|
||||||
|
normalizeQueueNames,
|
||||||
} from "@/lib/task-monitor-display";
|
} from "@/lib/task-monitor-display";
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
@@ -131,9 +132,10 @@ function renderWorkerStatusTag(status: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderQueueTags(queueNames: string[]) {
|
function renderQueueTags(queueNames: string[]) {
|
||||||
return queueNames.length > 0 ? (
|
const normalized = normalizeQueueNames(queueNames);
|
||||||
|
return normalized.length > 0 ? (
|
||||||
<Space wrap size={[4, 4]}>
|
<Space wrap size={[4, 4]}>
|
||||||
{queueNames.map((queueName) => (
|
{normalized.map((queueName) => (
|
||||||
<Tag key={queueName} color="blue" bordered={false}>
|
<Tag key={queueName} color="blue" bordered={false}>
|
||||||
{getQueueDisplayName(queueName)}
|
{getQueueDisplayName(queueName)}
|
||||||
</Tag>
|
</Tag>
|
||||||
@@ -163,7 +165,6 @@ export default function AdminWorkersPage() {
|
|||||||
const isMobile = useMobileDetection();
|
const isMobile = useMobileDetection();
|
||||||
const canRead = hasPermission("celery.read") || hasPermission("celery.manage");
|
const canRead = hasPermission("celery.read") || hasPermission("celery.manage");
|
||||||
|
|
||||||
const [autoRefresh, setAutoRefresh] = useState(true);
|
|
||||||
const [workerKeyword, setWorkerKeyword] = useState("");
|
const [workerKeyword, setWorkerKeyword] = useState("");
|
||||||
const [queueKeyword, setQueueKeyword] = useState("");
|
const [queueKeyword, setQueueKeyword] = useState("");
|
||||||
const [statusFilter, setStatusFilter] = useState<"all" | "online" | "offline">("all");
|
const [statusFilter, setStatusFilter] = useState<"all" | "online" | "offline">("all");
|
||||||
@@ -182,7 +183,7 @@ export default function AdminWorkersPage() {
|
|||||||
}
|
}
|
||||||
return (await response.json()) as WorkerMonitorOverviewResponse;
|
return (await response.json()) as WorkerMonitorOverviewResponse;
|
||||||
},
|
},
|
||||||
refetchInterval: autoRefresh ? 5_000 : false,
|
refetchInterval: false,
|
||||||
staleTime: 15_000,
|
staleTime: 15_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,7 +211,7 @@ export default function AdminWorkersPage() {
|
|||||||
}
|
}
|
||||||
return (await response.json()) as WorkerMonitorTaskOverviewResponse;
|
return (await response.json()) as WorkerMonitorTaskOverviewResponse;
|
||||||
},
|
},
|
||||||
refetchInterval: autoRefresh ? 5_000 : false,
|
refetchInterval: false,
|
||||||
staleTime: 15_000,
|
staleTime: 15_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -221,6 +222,9 @@ export default function AdminWorkersPage() {
|
|||||||
dataIndex: "worker",
|
dataIndex: "worker",
|
||||||
key: "worker",
|
key: "worker",
|
||||||
width: 220,
|
width: 220,
|
||||||
|
ellipsis: {
|
||||||
|
showTitle: false,
|
||||||
|
},
|
||||||
render: (value: string) => (
|
render: (value: string) => (
|
||||||
<Typography.Text ellipsis={{ tooltip: value || "-" }}>
|
<Typography.Text ellipsis={{ tooltip: value || "-" }}>
|
||||||
{value || "-"}
|
{value || "-"}
|
||||||
@@ -255,6 +259,7 @@ export default function AdminWorkersPage() {
|
|||||||
key: "prefetch_count",
|
key: "prefetch_count",
|
||||||
width: 70,
|
width: 70,
|
||||||
align: "center",
|
align: "center",
|
||||||
|
render: () => 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "任务统计",
|
title: "任务统计",
|
||||||
@@ -586,7 +591,7 @@ export default function AdminWorkersPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="admin-workers-worker-card-field">
|
<div className="admin-workers-worker-card-field">
|
||||||
<Typography.Text type="secondary">并发/预取</Typography.Text>
|
<Typography.Text type="secondary">并发/预取</Typography.Text>
|
||||||
<Typography.Text>{workerItem.concurrency}/{workerItem.prefetch_count}</Typography.Text>
|
<Typography.Text>{workerItem.concurrency}/1</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="admin-workers-worker-card-field">
|
<div className="admin-workers-worker-card-field">
|
||||||
<Typography.Text type="secondary">任务</Typography.Text>
|
<Typography.Text type="secondary">任务</Typography.Text>
|
||||||
@@ -616,11 +621,7 @@ export default function AdminWorkersPage() {
|
|||||||
extra={(
|
extra={(
|
||||||
<Space size={8} wrap>
|
<Space size={8} wrap>
|
||||||
{overviewQuery.isFetching && <Spin size="small" />}
|
{overviewQuery.isFetching && <Spin size="small" />}
|
||||||
<Space size={8}>
|
<Button type="primary" onClick={() => void overviewQuery.refetch()} loading={overviewQuery.isFetching}>
|
||||||
<Text type="secondary">自动刷新</Text>
|
|
||||||
<Switch size="small" checked={autoRefresh} onChange={setAutoRefresh} />
|
|
||||||
</Space>
|
|
||||||
<Button onClick={() => void overviewQuery.refetch()} loading={overviewQuery.isFetching}>
|
|
||||||
刷新
|
刷新
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@@ -692,13 +693,6 @@ export default function AdminWorkersPage() {
|
|||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Space className="mt-4" size={[16, 8]} wrap>
|
|
||||||
<Text type="secondary">生成时间:{formatDateTime(overview?.generated_at)}</Text>
|
|
||||||
<Text type="secondary">执行节点:{filteredWorkers.length}/{overview?.summary.total ?? 0}</Text>
|
|
||||||
<Text type="secondary">在线:{overview?.summary.online ?? 0}</Text>
|
|
||||||
<Text type="secondary">离线:{overview?.summary.offline ?? 0}</Text>
|
|
||||||
</Space>
|
|
||||||
|
|
||||||
{viewMode === "table" ? (
|
{viewMode === "table" ? (
|
||||||
<div
|
<div
|
||||||
ref={tableScrollAnchorRef}
|
ref={tableScrollAnchorRef}
|
||||||
|
|||||||
@@ -71,6 +71,21 @@ export function getQueueDisplayName(queueName: string | null | undefined): strin
|
|||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeQueueNames(queueNames: string[]): string[] {
|
||||||
|
const seen = new Set<string>();
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const queueName of queueNames) {
|
||||||
|
const displayName = getQueueDisplayName(queueName);
|
||||||
|
if (!seen.has(displayName)) {
|
||||||
|
seen.add(displayName);
|
||||||
|
result.push(queueName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export function formatTaskMonitorDuration(value: number | null | undefined): string {
|
export function formatTaskMonitorDuration(value: number | null | undefined): string {
|
||||||
if (value === null || value === undefined || !Number.isFinite(value)) {
|
if (value === null || value === undefined || !Number.isFinite(value)) {
|
||||||
return "-";
|
return "-";
|
||||||
|
|||||||
Reference in New Issue
Block a user