""" 主題配置模組 - 定義亮色和深色主題的顏色方案 支援 Gradio UI 和 Plotly 圖表的主題切換 """ # 亮色主題配置 LIGHT_THEME = { "colors": { "primary": "#1f77b4", # 主要顏色 "secondary": "#ff7f0e", # 次要顏色 "accent": "#2ca02c", # 強調色 "background": "#ffffff", # 背景色 "surface": "#f8f9fa", # 表面色 "text": "#212529", # 文字色 "text_secondary": "#6c757d", # 次要文字色 "border": "#dee2e6", # 邊框色 "hover": "#e9ecef", # 懸停色 "success": "#28a745", # 成功色 "warning": "#ffc107", # 警告色 "error": "#dc3545", # 錯誤色 }, "name": "light" } # 深色主題配置 DARK_THEME = { "colors": { "primary": "#4a9eff", # 主要顏色(調整以增加對比度) "secondary": "#ffb366", # 次要顏色 "accent": "#66dd88", # 強調色 "background": "#1a1a1a", # 背景色 "surface": "#2d2d2d", # 表面色 "text": "#e8e8e8", # 文字色 "text_secondary": "#a0a0a0", # 次要文字色 "border": "#404040", # 邊框色 "hover": "#383838", # 懸停色 "success": "#4ade80", # 成功色 "warning": "#facc15", # 警告色 "error": "#ef4444", # 錯誤色 }, "name": "dark" } # 預設主題 DEFAULT_THEME = LIGHT_THEME def get_theme(theme_name="light"): """ 根據主題名稱取得主題配置 Args: theme_name (str): 'light' 或 'dark' Returns: dict: 主題配置字典 """ if theme_name.lower() == "dark": return DARK_THEME return LIGHT_THEME def get_theme_colors(theme_name="light"): """ 取得指定主題的顏色字典 Args: theme_name (str): 'light' 或 'dark' Returns: dict: 顏色變數字典 """ theme = get_theme(theme_name) return theme.get("colors", {}) def create_gradio_theme(theme_name="light"): """ 建立 Gradio 主題配置物件 Args: theme_name (str): 'light' 或 'dark' Returns: gr.themes.Base: Gradio 主題物件 """ import gradio as gr colors = get_theme_colors(theme_name) if theme_name.lower() == "dark": return gr.themes.Base( primary_hue="blue", secondary_hue="orange", ).set( body_background_fill=colors["background"], body_background_fill_secondary=colors["surface"], border_color_accent=colors["accent"], border_color_primary=colors["border"], link_text_color=colors["primary"], link_text_color_hover=colors["accent"], link_text_color_visited=colors["secondary"], ) else: return gr.themes.Base( primary_hue="blue", secondary_hue="orange", ).set( body_background_fill=colors["background"], body_background_fill_secondary=colors["surface"], border_color_accent=colors["accent"], border_color_primary=colors["border"], link_text_color=colors["primary"], link_text_color_hover=colors["accent"], link_text_color_visited=colors["secondary"], ) def get_plotly_theme(theme_name="light"): """ 取得 Plotly 圖表的主題配置 Args: theme_name (str): 'light' 或 'dark' Returns: dict: Plotly 主題參數 """ colors = get_theme_colors(theme_name) if theme_name.lower() == "dark": return { "template": "plotly_dark", "paper_bgcolor": colors["background"], "plot_bgcolor": colors["surface"], "font": { "color": colors["text"], "family": "Arial, sans-serif", "size": 12 }, "colorway": [ colors["primary"], colors["secondary"], colors["accent"], colors["warning"], colors["error"], colors["success"] ] } else: return { "template": "plotly", "paper_bgcolor": colors["background"], "plot_bgcolor": colors["surface"], "font": { "color": colors["text"], "family": "Arial, sans-serif", "size": 12 }, "colorway": [ colors["primary"], colors["secondary"], colors["accent"], colors["warning"], colors["error"], colors["success"] ] } def get_default_theme(): """ 取得預設主題(伺服器端預設值) 當 localStorage 不可用時作為備選方案 Returns: str: 預設主題名稱 ('light') """ return "light" def apply_theme_fallback(theme_name=None): """ 當 localStorage 或其他機制失敗時的備選方案 Args: theme_name (str): 試圖套用的主題名稱,為 None 時使用預設 Returns: str: 實際套用的主題名稱 """ if theme_name is None or theme_name not in ["light", "dark"]: return get_default_theme() return theme_name