PawMatchAI / search_history.py
DawnC's picture
Upload 6 files
71c450e
raw
history blame
9.94 kB
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 """
<div style='
text-align: center;
padding: 40px 20px;
color: #666;
background: linear-gradient(to right, rgba(66, 153, 225, 0.05), rgba(72, 187, 120, 0.05));
border-radius: 10px;
margin: 20px 0;
'>
<p style='
font-size: 1.1em;
margin: 0;
background: linear-gradient(90deg, #4299e1, #48bb78);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 600;
'>
No search history yet. Try making some breed recommendations!
</p>
</div>
"""
html = "<div class='history-container'>"
for entry in reversed(history_data):
timestamp = entry.get('timestamp', 'Unknown time')
search_type = entry.get('search_type', 'criteria')
results = entry.get('results', [])
# 根據搜尋類型使用不同的標題樣式
type_label = "Criteria History" if search_type == "criteria" else "Description History"
type_color = "#4299e1" if search_type == "criteria" else "#48bb78" # 藍色vs綠色
html += f"""
<div class="history-entry">
<div class="history-header" style="border-left: 4px solid {type_color}; padding-left: 10px;">
<span class="timestamp">🕒 {timestamp}</span>
<span class="search-type" style="color: {type_color}; font-weight: bold; margin-left: 10px;">
{type_label}
</span>
</div>
"""
if search_type == "criteria":
# 原有的條件搜尋顯示邏輯
prefs = entry.get('preferences', {})
html += f"""
<div class="params-list">
<h4>Search Parameters:</h4>
<ul>
<li><span class="param-label">Living Space:</span> {prefs.get('living_space', 'N/A')}</li>
<li><span class="param-label">Exercise Time:</span> {prefs.get('exercise_time', 'N/A')} minutes</li>
<li><span class="param-label">Grooming:</span> {prefs.get('grooming_commitment', 'N/A')}</li>
<li><span class="param-label">Experience:</span> {prefs.get('experience_level', 'N/A')}</li>
<li><span class="param-label">Children at Home:</span> {"Yes" if prefs.get('has_children') else "No"}</li>
<li><span class="param-label">Noise Tolerance:</span> {prefs.get('noise_tolerance', 'N/A')}</li>
</ul>
</div>
"""
else:
# Description 搜尋的顯示邏輯
description = entry.get('description', 'No description provided')
html += f"""
<div class="description-section">
<h4>Search Description:</h4>
<p class="user-description">{description}</p>
</div>
"""
# 共用的結果顯示邏輯
html += """
<div class="results-list">
<h4>Top 10 Breed Matches:</h4>
<div class="breed-list">
"""
if results:
for i, result in enumerate(results[:10], 1):
breed_name = result.get('breed', 'Unknown breed').replace('_', ' ')
score = result.get('overall_score', result.get('final_score', 0))
html += f"""
<div class="breed-item">
<div class="breed-info">
<span class="breed-rank">#{i}</span>
<span class="breed-name">{breed_name}</span>
<span class="breed-score">{score*100:.1f}%</span>
</div>
</div>
"""
html += """
</div>
</div>
</div>
"""
html += "</div>"
return html
except Exception as e:
print(f"Error formatting history: {str(e)}")
print(traceback.format_exc())
return f"""
<div style='text-align: center; padding: 20px; color: #dc2626;'>
Error formatting history. Please try refreshing the page.
<br>Error details: {str(e)}
</div>
"""
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:
"""保存搜索結果
Args:
user_preferences: 使用者偏好設定 (僅用於criteria搜尋)
results: 推薦結果列表
search_type: 搜尋類型 ("criteria" 或 "description")
description: 使用者輸入的描述 (僅用於description搜尋)
"""
return self.history_manager.save_history(
user_preferences=user_preferences,
results=results,
search_type=search_type,
description=description
)
def create_history_component():
"""只創建實例"""
return SearchHistoryComponent()
def create_history_tab(history_component: SearchHistoryComponent):
"""創建歷史紀錄的頁面
Args:
history_component: 已创建的历史组件实例
"""
with gr.TabItem("Recommendation Search History"):
gr.HTML("""
<div style='text-align: center; padding: 20px;'>
<h3 style='
color: #2D3748;
margin-bottom: 10px;
font-size: 1.5em;
background: linear-gradient(90deg, #4299e1, #48bb78);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 600;
'>Search History</h3>
<div style='
text-align: center;
padding: 20px 0;
margin: 15px 0;
background: linear-gradient(to right, rgba(66, 153, 225, 0.1), rgba(72, 187, 120, 0.1));
border-radius: 10px;
'>
<p style='
font-size: 1.2em;
margin: 0;
padding: 0 20px;
line-height: 1.5;
background: linear-gradient(90deg, #4299e1, #48bb78);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 600;
'>
View your previous breed recommendations and search preferences
</p>
</div>
</div>
""")
with gr.Row():
with gr.Column(scale=4):
history_display = gr.HTML()
with gr.Row():
with gr.Column(scale=1):
clear_history_btn = gr.Button(
"🗑️ Clear History",
variant="secondary",
size="sm"
)
with gr.Column(scale=1):
refresh_btn = gr.Button(
"🔄 Refresh",
variant="secondary",
size="sm"
)
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"
)