This commit is contained in:
root 2025-07-11 00:57:19 +08:00
parent dcae1469bf
commit 426bfff6cd
4 changed files with 89 additions and 24 deletions

View File

@ -151,16 +151,18 @@ class ResourceCategoryManager:
return asdict(new_category)
def update_category(self, category_id: str, title: str = None,
ai_prompt: str = None, color: str = None) -> Optional[Dict]:
ai_prompt: str = None, color: str = None, is_active: bool = None) -> Optional[Dict]:
"""更新分类"""
for i, category in enumerate(self.categories):
if category.id == category_id and category.is_active:
if category.id == category_id:
if title is not None:
category.title = title
if ai_prompt is not None:
category.ai_prompt = ai_prompt
if color is not None:
category.color = color
if is_active is not None:
category.is_active = is_active
category.updated_at = datetime.now().isoformat()
self.categories[i] = category
@ -250,7 +252,8 @@ def main():
category_id,
update_data.get('title'),
update_data.get('ai_prompt'),
update_data.get('color')
update_data.get('color'),
update_data.get('is_active')
)
if result:
rpc.success(result)

View File

@ -14,6 +14,7 @@ pub struct UpdateCategoryRequest {
pub title: Option<String>,
pub ai_prompt: Option<String>,
pub color: Option<String>,
pub is_active: Option<bool>,
}
/// 获取所有资源分类

View File

@ -8,6 +8,7 @@ const ResourceCategoryPage: React.FC = () => {
const [searchTerm, setSearchTerm] = useState('')
const [editingCategory, setEditingCategory] = useState<ResourceCategory | null>(null)
const [showCreateForm, setShowCreateForm] = useState(false)
const [showDisabled, setShowDisabled] = useState(true) // 在管理页面默认显示所有分类
const [formData, setFormData] = useState({
title: '',
ai_prompt: '',
@ -93,6 +94,24 @@ const ResourceCategoryPage: React.FC = () => {
}
}
const handleToggleCategory = async (categoryId: string, isActive: boolean) => {
try {
const response = await ResourceCategoryService.updateCategory(categoryId, {
is_active: isActive
})
if (response.status && response.data) {
const updatedCategories = categories.map(cat =>
cat.id === categoryId ? response.data! : cat
)
setCategories(updatedCategories)
} else {
console.error('切换状态失败:', response.msg || '未知错误')
}
} catch (error) {
console.error('Failed to toggle category:', error)
}
}
const startEdit = (category: ResourceCategory) => {
setEditingCategory(category)
setFormData({
@ -109,10 +128,16 @@ const ResourceCategoryPage: React.FC = () => {
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B' })
}
const filteredCategories = categories.filter(category =>
category.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
const filteredCategories = categories.filter(category => {
// 搜索过滤
const matchesSearch = category.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
category.ai_prompt.toLowerCase().includes(searchTerm.toLowerCase())
)
// 状态过滤:在管理页面显示所有分类,其他地方只显示启用的
const matchesStatus = showDisabled || category.is_active
return matchesSearch && matchesStatus
})
if (loading) {
return (
@ -143,23 +168,40 @@ const ResourceCategoryPage: React.FC = () => {
/>
</div>
<div className="flex items-center space-x-3 ml-4">
{/* 显示禁用分类开关 */}
<label className="flex items-center text-sm text-gray-600">
<input
type="checkbox"
checked={showDisabled}
onChange={(e) => setShowDisabled(e.target.checked)}
className="mr-2"
/>
</label>
<button
onClick={() => {
setShowCreateForm(true)
setEditingCategory(null)
setFormData({ title: '', ai_prompt: '', color: '#FF6B6B' })
}}
className="ml-4 flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
className="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
<Plus size={20} className="mr-2" />
</button>
</div>
</div>
{/* 分类列表 */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredCategories.map((category) => (
<div key={category.id} className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<div key={category.id} className={`bg-white rounded-lg shadow-sm border p-6 transition-all ${
category.is_active
? 'border-gray-200'
: 'border-gray-300 bg-gray-50 opacity-75'
}`}>
{/* 分类标题和颜色 */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center">
@ -167,10 +209,28 @@ const ResourceCategoryPage: React.FC = () => {
className="w-4 h-4 rounded-full mr-3"
style={{ backgroundColor: category.color }}
/>
<h3 className="text-lg font-semibold text-gray-900">{category.title}</h3>
<h3 className={`text-lg font-semibold ${category.is_active ? 'text-gray-900' : 'text-gray-400'}`}>
{category.title}
</h3>
{!category.is_active && (
<span className="ml-2 px-2 py-1 text-xs bg-gray-100 text-gray-500 rounded">
</span>
)}
</div>
<div className="flex items-center space-x-2">
{/* 启用/禁用开关 */}
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
checked={category.is_active}
onChange={(e) => handleToggleCategory(category.id, e.target.checked)}
className="sr-only peer"
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
<button
onClick={() => startEdit(category)}
className="p-2 text-gray-400 hover:text-blue-600 transition-colors"

View File

@ -20,6 +20,7 @@ export interface UpdateCategoryRequest {
title?: string
ai_prompt?: string
color?: string
is_active?: boolean
}
export interface ApiResponse<T> {