项目代码提交
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# main0814.py
|
||||
# 项目入口文件:创建 FastAPI 应用、注册路由、创建数据库表
|
||||
import os
|
||||
from fastapi import FastAPI
|
||||
from pathlib import Path
|
||||
from fastapi.responses import FileResponse, HTMLResponse, 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
|
||||
from database import engine
|
||||
from sqlalchemy import text
|
||||
from service.web_auth import install_web_auth
|
||||
|
||||
# 2. 创建 FastAPI 实例
|
||||
app = FastAPI(
|
||||
title="FastAPI + SQLAlchemy 分层架构(MySQL)",
|
||||
description="用户管理示例,演示分层架构和 MySQL 集成",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# 3. 添加跨域中间件(允许前端跨域请求)
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[value.strip() for value in os.getenv("CORS_ORIGINS", "*").split(",") if value.strip()],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
install_web_auth(app)
|
||||
|
||||
# 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():
|
||||
if os.getenv("AUTH_ENABLED", "").lower() in {"1", "true", "yes", "on"}:
|
||||
html = (FRONTEND_DIR / "index.html").read_text(encoding="utf-8")
|
||||
actions = '''<button type="button" class="button subtle" id="sign-out">退出登录</button>
|
||||
<script>document.getElementById('sign-out').addEventListener('click',async function(){
|
||||
this.disabled=true;try{const base=new URL('.',document.baseURI);
|
||||
const response=await fetch(new URL('auth/logout',base),{method:'POST',credentials:'same-origin'});
|
||||
if(!response.ok)throw new Error();location.replace(new URL('login',base).href);
|
||||
}catch(error){this.disabled=false;this.textContent='退出失败,请重试';}});</script>'''
|
||||
return HTMLResponse(html.replace("<!--AUTH_ACTIONS-->", actions), headers={"Cache-Control": "no-store"})
|
||||
return FileResponse(FRONTEND_DIR / "index.html")
|
||||
|
||||
|
||||
@app.get("/healthz", include_in_schema=False)
|
||||
def healthz():
|
||||
with engine.connect() as connection:
|
||||
connection.execute(text("SELECT 1"))
|
||||
return {"status": "ok"}
|
||||
|
||||
# 6. 如果直接运行此文件,启动 uvicorn 服务器
|
||||
if __name__ == "__main__":
|
||||
# drop_tables()
|
||||
init_all(True, False)
|
||||
import uvicorn
|
||||
uvicorn.run(
|
||||
"main:app", # 指定应用位置(模块名:应用变量名)
|
||||
host=os.getenv("APP_HOST", "127.0.0.1"), # 默认仅本机访问,不依赖 Wi-Fi / 局域网 IP
|
||||
port=int(os.getenv("APP_PORT", "8004")), # 可通过环境变量调整端口
|
||||
reload=True # 开发模式,代码变动自动重启
|
||||
)
|
||||
Reference in New Issue
Block a user