refactor: 统一权限标识前缀为module_格式

feat(tenant): 新增租户管理模块相关文件

style: 优化代码导入和类型提示

fix: 修复前端权限标识校验逻辑

docs: 更新注释中的权限标识示例

test: 更新测试用例中的权限标识

chore: 清理无用导入和类型定义
This commit is contained in:
zhangtao
2025-11-11 01:06:40 +08:00
parent 379df71baa
commit 5d0d0cd26a
54 changed files with 2109 additions and 445 deletions
@@ -21,7 +21,7 @@ AIRouter = APIRouter(route_class=OperationLogRoute, prefix="/ai", tags=["MCP智
@AIRouter.post("/chat", summary="智能对话", description="与MCP智能助手进行对话")
async def chat_controller(
query: ChatQuerySchema,
auth: AuthSchema = Depends(AuthPermission(["app:ai:chat"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:chat"]))
) -> StreamingResponse:
"""
智能对话接口
@@ -51,7 +51,7 @@ async def chat_controller(
@AIRouter.get("/detail/{id}", summary="获取 MCP 服务器详情", description="获取 MCP 服务器详情")
async def detail_controller(
id: int = Path(..., description="MCP ID"),
auth: AuthSchema = Depends(AuthPermission(["app:ai:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:query"]))
) -> JSONResponse:
"""
获取 MCP 服务器详情接口
@@ -71,7 +71,7 @@ async def detail_controller(
async def list_controller(
page: PaginationQueryParam = Depends(),
search: McpQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:ai:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:query"]))
) -> JSONResponse:
"""
查询 MCP 服务器列表接口
@@ -93,7 +93,7 @@ async def list_controller(
@AIRouter.post("/create", summary="创建 MCP 服务器", description="创建 MCP 服务器")
async def create_controller(
data: McpCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["app:ai:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:create"]))
) -> JSONResponse:
"""
创建 MCP 服务器接口
@@ -114,7 +114,7 @@ async def create_controller(
async def update_controller(
data: McpUpdateSchema,
id: int = Path(..., description="MCP ID"),
auth: AuthSchema = Depends(AuthPermission(["app:ai:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:update"]))
) -> JSONResponse:
"""
修改 MCP 服务器接口
@@ -135,7 +135,7 @@ async def update_controller(
@AIRouter.delete("/delete", summary="删除 MCP 服务器", description="删除 MCP 服务器")
async def delete_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["app:ai:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:ai:delete"]))
) -> JSONResponse:
"""
删除 MCP 服务器接口
@@ -25,7 +25,7 @@ JobRouter = APIRouter(route_class=OperationLogRoute, prefix="/job", tags=["定
@JobRouter.get("/detail/{id}", summary="获取定时任务详情", description="获取定时任务详情")
async def get_obj_detail_controller(
id: int = Path(..., description="定时任务ID"),
auth: AuthSchema = Depends(AuthPermission(["app:job:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:query"]))
) -> JSONResponse:
"""
获取定时任务详情
@@ -45,7 +45,7 @@ async def get_obj_detail_controller(
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: JobQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:job:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:query"]))
) -> JSONResponse:
"""
查询定时任务
@@ -66,7 +66,7 @@ async def get_obj_list_controller(
@JobRouter.post("/create", summary="创建定时任务", description="创建定时任务")
async def create_obj_controller(
data: JobCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["app:job:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:create"]))
) -> JSONResponse:
"""
创建定时任务
@@ -86,7 +86,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: JobUpdateSchema,
id: int = Path(..., description="定时任务ID"),
auth: AuthSchema = Depends(AuthPermission(["app:job:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:update"]))
) -> JSONResponse:
"""
修改定时任务
@@ -106,7 +106,7 @@ async def update_obj_controller(
@JobRouter.delete("/delete", summary="删除定时任务", description="删除定时任务")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["app:job:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:delete"]))
) -> JSONResponse:
"""
删除定时任务
@@ -125,7 +125,7 @@ async def delete_obj_controller(
@JobRouter.post('/export', summary="导出定时任务", description="导出定时任务")
async def export_obj_list_controller(
search: JobQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:job:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:export"]))
) -> StreamingResponse:
"""
导出定时任务
@@ -151,7 +151,7 @@ async def export_obj_list_controller(
@JobRouter.delete("/clear", summary="清空定时任务日志", description="清空定时任务日志")
async def clear_obj_log_controller(
auth: AuthSchema = Depends(AuthPermission(["app:job:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:delete"]))
) -> JSONResponse:
"""
清空定时任务日志
@@ -170,7 +170,7 @@ async def clear_obj_log_controller(
async def option_obj_controller(
id: int = Body(..., description="定时任务ID"),
option: int = Body(..., description="操作类型 1: 暂停 2: 恢复 3: 重启"),
auth: AuthSchema = Depends(AuthPermission(["app:job:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:update"]))
) -> JSONResponse:
"""
暂停/恢复/重启定时任务
@@ -187,7 +187,7 @@ async def option_obj_controller(
logger.info(f"操作定时任务成功: {id}")
return SuccessResponse(msg="操作定时任务成功")
@JobRouter.get("/log", summary="获取定时任务日志", description="获取定时任务日志", dependencies=[Depends(AuthPermission(["app:job:query"]))])
@JobRouter.get("/log", summary="获取定时任务日志", description="获取定时任务日志", dependencies=[Depends(AuthPermission(["module_application:job:query"]))])
async def get_job_log_controller():
"""
获取定时任务日志
@@ -221,7 +221,7 @@ async def get_job_log_controller():
@JobRouter.get("/log/detail/{id}", summary="获取定时任务日志详情", description="获取定时任务日志详情")
async def get_job_log_detail_controller(
id: int = Path(..., description="定时任务日志ID"),
auth: AuthSchema = Depends(AuthPermission(["app:job:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:query"]))
) -> JSONResponse:
"""
获取定时任务日志详情
@@ -242,7 +242,7 @@ async def get_job_log_detail_controller(
async def get_job_log_list_controller(
page: PaginationQueryParam = Depends(),
search: JobLogQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:job:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:query"]))
) -> JSONResponse:
"""
查询定时任务日志
@@ -265,7 +265,7 @@ async def get_job_log_list_controller(
@JobRouter.delete("/log/delete", summary="删除定时任务日志", description="删除定时任务日志")
async def delete_job_log_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["app:job:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:delete"]))
) -> JSONResponse:
"""
删除定时任务日志
@@ -284,7 +284,7 @@ async def delete_job_log_controller(
@JobRouter.delete("/log/clear", summary="清空定时任务日志", description="清空定时任务日志")
async def clear_job_log_controller(
auth: AuthSchema = Depends(AuthPermission(["app:job:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:delete"]))
) -> JSONResponse:
"""
清空定时任务日志
@@ -303,7 +303,7 @@ async def clear_job_log_controller(
@JobRouter.post('/log/export', summary="导出定时任务日志", description="导出定时任务日志")
async def export_job_log_list_controller(
search: JobLogQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:job:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:job:export"]))
) -> StreamingResponse:
"""
导出定时任务日志
@@ -24,7 +24,7 @@ MyAppRouter = APIRouter(route_class=OperationLogRoute, prefix="/myapp", tags=["
@MyAppRouter.get("/detail/{id}", summary="获取应用详情", description="获取应用详情")
async def get_obj_detail_controller(
id: int = Path(..., description="应用ID"),
auth: AuthSchema = Depends(AuthPermission(["app:myapp:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:query"]))
) -> JSONResponse:
"""
获取应用详情
@@ -44,7 +44,7 @@ async def get_obj_detail_controller(
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: ApplicationQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["app:myapp:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:query"]))
) -> JSONResponse:
"""
查询应用列表
@@ -65,7 +65,7 @@ async def get_obj_list_controller(
@MyAppRouter.post("/create", summary="创建应用", description="创建应用")
async def create_obj_controller(
data: ApplicationCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["app:myapp:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:create"]))
) -> JSONResponse:
"""
创建应用
@@ -85,7 +85,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: ApplicationUpdateSchema,
id: int = Path(..., description="应用ID"),
auth: AuthSchema = Depends(AuthPermission(["app:myapp:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:update"]))
) -> JSONResponse:
"""
修改应用
@@ -105,7 +105,7 @@ async def update_obj_controller(
@MyAppRouter.delete("/delete", summary="删除应用", description="删除应用")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["app:myapp:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:delete"]))
) -> JSONResponse:
"""
删除应用
@@ -124,7 +124,7 @@ async def delete_obj_controller(
@MyAppRouter.patch("/available/setting", summary="批量修改应用状态", description="批量修改应用状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["app:myapp:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_application:myapp:patch"]))
) -> JSONResponse:
"""
批量修改应用状态
@@ -13,7 +13,7 @@ from .service import FileService
FileRouter = APIRouter(route_class=OperationLogRoute, prefix="/file", tags=["文件管理"])
@FileRouter.post("/upload", summary="上传文件", description="上传文件",dependencies=[Depends(AuthPermission(["common:file:upload"]))])
@FileRouter.post("/upload", summary="上传文件", description="上传文件",dependencies=[Depends(AuthPermission(["module_common:file:upload"]))])
async def upload_controller(
file: UploadFile,
request: Request,
@@ -32,7 +32,7 @@ async def upload_controller(
logger.info(f"上传文件成功 {result_dict}")
return SuccessResponse(data=result_dict, msg="上传文件成功")
@FileRouter.post("/download", summary="下载文件", description="下载文件", dependencies=[Depends(AuthPermission(["common:file:download"]))])
@FileRouter.post("/download", summary="下载文件", description="下载文件", dependencies=[Depends(AuthPermission(["module_common:file:download"]))])
async def download_controller(
background_tasks: BackgroundTasks,
file_path: str = Body(..., description="文件路径"),
@@ -25,7 +25,7 @@ DemoRouter = APIRouter(route_class=OperationLogRoute, prefix="/demo", tags=["示
@DemoRouter.get("/detail/{id}", summary="获取示例详情", description="获取示例详情")
async def get_obj_detail_controller(
id: int = Path(..., description="示例ID"),
auth: AuthSchema = Depends(AuthPermission(["generator:demo:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:query"]))
) -> JSONResponse:
"""
获取示例详情
@@ -45,7 +45,7 @@ async def get_obj_detail_controller(
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: DemoQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["generator:demo:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:query"]))
) -> JSONResponse:
"""
查询示例列表
@@ -72,7 +72,7 @@ async def get_obj_list_controller(
@DemoRouter.post("/create", summary="创建示例", description="创建示例")
async def create_obj_controller(
data: DemoCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["generator:demo:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:create"]))
) -> JSONResponse:
"""
创建示例
@@ -92,7 +92,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: DemoUpdateSchema,
id: int = Path(..., description="示例ID"),
auth: AuthSchema = Depends(AuthPermission(["generator:demo:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:update"]))
) -> JSONResponse:
"""
修改示例
@@ -112,7 +112,7 @@ async def update_obj_controller(
@DemoRouter.delete("/delete", summary="删除示例", description="删除示例")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:demo:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:delete"]))
) -> JSONResponse:
"""
删除示例
@@ -131,7 +131,7 @@ async def delete_obj_controller(
@DemoRouter.patch("/available/setting", summary="批量修改示例状态", description="批量修改示例状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["generator:demo:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:patch"]))
) -> JSONResponse:
"""
批量修改示例状态
@@ -150,7 +150,7 @@ async def batch_set_available_obj_controller(
@DemoRouter.post('/export', summary="导出示例", description="导出示例")
async def export_obj_list_controller(
search: DemoQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["generator:demo:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:export"]))
) -> StreamingResponse:
"""
导出示例
@@ -177,7 +177,7 @@ async def export_obj_list_controller(
@DemoRouter.post('/import', summary="导入示例", description="导入示例")
async def import_obj_list_controller(
file: UploadFile,
auth: AuthSchema = Depends(AuthPermission(["generator:demo:import"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:demo:import"]))
) -> JSONResponse:
"""
导入示例
@@ -193,7 +193,7 @@ async def import_obj_list_controller(
logger.info(f"导入示例成功: {batch_import_result}")
return SuccessResponse(data=batch_import_result, msg="导入示例成功")
@DemoRouter.post('/download/template', summary="获取示例导入模板", description="获取示例导入模板", dependencies=[Depends(AuthPermission(["generator:demo:download"]))])
@DemoRouter.post('/download/template', summary="获取示例导入模板", description="获取示例导入模板", dependencies=[Depends(AuthPermission(["module_generator:demo:download"]))])
async def export_obj_template_controller() -> StreamingResponse:
"""
获取示例导入模板
@@ -24,7 +24,7 @@ GenRouter = APIRouter(route_class=OperationLogRoute, prefix='/gencode', tags=["
async def gen_table_list_controller(
page: PaginationQueryParam = Depends(),
search: GenTableQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:query"]))
) -> JSONResponse:
"""
查询代码生成业务表列表
@@ -47,7 +47,7 @@ async def gen_table_list_controller(
async def get_gen_db_table_list_controller(
page: PaginationQueryParam = Depends(),
search: GenTableQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["generator:dblist:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:dblist:query"]))
) -> JSONResponse:
"""
查询数据库表列表
@@ -69,7 +69,7 @@ async def get_gen_db_table_list_controller(
@GenRouter.post("/import", summary="导入表结构", description="导入表结构")
async def import_gen_table_controller(
table_names: List[str] = Body(..., description="表名列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:import"])),
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:import"])),
) -> JSONResponse:
"""
导入表结构
@@ -90,7 +90,7 @@ async def import_gen_table_controller(
@GenRouter.get("/detail/{table_id}", summary="获取业务表详细信息", description="获取业务表详细信息")
async def gen_table_detail_controller(
table_id: int = Path(..., description="业务表ID"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:query"]))
) -> JSONResponse:
"""
获取业务表详细信息
@@ -110,7 +110,7 @@ async def gen_table_detail_controller(
@GenRouter.post("/create", summary="创建表结构", description="创建表结构")
async def create_table_controller(
sql: str = Body(..., description="SQL语句,用于创建表结构"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:create"])),
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:create"])),
) -> JSONResponse:
"""
创建表结构
@@ -131,7 +131,7 @@ async def create_table_controller(
async def update_gen_table_controller(
table_id: int = Path(..., description="业务表ID"),
data: GenTableSchema = Body(..., description="业务表信息"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:update"])),
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:update"])),
) -> JSONResponse:
"""
编辑业务表信息
@@ -152,7 +152,7 @@ async def update_gen_table_controller(
@GenRouter.delete("/delete", summary="删除业务表信息", description="删除业务表信息")
async def delete_gen_table_controller(
ids: List[int] = Body(..., description="业务表ID列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:delete"]))
) -> JSONResponse:
"""
删除业务表信息
@@ -172,7 +172,7 @@ async def delete_gen_table_controller(
@GenRouter.patch("/batch/output", summary="批量生成代码", description="批量生成代码")
async def batch_gen_code_controller(
table_names: List[str] = Body(..., description="表名列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:operate"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:operate"]))
) -> StreamResponse:
"""
批量生成代码
@@ -196,7 +196,7 @@ async def batch_gen_code_controller(
@GenRouter.post("/output/{table_name}", summary="生成代码到指定路径", description="生成代码到指定路径")
async def gen_code_local_controller(
table_name: str = Path(..., description="表名"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:code"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:code"]))
) -> JSONResponse:
"""
生成代码到指定路径
@@ -216,7 +216,7 @@ async def gen_code_local_controller(
@GenRouter.get("/preview/{table_id}", summary="预览代码", description="预览代码")
async def preview_code_controller(
table_id: int = Path(..., description="业务表ID"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:gencode:query"]))
) -> JSONResponse:
"""
预览代码
@@ -236,7 +236,7 @@ async def preview_code_controller(
@GenRouter.post("/sync_db/{table_name}", summary="同步数据库", description="同步数据库")
async def sync_db_controller(
table_name: str = Path(..., description="表名"),
auth: AuthSchema = Depends(AuthPermission(["generator:db:sync"]))
auth: AuthSchema = Depends(AuthPermission(["module_generator:db:sync"]))
) -> JSONResponse:
"""
同步数据库
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from typing import Optional, List, Dict, Any
from sqlalchemy import String, Integer, ForeignKey, Boolean, JSON, Text
from typing import Optional, List
from sqlalchemy import String, Integer, ForeignKey, Boolean
from sqlalchemy.orm import Mapped, mapped_column, relationship, validates
from sqlalchemy.sql import expression
+7 -7
View File
@@ -17,7 +17,7 @@ CacheRouter = APIRouter(route_class=OperationLogRoute, prefix="/cache", tags=["
@CacheRouter.get(
'/info',
dependencies=[Depends(AuthPermission(['monitor:cache:query']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:query']))],
summary="获取缓存监控信息",
description="获取缓存监控信息"
)
@@ -37,7 +37,7 @@ async def get_monitor_cache_info_controller(
@CacheRouter.get(
'/get/names',
dependencies=[Depends(AuthPermission(['monitor:cache:query']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:query']))],
summary="获取缓存名称列表",
description="获取缓存名称列表"
)
@@ -55,7 +55,7 @@ async def get_monitor_cache_name_controller() -> JSONResponse:
@CacheRouter.get(
'/get/keys/{cache_name}',
dependencies=[Depends(AuthPermission(['monitor:cache:query']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:query']))],
summary="获取缓存键名列表",
description="获取缓存键名列表"
)
@@ -79,7 +79,7 @@ async def get_monitor_cache_key_controller(
@CacheRouter.get(
'/get/value/{cache_name}/{cache_key}',
dependencies=[Depends(AuthPermission(['monitor:cache:query']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:query']))],
summary="获取缓存值",
description="获取缓存值"
)
@@ -105,7 +105,7 @@ async def get_monitor_cache_value_controller(
@CacheRouter.delete(
'/delete/name/{cache_name}',
dependencies=[Depends(AuthPermission(['monitor:cache:delete']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:delete']))],
summary="清除指定缓存名称的所有缓存",
description="清除指定缓存名称的所有缓存"
)
@@ -131,7 +131,7 @@ async def clear_monitor_cache_name_controller(
@CacheRouter.delete(
'/delete/key/{cache_key}',
dependencies=[Depends(AuthPermission(['monitor:cache:delete']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:delete']))],
summary="清除指定缓存键",
description="清除指定缓存键"
)
@@ -157,7 +157,7 @@ async def clear_monitor_cache_key_controller(
@CacheRouter.delete(
'/delete/all',
dependencies=[Depends(AuthPermission(['monitor:cache:delete']))],
dependencies=[Depends(AuthPermission(['module_monitor:cache:delete']))],
summary="清除所有缓存",
description="清除所有缓存"
)
@@ -19,7 +19,7 @@ OnlineRouter = APIRouter(route_class=OperationLogRoute, prefix="/online", tags=[
@OnlineRouter.get(
'/list',
dependencies=[Depends(AuthPermission(['monitor:online:query']))],
dependencies=[Depends(AuthPermission(['module_monitor:online:query']))],
summary="获取在线用户列表",
description="获取在线用户列表"
)
@@ -48,7 +48,7 @@ async def get_online_list_controller(
@OnlineRouter.delete(
'/delete',
dependencies=[Depends(AuthPermission(['monitor:online:delete']))],
dependencies=[Depends(AuthPermission(['module_monitor:online:delete']))],
summary="强制下线",
description="强制下线"
)
@@ -76,7 +76,7 @@ async def delete_online_controller(
@OnlineRouter.delete(
'/clear',
dependencies=[Depends(AuthPermission(['monitor:online:delete']))],
dependencies=[Depends(AuthPermission(['module_monitor:online:delete']))],
summary="清除所有在线用户",
description="清除所有在线用户"
)
@@ -26,7 +26,7 @@ ResourceRouter = APIRouter(route_class=OperationLogRoute, prefix="/resource", ta
"/list",
summary="获取目录列表",
description="获取指定目录下的文件和子目录列表",
dependencies=[Depends(AuthPermission(["monitor:resource:query"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:query"]))]
)
async def get_directory_list_controller(
request: Request,
@@ -64,7 +64,7 @@ async def get_directory_list_controller(
"/upload",
summary="上传文件",
description="上传文件到指定目录",
dependencies=[Depends(AuthPermission(["monitor:resource:upload"]))])
dependencies=[Depends(AuthPermission(["module_monitor:resource:upload"]))])
async def upload_file_controller(
file: UploadFile,
request: Request,
@@ -94,7 +94,7 @@ async def upload_file_controller(
"/download",
summary="下载文件",
description="下载指定文件",
dependencies=[Depends(AuthPermission(["monitor:resource:download"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:download"]))]
)
async def download_file_controller(
request: Request,
@@ -131,7 +131,7 @@ async def download_file_controller(
"/delete",
summary="删除文件",
description="删除指定文件或目录",
dependencies=[Depends(AuthPermission(["monitor:resource:delete"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:delete"]))]
)
async def delete_files_controller(
paths: List[str] = Body(..., description="文件路径列表")
@@ -154,7 +154,7 @@ async def delete_files_controller(
"/move",
summary="移动文件",
description="移动文件或目录",
dependencies=[Depends(AuthPermission(["monitor:resource:move"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:move"]))]
)
async def move_file_controller(
data: ResourceMoveSchema
@@ -177,7 +177,7 @@ async def move_file_controller(
"/copy",
summary="复制文件",
description="复制文件或目录",
dependencies=[Depends(AuthPermission(["monitor:resource:copy"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:copy"]))]
)
async def copy_file_controller(
data: ResourceCopySchema
@@ -200,7 +200,7 @@ async def copy_file_controller(
"/rename",
summary="重命名文件",
description="重命名文件或目录",
dependencies=[Depends(AuthPermission(["monitor:resource:rename"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:rename"]))]
)
async def rename_file_controller(
data: ResourceRenameSchema
@@ -223,7 +223,7 @@ async def rename_file_controller(
"/create-dir",
summary="创建目录",
description="在指定路径创建新目录",
dependencies=[Depends(AuthPermission(["monitor:resource:create_dir"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:create_dir"]))]
)
async def create_directory_controller(
data: ResourceCreateDirSchema
@@ -246,7 +246,7 @@ async def create_directory_controller(
"/export",
summary="导出资源列表",
description="导出资源列表",
dependencies=[Depends(AuthPermission(["monitor:resource:export"]))]
dependencies=[Depends(AuthPermission(["module_monitor:resource:export"]))]
)
async def export_resource_list_controller(
request: Request,
@@ -17,7 +17,7 @@ ServerRouter = APIRouter(route_class=OperationLogRoute, prefix="/server", tags=[
'/info',
summary="查询服务器监控信息",
description="查询服务器监控信息",
dependencies=[Depends(AuthPermission(["monitor:server:query"]))]
dependencies=[Depends(AuthPermission(["module_monitor:server:query"]))]
)
async def get_monitor_server_info_controller() -> JSONResponse:
"""
@@ -23,7 +23,7 @@ DeptRouter = APIRouter(route_class=OperationLogRoute, prefix="/dept", tags=["部
@DeptRouter.get("/tree", summary="查询部门树", description="查询部门树")
async def get_dept_tree_controller(
search: DeptQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:dept:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:query"]))
) -> JSONResponse:
"""
查询部门树
@@ -47,7 +47,7 @@ async def get_dept_tree_controller(
@DeptRouter.get("/detail/{id}", summary="查询部门详情", description="查询部门详情")
async def get_obj_detail_controller(
id: int = Path(..., description="部门ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dept:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:query"]))
) -> JSONResponse:
"""
查询部门详情
@@ -70,7 +70,7 @@ async def get_obj_detail_controller(
@DeptRouter.post("/create", summary="创建部门", description="创建部门")
async def create_obj_controller(
data: DeptCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:dept:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:create"]))
) -> JSONResponse:
"""
创建部门
@@ -94,7 +94,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: DeptUpdateSchema,
id: int = Path(..., description="部门ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dept:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:update"]))
) -> JSONResponse:
"""
修改部门
@@ -118,7 +118,7 @@ async def update_obj_controller(
@DeptRouter.delete("/delete", summary="删除部门", description="删除部门")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:dept:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:delete"]))
) -> JSONResponse:
"""
删除部门
@@ -141,7 +141,7 @@ async def delete_obj_controller(
@DeptRouter.patch("/available/setting", summary="批量修改部门状态", description="批量修改部门状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:dept:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dept:patch"]))
) -> JSONResponse:
"""
批量修改部门状态
@@ -29,7 +29,7 @@ DictRouter = APIRouter(route_class=OperationLogRoute, prefix="/dict", tags=["字
@DictRouter.get("/type/detail/{id}", summary="获取字典类型详情", description="获取字典类型详情")
async def get_type_detail_controller(
id: int = Path(..., description="字典类型ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:query"]))
) -> JSONResponse:
"""
获取字典类型详情
@@ -52,7 +52,7 @@ async def get_type_detail_controller(
async def get_type_list_controller(
page: PaginationQueryParam = Depends(),
search: DictTypeQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:query"]))
) -> JSONResponse:
"""
查询字典类型列表
@@ -75,7 +75,7 @@ async def get_type_list_controller(
@DictRouter.get("/type/optionselect", summary="获取全部字典类型", description="获取全部字典类型")
async def get_type_loptionselect_controller(
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:query"]))
) -> JSONResponse:
"""
获取全部字典类型
@@ -97,7 +97,7 @@ async def get_type_loptionselect_controller(
async def create_type_controller(
data: DictTypeCreateSchema,
redis: Redis = Depends(redis_getter),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:create"]))
) -> JSONResponse:
"""
创建字典类型
@@ -122,7 +122,7 @@ async def update_type_controller(
data: DictTypeUpdateSchema,
redis: Redis = Depends(redis_getter),
id: int = Path(..., description="字典类型ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:update"]))
) -> JSONResponse:
"""
修改字典类型
@@ -147,7 +147,7 @@ async def update_type_controller(
async def delete_type_controller(
redis: Redis = Depends(redis_getter),
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:delete"]))
) -> JSONResponse:
"""
删除字典类型
@@ -170,7 +170,7 @@ async def delete_type_controller(
@DictRouter.patch("/type/available/setting", summary="批量修改字典类型状态", description="批量修改字典类型状态")
async def batch_set_available_dict_type_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:patch"]))
) -> JSONResponse:
"""
批量修改字典类型状态
@@ -192,7 +192,7 @@ async def batch_set_available_dict_type_controller(
@DictRouter.post('/type/export', summary="导出字典类型", description="导出字典类型")
async def export_type_list_controller(
search: DictTypeQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:dict_type:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_type:export"]))
) -> StreamingResponse:
"""
导出字典类型
@@ -223,7 +223,7 @@ async def export_type_list_controller(
@DictRouter.get("/data/detail/{id}", summary="获取字典数据详情", description="获取字典数据详情")
async def get_data_detail_controller(
id: int = Path(..., description="字典数据ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:query"]))
) -> JSONResponse:
"""
获取字典数据详情
@@ -246,7 +246,7 @@ async def get_data_detail_controller(
async def get_data_list_controller(
page: PaginationQueryParam = Depends(),
search: DictDataQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:query"]))
) -> JSONResponse:
"""
查询字典数据
@@ -274,7 +274,7 @@ async def get_data_list_controller(
async def create_data_controller(
data: DictDataCreateSchema,
redis: Redis = Depends(redis_getter),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:create"]))
) -> JSONResponse:
"""
创建字典数据
@@ -299,7 +299,7 @@ async def update_data_controller(
data: DictDataUpdateSchema,
redis: Redis = Depends(redis_getter),
id: int = Path(..., description="字典数据ID"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:update"]))
) -> JSONResponse:
"""
修改字典数据
@@ -324,7 +324,7 @@ async def update_data_controller(
async def delete_data_controller(
redis: Redis = Depends(redis_getter),
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:delete"]))
) -> JSONResponse:
"""
删除字典数据
@@ -347,7 +347,7 @@ async def delete_data_controller(
@DictRouter.patch("/data/available/setting", summary="批量修改字典数据状态", description="批量修改字典数据状态")
async def batch_set_available_dict_data_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:patch"]))
) -> JSONResponse:
"""
批量修改字典数据状态
@@ -370,7 +370,7 @@ async def batch_set_available_dict_data_controller(
async def export_data_list_controller(
search: DictDataQueryParam = Depends(),
page: PaginationQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:dict_data:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:dict_data:export"]))
) -> StreamingResponse:
"""
导出字典数据
@@ -22,7 +22,7 @@ LogRouter = APIRouter(route_class=OperationLogRoute, prefix="/log", tags=["日
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: OperationLogQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:log:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:log:query"]))
) -> JSONResponse:
"""
查询日志
@@ -47,7 +47,7 @@ async def get_obj_list_controller(
@LogRouter.get("/detail/{id}", summary="日志详情", description="日志详情")
async def get_obj_detail_controller(
id: int = Path(..., description="操作日志ID"),
auth: AuthSchema = Depends(AuthPermission(["system:log:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:log:query"]))
) -> JSONResponse:
"""
获取日志详情
@@ -67,7 +67,7 @@ async def get_obj_detail_controller(
@LogRouter.delete("/delete", summary="删除日志", description="删除日志")
async def delete_obj_log_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:log:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:log:delete"]))
) -> JSONResponse:
"""
删除日志
@@ -87,7 +87,7 @@ async def delete_obj_log_controller(
@LogRouter.post("/export", summary="导出日志", description="导出日志")
async def export_obj_list_controller(
search: OperationLogQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:log:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:log:export"]))
) -> StreamingResponse:
"""
导出日志
@@ -22,7 +22,7 @@ MenuRouter = APIRouter(route_class=OperationLogRoute, prefix="/menu", tags=["菜
@MenuRouter.get("/tree", summary="查询菜单树", description="查询菜单树")
async def get_menu_tree_controller(
search: MenuQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:menu:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:query"]))
) -> JSONResponse:
"""
查询菜单树
@@ -42,7 +42,7 @@ async def get_menu_tree_controller(
@MenuRouter.get("/detail/{id}", summary="查询菜单详情", description="查询菜单详情")
async def get_obj_detail_controller(
id: int = Path(..., description="菜单ID"),
auth: AuthSchema = Depends(AuthPermission(["system:menu:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:query"]))
) -> JSONResponse:
"""
查询菜单详情
@@ -61,7 +61,7 @@ async def get_obj_detail_controller(
@MenuRouter.post("/create", summary="创建菜单", description="创建菜单")
async def create_obj_controller(
data: MenuCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:menu:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:create"]))
) -> JSONResponse:
"""
创建菜单
@@ -81,7 +81,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: MenuUpdateSchema,
id: int = Path(..., description="菜单ID"),
auth: AuthSchema = Depends(AuthPermission(["system:menu:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:update"]))
) -> JSONResponse:
"""
修改菜单
@@ -101,7 +101,7 @@ async def update_obj_controller(
@MenuRouter.delete("/delete", summary="删除菜单", description="删除菜单")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:menu:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:delete"]))
) -> JSONResponse:
"""
删除菜单
@@ -120,7 +120,7 @@ async def delete_obj_controller(
@MenuRouter.patch("/available/setting", summary="批量修改菜单状态", description="批量修改菜单状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:menu:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:menu:patch"]))
) -> JSONResponse:
"""
批量修改菜单状态
@@ -34,7 +34,7 @@ class MenuModel(ModelMixin):
type: Mapped[int] = mapped_column(Integer, nullable=False, default=2, comment='菜单类型(1:目录 2:菜单 3:按钮/权限 4:链接)')
order: Mapped[int] = mapped_column(Integer, nullable=False, default=999, comment='显示排序')
status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)")
permission: Mapped[Optional[str]] = mapped_column(String(100), comment='权限标识(如:system:user:list)')
permission: Mapped[Optional[str]] = mapped_column(String(100), comment='权限标识(如:module_system:user:list)')
icon: Mapped[Optional[str]] = mapped_column(String(50), comment='菜单图标')
route_name: Mapped[Optional[str]] = mapped_column(String(100), comment='路由名称')
route_path: Mapped[Optional[str]] = mapped_column(String(200), comment='路由路径')
@@ -25,7 +25,7 @@ NoticeRouter = APIRouter(route_class=OperationLogRoute, prefix="/notice", tags=[
@NoticeRouter.get("/detail/{id}", summary="获取公告详情", description="获取公告详情")
async def get_obj_detail_controller(
id: int = Path(..., description="公告ID"),
auth: AuthSchema = Depends(AuthPermission(["system:notice:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:query"]))
) -> JSONResponse:
"""
获取公告详情
@@ -45,7 +45,7 @@ async def get_obj_detail_controller(
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: NoticeQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:notice:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:query"]))
) -> JSONResponse:
"""
查询公告
@@ -66,7 +66,7 @@ async def get_obj_list_controller(
@NoticeRouter.post("/create", summary="创建公告", description="创建公告")
async def create_obj_controller(
data: NoticeCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:notice:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:create"]))
) -> JSONResponse:
"""
创建公告
@@ -86,7 +86,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: NoticeUpdateSchema,
id: int = Path(..., description="公告ID"),
auth: AuthSchema = Depends(AuthPermission(["system:notice:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:update"]))
) -> JSONResponse:
"""
修改公告
@@ -106,7 +106,7 @@ async def update_obj_controller(
@NoticeRouter.delete("/delete", summary="删除公告", description="删除公告")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:notice:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:delete"]))
) -> JSONResponse:
"""
删除公告
@@ -125,7 +125,7 @@ async def delete_obj_controller(
@NoticeRouter.patch("/available/setting", summary="批量修改公告状态", description="批量修改公告状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:notice:patch"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:patch"]))
) -> JSONResponse:
"""
批量修改公告状态
@@ -144,7 +144,7 @@ async def batch_set_available_obj_controller(
@NoticeRouter.post('/export', summary="导出公告", description="导出公告")
async def export_obj_list_controller(
search: NoticeQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:notice:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:notice:export"]))
) -> StreamingResponse:
"""
导出公告
@@ -23,7 +23,7 @@ ParamsRouter = APIRouter(route_class=OperationLogRoute, prefix="/param", tags=["
@ParamsRouter.get("/detail/{id}", summary="获取参数详情", description="获取参数详情")
async def get_type_detail_controller(
id: int = Path(..., description="参数ID"),
auth: AuthSchema = Depends(AuthPermission(["system:param:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:query"]))
) -> JSONResponse:
"""
获取参数详情
@@ -43,7 +43,7 @@ async def get_type_detail_controller(
@ParamsRouter.get("/key/{config_key}", summary="根据配置键获取参数详情", description="根据配置键获取参数详情")
async def get_obj_by_key_controller(
config_key: str = Path(..., description="配置键"),
auth: AuthSchema = Depends(AuthPermission(["system:param:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:query"]))
) -> JSONResponse:
"""
根据配置键获取参数详情
@@ -63,7 +63,7 @@ async def get_obj_by_key_controller(
@ParamsRouter.get("/value/{config_key}", summary="根据配置键获取参数值", description="根据配置键获取参数值")
async def get_config_value_by_key_controller(
config_key: str = Path(..., description="配置键"),
auth: AuthSchema = Depends(AuthPermission(["system:param:query"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:query"]))
) -> JSONResponse:
"""
根据配置键获取参数值
@@ -82,7 +82,7 @@ async def get_config_value_by_key_controller(
@ParamsRouter.get("/list", summary="获取参数列表", description="获取参数列表")
async def get_obj_list_controller(
auth: AuthSchema = Depends(AuthPermission(["system:param:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:param:query"])),
page: PaginationQueryParam = Depends(),
search: ParamsQueryParam = Depends(),
) -> JSONResponse:
@@ -107,7 +107,7 @@ async def get_obj_list_controller(
async def create_obj_controller(
data: ParamsCreateSchema,
redis: Redis = Depends(redis_getter),
auth: AuthSchema = Depends(AuthPermission(["system:param:create"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:create"]))
) -> JSONResponse:
"""
创建参数
@@ -130,7 +130,7 @@ async def update_objs_controller(
data: ParamsUpdateSchema,
id: int = Path(..., description="参数ID"),
redis: Redis = Depends(redis_getter),
auth: AuthSchema = Depends(AuthPermission(["system:param:update"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:update"]))
) -> JSONResponse:
"""
修改参数
@@ -153,7 +153,7 @@ async def update_objs_controller(
async def delete_obj_controller(
redis: Redis = Depends(redis_getter),
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:param:delete"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:delete"]))
) -> JSONResponse:
"""
删除参数
@@ -174,7 +174,7 @@ async def delete_obj_controller(
@ParamsRouter.post('/export', summary="导出参数", description="导出参数")
async def export_obj_list_controller(
search: ParamsQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:param:export"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:param:export"]))
) -> StreamingResponse:
"""
导出参数
@@ -199,7 +199,7 @@ async def export_obj_list_controller(
)
@ParamsRouter.post("/upload", summary="上传文件", dependencies=[Depends(AuthPermission(["system:param:upload"]))])
@ParamsRouter.post("/upload", summary="上传文件", dependencies=[Depends(AuthPermission(["module_system:param:upload"]))])
async def upload_file_controller(
file: UploadFile,
request: Request
@@ -27,7 +27,7 @@ PositionRouter = APIRouter(route_class=OperationLogRoute, prefix="/position", ta
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: PositionQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:position:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:query"])),
) -> JSONResponse:
"""
查询岗位列表
@@ -52,7 +52,7 @@ async def get_obj_list_controller(
@PositionRouter.get("/detail/{id}", summary="查询岗位详情", description="查询岗位详情")
async def get_obj_detail_controller(
id: int = Path(..., description="岗位ID"),
auth: AuthSchema = Depends(AuthPermission(["system:position:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:query"])),
) -> JSONResponse:
"""
查询岗位详情
@@ -72,7 +72,7 @@ async def get_obj_detail_controller(
@PositionRouter.post("/create", summary="创建岗位", description="创建岗位")
async def create_obj_controller(
data: PositionCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:position:create"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:create"])),
) -> JSONResponse:
"""
创建岗位
@@ -93,7 +93,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: PositionUpdateSchema,
id: int = Path(..., description="岗位ID"),
auth: AuthSchema = Depends(AuthPermission(["system:position:update"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:update"])),
) -> JSONResponse:
"""
修改岗位
@@ -114,7 +114,7 @@ async def update_obj_controller(
@PositionRouter.delete("/delete", summary="删除岗位", description="删除岗位")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:position:delete"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:delete"])),
) -> JSONResponse:
"""
删除岗位
@@ -134,7 +134,7 @@ async def delete_obj_controller(
@PositionRouter.patch("/available/setting", summary="批量修改岗位状态", description="批量修改岗位状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:position:patch"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:patch"])),
) -> JSONResponse:
"""
批量修改岗位状态
@@ -154,7 +154,7 @@ async def batch_set_available_obj_controller(
@PositionRouter.post('/export', summary="导出岗位", description="导出岗位")
async def export_obj_list_controller(
search: PositionQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:position:export"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:position:export"])),
) -> StreamingResponse:
"""
导出岗位
@@ -28,7 +28,7 @@ RoleRouter = APIRouter(route_class=OperationLogRoute, prefix="/role", tags=["角
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: RoleQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:role:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:query"])),
) -> JSONResponse:
"""
查询角色
@@ -53,7 +53,7 @@ async def get_obj_list_controller(
@RoleRouter.get("/detail/{id}", summary="查询角色详情", description="查询角色详情")
async def get_obj_detail_controller(
id: int = Path(..., description="角色ID"),
auth: AuthSchema = Depends(AuthPermission(["system:role:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:query"])),
) -> JSONResponse:
"""
查询角色详情
@@ -73,7 +73,7 @@ async def get_obj_detail_controller(
@RoleRouter.post("/create", summary="创建角色", description="创建角色")
async def create_obj_controller(
data: RoleCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:role:create"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:create"])),
) -> JSONResponse:
"""
创建角色
@@ -94,7 +94,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: RoleUpdateSchema,
id: int = Path(..., description="角色ID"),
auth: AuthSchema = Depends(AuthPermission(["system:role:update"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:update"])),
) -> JSONResponse:
"""
修改角色
@@ -115,7 +115,7 @@ async def update_obj_controller(
@RoleRouter.delete("/delete", summary="删除角色", description="删除角色")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:role:delete"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:delete"])),
) -> JSONResponse:
"""
删除角色
@@ -135,7 +135,7 @@ async def delete_obj_controller(
@RoleRouter.patch("/available/setting", summary="批量修改角色状态", description="批量修改角色状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:role:patch"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:patch"])),
) -> JSONResponse:
"""
批量修改角色状态
@@ -155,7 +155,7 @@ async def batch_set_available_obj_controller(
@RoleRouter.patch("/permission/setting", summary="角色授权", description="角色授权")
async def set_role_permission_controller(
data: RolePermissionSettingSchema,
auth: AuthSchema = Depends(AuthPermission(["system:role:permission"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:permission"])),
) -> JSONResponse:
"""
角色授权
@@ -175,7 +175,7 @@ async def set_role_permission_controller(
@RoleRouter.post('/export', summary="导出角色", description="导出角色")
async def export_obj_list_controller(
search: RoleQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:role:export"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:role:export"])),
) -> StreamingResponse:
"""
导出角色
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
@@ -0,0 +1,214 @@
# -*- coding: utf-8 -*-
from fastapi import APIRouter, Body, Depends, Path, UploadFile
from fastapi.responses import JSONResponse, StreamingResponse
import urllib.parse
from app.common.response import StreamResponse, SuccessResponse
from app.utils.common_util import bytes2file_response
from app.core.base_params import PaginationQueryParam
from app.core.dependencies import AuthPermission
from app.core.router_class import OperationLogRoute
from app.core.base_schema import BatchSetAvailable
from app.core.logger import logger
from app.api.v1.module_system.auth.schema import AuthSchema
from .param import TenantQueryParam
from .service import TenantService
from .schema import (
TenantCreateSchema,
TenantUpdateSchema
)
TenantRouter = APIRouter(route_class=OperationLogRoute, prefix="/tenant", tags=["租户模块"])
@TenantRouter.get("/detail/{id}", summary="获取租户详情", description="获取租户详情")
async def get_obj_detail_controller(
id: int = Path(..., description="租户ID"),
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:query"]))
) -> JSONResponse:
"""
获取租户详情
参数:
- id (int): 租户ID
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含租户详情的JSON响应
"""
result_dict = await TenantService.detail_service(id=id, auth=auth)
logger.info(f"获取租户详情成功 {id}")
return SuccessResponse(data=result_dict, msg="获取租户详情成功")
@TenantRouter.get("/list", summary="查询租户列表", description="查询租户列表")
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: TenantQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:query"]))
) -> JSONResponse:
"""
查询租户列表
参数:
- page (PaginationQueryParam): 分页查询参数
- search (TenantQueryParam): 查询参数
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含租户列表分页信息的JSON响应
"""
# 使用数据库分页而不是应用层分页
result_dict = await TenantService.page_service(
auth=auth,
page_no=page.page_no if page.page_no is not None else 1,
page_size=page.page_size if page.page_size is not None else 10,
search=search,
order_by=page.order_by
)
logger.info("查询租户列表成功")
return SuccessResponse(data=result_dict, msg="查询租户列表成功")
@TenantRouter.post("/create", summary="创建租户", description="创建租户")
async def create_obj_controller(
data: TenantCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:create"]))
) -> JSONResponse:
"""
创建租户
参数:
- data (TenantCreateSchema): 租户创建模型
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含创建租户详情的JSON响应
"""
result_dict = await TenantService.create_service(auth=auth, data=data)
logger.info(f"创建租户成功: {result_dict.get('name')}")
return SuccessResponse(data=result_dict, msg="创建租户成功")
@TenantRouter.put("/update/{id}", summary="修改租户", description="修改租户")
async def update_obj_controller(
data: TenantUpdateSchema,
id: int = Path(..., description="租户ID"),
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:update"]))
) -> JSONResponse:
"""
修改租户
参数:
- data (TenantUpdateSchema): 租户更新模型
- id (int): 租户ID
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含修改租户详情的JSON响应
"""
result_dict = await TenantService.update_service(auth=auth, id=id, data=data)
logger.info(f"修改租户成功: {result_dict.get('name')}")
return SuccessResponse(data=result_dict, msg="修改租户成功")
@TenantRouter.delete("/delete", summary="删除租户", description="删除租户")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:delete"]))
) -> JSONResponse:
"""
删除租户
参数:
- ids (list[int]): 租户ID列表
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含删除租户详情的JSON响应
"""
await TenantService.delete_service(auth=auth, ids=ids)
logger.info(f"删除租户成功: {ids}")
return SuccessResponse(msg="删除租户成功")
@TenantRouter.patch("/available/setting", summary="批量修改租户状态", description="批量修改租户状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:patch"]))
) -> JSONResponse:
"""
批量修改租户状态
参数:
- data (BatchSetAvailable): 批量修改租户状态模型
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含批量修改租户状态详情的JSON响应
"""
await TenantService.set_available_service(auth=auth, data=data)
logger.info(f"批量修改租户状态成功: {data.ids}")
return SuccessResponse(msg="批量修改租户状态成功")
@TenantRouter.post('/export', summary="导出租户", description="导出租户")
async def export_obj_list_controller(
search: TenantQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:export"]))
) -> StreamingResponse:
"""
导出租户
参数:
- search (TenantQueryParam): 查询参数
- auth (AuthSchema): 认证信息模型
返回:
- StreamingResponse: 包含租户列表的Excel文件流响应
"""
result_dict_list = await TenantService.list_service(search=search, auth=auth)
export_result = await TenantService.batch_export_service(obj_list=result_dict_list)
logger.info('导出租户成功')
return StreamResponse(
data=bytes2file_response(export_result),
media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
headers={
'Content-Disposition': 'attachment; filename=example.xlsx'
}
)
@TenantRouter.post('/import', summary="导入租户", description="导入租户")
async def import_obj_list_controller(
file: UploadFile,
auth: AuthSchema = Depends(AuthPermission(["module_system:tenant:import"]))
) -> JSONResponse:
"""
导入租户
参数:
- file (UploadFile): 导入的Excel文件
- auth (AuthSchema): 认证信息模型
返回:
- JSONResponse: 包含导入租户详情的JSON响应
"""
batch_import_result = await TenantService.batch_import_service(file=file, auth=auth, update_support=True)
logger.info(f"导入租户成功: {batch_import_result}")
return SuccessResponse(data=batch_import_result, msg="导入租户成功")
@TenantRouter.post('/download/template', summary="获取租户导入模板", description="获取租户导入模板", dependencies=[Depends(AuthPermission(["module_system:tenant:download"]))])
async def export_obj_template_controller() -> StreamingResponse:
"""
获取租户导入模板
返回:
- StreamingResponse: 包含租户导入模板的Excel文件流响应
"""
example_import_template_result = await TenantService.import_template_download_service()
logger.info('获取租户导入模板成功')
return StreamResponse(
data=bytes2file_response(example_import_template_result),
media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
headers={
'Content-Disposition': f'attachment; filename={urllib.parse.quote("租户导入模板.xlsx")}',
'Access-Control-Expose-Headers': 'Content-Disposition'
}
)
@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
from typing import Dict, List, Optional, Sequence, Union, Any
from app.core.base_crud import CRUDBase
from app.api.v1.module_system.auth.schema import AuthSchema
from .model import TenantModel
from .schema import TenantCreateSchema, TenantUpdateSchema, TenantOutSchema
class TenantCRUD(CRUDBase[TenantModel, TenantCreateSchema, TenantUpdateSchema]):
"""租户数据层"""
def __init__(self, auth: AuthSchema) -> None:
"""
初始化CRUD数据层
参数:
- auth (AuthSchema): 认证信息模型
"""
super().__init__(model=TenantModel, auth=auth)
async def get_by_id_crud(self, id: int, preload: Optional[List[Union[str, Any]]] = None) -> Optional[TenantModel]:
"""
详情
参数:
- id (int): 租户ID
- preload (Optional[List[Union[str, Any]]]): 预加载关系未提供时使用模型默认项
返回:
- Optional[TenantModel]: 租户模型实例或None
"""
return await self.get(id=id, preload=preload)
async def list_crud(self, search: Optional[Dict] = None, order_by: Optional[List[Dict[str, str]]] = None, preload: Optional[List[Union[str, Any]]] = None) -> Sequence[TenantModel]:
"""
列表查询
参数:
- search (Optional[Dict]): 查询参数
- order_by (Optional[List[Dict[str, str]]]): 排序参数
- preload (Optional[List[Union[str, Any]]]): 预加载关系未提供时使用模型默认项
返回:
- Sequence[TenantModel]: 租户模型实例序列
"""
return await self.list(search=search, order_by=order_by, preload=preload)
async def create_crud(self, data: TenantCreateSchema) -> Optional[TenantModel]:
"""
创建
参数:
- data (TenantCreateSchema): 租户创建模型
返回:
- Optional[TenantModel]: 租户模型实例或None
"""
return await self.create(data=data)
async def update_crud(self, id: int, data: TenantUpdateSchema) -> Optional[TenantModel]:
"""
更新
参数:
- id (int): 租户ID
- data (TenantUpdateSchema): 租户更新模型
返回:
- Optional[TenantModel]: 租户模型实例或None
"""
return await self.update(id=id, data=data)
async def delete_crud(self, ids: List[int]) -> None:
"""
批量删除
参数:
- ids (List[int]): 租户ID列表
返回:
- None
"""
return await self.delete(ids=ids)
async def set_available_crud(self, ids: List[int], status: bool) -> None:
"""
批量设置可用状态
参数:
- ids (List[int]): 租户ID列表
- status (bool): 可用状态
返回:
- None
"""
return await self.set(ids=ids, status=status)
async def page_crud(self, offset: int, limit: int, order_by: Optional[List[Dict[str, str]]] = None, search: Optional[Dict] = None, preload: Optional[List[Union[str, Any]]] = None) -> Dict:
"""
分页查询
参数:
- offset (int): 偏移量
- limit (int): 每页数量
- order_by (Optional[List[Dict[str, str]]]): 排序参数
- search (Optional[Dict]): 查询参数
- preload (Optional[List[Union[str, Any]]]): 预加载关系未提供时使用模型默认项
返回:
- Dict: 分页数据
"""
order_by_list = order_by or [{'id': 'asc'}]
search_dict = search or {}
return await self.page(
offset=offset,
limit=limit,
order_by=order_by_list,
search=search_dict,
out_schema=TenantOutSchema,
preload=preload
)
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from typing import Optional
from sqlalchemy import Boolean, String
from sqlalchemy.orm import Mapped, mapped_column, validates
from app.core.base_model import ModelMixin
class TenantModel(ModelMixin):
"""
租户表
"""
__tablename__ = 'system_tenant'
__table_args__ = ({'comment': '租户表'})
name: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, default='', comment='租户名称')
status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)")
@validates('name')
def validate_name(self, key: str, name: str) -> str:
"""验证名称不为空"""
if not name or not name.strip():
raise ValueError('名称不能为空')
return name
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from typing import Optional
from fastapi import Query
from app.core.validator import DateTimeStr
class TenantQueryParam:
"""租户查询参数"""
def __init__(
self,
name: Optional[str] = Query(None, description="租户名称"),
status: Optional[bool] = Query(None, description="状态用(True:启用 False:禁用)"),
creator: Optional[int] = Query(None, description="创建人"),
start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2025-01-01 00:00:00"),
end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2025-12-31 23:59:59"),
) -> None:
# 模糊查询字段
self.name = ("like", name)
# 精确查询字段
self.creator_id = creator
self.status = status
# 时间范围查询
if start_time and end_time:
self.created_at = ("between", (start_time, end_time))
@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from app.core.base_schema import BaseSchema
class TenantCreateSchema(BaseModel):
"""新增模型"""
name: str = Field(..., max_length=50, description='租户名称')
status: bool = Field(True, description="是否启用(True:启用 False:禁用)")
description: Optional[str] = Field(default=None, max_length=255, description="描述")
@field_validator('name')
@classmethod
def _validate_name(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError('名称不能为空')
return v
@model_validator(mode='before')
@classmethod
def _normalize(cls, data):
if isinstance(data, dict):
for key in ('name', 'description'):
val = data.get(key)
if isinstance(val, str):
val = val.strip()
if key == 'description' and val == '':
val = None
data[key] = val
# status兼容
val = data.get('status')
if isinstance(val, str):
lowered = val.strip().lower()
if lowered in {'true', '1', 'y', 'yes'}:
data['status'] = True
elif lowered in {'false', '0', 'n', 'no'}:
data['status'] = False
elif isinstance(val, int):
data['status'] = bool(val)
return data
@model_validator(mode='wrap')
@classmethod
def _wrap(cls, data, handler):
# 进一步处理:压缩名称/描述中的多余空白,并支持更多 status 同义词
if isinstance(data, dict):
name = data.get('name')
if isinstance(name, str):
data['name'] = ' '.join(name.split())
status_val = data.get('status')
if isinstance(status_val, str):
lowered = status_val.strip().lower()
if lowered in {'enabled', 'enable', 'on'}:
data['status'] = True
elif lowered in {'disabled', 'disable', 'off'}:
data['status'] = False
desc = data.get('description')
if isinstance(desc, str):
data['description'] = ' '.join(desc.split())
result = handler(data)
return result
@model_validator(mode='after')
def _check_disabled_requires_description(self):
# 业务示例:禁用时必须填写描述
if self.status is False and (self.description is None or (isinstance(self.description, str) and self.description.strip() == '')):
raise ValueError('禁用时必须填写描述')
return self
class TenantUpdateSchema(TenantCreateSchema):
"""更新模型"""
...
class TenantOutSchema(TenantCreateSchema, BaseSchema):
"""响应模型"""
model_config = ConfigDict(from_attributes=True)
@@ -0,0 +1,306 @@
# -*- coding: utf-8 -*-
import io
from typing import Any, List, Dict, Optional
from fastapi import UploadFile
import pandas as pd
from app.core.base_schema import BatchSetAvailable
from app.core.exceptions import CustomException
from app.utils.excel_util import ExcelUtil
from app.core.logger import logger
from app.api.v1.module_system.auth.schema import AuthSchema
from .schema import TenantCreateSchema, TenantUpdateSchema, TenantOutSchema
from .param import TenantQueryParam
from .crud import TenantCRUD
class TenantService:
"""
租户管理模块服务层
"""
@classmethod
async def detail_service(cls, auth: AuthSchema, id: int) -> Dict:
"""
详情
参数:
- auth (AuthSchema): 认证信息模型
- id (int): 租户ID
返回:
- Dict: 租户模型实例字典
"""
obj = await TenantCRUD(auth).get_by_id_crud(id=id)
if not obj:
raise CustomException(msg="该数据不存在")
return TenantOutSchema.model_validate(obj).model_dump()
@classmethod
async def list_service(cls, auth: AuthSchema, search: Optional[TenantQueryParam] = None, order_by: Optional[List[Dict[str, str]]] = None) -> List[Dict]:
"""
列表查询
参数:
- auth (AuthSchema): 认证信息模型
- search (Optional[TenantQueryParam]): 查询参数
- order_by (Optional[List[Dict[str, str]]]): 排序参数
返回:
- List[Dict]: 租户模型实例字典列表
"""
search_dict = search.__dict__ if search else None
obj_list = await TenantCRUD(auth).list_crud(search=search_dict, order_by=order_by)
return [TenantOutSchema.model_validate(obj).model_dump() for obj in obj_list]
@classmethod
async def page_service(cls, auth: AuthSchema, page_no: int, page_size: int, search: Optional[TenantQueryParam] = None, order_by: Optional[List[Dict[str, str]]] = None) -> Dict:
"""
分页查询
参数:
- auth (AuthSchema): 认证信息模型
- page_no (int): 页码
- page_size (int): 每页数量
- search (Optional[TenantQueryParam]): 查询参数
- order_by (Optional[List[Dict[str, str]]]): 排序参数
返回:
- Dict: 分页数据
"""
search_dict = search.__dict__ if search else {}
order_by_list = order_by or [{'id': 'asc'}]
offset = (page_no - 1) * page_size
result = await TenantCRUD(auth).page_crud(
offset=offset,
limit=page_size,
order_by=order_by_list,
search=search_dict
)
return result
@classmethod
async def create_service(cls, auth: AuthSchema, data: TenantCreateSchema) -> Dict:
"""
创建
参数:
- auth (AuthSchema): 认证信息模型
- data (TenantCreateSchema): 租户创建模型
返回:
- Dict: 租户模型实例字典
"""
obj = await TenantCRUD(auth).get(name=data.name)
if obj:
raise CustomException(msg='创建失败,名称已存在')
obj = await TenantCRUD(auth).create_crud(data=data)
return TenantOutSchema.model_validate(obj).model_dump()
@classmethod
async def update_service(cls, auth: AuthSchema, id: int, data: TenantUpdateSchema) -> Dict:
"""
更新
参数:
- auth (AuthSchema): 认证信息模型
- id (int): 租户ID
- data (TenantUpdateSchema): 租户更新模型
返回:
- Dict: 租户模型实例字典
"""
# 检查数据是否存在
obj = await TenantCRUD(auth).get_by_id_crud(id=id)
if not obj:
raise CustomException(msg='更新失败,该数据不存在')
# 检查名称是否重复
exist_obj = await TenantCRUD(auth).get(name=data.name)
if exist_obj and exist_obj.id != id:
raise CustomException(msg='更新失败,名称重复')
obj = await TenantCRUD(auth).update_crud(id=id, data=data)
return TenantOutSchema.model_validate(obj).model_dump()
@classmethod
async def delete_service(cls, auth: AuthSchema, ids: List[int]) -> None:
"""
删除
参数:
- auth (AuthSchema): 认证信息模型
- ids (List[int]): 租户ID列表
返回:
- None
"""
if len(ids) < 1:
raise CustomException(msg='删除失败,删除对象不能为空')
# 检查所有要删除的数据是否存在
for id in ids:
obj = await TenantCRUD(auth).get_by_id_crud(id=id)
if not obj:
raise CustomException(msg=f'删除失败,ID为{id}的数据不存在')
await TenantCRUD(auth).delete_crud(ids=ids)
@classmethod
async def set_available_service(cls, auth: AuthSchema, data: BatchSetAvailable) -> None:
"""
批量设置状态
参数:
- auth (AuthSchema): 认证信息模型
- data (BatchSetAvailable): 批量设置状态模型
返回:
- None
"""
await TenantCRUD(auth).set_available_crud(ids=data.ids, status=data.status)
@classmethod
async def batch_export_service(cls, obj_list: List[Dict[str, Any]]) -> bytes:
"""
批量导出
参数:
- obj_list (List[Dict[str, Any]]): 租户模型实例字典列表
返回:
- bytes: Excel文件字节流
"""
mapping_dict = {
'id': '编号',
'name': '名称',
'status': '状态',
'description': '备注',
'created_at': '创建时间',
'updated_at': '更新时间',
'creator': '创建者',
}
# 复制数据并转换状态
data = obj_list.copy()
for item in data:
# 处理状态
item['status'] = '正常' if item.get('status') else '停用'
# 处理创建者
creator_info = item.get('creator')
if isinstance(creator_info, dict):
item['creator'] = creator_info.get('name', '未知')
else:
item['creator'] = '未知'
return ExcelUtil.export_list2excel(list_data=data, mapping_dict=mapping_dict)
@classmethod
async def batch_import_service(cls, auth: AuthSchema, file: UploadFile, update_support: bool = False) -> str:
"""
批量导入
参数:
- auth (AuthSchema): 认证信息模型
- file (UploadFile): 上传的Excel文件
- update_support (bool): 是否支持更新存在数据
返回:
- str: 导入结果信息
"""
header_dict = {
'名称': 'name',
'状态': 'status',
'描述': 'description'
}
try:
# 读取Excel文件
contents = await file.read()
df = pd.read_excel(io.BytesIO(contents))
await file.close()
if df.empty:
raise CustomException(msg="导入文件为空")
# 检查表头是否完整
missing_headers = [header for header in header_dict.keys() if header not in df.columns]
if missing_headers:
raise CustomException(msg=f"导入文件缺少必要的列: {', '.join(missing_headers)}")
# 重命名列名
df.rename(columns=header_dict, inplace=True)
# 验证必填字段
required_fields = ['name', 'status']
for field in required_fields:
missing_rows = df[df[field].isnull()].index.tolist()
raise CustomException(msg=f"{[k for k,v in header_dict.items() if v == field][0]}不能为空,第{[i+1 for i in missing_rows]}")
error_msgs = []
success_count = 0
count = 0
# 处理每一行数据
for index, row in df.iterrows():
count += 1
try:
# 数据转换前的类型检查
try:
status = True if row['status'] == '正常' else False
except ValueError:
error_msgs.append(f"{count}行: 状态必须是'正常''停用'")
continue
# 构建用户数据
data = {
"name": str(row['name']),
"status": status,
"description": str(row['description']),
}
# 处理用户导入
exists_obj = await TenantCRUD(auth).get(name=data["name"])
if exists_obj:
if update_support:
await TenantCRUD(auth).update(id=exists_obj.id, data=data)
success_count += 1
else:
error_msgs.append(f"{count}行: 对象 {data['name']} 已存在")
else:
await TenantCRUD(auth).create(data=data)
success_count += 1
except Exception as e:
error_msgs.append(f"{count}行: {str(e)}")
continue
# 返回详细的导入结果
result = f"成功导入 {success_count} 条数据"
if error_msgs:
result += "\n错误信息:\n" + "\n".join(error_msgs)
return result
except Exception as e:
logger.error(f"批量导入用户失败: {str(e)}")
raise CustomException(msg=f"导入失败: {str(e)}")
@classmethod
async def import_template_download_service(cls) -> bytes:
"""
下载导入模板
返回:
- bytes: Excel文件字节流
"""
header_list = ['名称', '状态', '描述']
selector_header_list = ['状态']
option_list = [{'状态': ['正常', '停用']}]
return ExcelUtil.get_excel_template(
header_list=header_list,
selector_header_list=selector_header_list,
option_list=option_list
)
@@ -172,7 +172,7 @@ async def forget_password_controller(
async def get_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: UserQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:user:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:query"])),
) -> JSONResponse:
"""
查询用户
@@ -194,7 +194,7 @@ async def get_obj_list_controller(
@UserRouter.get("/detail/{id}", summary="查询用户详情", description="查询用户详情")
async def get_obj_detail_controller(
id: int = Path(..., description="用户ID"),
auth: AuthSchema = Depends(AuthPermission(["system:user:query"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:query"])),
) -> JSONResponse:
"""
查询用户详情
@@ -214,7 +214,7 @@ async def get_obj_detail_controller(
@UserRouter.post("/create", summary="创建用户", description="创建用户")
async def create_obj_controller(
data: UserCreateSchema,
auth: AuthSchema = Depends(AuthPermission(["system:user:create"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:create"])),
) -> JSONResponse:
"""
创建用户
@@ -239,7 +239,7 @@ async def create_obj_controller(
async def update_obj_controller(
data: UserUpdateSchema,
id: int = Path(..., description="用户ID"),
auth: AuthSchema = Depends(AuthPermission(["system:user:update"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:update"])),
) -> JSONResponse:
"""
修改用户
@@ -260,7 +260,7 @@ async def update_obj_controller(
@UserRouter.delete("/delete", summary="删除用户", description="删除用户")
async def delete_obj_controller(
ids: list[int] = Body(..., description="ID列表"),
auth: AuthSchema = Depends(AuthPermission(["system:user:delete"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:delete"])),
) -> JSONResponse:
"""
删除用户
@@ -280,7 +280,7 @@ async def delete_obj_controller(
@UserRouter.patch("/available/setting", summary="批量修改用户状态", description="批量修改用户状态")
async def batch_set_available_obj_controller(
data: BatchSetAvailable,
auth: AuthSchema = Depends(AuthPermission(["system:user:patch"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:patch"])),
) -> JSONResponse:
"""
批量修改用户状态
@@ -297,7 +297,7 @@ async def batch_set_available_obj_controller(
return SuccessResponse(msg="批量修改用户状态成功")
@UserRouter.post('/import/template', summary="获取用户导入模板", description="获取用户导入模板", dependencies=[Depends(AuthPermission(["system:user:import"]))])
@UserRouter.post('/import/template', summary="获取用户导入模板", description="获取用户导入模板", dependencies=[Depends(AuthPermission(["module_system:user:import"]))])
async def export_obj_template_controller()-> StreamingResponse:
"""
获取用户导入模板
@@ -322,7 +322,7 @@ async def export_obj_template_controller()-> StreamingResponse:
async def export_obj_list_controller(
page: PaginationQueryParam = Depends(),
search: UserQueryParam = Depends(),
auth: AuthSchema = Depends(AuthPermission(["system:user:export"])),
auth: AuthSchema = Depends(AuthPermission(["module_system:user:export"])),
) -> StreamingResponse:
"""
导出用户
@@ -351,7 +351,7 @@ async def export_obj_list_controller(
@UserRouter.post('/import/data', summary="导入用户", description="导入用户")
async def import_obj_list_controller(
file: UploadFile,
auth: AuthSchema = Depends(AuthPermission(["system:user:import"]))
auth: AuthSchema = Depends(AuthPermission(["module_system:user:import"]))
) -> JSONResponse:
"""
导入用户