0841b1a103
- 前端:Vue3 + TS + Element Plus,24 个页面路由(课件/组题/教案/动画/思维导图/作文批改/命题/课堂/资源/社区等) - 后端:FastAPI + SQLAlchemy + SQLite,17 个路由模块,AI 服务层含降级模板 - AI:glm-5.x 推理模型已禁用思维链,确保输出真实内容 - 修复:ai_service 两处请求体注入 enable_thinking/thinking disabled - 测试账号:13900999999 / test1234
92 lines
2.8 KiB
Python
92 lines
2.8 KiB
Python
import os
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
from starlette.requests import Request as StarletteRequest
|
|
from starlette.responses import JSONResponse
|
|
from slowapi import _rate_limit_exceeded_handler
|
|
from slowapi.errors import RateLimitExceeded
|
|
from services.limiter import limiter
|
|
from fastapi.staticfiles import StaticFiles
|
|
from config import get_settings
|
|
from database import engine, Base
|
|
import models # noqa: F401
|
|
from routers import auth, courseware, animation, exercise, lesson_plan, essay, ai, resource, community, exam, classroom, material, search, admin, mindmap, notification, chat
|
|
|
|
settings = get_settings()
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
Base.metadata.create_all(bind=engine)
|
|
os.makedirs(settings.UPLOAD_DIR, exist_ok=True)
|
|
yield
|
|
|
|
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version=settings.APP_VERSION,
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
app.state.limiter = limiter
|
|
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
class BodySizeLimitMiddleware(BaseHTTPMiddleware):
|
|
"""Reject request bodies exceeding MAX_REQUEST_BODY_SIZE (default 60MB)."""
|
|
|
|
async def dispatch(self, request: StarletteRequest, call_next):
|
|
max_size = getattr(settings, "MAX_REQUEST_BODY_SIZE", 60 * 1024 * 1024)
|
|
cl = request.headers.get("content-length")
|
|
if cl and int(cl) > max_size:
|
|
return JSONResponse(
|
|
status_code=413,
|
|
content={"detail": f"请求体过大,最大允许 {max_size // (1024*1024)}MB"},
|
|
)
|
|
return await call_next(request)
|
|
|
|
|
|
app.add_middleware(BodySizeLimitMiddleware)
|
|
|
|
app.include_router(auth.router)
|
|
app.include_router(courseware.router)
|
|
app.include_router(animation.router)
|
|
app.include_router(exercise.router)
|
|
app.include_router(lesson_plan.router)
|
|
app.include_router(essay.router)
|
|
app.include_router(exam.router)
|
|
app.include_router(ai.router)
|
|
app.include_router(resource.router)
|
|
app.include_router(material.router)
|
|
app.include_router(community.router)
|
|
app.include_router(classroom.router)
|
|
app.include_router(search.router)
|
|
app.include_router(admin.router)
|
|
app.include_router(mindmap.router)
|
|
app.include_router(notification.router)
|
|
app.include_router(chat.router)
|
|
|
|
if os.path.exists(settings.UPLOAD_DIR):
|
|
app.mount("/uploads", StaticFiles(directory=settings.UPLOAD_DIR), name="uploads")
|
|
|
|
|
|
@app.get("/api/health")
|
|
def health_check():
|
|
return {"status": "ok", "version": settings.APP_VERSION}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=settings.DEBUG)
|