2026-09-21 19:22:31 +08:00
|
|
|
|
# main0814.py
|
|
|
|
|
|
# 项目入口文件:创建 FastAPI 应用、注册路由、创建数据库表
|
2026-09-21 20:43:32 +08:00
|
|
|
|
from contextlib import asynccontextmanager
|
2026-09-21 19:22:31 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
2026-09-21 20:43:32 +08:00
|
|
|
|
|
|
|
|
|
|
# 1. 应用生命周期:启动时自动建表(幂等,已有表不会重建)
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
|
async def lifespan(app: FastAPI):
|
|
|
|
|
|
init_all(False, False) # 不重置、不灌种子,仅保证表存在
|
|
|
|
|
|
yield
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-21 19:22:31 +08:00
|
|
|
|
# 2. 创建 FastAPI 实例
|
|
|
|
|
|
app = FastAPI(
|
|
|
|
|
|
title="FastAPI + SQLAlchemy 分层架构(MySQL)",
|
|
|
|
|
|
description="用户管理示例,演示分层架构和 MySQL 集成",
|
2026-09-21 20:43:32 +08:00
|
|
|
|
version="1.0.0",
|
|
|
|
|
|
lifespan=lifespan,
|
2026-09-21 19:22:31 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 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", # 指定应用位置(模块名:应用变量名)
|
2026-09-21 20:43:32 +08:00
|
|
|
|
host="127.0.0.1", # 只监听本机,终端里的链接可直接点击打开
|
|
|
|
|
|
port=8005, # 端口(与 Dockerfile / docker-compose 一致)
|
|
|
|
|
|
reload=True # 开发模式,代码变动自动重启
|
2026-09-21 19:22:31 +08:00
|
|
|
|
)
|