diff --git a/apps/web/src/pages/titles/TitleLibrary.tsx b/apps/web/src/pages/titles/TitleLibrary.tsx index 5becdbca6..9a102fa01 100644 --- a/apps/web/src/pages/titles/TitleLibrary.tsx +++ b/apps/web/src/pages/titles/TitleLibrary.tsx @@ -4,731 +4,132 @@ * 支持:标题卡片展示、AI 生成标题、复制/编辑/删除、收藏、分类筛选、搜索 * 对接后端真实 API(GET/POST/PUT/DELETE /titles) */ -import React, { useMemo, useState, useCallback } from "react" -import { Modal as AntModal, message, Popconfirm } from "antd" -import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" -import { - PlusOutlined, - SearchOutlined, - DeleteOutlined, - EditOutlined, - CopyOutlined, - CheckOutlined, - RobotOutlined, - StarOutlined, - StarFilled, - FileTextOutlined, -} from "@ant-design/icons" -import { Button, Input, Select } from "@/components/ui" -import { getTitles, createTitle, updateTitle, deleteTitle, type TitleItem } from "@/api/titles" +import React from "react" +import { useTitleLibrary } from "./hooks/useTitleLibrary" +import { useTitleEdit } from "./hooks/useTitleEdit" +import { useTitleAI } from "./hooks/useTitleAI" +import { CategorySidebar } from "./components/title-library/CategorySidebar" +import { FilterBar } from "./components/title-library/FilterBar" +import { TitleGrid } from "./components/title-library/TitleGrid" +import { CreateTitleModal } from "./components/title-library/CreateTitleModal" +import { AIGenerateModal } from "./components/title-library/AIGenerateModal" import "./titles.css" -/* ============================================================ - * 类型 - * ============================================================ */ -type TitleType = "hot" | "normal" | "creative" -type Industry = "general" | "food" | "tech" | "beauty" | "education" | "travel" -type Frequency = "all" | "high" | "medium" | "low" - -interface TitleData { - id: string - content: string - type: TitleType - industry: Industry - category: string - usageCount: number - isFavorited: boolean - createdAt: string -} - -/** 后端 TitleItem → 前端 TitleData 映射 */ -const toTitleData = (item: TitleItem): TitleData => ({ - id: item.id, - content: item.content, - type: (item.category as TitleType) || "normal", - industry: "general", - category: item.category || "未分类", - usageCount: 0, - isFavorited: false, - createdAt: item.created_at?.slice(0, 10) || "", -}) - -/* ============================================================ - * 工具函数 - * ============================================================ */ -const typeLabel = (type: TitleType): string => { - switch (type) { - case "hot": - return "爆款" - case "normal": - return "常规" - case "creative": - return "创意" - } -} - -/** 复制文本到剪贴板 */ -const copyToClipboard = async (text: string): Promise => { - try { - await navigator.clipboard.writeText(text) - return true - } catch { - /* 降级方案 */ - const textarea = document.createElement("textarea") - textarea.value = text - textarea.style.position = "fixed" - textarea.style.opacity = "0" - document.body.appendChild(textarea) - textarea.select() - try { - document.execCommand("copy") - return true - } catch { - return false - } finally { - document.body.removeChild(textarea) - } - } -} - -/* ============================================================ - * TitleCard 组件 - * ============================================================ */ -const TitleCard: React.FC<{ - title: TitleData - isEditing: boolean - editText: string - onEditChange: (text: string) => void - onStartEdit: () => void - onSaveEdit: () => void - onCancelEdit: () => void - onCopy: () => void - onDelete: () => void - onToggleFavorite: () => void -}> = ({ - title, - isEditing, - editText, - onEditChange, - onStartEdit, - onSaveEdit, - onCancelEdit, - onCopy, - onDelete, - onToggleFavorite, -}) => { - return ( -
- {/* 收藏按钮 */} - - - {/* 标题文本 / 编辑区 */} - {isEditing ? ( -