# main0814.py # 项目入口文件:创建 FastAPI 应用、注册路由、创建数据库表 from contextlib import asynccontextmanager from fastapi import FastAPI from pathlib import Path from fastapi.responses import FileResponse, JSONResponse from fastapi.staticfiles import StaticFiles from sqlalchemy.exc import IntegrityError, SQLAlchemyError from api import workspace_api, ai_api from starlette.middleware.cors import CORSMiddleware from api import student_api, advisor_api, employment_api, score_api, class_api, teacher_api from init_db import init_all, drop_tables # 1. 应用生命周期:启动时自动建表(幂等,已有表不会重建) @asynccontextmanager async def lifespan(app: FastAPI): init_all(False, False) # 不重置、不灌种子,仅保证表存在 yield # 2. 创建 FastAPI 实例 app = FastAPI( title="FastAPI + SQLAlchemy 分层架构(MySQL)", description="用户管理示例,演示分层架构和 MySQL 集成", version="1.0.0", lifespan=lifespan, ) # 3. 添加跨域中间件(允许前端跨域请求) app.add_middleware( CORSMiddleware, allow_origins=["*"], # 允许所有来源,生产环境应指定具体域名 allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 4. 注册子路由 # prefix 为路由前缀,所有用户接口都以 /api/users 开头 app.include_router( student_api.router, prefix="/api/studentsManagement", tags=["学生管理 (文涛,浩霖)"] ) # app.include_router( class_api.router, prefix="/api/studentsManagement", tags=["班级管理 (薛炎)"] ) # app.include_router( teacher_api.router, prefix="/api/studentsManagement", tags=["老师管理 (广龙)"] ) # app.include_router( advisor_api.router, prefix="/api/studentsManagement", tags=["顾问管理 (子镜)"] ) # app.include_router( score_api.router, prefix="/api/studentsManagement", tags=["成绩管理 (广湘)"] ) app.include_router( employment_api.router, prefix="/api/studentsManagement", tags=["就业管理 (周兴)"] ) # 5. 前端及聚合查询接口 app.include_router(workspace_api.router, prefix="/api/studentsManagement") app.include_router(ai_api.router, prefix="/api/studentsManagement") FRONTEND_DIR = Path(__file__).resolve().parent / "frontend" app.mount("/static", StaticFiles(directory=FRONTEND_DIR), name="frontend") @app.exception_handler(IntegrityError) async def integrity_error(request, error): return JSONResponse(status_code=409, content={"detail": "保存失败:学号、手机号、名称或学生就业记录已存在,或关联记录不存在。请检查后重试。"}) @app.exception_handler(SQLAlchemyError) async def database_error(request, error): return JSONResponse(status_code=503, content={"detail": "数据库暂时不可用,请检查 MySQL 服务和表结构。"}) # 根路径直接打开前端页面,API 文档仍位于 /docs。 @app.get("/") async def root(): return FileResponse(FRONTEND_DIR / "index.html") # 6. 如果直接运行此文件,启动 uvicorn 服务器 if __name__ == "__main__": # drop_tables() init_all(True, False) import uvicorn uvicorn.run( "main:app", # 指定应用位置(模块名:应用变量名) host="127.0.0.1", # 只监听本机,终端里的链接可直接点击打开 port=8005, # 端口(与 Dockerfile / docker-compose 一致) reload=True # 开发模式,代码变动自动重启 )