import { create } from 'zustand'; import { OutfitSearchState, SearchRequest, DEFAULT_SEARCH_CONFIG, } from '../types/outfitSearch'; import OutfitSearchService from '../services/outfitSearchService'; import IntelligentSearchService from '../services/intelligentSearchService'; /** * 服装搭配搜索状态管理 * 遵循 Tauri 开发规范的状态管理模式 */ export const useOutfitSearchStore = create((set, _get) => ({ // 搜索状态 searchConfig: DEFAULT_SEARCH_CONFIG, searchResults: [], isSearching: false, searchError: null, // 分析状态 analysisResult: null, isAnalyzing: false, analysisError: null, // LLM问答状态 llmResponse: null, isAsking: false, llmError: null, // UI状态 selectedImage: null, showAdvancedFilters: false, currentPage: 1, // 历史记录 searchHistory: [], // 操作方法 updateSearchConfig: (config) => { set((state) => ({ searchConfig: { ...state.searchConfig, ...config }, })); }, executeSearch: async (request) => { set({ isSearching: true, searchError: null }); try { const response = await OutfitSearchService.searchSimilarOutfits(request); set({ searchResults: response.results, isSearching: false, currentPage: Math.floor(request.page_offset / request.page_size) + 1, }); // 添加到搜索历史 const historyItem = { id: Date.now().toString(), query: request.query, config: request.config, results_count: response.total_size, search_time_ms: response.search_time_ms, created_at: new Date().toISOString(), }; set((state) => ({ searchHistory: [historyItem, ...state.searchHistory.slice(0, 9)], // 保留最近10条 })); } catch (error) { console.error('Search failed:', error); set({ isSearching: false, searchError: error instanceof Error ? error.message : '搜索失败', searchResults: [], }); } }, // 智能搜索 executeIntelligentSearch: async (params: { query?: string; imagePath?: string; llmQuery?: string; mode?: 'TEXT' | 'IMAGE' | 'LLM' | 'HYBRID'; }) => { set({ isSearching: true, searchError: null }); try { const result = await IntelligentSearchService.executeIntelligentSearch({ ...params, config: useOutfitSearchStore.getState().searchConfig, }); set({ searchResults: result.searchResponse.results, isSearching: false, currentPage: 1, }); // 如果有分析结果,更新分析状态 if (result.analysisResult) { set({ analysisResult: result.analysisResult, }); } // 如果有LLM响应,更新LLM状态 if (result.llmResponse) { set({ llmResponse: result.llmResponse, }); } // 添加到搜索历史 const historyItem = { id: Date.now().toString(), query: params.query || params.llmQuery || '智能搜索', config: useOutfitSearchStore.getState().searchConfig, results_count: result.searchResponse.total_size, search_time_ms: result.searchResponse.search_time_ms, created_at: new Date().toISOString(), }; set((state) => ({ searchHistory: [historyItem, ...state.searchHistory.slice(0, 9)], })); return result; } catch (error) { console.error('Intelligent search failed:', error); set({ searchError: error instanceof Error ? error.message : '智能搜索失败', isSearching: false, }); throw error; } }, analyzeImage: async (request) => { set({ isAnalyzing: true, analysisError: null }); try { const response = await OutfitSearchService.analyzeOutfitImage(request); set({ analysisResult: response.result, isAnalyzing: false, }); // 基于分析结果生成搜索配置 try { const generatedConfig = await OutfitSearchService.generateSearchConfigFromAnalysis( response.result ); set((state) => ({ searchConfig: { ...state.searchConfig, ...generatedConfig }, })); } catch (configError) { console.warn('Failed to generate search config from analysis:', configError); } } catch (error) { console.error('Image analysis failed:', error); // 提供更友好的错误信息 let errorMessage = '图像分析失败'; if (error instanceof Error) { if (error.message.includes('无法从Gemini响应中提取有效的JSON数据')) { errorMessage = 'AI分析服务返回了不完整的数据,请重试或尝试其他图片'; } else if (error.message.includes('网络')) { errorMessage = '网络连接问题,请检查网络后重试'; } else { errorMessage = error.message; } } set({ isAnalyzing: false, analysisError: errorMessage, analysisResult: null, }); } }, askLLM: async (request) => { set({ isAsking: true, llmError: null }); try { const response = await OutfitSearchService.askLLMOutfitAdvice(request); set({ llmResponse: response, isAsking: false, }); } catch (error) { console.error('LLM query failed:', error); set({ isAsking: false, llmError: error instanceof Error ? error.message : 'LLM问答失败', llmResponse: null, }); } }, clearResults: () => { set({ searchResults: [], searchError: null, currentPage: 1, }); }, clearErrors: () => { set({ searchError: null, analysisError: null, llmError: null, }); }, setSelectedImage: (imagePath) => { set({ selectedImage: imagePath }); // 如果清除了图像,也清除分析结果 if (!imagePath) { set({ analysisResult: null, analysisError: null }); } }, toggleAdvancedFilters: () => { set((state) => ({ showAdvancedFilters: !state.showAdvancedFilters, })); }, loadSearchHistory: async () => { // 这里可以从本地存储或数据库加载搜索历史 // 暂时使用空实现 try { // const history = await loadSearchHistoryFromStorage(); // set({ searchHistory: history }); } catch (error) { console.error('Failed to load search history:', error); } }, })); /** * 搜索相关的辅助函数 */ export const useOutfitSearchActions = () => { const store = useOutfitSearchStore(); return { // 快速搜索 quickSearch: async (query: string) => { const request: SearchRequest = { query, config: store.searchConfig, page_size: 9, page_offset: 0, }; await store.executeSearch(request); }, // 分页搜索 searchWithPagination: async (page: number, pageSize: number = 9) => { const request: SearchRequest = { query: store.searchHistory[0]?.query || 'model', config: store.searchConfig, page_size: pageSize, page_offset: (page - 1) * pageSize, }; await store.executeSearch(request); }, // 基于分析结果搜索 searchFromAnalysis: async () => { if (!store.analysisResult) return; try { const generatedConfig = await OutfitSearchService.generateSearchConfigFromAnalysis( store.analysisResult ); // 更新搜索配置以反映分析结果 store.updateSearchConfig(generatedConfig); const request: SearchRequest = { query: store.analysisResult.style_description || 'model', config: generatedConfig, page_size: 9, page_offset: 0, }; await store.executeSearch(request); } catch (error) { console.error('Failed to search from analysis:', error); } }, // 将分析结果应用到筛选条件 applyAnalysisToFilters: () => { if (!store.analysisResult) return; const analysisResult = store.analysisResult; const newConfig = { ...store.searchConfig }; // 提取类别信息 if (analysisResult.products && analysisResult.products.length > 0) { const categories = analysisResult.products.map(p => p.category); newConfig.categories = [...new Set(categories)]; // 去重 // 设置颜色过滤器 const colorFilters: Record = {}; analysisResult.products.forEach(product => { if (product.color_pattern) { colorFilters[product.category] = { enabled: true, color: product.color_pattern, hue_threshold: 0.05, saturation_threshold: 0.05, value_threshold: 0.20, }; } }); newConfig.color_filters = colorFilters; // 设置设计风格 const designStyles: Record = {}; analysisResult.products.forEach(product => { if (product.design_styles && product.design_styles.length > 0) { designStyles[product.category] = product.design_styles; } }); newConfig.design_styles = designStyles; } else { // 如果没有具体产品信息,使用颜色信息创建通用筛选器 if (analysisResult.dress_color_pattern) { newConfig.color_filters = { 'general': { enabled: true, color: analysisResult.dress_color_pattern, hue_threshold: 0.1, saturation_threshold: 0.1, value_threshold: 0.2, } }; } } // 设置环境标签(过滤掉Unknown) if (analysisResult.environment_tags && analysisResult.environment_tags.length > 0) { const validTags = analysisResult.environment_tags.filter(tag => tag !== 'Unknown'); if (validTags.length > 0) { newConfig.environments = validTags; } } // 更新配置 store.updateSearchConfig(newConfig); }, // 重置所有状态 resetAll: () => { store.clearResults(); store.clearErrors(); store.setSelectedImage(null); store.updateSearchConfig(DEFAULT_SEARCH_CONFIG); useOutfitSearchStore.setState({ analysisResult: null, llmResponse: null, showAdvancedFilters: false, currentPage: 1, }); }, // 导出搜索配置 exportSearchConfig: () => { return JSON.stringify(store.searchConfig, null, 2); }, // 导入搜索配置 importSearchConfig: (configJson: string) => { try { const config = JSON.parse(configJson); store.updateSearchConfig(config); return true; } catch (error) { console.error('Failed to import search config:', error); return false; } }, // 获取搜索统计 getSearchStats: () => { const { searchHistory, searchResults } = store; return { totalSearches: searchHistory.length, averageResultsCount: searchHistory.length > 0 ? searchHistory.reduce((sum, item) => sum + item.results_count, 0) / searchHistory.length : 0, averageSearchTime: searchHistory.length > 0 ? searchHistory.reduce((sum, item) => sum + item.search_time_ms, 0) / searchHistory.length : 0, currentResultsCount: searchResults.length, }; }, }; }; /** * 选择器函数 */ export const useOutfitSearchSelectors = () => { return { // 获取当前搜索状态 useSearchState: () => useOutfitSearchStore((state) => ({ isSearching: state.isSearching, searchError: state.searchError, results: state.searchResults, currentPage: state.currentPage, })), // 获取分析状态 useAnalysisState: () => useOutfitSearchStore((state) => ({ isAnalyzing: state.isAnalyzing, analysisError: state.analysisError, result: state.analysisResult, selectedImage: state.selectedImage, })), // 获取LLM状态 useLLMState: () => useOutfitSearchStore((state) => ({ isAsking: state.isAsking, llmError: state.llmError, response: state.llmResponse, })), // 获取UI状态 useUIState: () => useOutfitSearchStore((state) => ({ showAdvancedFilters: state.showAdvancedFilters, searchConfig: state.searchConfig, })), // 检查是否有活动筛选 useHasActiveFilters: () => useOutfitSearchStore((state) => { const { searchConfig } = state; return ( searchConfig.categories.length > 0 || searchConfig.environments.length > 0 || Object.values(searchConfig.color_filters).some(f => f.enabled) || Object.values(searchConfig.design_styles).some(styles => styles.length > 0) ); }), }; }; export default useOutfitSearchStore;