feat(后端): 添加授权体系、系统监控与试用期计提
按 2026-11-02 需求补齐计划交付后端能力: - 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝; 管理员判断改为按数据库角色重新判定,防止权限码持有者绕过 - 系统监控:单进程采集资源、请求与异常指标,分钟级聚合, 阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义 - 试用期计提:按回款日判定并写入快照,年度结清与调整单联动; 人员模型补试用期、离职日期与工资版本历史字段 - 计提模板:公式骨架受控,页面维护名称与参数绑定 - T+ 采集:自动化配置表与进度查询 内置角色禁停用保护对齐模块注释;核算规则版本提为常量并 补充批量核算失败堆栈日志。 影响范围:后端全部模块、数据库迁移 V22-V28 验证:uv run ruff check 通过;922 个单元测试全部通过; 集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
This commit is contained in:
1 parent
02fb06e0af
commit
1461a8d113
149 files changed
+8736
-368
No files matched your search
@@ -0,0 +1,56 @@
|
||||
"""系统监控只读接口;全部复用管理员依赖,不提供运维写操作。"""
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Path, Query, Request
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.api.deps import AdminUser, DbSession
|
||||
from app.core.response import ApiResponse, PageResult, ok
|
||||
from app.schemas.monitor import EventOut, EventQuery, MonitorWindow, OverviewOut
|
||||
from app.services import monitor_service
|
||||
|
||||
router = APIRouter(prefix="/monitor", tags=["系统管理 · 系统监控"])
|
||||
|
||||
|
||||
@router.get("/overview", response_model=ApiResponse[OverviewOut], summary="健康总览")
|
||||
def overview(request: Request, session: DbSession, _: AdminUser):
|
||||
return ok(monitor_service.overview(session, request.app.state.monitor))
|
||||
|
||||
|
||||
@router.get("/trends", response_model=ApiResponse[dict], summary="分钟级监控趋势")
|
||||
def trends(
|
||||
request: Request, session: DbSession, _: AdminUser, query: Annotated[MonitorWindow, Query()]
|
||||
):
|
||||
return ok(monitor_service.trends(session, request.app.state.monitor, query))
|
||||
|
||||
|
||||
@router.get("/interfaces", response_model=ApiResponse[dict], summary="接口性能排行")
|
||||
def interfaces(
|
||||
request: Request, session: DbSession, _: AdminUser, query: Annotated[MonitorWindow, Query()]
|
||||
):
|
||||
return ok(monitor_service.interfaces(session, request.app.state.monitor, query))
|
||||
|
||||
|
||||
@router.get("/events", response_model=ApiResponse[PageResult[EventOut]], summary="诊断事件")
|
||||
def events(session: DbSession, _: AdminUser, query: Annotated[EventQuery, Query()]):
|
||||
return ok(monitor_service.events(session, query))
|
||||
|
||||
|
||||
@router.get("/events/{event_id}", response_model=ApiResponse[EventOut], summary="诊断事件详情")
|
||||
def event(session: DbSession, _: AdminUser, event_id: Annotated[int, Path(ge=1)]):
|
||||
return ok(monitor_service.event(session, event_id))
|
||||
|
||||
|
||||
@router.get("/diagnostic", summary="下载脱敏诊断摘要")
|
||||
def diagnostic(
|
||||
request: Request, session: DbSession, _: AdminUser, query: Annotated[EventQuery, Query()]
|
||||
):
|
||||
return JSONResponse(
|
||||
jsonable_encoder(monitor_service.diagnostic(session, request.app.state.monitor, query)),
|
||||
headers={
|
||||
"Content-Disposition": 'attachment; filename="monitor-diagnostic.json"',
|
||||
"Cache-Control": "no-store",
|
||||
},
|
||||
)
|
||||
Reference in new issue
Block a user