This commit is contained in:
2026-06-06 23:54:11 +08:00
commit 33639129b1
58 changed files with 10309 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
from __future__ import annotations
import logging
from fastapi import FastAPI, HTTPException, Request
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from app.api.routes_admin import router as admin_router
from app.api.routes_auth import router as auth_router
from app.api.routes_student import router as student_router
from app.core.database import get_connection
from app.core.settings import FRONTEND_ORIGINS, UPLOADS_DIR, ensure_runtime_dirs
from app.services.repository import init_db
logger = logging.getLogger(__name__)
ERROR_DETAIL_MAP: dict[str, str] = {
"missing_token": "缺少认证令牌",
"invalid_token": "认证已过期,请重新登录",
"invalid_credentials": "用户名或密码错误",
"student_only": "此功能仅限学生使用",
"admin_only": "此功能仅限管理员使用",
"order_not_found": "工单不存在或已被删除",
"session_not_found": "诊断会话已过期,请重新描述故障",
"order_not_completed": "维修尚未完成,无法执行此操作",
"order_not_ready_for_feedback": "当前状态不可评价",
"order_cannot_cancel": "当前状态无法取消,仅已提交或待处理的工单可取消",
"order_not_in_rework": "当前工单不在返工申请状态",
"unsupported_file_type": "仅支持上传图片文件(jpg, png, gif, webp",
"file_too_large": "文件大小超过限制(最大10MB",
"validation_error": "请求参数有误",
}
ensure_runtime_dirs()
with get_connection() as conn:
init_db(conn)
conn.execute("DELETE FROM sessions WHERE expires_at < datetime('now')")
conn.commit()
app = FastAPI(title="Dorm Repair API", version="0.1.0")
app.add_middleware(
CORSMiddleware,
allow_origins=FRONTEND_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth_router)
app.include_router(student_router)
app.include_router(admin_router)
app.mount("/uploads", StaticFiles(directory=UPLOADS_DIR), name="uploads")
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
error_code = str(exc.detail) if not isinstance(exc.detail, dict) else exc.detail.get("error_code", str(exc.detail))
detail = ERROR_DETAIL_MAP.get(error_code, str(exc.detail))
return JSONResponse(
status_code=exc.status_code,
content={"detail": detail, "error_code": error_code},
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
return JSONResponse(
status_code=422,
content={"detail": "请求参数有误", "error_code": "validation_error"},
)
@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception) -> JSONResponse:
logger.exception("Unhandled exception: %s", exc)
return JSONResponse(
status_code=500,
content={"detail": "服务器内部错误", "error_code": "internal_error"},
)
@app.on_event("shutdown")
async def shutdown() -> None:
from app.services.diagnosis import close_diagnosis_provider
await close_diagnosis_provider()
@app.get("/api/health")
def health() -> dict[str, str]:
return {"status": "ok"}