fix: 前端构建修复+后端静态托管+Docker部署

This commit is contained in:
2026-08-12 17:05:16 +08:00
parent 068f8459fe
commit 604d29b5f0
+40 -3
View File
@@ -1,20 +1,24 @@
"""AI Worker Platform - FastAPI Application Entry Point."""
import os
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.responses import JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from app.config import settings
from app.database import init_db
from app.api.v1 import api_router
from app.core.exceptions import AppException
# Frontend dist path (relative to backend dir)
FRONTEND_DIST = Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialize database on startup."""
init_db()
# Seed default tenant if not exists
from app.database import SessionLocal
from app.models.tenant import Tenant
db = SessionLocal()
@@ -41,7 +45,7 @@ app = FastAPI(
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins_list,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
@@ -65,3 +69,36 @@ def health():
# API routes
app.include_router(api_router)
# --- Serve frontend (SPA) ---
if FRONTEND_DIST.exists():
# Mount static assets (js, css, images)
app.mount("/assets", StaticFiles(directory=FRONTEND_DIST / "assets"), name="assets")
@app.get("/{full_path:path}")
async def serve_spa(full_path: str, request: Request):
"""Catch-all: serve index.html for SPA routing, or static files."""
# Don't intercept API routes
if full_path.startswith("api/") or full_path.startswith("health"):
return JSONResponse({"detail": "Not Found"}, status_code=404)
# Try to serve a real file first
file_path = FRONTEND_DIST / full_path
if file_path.is_file():
return FileResponse(file_path)
# Fallback to index.html for SPA client-side routing
index = FRONTEND_DIST / "index.html"
if index.exists():
return FileResponse(index)
return JSONResponse({"detail": "Frontend not built"}, status_code=404)
else:
@app.get("/")
def root():
return {
"message": "AI Worker Platform API",
"version": settings.APP_VERSION,
"docs": "/docs",
"frontend": "Run 'npm run build' in frontend/ to enable web UI",
}