unis_manager/app/main.py

78 lines
2.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from __future__ import annotations
import uuid
from fastapi import Depends, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from . import config, security
from .db import Base, SessionLocal, engine
from .routers import ai, auth, board, custom, export, focus, projects, rbac, staff, weekly
from .schema_patch import ensure_columns
Base.metadata.create_all(bind=engine)
_patch = ensure_columns(engine, Base.metadata)
if _patch:
print(f"[ok] 已补齐数据库字段:{', '.join(_patch)}")
# 内置角色 + 管理员账号(只在缺失时补,不会覆盖已改过的密码/权限)
with SessionLocal() as _db:
for _note in security.ensure_seed(_db):
print(f"[ok] {_note}")
# 每次进程启动换一个值;热加载重启后前端据此自动刷新
BOOT_ID = uuid.uuid4().hex
app = FastAPI(title="部门关键任务追踪看板", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# 所有 /api 接口先过 RBAC 总闸(登录 + 菜单权限),登录接口自身除外
api = FastAPI(title="部门关键任务追踪看板 API", dependencies=[Depends(security.guard)])
api.include_router(board.router, prefix="", tags=["board"])
api.include_router(projects.router, prefix="", tags=["projects"])
api.include_router(ai.router, prefix="", tags=["ai"])
api.include_router(custom.router, prefix="", tags=["custom"])
api.include_router(export.router, prefix="", tags=["export"])
api.include_router(staff.router, prefix="", tags=["staff"])
api.include_router(weekly.router, prefix="", tags=["weekly"])
api.include_router(focus.router, prefix="", tags=["focus"])
api.include_router(auth.router, prefix="", tags=["auth"])
api.include_router(rbac.router, prefix="", tags=["rbac"])
app.mount("/api", api)
WEB_DIR = config.BASE_DIR / "web"
app.mount("/static", StaticFiles(directory=str(WEB_DIR)), name="static")
# 前端零构建、文件名不带版本号,浏览器会启发式缓存 index.html / app.js / styles.css,
# 改完界面看不到新版。no-cache 不做新鲜度缓存、只带 ETag 回源校验(未变更时返回 304)。
@app.middleware("http")
async def no_cache_frontend(request, call_next):
response = await call_next(request)
if request.url.path == "/" or request.url.path.startswith("/static/"):
response.headers["Cache-Control"] = "no-cache"
return response
@app.get("/health")
def health():
return {
"ok": True,
"db": config.DATABASE_URL.split("://")[0],
"dev": config.DEV,
"boot": BOOT_ID,
}
@app.get("/")
def index():
return FileResponse(str(WEB_DIR / "index.html"))