refactor(layout): 重构应用布局结构和全局副作用处理

- 移除 AppShell 组件,将布局逻辑直接集成到各层级 layout
- 提取全局 Provider 到 AppProviders 组件统一管理
- 移除独立的 ThemeSync 和 QueryProvider 组件
- 将 AntThemeProvider 功能整合到 AppProviders
- 更新用户状态和主题相关的 prop 传递方式
- 优化管理后台菜单结构为全局常量定义
- 迁移页面私有 hooks 到对应页面目录下
- 提取通用 UI 副作用动作为全局 hooks 以减少重复代码
This commit is contained in:
HouYunFei
2026-05-21 11:42:22 +08:00
parent dce6ab2282
commit 603deee962
25 changed files with 151 additions and 257 deletions
+4 -8
View File
@@ -3,11 +3,11 @@
import { FolderPlus, Search } from "lucide-react";
import { type UIEvent, useEffect, useState } from "react";
import { App, Button, Empty, Input, Spin, Tag } from "antd";
import copy from "copy-to-clipboard";
import { PromptCard } from "@/components/prompts/prompt-card";
import { PromptDetailDialog } from "@/components/prompts/prompt-detail-dialog";
import { usePromptList } from "@/components/prompts/use-prompt-list";
import { useCopyText } from "@/hooks/use-copy-text";
import { cn } from "@/lib/utils";
import { useAssetStore } from "@/stores/use-asset-store";
import { ALL_PROMPTS_OPTION, type Prompt } from "@/services/api/prompts";
@@ -19,6 +19,7 @@ export default function PromptsPage() {
const [selectedCategory, setSelectedCategory] = useState(ALL_PROMPTS_OPTION);
const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null);
const addAsset = useAssetStore((state) => state.addAsset);
const copyText = useCopyText();
const { query, items: promptItems, tags: promptTags, categories: promptCategoryOptions, total: totalPrompts } = usePromptList({ keyword: titleKeyword, tags: selectedTags, category: selectedCategory });
useEffect(() => {
@@ -32,11 +33,6 @@ export default function PromptsPage() {
setSelectedTags((items) => items.includes(tag) ? items.filter((item) => item !== tag) : [...items, tag]);
};
const copyPrompt = async (prompt: string) => {
copy(prompt);
message.success("提示词已复制");
};
const savePromptAsset = (item: Prompt) => {
addAsset({ kind: "text", title: item.title, coverUrl: item.coverUrl, tags: item.tags, source: item.category, data: { content: item.prompt }, metadata: { source: "prompt-library", promptId: item.id, githubUrl: item.githubUrl } });
message.success("已加入我的素材");
@@ -93,7 +89,7 @@ export default function PromptsPage() {
<div>
<div className="mx-auto grid max-w-7xl gap-5 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
{promptItems.map((item) => (
<PromptCard key={item.id} item={item} onOpen={() => setSelectedPrompt(item)} onCopy={() => void copyPrompt(item.prompt)} extraAction={<Button size="small" icon={<FolderPlus className="size-3.5" />} onClick={() => savePromptAsset(item)}></Button>} />
<PromptCard key={item.id} item={item} onOpen={() => setSelectedPrompt(item)} onCopy={() => copyText(item.prompt, "提示词已复制")} extraAction={<Button size="small" icon={<FolderPlus className="size-3.5" />} onClick={() => savePromptAsset(item)}></Button>} />
))}
</div>
{promptItems.length === 0 ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="没有找到匹配的提示词" className="py-16" /> : null}
@@ -102,7 +98,7 @@ export default function PromptsPage() {
) : null}
</main>
<PromptDetailDialog prompt={selectedPrompt} onClose={() => setSelectedPrompt(null)} onCopy={(prompt) => void copyPrompt(prompt)} onSaveAsset={savePromptAsset} />
<PromptDetailDialog prompt={selectedPrompt} onClose={() => setSelectedPrompt(null)} onCopy={(prompt) => copyText(prompt, "提示词已复制")} onSaveAsset={savePromptAsset} />
</div>
);
}