feat: 实现AI穿搭方案推荐素材库检索功能

新增功能:
- 为每个穿搭方案添加素材库检索功能
- 智能生成检索条件基于穿搭方案内容
- 调用Google VET API进行素材检索
- 实现分页展示和导航功能

 架构改进:
- 新增MaterialSearchService前端服务
- 新增material_search_commands后端命令
- 新增material_search数据模型
- 遵循Tauri开发规范的组件设计

 UI/UX优化:
- 美观的素材卡片展示
- 流畅的分页导航体验
- 响应式设计和动画效果
- 遵循promptx/frontend-developer标准

 组件结构:
- MaterialSearchPanel: 素材检索面板
- MaterialSearchResults: 搜索结果列表
- MaterialCard: 素材卡片组件
- MaterialSearchPagination: 分页组件

 技术实现:
- TypeScript类型安全
- React Hooks状态管理
- TailwindCSS样式系统
- 错误处理和加载状态
- 无障碍访问支持
This commit is contained in:
imeepos
2025-07-25 15:05:22 +08:00
parent 8f88ace388
commit 82d9ccfe21
17 changed files with 2270 additions and 23 deletions

View File

@@ -12,6 +12,7 @@ import {
Moon,
Sunrise,
Sunset,
Search,
} from 'lucide-react';
import { OutfitRecommendationCardProps } from '../../types/outfitRecommendation';
@@ -23,6 +24,7 @@ export const OutfitRecommendationCard: React.FC<OutfitRecommendationCardProps> =
recommendation,
onSelect,
onSceneSearch,
onMaterialSearch,
showDetails = true,
compact = false,
className = '',
@@ -50,6 +52,14 @@ export const OutfitRecommendationCard: React.FC<OutfitRecommendationCardProps> =
}
}, [recommendation, onSceneSearch]);
// 处理素材检索
const handleMaterialSearch = useCallback((e: React.MouseEvent) => {
e.stopPropagation();
if (onMaterialSearch) {
onMaterialSearch(recommendation);
}
}, [recommendation, onMaterialSearch]);
// 处理展开/收起
const handleToggleExpand = useCallback((e: React.MouseEvent) => {
e.stopPropagation();
@@ -272,17 +282,29 @@ export const OutfitRecommendationCard: React.FC<OutfitRecommendationCardProps> =
<div className="text-xs text-gray-500">
{recommendation.color_theme}
</div>
{onSceneSearch && (
<button
onClick={handleSceneSearch}
className="flex items-center gap-2 px-3 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 transition-colors duration-200 text-sm font-medium"
>
<MapPin className="w-4 h-4" />
<ExternalLink className="w-3 h-3" />
</button>
)}
<div className="flex items-center gap-2">
{onMaterialSearch && (
<button
onClick={handleMaterialSearch}
className="flex items-center gap-2 px-3 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors duration-200 text-sm font-medium"
>
<Search className="w-4 h-4" />
</button>
)}
{onSceneSearch && (
<button
onClick={handleSceneSearch}
className="flex items-center gap-2 px-3 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 transition-colors duration-200 text-sm font-medium"
>
<MapPin className="w-4 h-4" />
<ExternalLink className="w-3 h-3" />
</button>
)}
</div>
</div>
</div>
</div>