docs(plan): on-demand site detail page parsing (HHClub details.php)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-29 15:13:35 +08:00
1 parent 94fd48bff2
commit ac478673bc
39 files changed
+2446 -339

No files matched your search

+8 -1
View File
@@ -1,10 +1,11 @@
import { Globe, LayoutGrid, List, Plus, RefreshCw } from "lucide-react";
import { Globe, LayoutGrid, List, PackageSearch, Plus, RefreshCw } from "lucide-react";
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router";
import { useSites } from "~/api/sites.ts";
import { EmptyState, ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
import { FilterSelect } from "~/components/console/filter-bar.tsx";
import { PageHeader } from "~/components/console/page-header.tsx";
import { SearchDefaultDialog } from "~/components/sites/search-default-dialog.tsx";
import { SiteAddDialog } from "~/components/sites/site-add-dialog.tsx";
import { SiteCard, SiteTable } from "~/components/sites/site-card.tsx";
import { type SiteDialog, SiteDialogHost, useSiteChecks } from "~/components/sites/site-dialogs.tsx";
@@ -88,6 +89,7 @@ export default function SitesPage() {
}, [credFor, sites.data]);
const all = sites.data?.items ?? [];
const [searchDefaults, setSearchDefaults] = useState(false);
const attention = all.filter(needsAttention).length;
const shown = sortSites(
all.filter((s) => (filter === "enabled" ? s.enabled : filter === "attention" ? needsAttention(s) : true)),
@@ -105,6 +107,10 @@ export default function SitesPage() {
<RefreshCw className={sites.isFetching ? "animate-spin" : undefined} />
刷新
</Button>
<Button variant="outline" size="sm" onClick={() => setSearchDefaults(true)} disabled={!all.length}>
<PackageSearch />
搜索站点
</Button>
<Button size="sm" onClick={() => setAdding(true)}>
<Plus />
添加站点
@@ -181,6 +187,7 @@ export default function SitesPage() {
{adding ? <SiteAddDialog onClose={() => setAdding(false)} /> : null}
<SiteDialogHost dialog={dialog} onClose={() => setDialog(null)} />
<SearchDefaultDialog open={searchDefaults} onOpenChange={setSearchDefaults} sites={all} />
</>
);
}