import React, { useEffect, useCallback, useState } from 'react'; import { Search, Sparkles, RotateCcw, TrendingUp, Zap, ArrowLeft, Loader2, X, ExternalLink, Copy, Download } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { useSimilaritySearchStore, useSimilaritySearchSelectors, useSimilaritySearchActions } from '../../store/similaritySearchStore'; import { SimilaritySearchPanel } from '../../components/similarity/SimilaritySearchPanel'; import SimilaritySearchResults from '../../components/similarity/SimilaritySearchResults'; import { SimilaritySearchRequest } from '../../types/similaritySearch'; import { CustomSelect } from '../../components/CustomSelect'; /** * 相似度检索工具页面 * 遵循 Tauri 开发规范和 UI/UX 设计标准 */ const SimilaritySearchTool: React.FC = () => { const navigate = useNavigate(); // 本地状态 const [selectedResult, setSelectedResult] = useState(null); const [showDetailModal, setShowDetailModal] = useState(false); // 状态管理 const { query, selectedThreshold, setQuery, setThreshold, executeSearch, searchWithPagination, changePageSize, loadConfig, clearError, setShowSuggestions, } = useSimilaritySearchStore(); // 选择器 const { useSearchState, useConfigState, useSuggestionsState } = useSimilaritySearchSelectors(); const { quickSearch, resetAll, selectSuggestionAndSearch } = useSimilaritySearchActions(); // 获取状态 const searchState = useSearchState(); const configState = useConfigState(); const suggestionsState = useSuggestionsState(); // 页面初始化 useEffect(() => { loadConfig(); clearError(); }, [loadConfig, clearError]); // 恢复持久化的查询内容 useEffect(() => { const persistedData = localStorage.getItem('similarity-search-storage'); if (persistedData) { try { const parsed = JSON.parse(persistedData); const persistedQuery = parsed.state?.query; if (persistedQuery && persistedQuery.trim() && persistedQuery !== query) { console.log('恢复持久化的查询内容:', persistedQuery); setQuery(persistedQuery); } } catch (e) { console.warn('无法解析持久化的查询内容:', e); } } }, []); // 只在组件挂载时执行一次 // 处理搜索 const handleSearch = useCallback((request: SimilaritySearchRequest) => { executeSearch(request); }, [executeSearch]); // 处理建议选择 const handleSuggestionSelect = useCallback((suggestion: string) => { selectSuggestionAndSearch(suggestion); }, [selectSuggestionAndSearch]); // 处理快速搜索标签点击 const handleQuickTagClick = useCallback((tag: string) => { quickSearch(tag); }, [quickSearch]); // 处理重置 const handleReset = useCallback(() => { // 清除持久化数据 localStorage.removeItem('similarity-search-storage'); // 重置所有状态 resetAll(); }, [resetAll]); // 处理分页 const handlePageChange = useCallback((page: number) => { searchWithPagination(page); }, [searchWithPagination]); // 处理每页显示数量变化 const handlePageSizeChange = useCallback((pageSize: number) => { changePageSize(pageSize); }, [changePageSize]); // 处理结果选择 const handleResultSelect = useCallback((result: any) => { console.log('Selected result:', result); setSelectedResult(result); setShowDetailModal(true); }, []); // 处理外部链接打开 const handleOpenExternal = useCallback((url: string) => { // 直接使用 window.open 打开外部链接 window.open(url, '_blank', 'noopener,noreferrer'); }, []); // 关闭详细信息模态框 const handleCloseDetailModal = useCallback(() => { setShowDetailModal(false); setSelectedResult(null); }, []); // 监听相关性阈值变化,立即重新搜索 useEffect(() => { const request: SimilaritySearchRequest = { query: query.trim(), relevance_threshold: selectedThreshold, page_size: configState.config?.max_results_per_page || 12, page_offset: (searchState.currentPage - 1) * (configState.config?.max_results_per_page || 12), }; executeSearch(request); }, [selectedThreshold]); // 只监听阈值变化 // 返回工具列表 const handleBackToTools = useCallback(() => { navigate('/tools'); }, [navigate]); return (
{/* 页面头部 */}

相似度检索工具

基于AI的智能相似度搜索

{/* 全局搜索状态指示器 */} {searchState.isSearching && (
正在搜索相似内容... 请稍候,AI正在为您分析匹配结果
)} {/* 主要内容 */}
{/* 搜索面板和结果 */}
{/* 搜索面板 */}
{/* 搜索结果 */}
{searchState.results.length > 0 ? ( ) : searchState.error ? (

❌ 搜索出错了

{searchState.error}

) : (

✨ 准备就绪

输入关键词开始搜索

或选择快速标签快速开始

)}
{/* 详细信息模态框 */} {showDetailModal && selectedResult && (
{/* 模态框头部 */}

搜索结果详情

{/* 模态框内容 */}
{/* 图片展示 */}
{selectedResult.style_description}
相关性: {(selectedResult.relevance_score * 100).toFixed(1)}%
{/* 基本信息 */}

风格描述

{selectedResult.style_description || '暂无描述'}

{/* 环境标签 */} {selectedResult.environment_tags && selectedResult.environment_tags.length > 0 && (

环境标签

{selectedResult.environment_tags.map((tag: string, index: number) => ( {tag} ))}
)} {/* 产品信息 */} {selectedResult.products && selectedResult.products.length > 0 && (

产品信息

{selectedResult.products.map((product: any, index: number) => (
{/* 产品类别 */}
{product.category} {product.color_pattern?.rgb_hex && (
)}
{/* 产品描述 */} {product.description && product.description !== "时尚单品" && (
{product.description}
)} {/* 设计风格 */} {product.design_styles && product.design_styles.length > 0 && (
{product.design_styles.map((style: string, styleIndex: number) => ( {style} ))}
)} {/* 颜色信息详细 */} {product.color_pattern && (
色相: {(product.color_pattern.hue * 360).toFixed(0)}° 饱和度: {(product.color_pattern.saturation * 100).toFixed(0)}% 明度: {(product.color_pattern.value * 100).toFixed(0)}%
)}
))}
)}
{/* 操作按钮 */}
)}
); }; export default SimilaritySearchTool;