#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 路由模組 - Blueprint 註冊中心 將所有路由模組集中管理,方便 app.py 統一註冊 重構狀態: 所有模組已獨立化並啟用: - system_routes: 系統設定、日誌、備份 (完全獨立) - edm_routes: EDM 與節慶儀表板 (完全獨立) - monthly_routes: 月結分析 (完全獨立) - dashboard_routes: 首頁商品看板 (完全獨立) - daily_sales_routes: 當日業績分析 (完全獨立) - api_routes: 通用 API (使用 task_runner, dashboard_routes) - export_routes: 匯出功能 (使用 dashboard_routes, cache_service) - import_routes: 匯入功能 (使用 cache_service) - sales_routes: 業績分析 (延遲導入 app.py 複雜函數) 啟用方式: 1. 在 config.py 中將對應的 USE_MODULAR_ROUTES[key] 設為 True 2. 重啟應用程式 3. app.py 中的對應路由會自動被跳過 (cleanup_duplicate_routes) 4. url_for 向後相容透過 register_endpoint_aliases 實現 """ from config import USE_MODULAR_ROUTES # 記錄已被模組化路由覆蓋的端點名稱 MODULAR_ENDPOINTS = set() def register_blueprints(app): """ 註冊所有 Blueprint 到 Flask app Args: app: Flask 應用程式實例 """ global MODULAR_ENDPOINTS registered = [] errors = [] # ============================================================ # 第一階段:完全獨立的模組(無 app.py 依賴) # 透過 config.USE_MODULAR_ROUTES 控制是否啟用 # ============================================================ # 系統管理路由 (設定、日誌、備份、分類管理) if USE_MODULAR_ROUTES.get('system', False): try: from routes.system_routes import system_bp app.register_blueprint(system_bp) registered.append('system_routes') # 記錄此模組覆蓋的端點 MODULAR_ENDPOINTS.update([ 'health_check', 'prometheus_metrics', 'settings', 'system_settings_page', 'add_category', 'update_category', 'delete_category', 'test_url', 'show_logs', 'get_logs_api', 'trigger_backup', 'download_backup' ]) except ImportError as e: errors.append(f"system_routes: {e}") # EDM 與節慶儀表板路由 if USE_MODULAR_ROUTES.get('edm', False): try: from routes.edm_routes import edm_bp app.register_blueprint(edm_bp) registered.append('edm_routes') MODULAR_ENDPOINTS.update(['edm_dashboard', 'festival_dashboard']) except ImportError as e: errors.append(f"edm_routes: {e}") # 月結分析路由 if USE_MODULAR_ROUTES.get('monthly', False): try: from routes.monthly_routes import monthly_bp app.register_blueprint(monthly_bp) registered.append('monthly_routes') MODULAR_ENDPOINTS.update(['monthly_summary_analysis_page', 'get_monthly_summary_data']) except ImportError as e: errors.append(f"monthly_routes: {e}") # 商品看板路由 (首頁) if USE_MODULAR_ROUTES.get('dashboard', False): try: from routes.dashboard_routes import dashboard_bp app.register_blueprint(dashboard_bp) registered.append('dashboard_routes') MODULAR_ENDPOINTS.update(['index', 'brand_assets']) except ImportError as e: errors.append(f"dashboard_routes: {e}") # 當日業績路由 if USE_MODULAR_ROUTES.get('daily_sales', False): try: from routes.daily_sales_routes import daily_sales_bp app.register_blueprint(daily_sales_bp) registered.append('daily_sales_routes') MODULAR_ENDPOINTS.update([ 'daily_sales', 'export_daily_sales_category', 'export_marketing_summary_excel' ]) except ImportError as e: errors.append(f"daily_sales_routes: {e}") # ============================================================ # 第二階段:有 app.py 依賴的模組(暫時保留在 app.py) # ============================================================ # 通用 API 路由 - 依賴: scheduled_job_wrapper, get_dashboard_stats if USE_MODULAR_ROUTES.get('api', False): try: from routes.api_routes import api_bp app.register_blueprint(api_bp) registered.append('api_routes') MODULAR_ENDPOINTS.update([ 'trigger_task', 'trigger_edm_task', 'trigger_festival_task', 'trigger_momo_notification', 'trigger_edm_notification', 'test_notification', 'get_price_history', 'get_price_change_details' ]) except ImportError as e: errors.append(f"api_routes: {e}") # 匯出功能路由 - 依賴: get_consolidated_data, _SALES_PROCESSED_CACHE if USE_MODULAR_ROUTES.get('export', False): try: from routes.export_routes import export_bp app.register_blueprint(export_bp) registered.append('export_routes') except ImportError as e: errors.append(f"export_routes: {e}") # 匯入功能路由 - 依賴: _SALES_DF_CACHE, _SALES_PROCESSED_CACHE if USE_MODULAR_ROUTES.get('import', False): try: from routes.import_routes import import_bp app.register_blueprint(import_bp) registered.append('import_routes') except ImportError as e: errors.append(f"import_routes: {e}") # 業績分析路由 - 依賴: 多個複雜函數 if USE_MODULAR_ROUTES.get('sales', False): try: from routes.sales_routes import sales_bp app.register_blueprint(sales_bp) registered.append('sales_routes') MODULAR_ENDPOINTS.update([ 'sales_analysis', 'growth_analysis', 'api_sales_table_data', 'api_sales_table_data_pandas', 'api_sales_top_detail', 'api_export_top_detail', 'api_yoy_comparison' ]) except ImportError as e: errors.append(f"sales_routes: {e}") # AI 推薦路由 - Ollama LLM 整合 if USE_MODULAR_ROUTES.get('ai', False): try: from routes.ai_routes import ai_bp app.register_blueprint(ai_bp) registered.append('ai_routes') MODULAR_ENDPOINTS.update([ 'ai_recommend', 'ai_status', 'ai_trends', 'ai_weather', 'ai_generate_copy', 'ai_recommend_products', 'ai_analyze_weather_products', 'ai_batch_generate_copy' ]) except ImportError as e: errors.append(f"ai_routes: {e}") # 輸出註冊結果 if registered: print(f"✅ 已註冊路由模組: {', '.join(registered)}") if errors: for err in errors: print(f"⚠️ 模組載入失敗: {err}") if not registered and not errors: print("ℹ️ 路由模組重構中,透過 config.USE_MODULAR_ROUTES 控制啟用") def is_endpoint_modular(endpoint_name): """ 檢查指定的端點是否已被模組化路由覆蓋 Args: endpoint_name: 端點函數名稱 Returns: bool: True 表示已被模組化,app.py 應跳過此路由 """ return endpoint_name in MODULAR_ENDPOINTS