import React, { useState, useEffect } from 'react' import { Plus, Edit, Trash2, Search, Save, X, Cloud, Users, Palette, BarChart3, Download, Upload } from 'lucide-react' import { ResourceCategoryServiceV2, ResourceCategoryV2, CategoryBatchItem } from '../services/resourceCategoryServiceV2' import { useCategoriesData, useCategoryActions, useCategoryStore } from '../stores/useCategoryStore' const ResourceCategoryPageV2: React.FC = () => { // 使用 Zustand store 管理分类数据 const { categories, loading } = useCategoriesData() const { loadCategories, refreshCategories, addCategory, updateCategory, removeCategory } = useCategoryActions() // 从 store 获取搜索功能 const { searchCategories } = useCategoryStore() // 本地 UI 状态 const [searchTerm, setSearchTerm] = useState('') const [editingCategory, setEditingCategory] = useState(null) const [showCreateForm, setShowCreateForm] = useState(false) const [showBatchImport, setShowBatchImport] = useState(false) const [includeCloud, setIncludeCloud] = useState(true) const [showDisabled, setShowDisabled] = useState(true) const [selectedColor, setSelectedColor] = useState('') const [formData, setFormData] = useState({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false }) const [batchData, setBatchData] = useState('') // 预设颜色选项(扩展版) const presetColors = [ '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#FF7675', '#74B9FF', '#00B894', '#FDCB6E', '#E17055', '#A29BFE', '#FD79A8', '#6C5CE7', '#00CEC9', '#55A3FF', '#FF9F43', '#26DE81', '#FF3838', '#FF9500', '#FFDD00', '#48CAE4', '#9B59B6', '#E74C3C', '#F39C12', '#27AE60', '#3498DB', '#8E44AD', '#34495E', '#95A5A6' ] useEffect(() => { // 使用 store 的 loadCategories 方法 loadCategories() }, [loadCategories]) // 获取过滤后的分类列表 const getFilteredCategories = () => { let filtered = categories // 根据搜索词过滤 if (searchTerm.trim()) { filtered = searchCategories(searchTerm.trim()) } // 根据云端/本地过滤 if (!includeCloud) { filtered = filtered.filter(cat => !cat.is_cloud) } // 根据启用/禁用状态过滤 if (!showDisabled) { filtered = filtered.filter(cat => cat.is_active) } // 根据颜色过滤 if (selectedColor) { filtered = filtered.filter(cat => cat.color === selectedColor) } return filtered } const filteredCategories = getFilteredCategories() // 刷新分类数据 const handleRefresh = async () => { await refreshCategories() } const handleCreateCategory = async () => { try { const newCategory = await ResourceCategoryServiceV2.createCategory( formData.title, formData.ai_prompt, formData.color, formData.is_cloud ) if (newCategory) { // 使用 store 的 addCategory 方法 addCategory(newCategory) setShowCreateForm(false) setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false }) } } catch (error) { console.error('Failed to create category:', error) alert('创建分类失败: ' + (error instanceof Error ? error.message : '未知错误')) } } const handleUpdateCategory = async () => { if (!editingCategory) return try { const updatedCategory = await ResourceCategoryServiceV2.updateCategory( editingCategory.id, { title: formData.title, ai_prompt: formData.ai_prompt, color: formData.color } ) if (updatedCategory) { // 使用 store 的 updateCategory 方法 updateCategory(editingCategory.id, updatedCategory) setEditingCategory(null) setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false }) } } catch (error) { console.error('Failed to update category:', error) alert('更新分类失败: ' + (error instanceof Error ? error.message : '未知错误')) } } const handleDeleteCategory = async (categoryId: string) => { if (!confirm('确定要删除这个分类吗?此操作不可恢复。')) return try { await ResourceCategoryServiceV2.deleteCategory(categoryId, true) // 使用 store 的 removeCategory 方法 removeCategory(categoryId) } catch (error) { console.error('Failed to delete category:', error) alert('删除分类失败: ' + (error instanceof Error ? error.message : '未知错误')) } } const handleToggleCategory = async (categoryId: string, isActive: boolean) => { try { if (isActive) { await ResourceCategoryServiceV2.activateCategory(categoryId) } else { await ResourceCategoryServiceV2.deactivateCategory(categoryId) } // 使用 store 的 updateCategory 方法 updateCategory(categoryId, { is_active: isActive }) } catch (error) { console.error('Failed to toggle category:', error) alert('切换分类状态失败: ' + (error instanceof Error ? error.message : '未知错误')) } } const handleBatchImport = async () => { try { const batchItems: CategoryBatchItem[] = JSON.parse(batchData) const result = await ResourceCategoryServiceV2.batchCreateCategories(batchItems) alert(`批量导入完成: 成功 ${result.success} 个,失败 ${result.failed} 个`) setShowBatchImport(false) setBatchData('') // 刷新分类数据 await refreshCategories() } catch (error) { console.error('Failed to batch import:', error) alert('批量导入失败: ' + (error instanceof Error ? error.message : '数据格式错误')) } } const handleSearchByColor = (color: string) => { if (color === selectedColor) { // 取消颜色筛选 setSelectedColor('') } else { // 按颜色筛选 setSelectedColor(color) } // 过滤逻辑已经在 getFilteredCategories 中处理 } const handleSearch = () => { // 搜索逻辑已经在 getFilteredCategories 中处理 // 这里只需要触发重新渲染,React 会自动调用 getFilteredCategories } const startEdit = (category: ResourceCategoryV2) => { setEditingCategory(category) setFormData({ title: category.title, ai_prompt: category.ai_prompt, color: category.color, is_cloud: category.is_cloud }) setShowCreateForm(false) } const cancelEdit = () => { setEditingCategory(null) setShowCreateForm(false) setShowBatchImport(false) setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false }) setBatchData('') } const exportCategories = () => { const exportData = categories.map(cat => ({ title: cat.title, ai_prompt: cat.ai_prompt, color: cat.color, is_cloud: cat.is_cloud })) const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = 'resource_categories.json' a.click() URL.revokeObjectURL(url) } // 统计信息 const stats = { total: categories.length, active: categories.filter(c => c.is_active).length, cloud: categories.filter(c => c.is_cloud).length, user: categories.filter(c => !c.is_cloud).length } if (loading) { return (
加载中...
) } return (
{/* 页面标题和统计 */}

素材分类管理 V2

基于最新API的增强版分类管理,支持云端分类、批量操作等高级功能

{/* 统计卡片 */}
{stats.total}
总数
{stats.active}
启用
{stats.cloud}
云端
{stats.user}
用户
{/* 搜索和操作栏 */}
{/* 搜索框 */}
setSearchTerm(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent w-full" />
{/* 筛选选项 */}
{/* 操作按钮 */}
{/* 颜色筛选栏 */}
按颜色筛选:
{presetColors.slice(0, 12).map((color) => ( )}
{/* 分类列表 */}
{filteredCategories.map((category) => (
{/* 分类标题和标识 */}

{category.title}

{/* 状态标识 */}
{category.is_cloud && ( 云端 )} {!category.is_active && ( 已禁用 )}
{/* 启用/禁用开关 */}
{/* AI提示词 */}

{category.ai_prompt}

{/* 分类信息 */}
{category.user_id}
创建于 {new Date(category.created_at).toLocaleDateString()}
))}
{/* 空状态 */} {filteredCategories.length === 0 && (
{searchTerm || selectedColor ? '没有找到匹配的分类' : '暂无分类'}
{!searchTerm && !selectedColor && ( )}
)} {/* 创建/编辑表单弹窗 */} {(showCreateForm || editingCategory) && (
{/* 表单标题 */}

{editingCategory ? '编辑分类' : '新建分类'}

{/* 表单内容 */}
{/* 分类标题 */}
setFormData({ ...formData, title: e.target.value })} placeholder="请输入分类标题" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" />
{/* AI识别提示词 */}