2025-09-25 14:20:11 +01:00
|
|
|
"""
|
|
|
|
|
主应用入口 - 个性化饮食推荐助手
|
|
|
|
|
基于基座架构的完整应用
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import Optional
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
# 添加项目根目录到Python路径
|
|
|
|
|
project_root = Path(__file__).parent
|
|
|
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
|
|
|
|
|
|
from core.base import BaseConfig, AppCore, ModuleManager, ModuleType, initialize_app, cleanup_app
|
|
|
|
|
from modules.data_collection import DataCollectionModule
|
|
|
|
|
from modules.ai_analysis import AIAnalysisModule
|
|
|
|
|
from modules.recommendation_engine import RecommendationEngine
|
|
|
|
|
from modules.ocr_calorie_recognition import OCRCalorieRecognitionModule
|
|
|
|
|
from gui.main_window import MainWindow
|
|
|
|
|
import tkinter as tk
|
|
|
|
|
from tkinter import messagebox
|
|
|
|
|
|
|
|
|
|
# 配置日志
|
|
|
|
|
logging.basicConfig(
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
|
|
|
handlers=[
|
|
|
|
|
logging.FileHandler('logs/app.log', encoding='utf-8'),
|
|
|
|
|
logging.StreamHandler()
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DietRecommendationApp:
|
|
|
|
|
"""饮食推荐应用主类"""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.config = self._load_config()
|
|
|
|
|
self.app_core: Optional[AppCore] = None
|
|
|
|
|
self.main_window: Optional[MainWindow] = None
|
|
|
|
|
self.is_running = False
|
|
|
|
|
|
|
|
|
|
def _load_config(self) -> BaseConfig:
|
|
|
|
|
"""加载配置"""
|
|
|
|
|
config = BaseConfig()
|
|
|
|
|
|
2025-09-25 14:34:58 +01:00
|
|
|
# 使用统一API密钥管理
|
|
|
|
|
from config.api_keys import get_qwen_key
|
|
|
|
|
config.qwen_api_key = get_qwen_key()
|
2025-09-25 14:20:11 +01:00
|
|
|
|
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
|
def initialize(self) -> bool:
|
|
|
|
|
"""初始化应用"""
|
|
|
|
|
try:
|
|
|
|
|
logger.info("正在初始化饮食推荐应用...")
|
|
|
|
|
|
|
|
|
|
# 创建必要的目录
|
|
|
|
|
self._create_directories()
|
|
|
|
|
|
|
|
|
|
# 初始化应用核心
|
|
|
|
|
if not initialize_app(self.config):
|
|
|
|
|
logger.error("应用核心初始化失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
self.app_core = AppCore(self.config)
|
|
|
|
|
|
|
|
|
|
# 注册所有模块
|
|
|
|
|
if not self._register_modules():
|
|
|
|
|
logger.error("模块注册失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 启动应用核心
|
|
|
|
|
if not self.app_core.start():
|
|
|
|
|
logger.error("应用核心启动失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
self.is_running = True
|
|
|
|
|
logger.info("饮食推荐应用初始化成功")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"应用初始化失败: {e}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def _create_directories(self):
|
|
|
|
|
"""创建必要的目录"""
|
|
|
|
|
directories = [
|
|
|
|
|
'data',
|
|
|
|
|
'data/users',
|
|
|
|
|
'data/training',
|
|
|
|
|
'models',
|
|
|
|
|
'logs',
|
|
|
|
|
'gui'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for directory in directories:
|
|
|
|
|
Path(directory).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
def _register_modules(self) -> bool:
|
|
|
|
|
"""注册所有模块"""
|
|
|
|
|
try:
|
|
|
|
|
module_manager = ModuleManager(self.config)
|
|
|
|
|
|
|
|
|
|
# 注册数据采集模块
|
|
|
|
|
data_collection_module = DataCollectionModule(self.config)
|
|
|
|
|
if not module_manager.register_module(data_collection_module):
|
|
|
|
|
logger.error("数据采集模块注册失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 注册AI分析模块
|
|
|
|
|
ai_analysis_module = AIAnalysisModule(self.config)
|
|
|
|
|
if not module_manager.register_module(ai_analysis_module):
|
|
|
|
|
logger.error("AI分析模块注册失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 注册推荐引擎模块
|
|
|
|
|
recommendation_module = RecommendationEngine(self.config)
|
|
|
|
|
if not module_manager.register_module(recommendation_module):
|
|
|
|
|
logger.error("推荐引擎模块注册失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 注册OCR热量识别模块
|
|
|
|
|
ocr_module = OCRCalorieRecognitionModule(self.config)
|
|
|
|
|
if not module_manager.register_module(ocr_module):
|
|
|
|
|
logger.error("OCR热量识别模块注册失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 初始化模块管理器
|
|
|
|
|
if not module_manager.initialize_all():
|
|
|
|
|
logger.error("模块管理器初始化失败")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 将模块管理器设置到应用核心
|
|
|
|
|
self.app_core.module_manager = module_manager
|
|
|
|
|
logger.info("所有模块注册成功")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"模块注册失败: {e}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def run_gui(self):
|
|
|
|
|
"""运行GUI界面"""
|
|
|
|
|
try:
|
|
|
|
|
logger.info("启动移动端GUI界面...")
|
|
|
|
|
|
|
|
|
|
# 使用移动端界面,传递应用核心
|
|
|
|
|
from gui.mobile_main_window import MobileMainWindow
|
|
|
|
|
self.main_window = MobileMainWindow(self.app_core)
|
|
|
|
|
|
|
|
|
|
# 启动GUI主循环
|
|
|
|
|
self.main_window.run()
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"GUI启动失败: {e}")
|
|
|
|
|
messagebox.showerror("错误", f"GUI启动失败: {str(e)}")
|
|
|
|
|
|
|
|
|
|
def _on_closing(self):
|
|
|
|
|
"""窗口关闭事件处理"""
|
|
|
|
|
try:
|
|
|
|
|
if messagebox.askokcancel("退出", "确定要退出应用吗?"):
|
|
|
|
|
self.shutdown()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"关闭应用失败: {e}")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
def shutdown(self):
|
|
|
|
|
"""关闭应用"""
|
|
|
|
|
try:
|
|
|
|
|
logger.info("正在关闭应用...")
|
|
|
|
|
|
|
|
|
|
# 关闭GUI
|
|
|
|
|
if self.main_window:
|
|
|
|
|
self.main_window.destroy()
|
|
|
|
|
|
|
|
|
|
# 关闭应用核心
|
|
|
|
|
if self.app_core:
|
|
|
|
|
self.app_core.stop()
|
|
|
|
|
|
|
|
|
|
# 清理资源
|
|
|
|
|
cleanup_app()
|
|
|
|
|
|
|
|
|
|
self.is_running = False
|
|
|
|
|
logger.info("应用关闭完成")
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"应用关闭失败: {e}")
|
|
|
|
|
finally:
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
def get_app_status(self) -> dict:
|
|
|
|
|
"""获取应用状态"""
|
|
|
|
|
if not self.app_core:
|
|
|
|
|
return {"status": "not_initialized"}
|
|
|
|
|
|
|
|
|
|
module_status = self.app_core.module_manager.get_module_status()
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"status": "running" if self.is_running else "stopped",
|
|
|
|
|
"modules": module_status,
|
|
|
|
|
"config": {
|
|
|
|
|
"app_name": self.config.app_name,
|
|
|
|
|
"version": self.config.version,
|
|
|
|
|
"debug": self.config.debug
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
"""主函数"""
|
|
|
|
|
try:
|
|
|
|
|
# 创建应用实例
|
|
|
|
|
app = DietRecommendationApp()
|
|
|
|
|
|
|
|
|
|
# 初始化应用
|
|
|
|
|
if not app.initialize():
|
|
|
|
|
logger.error("应用初始化失败,退出")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
# 运行GUI
|
|
|
|
|
app.run_gui()
|
|
|
|
|
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
logger.info("用户中断,正在退出...")
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"应用运行失败: {e}")
|
|
|
|
|
import traceback
|
|
|
|
|
logger.error(f"详细错误信息: {traceback.format_exc()}")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|