fix
This commit is contained in:
parent
dcae1469bf
commit
426bfff6cd
|
|
@ -150,22 +150,24 @@ class ResourceCategoryManager:
|
|||
logger.info(f"Created new category: {title}")
|
||||
return asdict(new_category)
|
||||
|
||||
def update_category(self, category_id: str, title: str = None,
|
||||
ai_prompt: str = None, color: str = None) -> Optional[Dict]:
|
||||
def update_category(self, category_id: str, title: str = None,
|
||||
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
|
||||
self._save_categories()
|
||||
|
||||
|
||||
logger.info(f"Updated category: {category_id}")
|
||||
return asdict(category)
|
||||
return None
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
||||
/// 获取所有资源分类
|
||||
|
|
|
|||
|
|
@ -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()) ||
|
||||
category.ai_prompt.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>
|
||||
|
||||
<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"
|
||||
>
|
||||
<Plus size={20} className="mr-2" />
|
||||
新建分类
|
||||
</button>
|
||||
<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="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"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export interface UpdateCategoryRequest {
|
|||
title?: string
|
||||
ai_prompt?: string
|
||||
color?: string
|
||||
is_active?: boolean
|
||||
}
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue