import gradio as gr import traceback from typing import Optional, Dict, List from history_manager import UserHistoryManager class SearchHistoryComponent : def __init__ ( self ): """初始化搜尋歷史組件""" self.history_manager = UserHistoryManager() def format_history_html ( self, history_data: Optional [ List [ Dict ]] = None ) -> str : try : if history_data is None : history_data = self.history_manager.get_history() if not history_data: return """

No search history yet. Try making some breed recommendations!

""" html = "
" # 對歷史記錄進行反轉,最新的顯示在前面 for entry in reversed (history_data): timestamp = entry.get( 'timestamp' , 'Unknown time' ) search_type = entry.get( 'search_type' , 'criteria' ) results = entry.get( 'results' , []) # 顯示時間戳記和搜尋類型 html += f"""
🕒 {timestamp} Search History
""" # 顯示搜尋參數 if search_type == "criteria" : prefs = entry.get( 'preferences' , {}) html += f"""

Search Parameters:

  • Living Space: {prefs.get( 'living_space' , 'N/A' )}
  • Exercise Time: {prefs.get( 'exercise_time' , 'N/A' )} minutes
  • Grooming: {prefs.get( 'grooming_commitment' , 'N/A' )}
  • Size Preference: {prefs.get( 'size_preference' , 'N/A' )}
  • Experience: {prefs.get( 'experience_level' , 'N/A' )}
  • Children at Home: { "Yes" if prefs.get( 'has_children' ) else "No" }
  • Noise Tolerance: {prefs.get( 'noise_tolerance' , 'N/A' )}
""" # 關鍵修改:確保結果部分始終顯示 if results: # 只有在有結果時才顯示結果區域 html += """

Top 15 Breed Matches:

""" # 顯示每個推薦結果 for i, result in enumerate (results[: 15 ], 1 ): breed = result.get( 'breed' , 'Unknown breed' ) score = result.get( 'overall_score' , 0 ) # 改用overall_score if isinstance (score, ( int , float )): # 確保分數是數字 score = float (score) * 100 # 轉換為百分比 html += f"""
#{i} {breed.replace('_', ' ')} {score:.1f}%
""" html += """
""" html += "
" # 關閉history-entry div html += "
" # 關閉history-container div return html except Exception as e: print ( f"Error formatting history: { str (e)} " ) print (traceback.format_exc()) return f"""
Error formatting history. Please try refreshing the page.
Error details: { str (e)}
""" def clear_history ( self ) -> str : """清除所有搜尋紀錄""" try : success = self.history_manager.clear_all_history() print ( f"Clear history result: {success} " ) return self.format_history_html() except Exception as e: print ( f"Error in clear_history: { str (e)} " ) print (traceback.format_exc()) return "Error clearing history" def refresh_history ( self ) -> str : """刷新歷史記錄顯示""" try : return self.format_history_html() except Exception as e: print ( f"Error in refresh_history: { str (e)} " ) return "Error refreshing history" def save_search ( self, user_preferences: Optional [ dict ] = None , results: list = None , search_type: str = "criteria" , description: str = None ) -> bool : """ 儲存搜尋結果到歷史記錄 這個方法負責處理搜尋結果的保存,並確保只保存前15個最相關的推薦結果。 在儲存之前,會處理結果資料確保格式正確且包含所需的所有資訊。 Args: user_preferences: 使用者偏好設定(僅用於criteria搜尋) 包含所有搜尋條件如居住空間、運動時間等 results: 推薦結果列表 包含所有推薦的狗品種及其評分 search_type: 搜尋類型("criteria" 或"description") 用於標識搜尋方式 description: 用戶輸入的描述(僅用於description搜尋) 用於自然語言搜尋時的描述文本 Returns: bool: 表示保存是否成功 """ # 首先確保結果不為空且為列表 if results and isinstance (results, list ): # 只取前15個結果 processed_results = [] for result in results[: 15 ]: # 限制為前15個結果 # 確保每個結果都包含必要的信息 if isinstance (result, dict ): processed_result = { 'breed' : result.get( 'breed' , 'Unknown' ), 'overall_score' : result.get( 'overall_score' , result.get( 'final_score' , 0 )), 'rank' : result.get( 'rank' , 0 ), 'base_score' : result.get( 'base_score' , 0 ), 'bonus_score' : result.get( 'bonus_score' , 0 ), 'scores' : result.get( 'scores' , {}) } processed_results.append(processed_result) else : # 如果沒有結果,創建空列表 processed_results = [] # 調用history_manager 的save_history 方法保存處理過的結果 return self.history_manager.save_history( user_preferences=user_preferences, results=processed_results, # 使用處理過的結果 search_type= 'criteria' ) def create_history_component (): """只建立實例""" return SearchHistoryComponent() def create_history_tab ( history_component: SearchHistoryComponent ): """創建歷史紀錄的頁面 Args: history_component: """ with gr.TabItem( "Recommendation Search History" ): gr.HTML( """

Search History

View your previous breed recommendations and search preferences

""" ) with gr.Row(): with gr.Column(scale= 4 ): history_display = gr.HTML() with gr.Row(equal_height= True ): with gr.Column(scale= 1 ): clear_history_btn = gr.Button( "🗑️ Clear History" , variant= "primary" , elem_classes= "custom-btn clear-btn" ) with gr.Column(scale= 1 ): refresh_btn = gr.Button( "🔄 Refresh" , variant= "primary" , elem_classes= "custom-btn refresh-btn" ) history_display.value = history_component.format_history_html() clear_history_btn.click( fn=history_component.clear_history, outputs=[history_display], api_name= "clear_history" ) refresh_btn.click( fn=history_component.refresh_history, outputs=[history_display], api_name= "refresh_history" )