This commit is contained in:
root 2025-07-11 01:22:52 +08:00
parent d6dd6109c0
commit c973aaa58c
2 changed files with 76 additions and 116 deletions

View File

@ -53,57 +53,7 @@ class ResourceCategoryManager:
def _create_default_categories(self) -> List[ResourceCategory]:
"""创建默认分类"""
now = datetime.now().isoformat()
default_categories = [
ResourceCategory(
id=str(uuid.uuid4()),
title="人物视频",
ai_prompt="包含人物、人脸、人体的视频素材",
color="#FF6B6B",
created_at=now,
updated_at=now
),
ResourceCategory(
id=str(uuid.uuid4()),
title="风景视频",
ai_prompt="自然风景、城市景观、建筑物的视频素材",
color="#4ECDC4",
created_at=now,
updated_at=now
),
ResourceCategory(
id=str(uuid.uuid4()),
title="动物视频",
ai_prompt="动物、宠物、野生动物的视频素材",
color="#45B7D1",
created_at=now,
updated_at=now
),
ResourceCategory(
id=str(uuid.uuid4()),
title="音乐音效",
ai_prompt="背景音乐、音效、声音素材",
color="#96CEB4",
created_at=now,
updated_at=now
),
ResourceCategory(
id=str(uuid.uuid4()),
title="文字图片",
ai_prompt="文字、标题、图标、图形素材",
color="#FFEAA7",
created_at=now,
updated_at=now
),
ResourceCategory(
id=str(uuid.uuid4()),
title="特效素材",
ai_prompt="转场、特效、动画、滤镜素材",
color="#DDA0DD",
created_at=now,
updated_at=now
)
]
default_categories = []
self._save_categories(default_categories)
return default_categories
@ -123,7 +73,7 @@ class ResourceCategoryManager:
def get_all_categories(self) -> List[Dict]:
"""获取所有分类"""
return [asdict(category) for category in self.categories if category.is_active]
return [asdict(category) for category in self.categories]
def get_category_by_id(self, category_id: str) -> Optional[Dict]:
"""根据ID获取分类"""
@ -192,9 +142,7 @@ class ResourceCategoryManager:
results = []
for category in self.categories:
if (category.is_active and
(keyword in category.title.lower() or
keyword in category.ai_prompt.lower())):
if (keyword in category.title.lower() or keyword in category.ai_prompt.lower()):
results.append(asdict(category))
return results

View File

@ -203,70 +203,79 @@ const ProjectManagePage: React.FC = () => {
{/* 项目列表 */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredProjects.map((project) => (
<div key={project.id} className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
{/* 项目标题 */}
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">{project.name}</h3>
<div className="flex items-center space-x-2">
<button
onClick={() => handleOpenDirectory(project.id)}
className="p-2 text-gray-400 hover:text-green-600 transition-colors"
title="打开目录"
>
<FolderOpen size={16} />
</button>
<button
onClick={() => startEdit(project)}
className="p-2 text-gray-400 hover:text-blue-600 transition-colors"
title="编辑"
>
<Edit size={16} />
</button>
<button
onClick={() => handleDeleteProject(project.id)}
className="p-2 text-gray-400 hover:text-red-600 transition-colors"
title="删除"
>
<Trash2 size={16} />
</button>
</div>
<div key={project.id} className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
{/* 商品图片 */}
<div className="h-32 bg-gray-100 overflow-hidden">
{project.product_image ? (
<>
<img
src={project.product_image.startsWith('http') ? project.product_image : `file://${project.product_image}`}
alt={project.product_name || project.name}
className="w-full h-full object-cover"
onError={(e) => {
const target = e.target as HTMLImageElement
target.style.display = 'none'
const fallback = target.parentElement?.querySelector('.image-fallback') as HTMLElement
if (fallback) {
fallback.style.display = 'flex'
}
}}
/>
<div className="image-fallback hidden w-full h-full bg-gray-200 flex items-center justify-center">
<Package size={32} className="text-gray-400" />
</div>
</>
) : (
<div className="w-full h-full bg-gray-200 flex items-center justify-center">
<Package size={32} className="text-gray-400" />
</div>
)}
</div>
{/* 项目信息 */}
<div className="space-y-3">
{/* 本地目录 */}
<div>
<p className="text-sm text-gray-600">:</p>
<p className="text-sm text-gray-900 truncate" title={project.local_directory}>
{project.local_directory}
</p>
<div className="p-6">
{/* 项目标题 */}
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">{project.name}</h3>
<div className="flex items-center space-x-2">
<button
onClick={() => handleOpenDirectory(project.id)}
className="p-2 text-gray-400 hover:text-green-600 transition-colors"
title="打开目录"
>
<FolderOpen size={16} />
</button>
<button
onClick={() => startEdit(project)}
className="p-2 text-gray-400 hover:text-blue-600 transition-colors"
title="编辑"
>
<Edit size={16} />
</button>
<button
onClick={() => handleDeleteProject(project.id)}
className="p-2 text-gray-400 hover:text-red-600 transition-colors"
title="删除"
>
<Trash2 size={16} />
</button>
</div>
</div>
{/* 商品信息 */}
{project.product_name && (
<div>
<p className="text-sm text-gray-600">:</p>
<p className="text-sm text-gray-900">{project.product_name}</p>
</div>
)}
{/* 商品图片 */}
{project.product_image && (
<div>
<p className="text-sm text-gray-600">:</p>
<div className="flex items-center space-x-2">
<Package size={16} className="text-gray-400" />
<p className="text-sm text-gray-900 truncate flex-1" title={project.product_image}>
{project.product_image.split('/').pop()}
</p>
{/* 项目信息 */}
<div className="space-y-3">
{/* 商品信息 */}
{project.product_name && (
<div>
<p className="text-sm text-gray-600">:</p>
<p className="text-sm text-gray-900">{project.product_name}</p>
</div>
</div>
)}
)}
{/* 创建时间 */}
<div className="text-xs text-gray-400 pt-2 border-t border-gray-100">
{new Date(project.created_at).toLocaleDateString()}
{/* 创建时间 */}
<div className="text-xs text-gray-400 pt-2 border-t border-gray-100">
{new Date(project.created_at).toLocaleDateString()}
</div>
</div>
</div>
</div>
@ -391,16 +400,19 @@ const ProjectManagePage: React.FC = () => {
<p className="text-xs text-gray-500 mb-1">:</p>
<div className="w-20 h-20 border border-gray-200 rounded-lg overflow-hidden bg-gray-50 flex items-center justify-center">
<img
src={`file://${formData.product_image}`}
src={formData.product_image.startsWith('http') ? formData.product_image : `file://${formData.product_image}`}
alt="商品图片预览"
className="w-full h-full object-cover"
onError={(e) => {
const target = e.target as HTMLImageElement
target.style.display = 'none'
target.nextElementSibling!.classList.remove('hidden')
const fallback = target.parentElement?.querySelector('.fallback-text') as HTMLElement
if (fallback) {
fallback.style.display = 'block'
}
}}
/>
<div className="hidden text-xs text-gray-400 text-center p-2">
<div className="fallback-text hidden text-xs text-gray-400 text-center p-2">
</div>
</div>