refactor: 整合仪表盘功能到监控模块,清理冗余代码

- 移除原监控仪表盘独立模块,将相关功能合并到在线监控模块
- 重构租户配置字段名,统一使用logo_url和name替代tenant_logo/tenant_name
- 优化搜索工具函数,移除重复导入
- 调整参数配置模型字段长度限制,移除config_value的max_length约束
- 清理冗余的常量定义和导入语句
- 修复批量状态设置接口的redis依赖注入
- 增强OAuth登录安全性,添加租户默认归属和state一次性消费
- 优化资源目录缓存逻辑,减少重复计算
- 新增API Token模块基础框架
- 完善用户token版本管理,支持主动失效JWT
- 调整AI模型配置缓存过期时间
- 修复菜单类型字段索引,提升查询性能
- 简化前端刷新token调用逻辑
- 新增滑块验证完成接口和忘记密码验证码校验
- 调整系统配置默认值,添加操作日志保留天数和接口白名单配置
- 限制Mock支付回调仅在开发环境可用
- 重构websocket认证方式,支持更安全的subprotocol传参
This commit is contained in:
zhangtao
2026-07-13 01:14:20 +08:00
parent 6a5f8cf0dd
commit cf88ab8897
102 changed files with 4078 additions and 3777 deletions
@@ -4,13 +4,15 @@ from fastapi import APIRouter, Body, Depends, Path, Query, Request, Security, st
from fastapi.responses import JSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.common.enums import RET
from app.common.enums import RET, EnvironmentEnum
from app.common.response import ErrorResponse, ResponseSchema, SuccessResponse
from app.config.setting import settings
from app.core.base_schema import AuthSchema, PageResultSchema, PaginationQueryParam
from app.core.dependencies import AuthPermission, db_getter
from app.core.exceptions import CustomException
from app.core.logger import logger
from app.core.router_class import OperationLogRoute
from app.utils.payment import get_mock_gateway
from .schema import (
OrderCreateSchema,
@@ -102,8 +104,8 @@ async def order_pay_create_controller(
async def order_pay_status_controller(
db: Annotated[AsyncSession, Depends(db_getter)],
order_id: Annotated[int, Path(description="订单ID", ge=1)],
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:order:query"], check_data_scope=False))],
) -> JSONResponse:
auth = AuthSchema(check_data_scope=False)
result = await OrderService.check_payment_status(auth=auth, db=db, order_id=order_id)
return SuccessResponse(data=result)
@@ -124,12 +126,18 @@ async def order_pay_callback_controller(
return ErrorResponse(msg=str(e))
@OrderRouter.post("/mock/callback", summary="Mock 支付回调(开发环境触发模拟支付)", response_model=ResponseSchema[dict])
@OrderRouter.post("/mock/callback", summary="Mock 支付回调(仅开发/测试环境可用)", response_model=ResponseSchema[dict])
async def order_pay_mock_callback_controller(
db: Annotated[AsyncSession, Depends(db_getter)],
order_id: Annotated[int, Body(description="订单ID", ge=1)],
) -> JSONResponse:
from app.utils.payment import get_mock_gateway
# Mock 回调仅在 DEV 环境暴露;生产环境必须通过真实支付网关的 webhook 触发
if settings.ENVIRONMENT != EnvironmentEnum.DEV:
raise CustomException(
msg="Mock 支付回调仅在开发环境可用",
code=RET.FORBIDDEN.code,
status_code=403,
)
from .service import OrderService
@@ -1,5 +1,3 @@
"""订单与支付 CRUD"""
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.base_crud import CRUDBase
@@ -1,15 +1,23 @@
import random
import secrets
import string
from datetime import datetime, timedelta
from sqlalchemy import select
from sqlalchemy import func, select
from sqlalchemy import update as sa_update
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.v1.module_system.dept.model import DeptModel
from app.api.v1.module_system.role.model import RoleModel
from app.api.v1.module_system.user.model import UserModel
from app.core.base_schema import AuthSchema
from app.core.database import async_db_session
from app.core.event_bus import EventBus
from app.core.exceptions import CustomException
from app.core.logger import logger
from app.utils.payment import create_payment_gateway
from ..package.model import PackageModel
from ..tenant.model import TenantModel
from .crud import OrderCRUD
from .model import OrderModel
from .schema import (
@@ -27,16 +35,19 @@ from .schema import (
def _generate_order_no() -> str:
"""生成订单号:YYYYMMDD + 6位随机数"""
"""生成订单号:YYYYMMDD + 10位加密安全随机数(碰撞概率极低)。
使用 :func:`secrets.choice` 而非 ``random``,避免伪随机带来的可预测性。
"""
today = datetime.now().strftime("%Y%m%d")
suffix = str(random.randint(100000, 999999))
return f"{today}{suffix}"
rand = "".join(secrets.choice(string.digits) for _ in range(10))
return f"{today}{rand}"
def _generate_refund_no() -> str:
"""生成退款单号"""
today = datetime.now().strftime("%Y%m%d")
suffix = str(random.randint(100000, 999999))
suffix = "".join(secrets.choice(string.digits) for _ in range(6))
return f"RF{today}{suffix}"
@@ -65,10 +76,10 @@ class OrderService:
- OrderOutSchema: 新创建的订单详情
"""
if amount is None:
from app.api.v1.module_platform.package.model import PackageModel
pkg = await db.get(PackageModel, data.package_id)
amount = pkg.price if pkg else 0
if not pkg:
raise CustomException(msg=f"套餐[{data.package_id}]不存在或已删除")
amount = pkg.price
order = await OrderCRUD(auth, db).create(
OrderCreateInternalSchema(
@@ -189,10 +200,6 @@ class OrderService:
@staticmethod
async def cancel_expired_orders() -> None:
from sqlalchemy import update as sa_update
from app.core.database import async_db_session
now = datetime.now()
async with async_db_session() as session:
async with session.begin():
@@ -224,8 +231,6 @@ class PaymentService:
返回:
- PaymentCreateOut: 支付创建结果(支付URL/二维码)
"""
from app.api.v1.module_platform.package.model import PackageModel
order = await OrderCRUD(auth, db).get_by_id(order_id)
if not order:
raise CustomException(msg="该数据不存在")
@@ -305,17 +310,12 @@ class PaymentService:
),
)
order.package_id = pid
order.tenant_id = tid
order.order_type = otype
# order 已被 update refresh,直接传给激活方法
await PaymentService._activate_tenant_package(auth, db, order)
logger.info(f"支付回调处理完成: order_id={oid} method={method} tenant_id={tid} type={otype}")
# SSE 推送支付成功通知
from app.api.v1.module_platform.package.model import PackageModel
from app.core.event_bus import EventBus
_pkg = await db.get(PackageModel, pid)
await EventBus.publish_tenant(
tid,
@@ -340,9 +340,6 @@ class PaymentService:
返回:
- None
"""
from app.api.v1.module_platform.package.model import PackageModel
from app.api.v1.module_platform.tenant.model import TenantModel
pkg = await db.get(PackageModel, order.package_id)
if not pkg:
logger.warning(f"支付回调:套餐 {order.package_id} 不存在,跳过激活")
@@ -391,12 +388,6 @@ class PaymentService:
返回:
- None
"""
from sqlalchemy import func
from app.api.v1.module_system.dept.model import DeptModel
from app.api.v1.module_system.role.model import RoleModel
from app.api.v1.module_system.user.model import UserModel
checks = {
"用户": (UserModel, new_pkg.max_users),
"角色": (RoleModel, new_pkg.max_roles),