from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from sqlalchemy import inspect, text from app.core.config import settings from app.core.database import Base, engine from app.api import auth, works, orders, payment, upload # 创建数据库表 Base.metadata.create_all(bind=engine) def ensure_runtime_schema(): inspector = inspect(engine) columns = {col["name"] for col in inspector.get_columns("download_records")} statements = [] if "designer_name" not in columns: statements.append("ALTER TABLE download_records ADD COLUMN designer_name VARCHAR(100)") if "work_title" not in columns: statements.append("ALTER TABLE download_records ADD COLUMN work_title VARCHAR(255)") if "amount" not in columns: statements.append("ALTER TABLE download_records ADD COLUMN amount FLOAT DEFAULT 0") if statements: with engine.begin() as conn: for sql in statements: conn.execute(text(sql)) ensure_runtime_schema() # 创建 FastAPI 应用 app = FastAPI( title=settings.PROJECT_NAME, version=settings.VERSION, description="图绘 - 设计作品交易平台 API" ) # 配置 CORS app.add_middleware( CORSMiddleware, allow_origins=settings.ALLOWED_ORIGINS, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["*"], expose_headers=["*"], max_age=600, ) # 添加全局 CORS 中间件 @app.middleware("http") async def add_cors_headers(request: Request, call_next): response = await call_next(request) origin = request.headers.get("origin", "") if origin in settings.ALLOWED_ORIGINS: response.headers["Access-Control-Allow-Origin"] = origin response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" response.headers["Access-Control-Allow-Headers"] = "*" if request.method == "OPTIONS": response.headers["Access-Control-Max-Age"] = "600" return response # 挂载静态文件目录 app.mount("/uploads", StaticFiles(directory="uploads"), name="uploads") # 注册路由 app.include_router(auth.router, prefix=settings.API_PREFIX) app.include_router(works.router, prefix=settings.API_PREFIX) app.include_router(orders.router, prefix=settings.API_PREFIX) app.include_router(payment.router, prefix=settings.API_PREFIX) app.include_router(upload.router, prefix=settings.API_PREFIX) @app.get("/") def root(): return { "message": "欢迎使用图绘 API", "version": settings.VERSION, "docs": "/docs" } @app.get("/health") def health_check(): return {"status": "healthy"}