- 下载面板:下载盘只显示「已用 x / 总量」与进度条,暂停线 / 在途 / 预留 / 可清理 / 做种保留收进详情; 阈值文案统一「暂停线 / 恢复线 / 下载盘满暂停」 - RSS 页去掉与站点页重复的站点表,节标题「RSS 地址」;用途只在非通用时显示 - 订阅:一条都没有时不铺筛选;表单里「空 = 24;0 = 关」等等式改成 placeholder + 一句说明 - 设置:浏览器服务、元数据识别、MCP 说明去掉组件名与实现细节;会话目录与 fake 脚本只在开发构建显示; API Key scope 前加中文名;命名模板变量去掉「MP 无」 - 待处理顶部计数卡改成一行筛选按钮 - 智能体悬浮按钮只在没有侧栏的窄屏出现,抽屉打开时不再显示「收起」胶囊 Co-Authored-By: Claude Opus 5.5 <[email protected]>
77 lines
2.8 KiB
TypeScript
77 lines
2.8 KiB
TypeScript
import type { FeedHealth } from "@umt/contracts";
|
|
import { Plus, RefreshCw } from "lucide-react";
|
|
import { useState } from "react";
|
|
import { useFeeds } from "~/api/feeds.ts";
|
|
import { useSites } from "~/api/sites.ts";
|
|
import { DetailSection } from "~/components/console/detail-sheet.tsx";
|
|
import { FilterBar, FilterSelect } from "~/components/console/filter-bar.tsx";
|
|
import { PageHeader } from "~/components/console/page-header.tsx";
|
|
import { useQueryState } from "~/components/console/use-query-state.ts";
|
|
import { Button } from "~/components/ui/button.tsx";
|
|
import { FEED_HEALTH, FeedTable } from "~/components/workbench/feed-table.tsx";
|
|
import { legacyRedirectLoader } from "./redirects.ts";
|
|
|
|
// RSS:跨站点的 RSS 列表;站点健康只在站点页(DEAI-2 去掉重复的站点表)。
|
|
|
|
export const meta = () => [{ title: "RSS · UHD 媒体自动化控制台" }];
|
|
|
|
// 旧的 ?tab=snapshots&siteId= 跳到站点详情的"快照与 Feed"
|
|
export const clientLoader = legacyRedirectLoader;
|
|
|
|
export default function SourcesPage() {
|
|
const f = useQueryState(["health", "siteId"] as const);
|
|
const [creating, setCreating] = useState(false);
|
|
const sites = useSites();
|
|
const feeds = useFeeds({
|
|
health: (f.values.health || undefined) as FeedHealth | undefined,
|
|
siteId: f.values.siteId || undefined,
|
|
});
|
|
|
|
return (
|
|
<>
|
|
<PageHeader
|
|
title="RSS"
|
|
actions={
|
|
<Button size="sm" onClick={() => setCreating(true)}>
|
|
<Plus />
|
|
新建 RSS
|
|
</Button>
|
|
}
|
|
/>
|
|
<div className="space-y-8">
|
|
<DetailSection title="RSS 地址">
|
|
<FilterBar
|
|
onReset={f.active ? f.reset : undefined}
|
|
actions={
|
|
<Button variant="ghost" size="sm" onClick={() => void feeds.refetch()} disabled={feeds.isFetching}>
|
|
<RefreshCw className={feeds.isFetching ? "animate-spin" : undefined} />
|
|
刷新
|
|
</Button>
|
|
}
|
|
>
|
|
<FilterSelect
|
|
label="健康"
|
|
value={f.values.health}
|
|
onChange={(v) => f.set("health", v)}
|
|
options={Object.entries(FEED_HEALTH).map(([value, h]) => ({ value, label: h.label }))}
|
|
/>
|
|
<FilterSelect
|
|
label="站点"
|
|
value={f.values.siteId}
|
|
onChange={(v) => f.set("siteId", v)}
|
|
options={(sites.data?.items ?? []).map((s) => ({ value: s.id, label: s.name }))}
|
|
/>
|
|
</FilterBar>
|
|
<FeedTable
|
|
health={(f.values.health || undefined) as FeedHealth | undefined}
|
|
siteId={f.values.siteId || undefined}
|
|
filtered={f.active}
|
|
creating={creating}
|
|
onCreatingChange={setCreating}
|
|
/>
|
|
</DetailSection>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|