Spaces:
Sleeping
Sleeping
| """ | |
| FastAPI 应用入口 | |
| 汇率换算服务主程序 | |
| """ | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, Request | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.templating import Jinja2Templates | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import HTMLResponse | |
| from app.config import get_settings | |
| from app.services.exchange_service import ExchangeRateService | |
| from app.services.scheduler import RateScheduler | |
| from app.api.routes import router | |
| from app.utils.logger import logger | |
| async def lifespan(app: FastAPI): | |
| """应用生命周期管理""" | |
| # ========== 启动时 ========== | |
| logger.info("=" * 50) | |
| logger.info("应用正在启动...") | |
| logger.info("=" * 50) | |
| try: | |
| # 加载配置 | |
| settings = get_settings() | |
| logger.info(f"配置加载完成: 基准货币 = {settings.BASE_CURRENCY}") | |
| logger.info(f"API Key 数量: {len(settings.API_KEYS)}") | |
| logger.info(f"缓存更新间隔: {settings.CACHE_UPDATE_INTERVAL} 秒") | |
| # 初始化汇率服务 | |
| exchange_service = ExchangeRateService(settings) | |
| # 初始化定时调度器 | |
| scheduler = RateScheduler(exchange_service, settings) | |
| # 保存到应用状态 | |
| app.state.exchange_service = exchange_service | |
| app.state.scheduler = scheduler | |
| app.state.settings = settings | |
| # 启动调度器(会立即获取一次数据) | |
| await scheduler.start() | |
| logger.info("应用启动成功!") | |
| logger.info("=" * 50) | |
| yield | |
| except Exception as e: | |
| logger.error(f"应用启动失败: {e}") | |
| raise | |
| finally: | |
| # ========== 关闭时 ========== | |
| logger.info("=" * 50) | |
| logger.info("应用正在关闭...") | |
| if hasattr(app.state, 'scheduler'): | |
| app.state.scheduler.stop() | |
| logger.info("应用已停止") | |
| logger.info("=" * 50) | |
| # ==================== 创建 FastAPI 应用 ==================== | |
| app = FastAPI( | |
| title="汇率换算服务", | |
| description=""" | |
| ## 汇率换算 API | |
| 提供实时汇率查询和换算功能。 | |
| ### 主要功能 | |
| - 📊 **查询汇率**: 获取所有货币或特定货币的实时汇率 | |
| - 💱 **货币换算**: 支持任意两种货币之间的换算 | |
| - 🔄 **批量换算**: 一次计算某金额对应所有货币的值 | |
| - 📋 **货币列表**: 获取支持的货币列表(含中英文名称) | |
| ### 数据来源 | |
| 数据来自 ExchangeRate-API,每日更新。 | |
| ### 缓存策略 | |
| 系统使用内存缓存,定时从 API 更新数据,避免频繁请求。 | |
| """, | |
| version="1.0.0", | |
| lifespan=lifespan, | |
| docs_url="/docs", | |
| redoc_url="/redoc" | |
| ) | |
| # ==================== 中间件配置 ==================== | |
| # CORS 中间件 | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ==================== 静态文件和模板 ==================== | |
| # 挂载静态文件目录 | |
| app.mount("/static", StaticFiles(directory="static"), name="static") | |
| # 配置模板引擎 | |
| templates = Jinja2Templates(directory="templates") | |
| # ==================== 注册路由 ==================== | |
| app.include_router(router) | |
| # ==================== 页面路由 ==================== | |
| async def home(request: Request): | |
| """首页 - 汇率换算器""" | |
| return templates.TemplateResponse("index.html", {"request": request}) | |
| async def health_check(): | |
| """健康检查接口""" | |
| return {"status": "ok", "service": "exchange-rates"} | |