fix
This commit is contained in:
@@ -1,14 +1,30 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { Plus, Edit, Trash2, Search, Save, X, Cloud, Users, Palette, BarChart3, Download, Upload } from 'lucide-react'
|
import { Plus, Edit, Trash2, Search, Save, X, Cloud, Users, Palette, BarChart3, Download, Upload } from 'lucide-react'
|
||||||
import {
|
import {
|
||||||
ResourceCategoryServiceV2,
|
ResourceCategoryServiceV2,
|
||||||
ResourceCategoryV2,
|
ResourceCategoryV2,
|
||||||
CategoryBatchItem
|
CategoryBatchItem
|
||||||
} from '../services/resourceCategoryServiceV2'
|
} from '../services/resourceCategoryServiceV2'
|
||||||
|
import {
|
||||||
|
useCategoriesData,
|
||||||
|
useCategoryActions,
|
||||||
|
useCategoryStore
|
||||||
|
} from '../stores/useCategoryStore'
|
||||||
|
|
||||||
const ResourceCategoryPageV2: React.FC = () => {
|
const ResourceCategoryPageV2: React.FC = () => {
|
||||||
const [categories, setCategories] = useState<ResourceCategoryV2[]>([])
|
// 使用 Zustand store 管理分类数据
|
||||||
const [loading, setLoading] = useState(true)
|
const { categories, loading, error } = useCategoriesData()
|
||||||
|
const {
|
||||||
|
loadCategories,
|
||||||
|
refreshCategories,
|
||||||
|
addCategory,
|
||||||
|
updateCategory,
|
||||||
|
removeCategory,
|
||||||
|
clearError,
|
||||||
|
searchCategories
|
||||||
|
} = useCategoryActions()
|
||||||
|
|
||||||
|
// 本地 UI 状态
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [editingCategory, setEditingCategory] = useState<ResourceCategoryV2 | null>(null)
|
const [editingCategory, setEditingCategory] = useState<ResourceCategoryV2 | null>(null)
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||||
@@ -16,7 +32,6 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
const [includeCloud, setIncludeCloud] = useState(true)
|
const [includeCloud, setIncludeCloud] = useState(true)
|
||||||
const [showDisabled, setShowDisabled] = useState(true)
|
const [showDisabled, setShowDisabled] = useState(true)
|
||||||
const [selectedColor, setSelectedColor] = useState<string>('')
|
const [selectedColor, setSelectedColor] = useState<string>('')
|
||||||
const [categoryCount, setCategoryCount] = useState(0)
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
title: '',
|
title: '',
|
||||||
ai_prompt: '',
|
ai_prompt: '',
|
||||||
@@ -35,32 +50,42 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// 使用 store 的 loadCategories 方法
|
||||||
loadCategories()
|
loadCategories()
|
||||||
loadCategoryCount()
|
}, [loadCategories])
|
||||||
}, [includeCloud])
|
|
||||||
|
|
||||||
const loadCategories = async () => {
|
// 获取过滤后的分类列表
|
||||||
try {
|
const getFilteredCategories = () => {
|
||||||
setLoading(true)
|
let filtered = categories
|
||||||
const result = await ResourceCategoryServiceV2.getAllCategories({
|
|
||||||
include_cloud: includeCloud,
|
// 根据搜索词过滤
|
||||||
limit: 200
|
if (searchTerm.trim()) {
|
||||||
})
|
filtered = searchCategories(searchTerm.trim())
|
||||||
setCategories(result)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load categories:', error)
|
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据云端/本地过滤
|
||||||
|
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 loadCategoryCount = async () => {
|
const filteredCategories = getFilteredCategories()
|
||||||
try {
|
|
||||||
const count = await ResourceCategoryServiceV2.getCategoryCount(includeCloud)
|
// 刷新分类数据
|
||||||
setCategoryCount(count)
|
const handleRefresh = async () => {
|
||||||
} catch (error) {
|
await refreshCategories()
|
||||||
console.error('Failed to load category count:', error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCreateCategory = async () => {
|
const handleCreateCategory = async () => {
|
||||||
@@ -73,10 +98,10 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (newCategory) {
|
if (newCategory) {
|
||||||
setCategories([...categories, newCategory])
|
// 使用 store 的 addCategory 方法
|
||||||
|
addCategory(newCategory)
|
||||||
setShowCreateForm(false)
|
setShowCreateForm(false)
|
||||||
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false })
|
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false })
|
||||||
await loadCategoryCount()
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to create category:', error)
|
console.error('Failed to create category:', error)
|
||||||
@@ -98,10 +123,8 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (updatedCategory) {
|
if (updatedCategory) {
|
||||||
const updatedCategories = categories.map(cat =>
|
// 使用 store 的 updateCategory 方法
|
||||||
cat.id === editingCategory.id ? updatedCategory : cat
|
updateCategory(editingCategory.id, updatedCategory)
|
||||||
)
|
|
||||||
setCategories(updatedCategories)
|
|
||||||
setEditingCategory(null)
|
setEditingCategory(null)
|
||||||
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false })
|
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B', is_cloud: false })
|
||||||
}
|
}
|
||||||
@@ -116,8 +139,8 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await ResourceCategoryServiceV2.deleteCategory(categoryId, true)
|
await ResourceCategoryServiceV2.deleteCategory(categoryId, true)
|
||||||
setCategories(categories.filter(cat => cat.id !== categoryId))
|
// 使用 store 的 removeCategory 方法
|
||||||
await loadCategoryCount()
|
removeCategory(categoryId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to delete category:', error)
|
console.error('Failed to delete category:', error)
|
||||||
alert('删除分类失败: ' + (error instanceof Error ? error.message : '未知错误'))
|
alert('删除分类失败: ' + (error instanceof Error ? error.message : '未知错误'))
|
||||||
@@ -132,10 +155,8 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
await ResourceCategoryServiceV2.deactivateCategory(categoryId)
|
await ResourceCategoryServiceV2.deactivateCategory(categoryId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedCategories = categories.map(cat =>
|
// 使用 store 的 updateCategory 方法
|
||||||
cat.id === categoryId ? { ...cat, is_active: isActive } : cat
|
updateCategory(categoryId, { is_active: isActive })
|
||||||
)
|
|
||||||
setCategories(updatedCategories)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to toggle category:', error)
|
console.error('Failed to toggle category:', error)
|
||||||
alert('切换分类状态失败: ' + (error instanceof Error ? error.message : '未知错误'))
|
alert('切换分类状态失败: ' + (error instanceof Error ? error.message : '未知错误'))
|
||||||
@@ -150,47 +171,28 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
alert(`批量导入完成: 成功 ${result.success} 个,失败 ${result.failed} 个`)
|
alert(`批量导入完成: 成功 ${result.success} 个,失败 ${result.failed} 个`)
|
||||||
setShowBatchImport(false)
|
setShowBatchImport(false)
|
||||||
setBatchData('')
|
setBatchData('')
|
||||||
await loadCategories()
|
// 刷新分类数据
|
||||||
await loadCategoryCount()
|
await refreshCategories()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to batch import:', error)
|
console.error('Failed to batch import:', error)
|
||||||
alert('批量导入失败: ' + (error instanceof Error ? error.message : '数据格式错误'))
|
alert('批量导入失败: ' + (error instanceof Error ? error.message : '数据格式错误'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSearchByColor = async (color: string) => {
|
const handleSearchByColor = (color: string) => {
|
||||||
if (color === selectedColor) {
|
if (color === selectedColor) {
|
||||||
// 取消颜色筛选
|
// 取消颜色筛选
|
||||||
setSelectedColor('')
|
setSelectedColor('')
|
||||||
await loadCategories()
|
|
||||||
} else {
|
} else {
|
||||||
// 按颜色筛选
|
// 按颜色筛选
|
||||||
setSelectedColor(color)
|
setSelectedColor(color)
|
||||||
try {
|
|
||||||
const result = await ResourceCategoryServiceV2.getCategoriesByColor(color, {
|
|
||||||
include_cloud: includeCloud
|
|
||||||
})
|
|
||||||
setCategories(result)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to search by color:', error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 过滤逻辑已经在 getFilteredCategories 中处理
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = () => {
|
||||||
if (!searchTerm.trim()) {
|
// 搜索逻辑已经在 getFilteredCategories 中处理
|
||||||
await loadCategories()
|
// 这里只需要触发重新渲染,React 会自动调用 getFilteredCategories
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await ResourceCategoryServiceV2.searchCategories(searchTerm, {
|
|
||||||
include_cloud: includeCloud
|
|
||||||
})
|
|
||||||
setCategories(result)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to search categories:', error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const startEdit = (category: ResourceCategoryV2) => {
|
const startEdit = (category: ResourceCategoryV2) => {
|
||||||
@@ -229,17 +231,7 @@ const ResourceCategoryPageV2: React.FC = () => {
|
|||||||
URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredCategories = categories.filter(category => {
|
|
||||||
// 搜索过滤
|
|
||||||
const matchesSearch = !searchTerm ||
|
|
||||||
category.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
||||||
category.ai_prompt.toLowerCase().includes(searchTerm.toLowerCase())
|
|
||||||
|
|
||||||
// 状态过滤
|
|
||||||
const matchesStatus = showDisabled || category.is_active
|
|
||||||
|
|
||||||
return matchesSearch && matchesStatus
|
|
||||||
})
|
|
||||||
|
|
||||||
// 统计信息
|
// 统计信息
|
||||||
const stats = {
|
const stats = {
|
||||||
|
|||||||
Reference in New Issue
Block a user