Spaces:
Sleeping
Sleeping
import React, { useState } from 'react'; | |
import Layout from '../components/Layout/Layout'; | |
import Card, { CardHeader, CardContent } from '../components/common/Card'; | |
import Button from '../components/common/Button'; | |
import Input from '../components/common/Input'; | |
import { useApp } from '../contexts/AppContext'; | |
const CategoriesPage: React.FC = () => { | |
const { categories, addCategory, updateCategory, deleteCategory, promptGroups } = useApp(); | |
const [showAddForm, setShowAddForm] = useState(false); | |
const [editingCategoryId, setEditingCategoryId] = useState<string | null>(null); | |
const [categoryName, setCategoryName] = useState(''); | |
const [categoryColor, setCategoryColor] = useState('#007AFF'); | |
const colorOptions = [ | |
{ color: '#007AFF', name: '蓝色' }, | |
{ color: '#4CD964', name: '绿色' }, | |
{ color: '#FF3B30', name: '红色' }, | |
{ color: '#FF9500', name: '橙色' }, | |
{ color: '#FFCC00', name: '黄色' }, | |
{ color: '#5856D6', name: '紫色' }, | |
{ color: '#FF2D55', name: '粉色' }, | |
{ color: '#5AC8FA', name: '浅蓝色' }, | |
]; | |
const resetForm = () => { | |
setCategoryName(''); | |
setCategoryColor('#007AFF'); | |
setShowAddForm(false); | |
setEditingCategoryId(null); | |
}; | |
const handleAddCategory = () => { | |
if (!categoryName.trim()) return; | |
addCategory({ | |
name: categoryName.trim(), | |
color: categoryColor | |
}); | |
resetForm(); | |
}; | |
const handleUpdateCategory = () => { | |
if (!editingCategoryId || !categoryName.trim()) return; | |
updateCategory(editingCategoryId, { | |
name: categoryName.trim(), | |
color: categoryColor | |
}); | |
resetForm(); | |
}; | |
const handleEditCategory = (categoryId: string) => { | |
const category = categories.find(c => c._id === categoryId); | |
if (category) { | |
setCategoryName(category.name); | |
setCategoryColor(category.color); | |
setEditingCategoryId(categoryId); | |
setShowAddForm(false); | |
} | |
}; | |
const handleDeleteCategory = (categoryId: string) => { | |
// 检查是否有使用该分类的提示词组 | |
const usingGroups = promptGroups.filter(group => group.category === categoryId); | |
if (usingGroups.length > 0) { | |
alert(`无法删除此分类,有 ${usingGroups.length} 个提示词组正在使用它。请先修改这些提示词组的分类。`); | |
return; | |
} | |
if (window.confirm('确定要删除此分类吗?')) { | |
deleteCategory(categoryId); | |
} | |
}; | |
const getCategoryUsageCount = (categoryId: string) => { | |
return promptGroups.filter(group => group.category === categoryId).length; | |
}; | |
return ( | |
<Layout title="分类管理"> | |
<div className="flex justify-between items-center mb-4"> | |
<h2 className="text-xl font-bold">分类管理</h2> | |
{!showAddForm && !editingCategoryId && ( | |
<Button | |
variant="primary" | |
onClick={() => setShowAddForm(true)} | |
> | |
添加分类 | |
</Button> | |
)} | |
</div> | |
{(showAddForm || editingCategoryId) && ( | |
<Card className="mb-4"> | |
<CardHeader | |
title={editingCategoryId ? "编辑分类" : "添加分类"} | |
/> | |
<CardContent> | |
<div className="space-y-4"> | |
<Input | |
label="分类名称" | |
value={categoryName} | |
onChange={(e) => setCategoryName(e.target.value)} | |
placeholder="请输入分类名称" | |
required | |
/> | |
<div> | |
<label className="block text-sm font-medium mb-1 text-gray-700"> | |
颜色 | |
</label> | |
<div className="flex flex-wrap gap-2"> | |
{colorOptions.map((option) => ( | |
<div | |
key={option.color} | |
className={` | |
w-8 h-8 rounded-full cursor-pointer | |
${categoryColor === option.color ? 'ring-2 ring-offset-2 ring-gray-400' : ''} | |
`} | |
style={{ backgroundColor: option.color }} | |
onClick={() => setCategoryColor(option.color)} | |
title={option.name} | |
/> | |
))} | |
</div> | |
</div> | |
<div className="flex justify-end space-x-2 mt-4"> | |
<Button | |
variant="secondary" | |
onClick={resetForm} | |
> | |
取消 | |
</Button> | |
<Button | |
variant="primary" | |
onClick={editingCategoryId ? handleUpdateCategory : handleAddCategory} | |
disabled={!categoryName.trim()} | |
> | |
{editingCategoryId ? '保存' : '添加'} | |
</Button> | |
</div> | |
</div> | |
</CardContent> | |
</Card> | |
)} | |
<div className="ios-list"> | |
{categories.map((category) => ( | |
<div key={category._id} className="ios-list-item"> | |
<div | |
className="w-4 h-4 rounded-full mr-3" | |
style={{ backgroundColor: category.color }} | |
/> | |
<div className="ios-list-item-content"> | |
<div className="ios-list-item-title">{category.name}</div> | |
<div className="ios-list-item-subtitle"> | |
使用次数: {getCategoryUsageCount(category._id)} | |
</div> | |
</div> | |
<div className="flex space-x-2"> | |
<button | |
className="text-blue-500 p-2" | |
onClick={() => handleEditCategory(category._id)} | |
> | |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | |
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path> | |
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path> | |
</svg> | |
</button> | |
<button | |
className="text-red-500 p-2" | |
onClick={() => handleDeleteCategory(category._id)} | |
disabled={getCategoryUsageCount(category._id) > 0} | |
> | |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | |
<polyline points="3 6 5 6 21 6"></polyline> | |
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path> | |
<line x1="10" y1="11" x2="10" y2="17"></line> | |
<line x1="14" y1="11" x2="14" y2="17"></line> | |
</svg> | |
</button> | |
</div> | |
</div> | |
))} | |
</div> | |
</Layout> | |
); | |
}; | |
export default CategoriesPage; |