mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 03:26:37 +08:00
refactor: split sites page sections
This commit is contained in:
+14
-76
@@ -1,10 +1,8 @@
|
||||
import { type FormEvent, useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { Globe, Plus, RefreshCw } from "lucide-react";
|
||||
|
||||
import { sitesAPI } from "../api/sites";
|
||||
import type { Site } from "../types";
|
||||
import { ManagementShortcuts } from "../components/ManagementShortcuts";
|
||||
import { confirmAction } from "../components/confirmAction";
|
||||
|
||||
import {
|
||||
@@ -12,8 +10,12 @@ import {
|
||||
siteFormToPayload,
|
||||
siteToForm,
|
||||
} from "./sitesPageModel";
|
||||
import { SiteCard } from "./SiteCard";
|
||||
import { SiteFormModal } from "./SiteFormModal";
|
||||
import {
|
||||
SitesGrid,
|
||||
SitesManagementShortcuts,
|
||||
SitesPageHeader,
|
||||
} from "./SitesPageSections";
|
||||
|
||||
function apiErrorMessage(err: unknown, fallback: string): string {
|
||||
const data = (err as { response?: { data?: { message?: string; error?: string } } })
|
||||
@@ -152,81 +154,17 @@ export function SitesPage() {
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<ManagementShortcuts
|
||||
title="站点与下载链路"
|
||||
description="把站点、搜索、订阅和下载器放在同一工作流里,避免功能入口被隐藏。"
|
||||
items={[
|
||||
{
|
||||
to: "/download-clients",
|
||||
title: "下载器管理",
|
||||
description: "添加、测试和维护下载器连接",
|
||||
badge: "必需",
|
||||
group: "基础配置",
|
||||
},
|
||||
{
|
||||
to: "/site-search",
|
||||
title: "站点检索",
|
||||
description: "跨 PT 站点搜索资源并创建下载任务",
|
||||
group: "资源获取",
|
||||
},
|
||||
{
|
||||
to: "/subscriptions",
|
||||
title: "订阅管理",
|
||||
description: "管理追剧追番和自动下载规则",
|
||||
group: "资源获取",
|
||||
},
|
||||
{
|
||||
to: "/downloads",
|
||||
title: "下载中心",
|
||||
description: "查看下载任务状态和历史记录",
|
||||
group: "任务状态",
|
||||
},
|
||||
]}
|
||||
<SitesManagementShortcuts />
|
||||
<SitesPageHeader onCreate={openCreate} />
|
||||
<SitesGrid
|
||||
sites={sites}
|
||||
loading={loading}
|
||||
testingId={testingId}
|
||||
onTest={handleTest}
|
||||
onEdit={openEdit}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="font-display text-3xl font-bold text-ink-600">
|
||||
站点管理
|
||||
</h1>
|
||||
<button
|
||||
onClick={openCreate}
|
||||
className="neon-button flex items-center gap-2"
|
||||
>
|
||||
<Plus size={16} />
|
||||
添加站点
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{sites.map((site) => (
|
||||
<SiteCard
|
||||
key={site.id}
|
||||
site={site}
|
||||
testing={testingId === site.id}
|
||||
onTest={() => handleTest(site.id)}
|
||||
onEdit={() => openEdit(site.id)}
|
||||
onDelete={() => handleDelete(site)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{!loading && sites.length === 0 && (
|
||||
<div className="col-span-full py-12 text-center text-ink-50">
|
||||
<Globe size={40} className="mx-auto mb-3 text-gray-500" />
|
||||
<p>暂无站点</p>
|
||||
<p className="text-sm mt-1 text-sand-500">
|
||||
点击「添加站点」添加 PT/BT 站点
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loading && (
|
||||
<div className="col-span-full py-12 text-center text-ink-50">
|
||||
<RefreshCw size={24} className="mx-auto mb-3 animate-spin" />
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{showModal && (
|
||||
<SiteFormModal
|
||||
editingId={editingId}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import { Globe, Plus, RefreshCw } from "lucide-react";
|
||||
|
||||
import { ManagementShortcuts } from "../components/ManagementShortcuts";
|
||||
import type { Site } from "../types";
|
||||
import { SiteCard } from "./SiteCard";
|
||||
|
||||
export function SitesManagementShortcuts() {
|
||||
return (
|
||||
<ManagementShortcuts
|
||||
title="站点与下载链路"
|
||||
description="把站点、搜索、订阅和下载器放在同一工作流里,避免功能入口被隐藏。"
|
||||
items={[
|
||||
{
|
||||
to: "/download-clients",
|
||||
title: "下载器管理",
|
||||
description: "添加、测试和维护下载器连接",
|
||||
badge: "必需",
|
||||
group: "基础配置",
|
||||
},
|
||||
{
|
||||
to: "/site-search",
|
||||
title: "站点检索",
|
||||
description: "跨 PT 站点搜索资源并创建下载任务",
|
||||
group: "资源获取",
|
||||
},
|
||||
{
|
||||
to: "/subscriptions",
|
||||
title: "订阅管理",
|
||||
description: "管理追剧追番和自动下载规则",
|
||||
group: "资源获取",
|
||||
},
|
||||
{
|
||||
to: "/downloads",
|
||||
title: "下载中心",
|
||||
description: "查看下载任务状态和历史记录",
|
||||
group: "任务状态",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function SitesPageHeader({ onCreate }: { onCreate: () => void }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="font-display text-3xl font-bold text-ink-600">
|
||||
站点管理
|
||||
</h1>
|
||||
<button
|
||||
onClick={onCreate}
|
||||
className="neon-button flex items-center gap-2"
|
||||
>
|
||||
<Plus size={16} />
|
||||
添加站点
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SitesGrid({
|
||||
sites,
|
||||
loading,
|
||||
testingId,
|
||||
onTest,
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: {
|
||||
sites: Site[];
|
||||
loading: boolean;
|
||||
testingId: string | null;
|
||||
onTest: (id: string) => void;
|
||||
onEdit: (id: string) => void;
|
||||
onDelete: (site: Site) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{sites.map((site) => (
|
||||
<SiteCard
|
||||
key={site.id}
|
||||
site={site}
|
||||
testing={testingId === site.id}
|
||||
onTest={() => onTest(site.id)}
|
||||
onEdit={() => onEdit(site.id)}
|
||||
onDelete={() => onDelete(site)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{!loading && sites.length === 0 && <SitesEmptyState />}
|
||||
{loading && <SitesLoadingState />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SitesEmptyState() {
|
||||
return (
|
||||
<div className="col-span-full py-12 text-center text-ink-50">
|
||||
<Globe size={40} className="mx-auto mb-3 text-gray-500" />
|
||||
<p>暂无站点</p>
|
||||
<p className="text-sm mt-1 text-sand-500">
|
||||
点击「添加站点」添加 PT/BT 站点
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SitesLoadingState() {
|
||||
return (
|
||||
<div className="col-span-full py-12 text-center text-ink-50">
|
||||
<RefreshCw size={24} className="mx-auto mb-3 animate-spin" />
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user