mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-29 15:42:55 +00:00
refactor: 重构查询参数处理逻辑,统一搜索参数处理
- 移除各模块查询schema中的自定义model_validator,统一通过search_to_dict处理搜索参数 - 为需要的字段添加json_schema_extra标记查询操作类型 - 重构base_crud的条件解析逻辑,支持直接处理普通字符串、数字类型参数 - 重构base_schema中的公共查询参数校验逻辑,简化时间范围和创建更新人参数处理 - 修复菜单查询的异步懒加载问题,添加多级预加载 - 调整日志打印配置,关闭uvicorn.access重复日志 - 修复前端路由跳转路径错误 - 调整弹窗宽度适配内容 - 修复测试环境限流器未注册问题 - 清理无用的导入和废弃函数
This commit is contained in:
@@ -38,7 +38,7 @@ async def get_session_detail_controller(
|
|||||||
async def get_session_list_controller(
|
async def get_session_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_ai:chat:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_ai:chat:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[ChatSessionQueryParam, Query(description="查询参数")],
|
search: Annotated[ChatSessionQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
service = ChatService(auth)
|
service = ChatService(auth)
|
||||||
result_dict = await service.page(
|
result_dict = await service.page(
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
from app.core.base_schema import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||||
|
|
||||||
|
|
||||||
@@ -57,13 +56,9 @@ class ChatSessionMessageSchema(BaseModel):
|
|||||||
class ChatSessionQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class ChatSessionQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""会话查询参数"""
|
"""会话查询参数"""
|
||||||
|
|
||||||
title: str | tuple[str, str] | None = Field(None, description="会话标题")
|
title: str | None = Field(None, description="会话标题")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "ChatSessionQueryParam":
|
|
||||||
if isinstance(self.title, str):
|
|
||||||
self.title = (QueueEnum.like.value, self.title)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class AiChatRequestSchema(BaseModel):
|
class AiChatRequestSchema(BaseModel):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ GenRouter = APIRouter(route_class=OperationLogRoute, prefix="/gencode", tags=["
|
|||||||
async def gen_table_list_controller(
|
async def gen_table_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_generator:gencode:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_generator:gencode:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[GenTableQueryParam, Query(description="查询参数")],
|
search: Annotated[GenTableQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
order_by = [{"created_time": "desc"}]
|
order_by = [{"created_time": "desc"}]
|
||||||
@@ -40,7 +40,7 @@ async def gen_table_list_controller(
|
|||||||
async def get_gen_db_table_list_controller(
|
async def get_gen_db_table_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_generator:dblist:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_generator:dblist:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[GenTableQueryParam, Query(description="查询参数")],
|
search: Annotated[GenTableQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await GenTableService(auth, db).get_gen_db_table_page(
|
result_dict = await GenTableService(auth, db).get_gen_db_table_page(
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -286,16 +285,8 @@ class GenTableQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
|||||||
- 空值将被忽略,不参与过滤。
|
- 空值将被忽略,不参与过滤。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
table_name: str | tuple[str, str] | None = Field(None, description="表名称")
|
table_name: str | None = Field(None, description="表名称")
|
||||||
table_comment: str | tuple[str, str] | None = Field(None, description="表注释")
|
table_comment: str | None = Field(None, description="表注释")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "GenTableQueryParam":
|
|
||||||
if isinstance(self.table_name, str):
|
|
||||||
self.table_name = (QueueEnum.like.value, self.table_name)
|
|
||||||
if isinstance(self.table_comment, str):
|
|
||||||
self.table_comment = (QueueEnum.like.value, self.table_comment)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ _STATS_NS = "online_stats"
|
|||||||
async def get_online_list_controller(
|
async def get_online_list_controller(
|
||||||
redis: Annotated[Redis, Depends(redis_getter)],
|
redis: Annotated[Redis, Depends(redis_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[OnlineQueryParam, Query(description="在线用户查询参数")],
|
search: Annotated[OnlineQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict_list = await OnlineService.get_online_list(redis=redis, search=search)
|
result_dict_list = await OnlineService.get_online_list(redis=redis, search=search)
|
||||||
result_dict = await PaginationService.paginate(
|
result_dict = await PaginationService.paginate(
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, model_validator
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import SessionInfoSchema
|
from app.core.base_schema import SessionInfoSchema
|
||||||
|
|
||||||
|
|
||||||
@@ -13,19 +12,9 @@ class OnlineOutSchema(SessionInfoSchema):
|
|||||||
class OnlineQueryParam(BaseModel):
|
class OnlineQueryParam(BaseModel):
|
||||||
"""在线用户查询参数"""
|
"""在线用户查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="登录名称")
|
name: str | None = Field(None, description="登录名称")
|
||||||
ipaddr: str | tuple[str, str] | None = Field(None, description="登陆IP地址")
|
ipaddr: str | None = Field(None, description="登陆IP地址")
|
||||||
login_location: str | tuple[str, str] | None = Field(None, description="登录所属地")
|
login_location: str | None = Field(None, description="登录所属地")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "OnlineQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.ipaddr, str):
|
|
||||||
self.ipaddr = (QueueEnum.like.value, self.ipaddr)
|
|
||||||
if isinstance(self.login_location, str):
|
|
||||||
self.login_location = (QueueEnum.like.value, self.login_location)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class RecentLoginItem(BaseModel):
|
class RecentLoginItem(BaseModel):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ ResourceRouter = APIRouter(route_class=OperationLogRoute, prefix="/resource", ta
|
|||||||
async def get_directory_list_controller(
|
async def get_directory_list_controller(
|
||||||
request: Request,
|
request: Request,
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[ResourceSearchQueryParam, Query(description="资源查询参数")],
|
search: Annotated[ResourceSearchQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict_list = await ResourceService.get_resources_list(search=search, base_url=str(request.base_url))
|
result_dict_list = await ResourceService.get_resources_list(search=search, base_url=str(request.base_url))
|
||||||
result_dict = await PaginationService.paginate(
|
result_dict = await PaginationService.paginate(
|
||||||
@@ -111,7 +111,7 @@ async def create_directory_controller(
|
|||||||
@ResourceRouter.post("/export", summary="导出资源列表", dependencies=[Security(AuthPermission(["module_monitor:resource:export"]))])
|
@ResourceRouter.post("/export", summary="导出资源列表", dependencies=[Security(AuthPermission(["module_monitor:resource:export"]))])
|
||||||
async def export_resource_list_controller(
|
async def export_resource_list_controller(
|
||||||
request: Request,
|
request: Request,
|
||||||
search: Annotated[ResourceSearchQueryParam, Query(description="资源查询参数")],
|
search: Annotated[ResourceSearchQueryParam, Query()],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
result_dict_list = await ResourceService.get_resources_list(search=search, base_url=str(request.base_url))
|
result_dict_list = await ResourceService.get_resources_list(search=search, base_url=str(request.base_url))
|
||||||
export_result = await ResourceService.export_resource(data_list=result_dict_list)
|
export_result = await ResourceService.export_resource(data_list=result_dict_list)
|
||||||
|
|||||||
@@ -9,9 +9,6 @@ from pydantic import (
|
|||||||
model_validator,
|
model_validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceItemSchema(BaseModel):
|
class ResourceItemSchema(BaseModel):
|
||||||
"""资源项目模型"""
|
"""资源项目模型"""
|
||||||
|
|
||||||
@@ -186,13 +183,7 @@ class ResourceCreateDirSchema(BaseModel):
|
|||||||
class ResourceSearchQueryParam(BaseModel):
|
class ResourceSearchQueryParam(BaseModel):
|
||||||
"""资源搜索查询参数"""
|
"""资源搜索查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="搜索关键词")
|
name: str | None = Field(None, description="搜索关键词")
|
||||||
path: str | tuple[str, str] | None = Field(None, description="目录路径")
|
path: str | None = Field(None, description="目录路径")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "ResourceSearchQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.path, str):
|
|
||||||
self.path = (QueueEnum.like.value, self.path)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ async def invoice_apply_controller(
|
|||||||
async def invoice_list_my_controller(
|
async def invoice_list_my_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:invoice:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:invoice:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[InvoiceQueryParam, Query(description="发票查询参数")],
|
search: Annotated[InvoiceQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result = await InvoiceTenantService.list_my(
|
result = await InvoiceTenantService.list_my(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
|
|
||||||
from app.common.enums import InvoiceTypeEnum, QueueEnum
|
from app.common.enums import InvoiceTypeEnum
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantBySchema, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantBySchema, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -55,16 +55,8 @@ class InvoiceOutSchema(InvoiceCreateSchema, BaseSchema, UserBySchema, TenantBySc
|
|||||||
class InvoiceQueryParam(BaseQueryParam):
|
class InvoiceQueryParam(BaseQueryParam):
|
||||||
"""发票查询参数"""
|
"""发票查询参数"""
|
||||||
|
|
||||||
invoice_type: InvoiceTypeEnum | tuple[str, InvoiceTypeEnum] | None = Field(None, description="发票类型")
|
invoice_type: InvoiceTypeEnum | None = Field(None, description="发票类型")
|
||||||
status: int | tuple[str, int] | None = Field(None, description="状态")
|
status: int | None = Field(None, description="状态")
|
||||||
tenant_id: int | tuple[str, int] | None = Field(None, description="租户ID")
|
tenant_id: int | None = Field(None, description="租户ID")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "InvoiceQueryParam":
|
|
||||||
if isinstance(self.invoice_type, InvoiceTypeEnum):
|
|
||||||
self.invoice_type = (QueueEnum.eq.value, self.invoice_type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
if isinstance(self.tenant_id, int):
|
|
||||||
self.tenant_id = (QueueEnum.eq.value, self.tenant_id)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ _MENU_NS = "menu"
|
|||||||
async def get_menu_tree_controller(
|
async def get_menu_tree_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:menu:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:menu:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
search: Annotated[MenuQueryParam, Query(description="菜单查询参数")],
|
search: Annotated[MenuQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
order_by = [{"order": "asc"}]
|
order_by = [{"order": "asc"}]
|
||||||
result_dict_tree = await MenuService(auth, db).tree(search=search, order_by=order_by)
|
result_dict_tree = await MenuService(auth, db).tree(search=search, order_by=order_by)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from typing import Literal
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema
|
||||||
from app.core.validator import menu_request_validator
|
from app.core.validator import menu_request_validator
|
||||||
|
|
||||||
@@ -202,42 +201,21 @@ class MenuTreeOutSchema(MenuOutSchema):
|
|||||||
class MenuQueryParam(BaseQueryParam):
|
class MenuQueryParam(BaseQueryParam):
|
||||||
"""菜单管理查询参数(菜单为平台级资源,无用户归属)"""
|
"""菜单管理查询参数(菜单为平台级资源,无用户归属)"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="菜单名称")
|
name: str | None = Field(None, description="菜单名称")
|
||||||
route_path: str | tuple[str, str] | None = Field(None, description="路由地址")
|
route_path: str | None = Field(None, description="路由地址")
|
||||||
component_path: str | tuple[str, str] | None = Field(None, description="组件路径")
|
component_path: str | None = Field(None, description="组件路径")
|
||||||
type: int | tuple[str, int] | None = Field(None, description="菜单类型(1:目录 2:菜单 3:按钮 4:外链)")
|
type: int | None = Field(None, description="菜单类型(1:目录 2:菜单 3:按钮 4:外链)")
|
||||||
permission: str | tuple[str, str] | None = Field(None, description="权限标识")
|
permission: str | None = Field(None, description="权限标识")
|
||||||
description: str | tuple[str, str] | None = Field(None, description="描述")
|
description: str | None = Field(None, description="描述")
|
||||||
status: int | tuple[str, int] | None = Field(None, description="是否启用")
|
status: int | None = Field(None, description="是否启用")
|
||||||
menu_client: Literal["pc", "app"] | None = Field(
|
client: str | None = Field(
|
||||||
None,
|
None,
|
||||||
description="管理端 Tab:pc=桌面端菜单 app=移动端菜单;不传则不过滤终端",
|
description="终端(pc:桌面端菜单 app:移动端菜单);不传则不过滤终端",
|
||||||
)
|
)
|
||||||
scope: str | tuple[str, str] | None = Field(
|
scope: str | None = Field(
|
||||||
None,
|
None,
|
||||||
description="菜单范围过滤:tenant=仅租户可用菜单",
|
description="菜单范围过滤:tenant=仅租户可用菜单",
|
||||||
|
json_schema_extra={"q": "eq"},
|
||||||
)
|
)
|
||||||
client: str | tuple[str, str] | None = Field(None)
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "MenuQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.route_path, str):
|
|
||||||
self.route_path = (QueueEnum.like.value, self.route_path)
|
|
||||||
if isinstance(self.component_path, str):
|
|
||||||
self.component_path = (QueueEnum.like.value, self.component_path)
|
|
||||||
if isinstance(self.permission, str):
|
|
||||||
self.permission = (QueueEnum.like.value, self.permission)
|
|
||||||
if isinstance(self.description, str):
|
|
||||||
self.description = (QueueEnum.like.value, self.description)
|
|
||||||
if isinstance(self.type, int):
|
|
||||||
self.type = (QueueEnum.eq.value, self.type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
if self.menu_client in ("pc", "app"):
|
|
||||||
self.client = (QueueEnum.eq.value, self.menu_client)
|
|
||||||
self.menu_client = None
|
|
||||||
if isinstance(self.scope, str):
|
|
||||||
self.scope = (QueueEnum.eq.value, self.scope)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
from app.core.base_schema import AuthSchema, BatchSetAvailable
|
from app.core.base_schema import AuthSchema, BatchSetAvailable
|
||||||
from app.core.exceptions import CustomException
|
from app.core.exceptions import CustomException
|
||||||
@@ -76,7 +77,12 @@ class MenuService:
|
|||||||
search: MenuQueryParam | None = None,
|
search: MenuQueryParam | None = None,
|
||||||
order_by: list[dict] | None = None,
|
order_by: list[dict] | None = None,
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
menu_list = await MenuCRUD(self.auth, self.db).tree_list(search=search_to_dict(search), order_by=order_by)
|
# 递归预加载所有层级 children(避免 Pydantic 校验时异步懒加载失败)
|
||||||
|
from .model import MenuModel
|
||||||
|
_loader = selectinload(MenuModel.children)
|
||||||
|
for _ in range(10):
|
||||||
|
_loader = _loader.selectinload(MenuModel.children)
|
||||||
|
menu_list = await MenuCRUD(self.auth, self.db).tree_list(search=search_to_dict(search), order_by=order_by, preload=[_loader])
|
||||||
menu_dict_list = [MenuTreeOutSchema.model_validate(menu).model_dump() for menu in menu_list]
|
menu_dict_list = [MenuTreeOutSchema.model_validate(menu).model_dump() for menu in menu_list]
|
||||||
return traversal_to_tree(menu_dict_list)
|
return traversal_to_tree(menu_dict_list)
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ async def order_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:order:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:order:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[OrderQueryParam, Query(description="查询参数")],
|
search: Annotated[OrderQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
items, total = await OrderService.get_list(
|
items, total = await OrderService.get_list(
|
||||||
auth=auth,
|
auth=auth,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import Literal
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -103,25 +102,13 @@ class OrderOutSchema(BaseSchema, TenantBySchema):
|
|||||||
class OrderQueryParam(BaseQueryParam):
|
class OrderQueryParam(BaseQueryParam):
|
||||||
"""订单查询参数"""
|
"""订单查询参数"""
|
||||||
|
|
||||||
tenant_id: int | tuple[str, int] | None = Field(None, description="租户ID")
|
tenant_id: int | None = Field(None, description="租户ID")
|
||||||
status: int | tuple[str, int] | None = Field(None, description="订单状态(0:待支付 1:已支付 2:已取消)")
|
status: int | None = Field(None, description="订单状态(0:待支付 1:已支付 2:已取消)")
|
||||||
refund_status: int | tuple[str, int] | None = Field(None, description="退款状态(1:申请中 2:已退款 3:已驳回)")
|
refund_status: int | None = Field(None, description="退款状态(1:申请中 2:已退款 3:已驳回)")
|
||||||
order_type: str | tuple[str, str] | None = Field(None, description="订单类型")
|
order_type: str | None = Field(None, description="订单类型", json_schema_extra={"q": "eq"})
|
||||||
order_no: str | tuple[str, str] | None = Field(None, description="订单号")
|
order_no: str | None = Field(None, description="订单号")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "OrderQueryParam":
|
|
||||||
if isinstance(self.tenant_id, int):
|
|
||||||
self.tenant_id = (QueueEnum.eq.value, self.tenant_id)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
if isinstance(self.refund_status, int):
|
|
||||||
self.refund_status = (QueueEnum.eq.value, self.refund_status)
|
|
||||||
if isinstance(self.order_type, str):
|
|
||||||
self.order_type = (QueueEnum.eq.value, self.order_type)
|
|
||||||
if isinstance(self.order_no, str):
|
|
||||||
self.order_no = (QueueEnum.like.value, self.order_no)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class PaymentCallbackSchema(BaseModel):
|
class PaymentCallbackSchema(BaseModel):
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ async def get_obj_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_package:package:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_package:package:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[PackageQueryParam, Query(description="查询参数")],
|
search: Annotated[PackageQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await PackageService(auth, db).page(
|
result_dict = await PackageService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema
|
||||||
|
|
||||||
|
|
||||||
@@ -93,19 +92,9 @@ class PackageOutSchema(PackageCreateSchema, BaseSchema):
|
|||||||
class PackageQueryParam(BaseQueryParam):
|
class PackageQueryParam(BaseQueryParam):
|
||||||
"""套餐查询参数"""
|
"""套餐查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="套餐名称")
|
name: str | None = Field(None, description="套餐名称")
|
||||||
code: str | tuple[str, str] | None = Field(None, description="套餐编码")
|
code: str | None = Field(None, description="套餐编码", json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "PackageQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.code, str):
|
|
||||||
self.code = (QueueEnum.like.value, self.code)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class PackageMenuSetSchema(BaseModel):
|
class PackageMenuSetSchema(BaseModel):
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ class PackageService:
|
|||||||
search: PackageQueryParam | None = None,
|
search: PackageQueryParam | None = None,
|
||||||
order_by: list[dict[str, str]] | None = None,
|
order_by: list[dict[str, str]] | None = None,
|
||||||
) -> PageResultSchema[PackageOutSchema]:
|
) -> PageResultSchema[PackageOutSchema]:
|
||||||
|
search_dict = search_to_dict(search)
|
||||||
return await PackageCRUD(self.auth, self.db).page(
|
return await PackageCRUD(self.auth, self.db).page(
|
||||||
offset=(page_no - 1) * page_size,
|
offset=(page_no - 1) * page_size,
|
||||||
limit=page_size,
|
limit=page_size,
|
||||||
order_by=order_by or [{"sort": "asc"}, {"id": "asc"}],
|
order_by=order_by or [{"sort": "asc"}, {"id": "asc"}],
|
||||||
search=search_to_dict(search),
|
search=search_dict,
|
||||||
out_schema=PackageOutSchema,
|
out_schema=PackageOutSchema,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async def get_obj_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:tenant:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_platform:tenant:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[TenantQueryParam, Depends()],
|
search: Annotated[TenantQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await TenantService(auth, db).page(
|
result_dict = await TenantService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import Literal
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from app.common.enums import OrderTypeEnum, QueueEnum
|
from app.common.enums import OrderTypeEnum
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema
|
||||||
from app.core.validator import DateTimeStr, email_validator, mobile_validator
|
from app.core.validator import DateTimeStr, email_validator, mobile_validator
|
||||||
|
|
||||||
@@ -172,19 +172,9 @@ class TenantCreateResult(BaseModel):
|
|||||||
class TenantQueryParam(BaseQueryParam):
|
class TenantQueryParam(BaseQueryParam):
|
||||||
"""租户查询参数"""
|
"""租户查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="租户名称")
|
name: str | None = Field(None, description="租户名称")
|
||||||
code: str | tuple[str, str] | None = Field(None, description="租户编码")
|
code: str | None = Field(None, description="租户编码", json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "TenantQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.code, str):
|
|
||||||
self.code = (QueueEnum.like.value, self.code)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class TenantUserAddSchema(BaseModel):
|
class TenantUserAddSchema(BaseModel):
|
||||||
|
|||||||
@@ -36,13 +36,12 @@ async def create_token_controller(
|
|||||||
result = await ApiTokenService(auth, db).create(data=data)
|
result = await ApiTokenService(auth, db).create(data=data)
|
||||||
return SuccessResponse(data=result, msg="创建 token 成功")
|
return SuccessResponse(data=result, msg="创建 token 成功")
|
||||||
|
|
||||||
|
|
||||||
@ApiTokenRouter.get("/list", summary="查询 token 列表", response_model=ResponseSchema[PageResultSchema[ApiTokenOutSchema]])
|
@ApiTokenRouter.get("/list", summary="查询 token 列表", response_model=ResponseSchema[PageResultSchema[ApiTokenOutSchema]])
|
||||||
async def get_token_list_controller(
|
async def get_token_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:api_token:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:api_token:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[ApiTokenQueryParam, Query(description="查询参数")],
|
search: Annotated[ApiTokenQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result = await ApiTokenService(auth, db).page(
|
result = await ApiTokenService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ _DEPT_NS = "dept"
|
|||||||
async def get_dept_tree_controller(
|
async def get_dept_tree_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dept:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dept:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
search: Annotated[DeptQueryParam, Query(description="部门查询参数")],
|
search: Annotated[DeptQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
order_by = [{"order": "asc"}]
|
order_by = [{"order": "asc"}]
|
||||||
result_dict_tree = await DeptService(auth, db).tree(search=search, order_by=order_by)
|
result_dict_tree = await DeptService(auth, db).tree(search=search, order_by=order_by)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import validate_required_code
|
from app.core.validator import validate_required_code
|
||||||
|
|
||||||
@@ -62,13 +61,5 @@ class DeptTreeOutSchema(DeptOutSchema):
|
|||||||
class DeptQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class DeptQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""部门管理查询参数"""
|
"""部门管理查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="部门名称")
|
name: str | None = Field(None, description="部门名称")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "DeptQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ async def get_type_detail_controller(
|
|||||||
async def get_type_list_controller(
|
async def get_type_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_type:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_type:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[DictTypeQueryParam, Query(description="字典类型查询参数")],
|
search: Annotated[DictTypeQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await DictTypeService(auth, db).page(
|
result_dict = await DictTypeService(auth, db).page(
|
||||||
@@ -117,7 +117,7 @@ async def batch_set_available_dict_type_controller(
|
|||||||
@DictRouter.post("/type/export", summary="导出字典类型")
|
@DictRouter.post("/type/export", summary="导出字典类型")
|
||||||
async def export_type_list_controller(
|
async def export_type_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_type:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_type:export"]))],
|
||||||
search: Annotated[DictTypeQueryParam, Query(description="字典类型查询参数")],
|
search: Annotated[DictTypeQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
# 获取全量数据并转为dict列表
|
# 获取全量数据并转为dict列表
|
||||||
@@ -146,7 +146,7 @@ async def get_data_detail_controller(
|
|||||||
async def get_data_list_controller(
|
async def get_data_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_data:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_data:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[DictDataQueryParam, Query(description="字典数据查询参数")],
|
search: Annotated[DictDataQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
order_by = [{"order": "asc"}]
|
order_by = [{"order": "asc"}]
|
||||||
@@ -209,7 +209,7 @@ async def batch_set_available_dict_data_controller(
|
|||||||
async def export_data_list_controller(
|
async def export_data_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_data:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:dict_data:export"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[DictDataQueryParam, Query(description="字典数据查询参数")],
|
search: Annotated[DictDataQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
result_dict_list = await DictDataService(auth, db).get_list(search=search, order_by=page.order_by)
|
result_dict_list = await DictDataService(auth, db).get_list(search=search, order_by=page.order_by)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from pydantic import (
|
|||||||
model_validator,
|
model_validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -81,19 +80,9 @@ class DictTypeOutSchema(DictTypeCreateSchema, BaseSchema, UserBySchema, TenantBy
|
|||||||
class DictTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class DictTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""字典类型查询参数"""
|
"""字典类型查询参数"""
|
||||||
|
|
||||||
dict_name: str | tuple[str, str] | None = Field(default=None, description="字典名称", max_length=100)
|
dict_name: str | None = Field(default=None, description="字典名称", max_length=100)
|
||||||
dict_type: str | tuple[str, str] | None = Field(default=None, description="字典类型", max_length=100)
|
dict_type: str | None = Field(default=None, description="字典类型", max_length=100, json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "DictTypeQueryParam":
|
|
||||||
if isinstance(self.dict_name, str):
|
|
||||||
self.dict_name = (QueueEnum.like.value, self.dict_name)
|
|
||||||
if isinstance(self.dict_type, str):
|
|
||||||
self.dict_type = (QueueEnum.eq.value, self.dict_type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class DictDataCreateSchema(BaseModel):
|
class DictDataCreateSchema(BaseModel):
|
||||||
@@ -158,19 +147,7 @@ class DictDataOutSchema(DictDataCreateSchema, BaseSchema, UserBySchema, TenantBy
|
|||||||
class DictDataQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class DictDataQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""字典数据查询参数"""
|
"""字典数据查询参数"""
|
||||||
|
|
||||||
dict_label: str | tuple[str, str] | None = Field(default=None, description="字典标签", max_length=100)
|
dict_label: str | None = Field(default=None, description="字典标签", max_length=100)
|
||||||
dict_type: str | tuple[str, str] | None = Field(default=None, description="字典类型", max_length=100)
|
dict_type: str | None = Field(default=None, description="字典类型", max_length=100, json_schema_extra={"q": "eq"})
|
||||||
dict_type_id: int | tuple[str, int] | None = Field(default=None, description="字典类型ID")
|
dict_type_id: int | None = Field(default=None, description="字典类型ID")
|
||||||
status: int | tuple[str, int] | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "DictDataQueryParam":
|
|
||||||
if isinstance(self.dict_label, str):
|
|
||||||
self.dict_label = (QueueEnum.like.value, self.dict_label)
|
|
||||||
if isinstance(self.dict_type, str):
|
|
||||||
self.dict_type = (QueueEnum.eq.value, self.dict_type)
|
|
||||||
if isinstance(self.dict_type_id, int):
|
|
||||||
self.dict_type_id = (QueueEnum.eq.value, self.dict_type_id)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ async def get_log_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:login_log:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:login_log:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[LoginLogQueryParam, Query(description="登录日志查询参数")],
|
search: Annotated[LoginLogQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await LoginLogService(auth, db).page(
|
result_dict = await LoginLogService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
@@ -75,7 +75,7 @@ async def get_operation_log_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[OperationLogQueryParam, Query(description="操作日志查询参数")],
|
search: Annotated[OperationLogQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await OperationLogService(auth, db).page(
|
result_dict = await OperationLogService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -63,25 +63,11 @@ class LoginLogQueryParam(BaseQueryParam, TenantByQueryParam):
|
|||||||
class OperationLogQueryParam(BaseQueryParam, TenantByQueryParam):
|
class OperationLogQueryParam(BaseQueryParam, TenantByQueryParam):
|
||||||
"""操作日志查询参数"""
|
"""操作日志查询参数"""
|
||||||
|
|
||||||
request_path: str | tuple[str, str] | None = Field(None, description="请求路径")
|
request_path: str | None = Field(None, description="请求路径")
|
||||||
request_method: str | tuple[str, str] | None = Field(None, description="请求方式")
|
request_method: str | None = Field(None, description="请求方式", json_schema_extra={"q": "eq"})
|
||||||
username: str | tuple[str, str] | None = Field(None, description="用户名")
|
username: str | None = Field(None, description="用户名")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:成功 1:失败)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:成功 1:失败)")
|
||||||
request_ip: str | tuple[str, str] | None = Field(None, description="请求IP")
|
request_ip: str | None = Field(None, description="请求IP")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "OperationLogQueryParam":
|
|
||||||
if isinstance(self.request_path, str):
|
|
||||||
self.request_path = (QueueEnum.like.value, self.request_path)
|
|
||||||
if isinstance(self.request_method, str):
|
|
||||||
self.request_method = (QueueEnum.eq.value, self.request_method)
|
|
||||||
if isinstance(self.username, str):
|
|
||||||
self.username = (QueueEnum.like.value, self.username)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
if isinstance(self.request_ip, str):
|
|
||||||
self.request_ip = (QueueEnum.eq.value, self.request_ip)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class OperationLogOutSchema(BaseSchema, TenantBySchema):
|
class OperationLogOutSchema(BaseSchema, TenantBySchema):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ async def get_notice_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:notice:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:notice:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[NoticeQueryParam, Query(description="公告查询参数")],
|
search: Annotated[NoticeQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await NoticeService(auth, db).page(
|
result_dict = await NoticeService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from pydantic import (
|
|||||||
model_validator,
|
model_validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.utils.xss_util import sanitize_html
|
from app.utils.xss_util import sanitize_html
|
||||||
|
|
||||||
@@ -63,16 +62,6 @@ class NoticeOutSchema(NoticeCreateSchema, BaseSchema, UserBySchema, TenantBySche
|
|||||||
class NoticeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class NoticeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""公告通知查询参数"""
|
"""公告通知查询参数"""
|
||||||
|
|
||||||
notice_title: str | tuple[str, str] | None = Field(None, description="公告标题")
|
notice_title: str | None = Field(None, description="公告标题")
|
||||||
notice_type: str | tuple[str, str] | None = Field(None, description="公告类型")
|
notice_type: str | None = Field(None, description="公告类型", json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "NoticeQueryParam":
|
|
||||||
if isinstance(self.notice_title, str):
|
|
||||||
self.notice_title = (QueueEnum.like.value, self.notice_title)
|
|
||||||
if isinstance(self.notice_type, str):
|
|
||||||
self.notice_type = (QueueEnum.eq.value, self.notice_type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async def get_param_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:param:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:param:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[ParamsQueryParam, Query(description="参数查询参数")],
|
search: Annotated[ParamsQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await ParamsService(auth, db).page(
|
result_dict = await ParamsService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
@@ -92,7 +92,7 @@ async def batch_set_status_controller(
|
|||||||
async def export_param_list_controller(
|
async def export_param_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:param:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:param:export"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
search: Annotated[ParamsQueryParam, Query(description="参数查询参数")],
|
search: Annotated[ParamsQueryParam, Query()],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
result_dict_list = await ParamsService(auth, db).get_list(search=search)
|
result_dict_list = await ParamsService(auth, db).get_list(search=search)
|
||||||
export_data = [item.model_dump() for item in result_dict_list]
|
export_data = [item.model_dump() for item in result_dict_list]
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -51,19 +50,7 @@ class ParamsQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
|||||||
"""参数管理查询参数
|
"""参数管理查询参数
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config_name: str | tuple[str, str] | None = Field(None, description="参数名称")
|
config_name: str | None = Field(None, description="参数名称")
|
||||||
config_key: str | tuple[str, str] | None = Field(None, description="参数键名")
|
config_key: str | None = Field(None, description="参数键名", json_schema_extra={"q": "eq"})
|
||||||
config_type: bool | tuple[str, bool] | None = Field(None, description="是否系统内置(True:是 False:否)")
|
config_type: bool | None = Field(None, description="是否系统内置(True:是 False:否)")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "ParamsQueryParam":
|
|
||||||
if isinstance(self.config_name, str):
|
|
||||||
self.config_name = (QueueEnum.like.value, self.config_name)
|
|
||||||
if isinstance(self.config_key, str):
|
|
||||||
self.config_key = (QueueEnum.like.value, self.config_key)
|
|
||||||
if isinstance(self.config_type, bool):
|
|
||||||
self.config_type = (QueueEnum.eq.value, self.config_type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async def get_obj_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:position:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:position:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[PositionQueryParam, Query(description="岗位查询参数")],
|
search: Annotated[PositionQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await PositionService(auth, db).page(
|
result_dict = await PositionService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
@@ -105,7 +105,7 @@ async def get_position_options_controller(
|
|||||||
async def export_obj_list_controller(
|
async def export_obj_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:position:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:position:export"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
search: Annotated[PositionQueryParam, Query(description="岗位查询参数")],
|
search: Annotated[PositionQueryParam, Query()],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
position_query_result = await PositionService(auth, db).get_list(search=search)
|
position_query_result = await PositionService(auth, db).get_list(search=search)
|
||||||
position_export_result = PositionService.export_list(position_list=[item.model_dump() for item in position_query_result])
|
position_export_result = PositionService.export_list(position_list=[item.model_dump() for item in position_query_result])
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -50,13 +49,5 @@ class PositionOutSchema(PositionCreateSchema, BaseSchema, UserBySchema, TenantBy
|
|||||||
class PositionQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class PositionQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""岗位管理查询参数"""
|
"""岗位管理查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="岗位名称")
|
name: str | None = Field(None, description="岗位名称")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "PositionQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async def get_role_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[RoleQueryParam, Query(description="角色查询参数")],
|
search: Annotated[RoleQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await RoleService(auth, db).page(
|
result_dict = await RoleService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
@@ -116,7 +116,7 @@ async def get_role_options_controller(
|
|||||||
async def export_role_list_controller(
|
async def export_role_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:export"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
search: Annotated[RoleQueryParam, Query(description="角色查询参数")],
|
search: Annotated[RoleQueryParam, Query()],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
role_query_result = await RoleService(auth, db).get_list(search=search)
|
role_query_result = await RoleService(auth, db).get_list(search=search)
|
||||||
role_export_result = RoleService.export_list(role_list=[item.model_dump() for item in role_query_result])
|
role_export_result = RoleService.export_list(role_list=[item.model_dump() for item in role_query_result])
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from pydantic import (
|
|||||||
|
|
||||||
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
||||||
from app.api.v1.module_system.dept.schema import DeptOutSchema
|
from app.api.v1.module_system.dept.schema import DeptOutSchema
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import (
|
from app.core.validator import (
|
||||||
role_permission_request_validator,
|
role_permission_request_validator,
|
||||||
@@ -99,16 +98,6 @@ class RoleQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
|||||||
"""角色管理查询参数
|
"""角色管理查询参数
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="角色名称")
|
name: str | None = Field(None, description="角色名称")
|
||||||
code: str | tuple[str, str] | None = Field(None, description="角色编码")
|
code: str | None = Field(None, description="角色编码", json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(None, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "RoleQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.code, str):
|
|
||||||
self.code = (QueueEnum.like.value, self.code)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ async def ticket_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:ticket:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:ticket:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[TicketQueryParam, Query(description="工单查询参数")],
|
search: Annotated[TicketQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result = await TicketService(auth, db).page(
|
result = await TicketService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum, TicketTypeEnum
|
from app.common.enums import TicketTypeEnum
|
||||||
from app.core.base_schema import (
|
from app.core.base_schema import (
|
||||||
BaseQueryParam,
|
BaseQueryParam,
|
||||||
BaseSchema,
|
BaseSchema,
|
||||||
@@ -86,22 +86,10 @@ class TicketBatchSchema(BaseModel):
|
|||||||
class TicketQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class TicketQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""工单查询参数"""
|
"""工单查询参数"""
|
||||||
|
|
||||||
title: str | tuple[str, str] | None = Field(None, description="工单标题")
|
title: str | None = Field(None, description="工单标题")
|
||||||
ticket_type: str | tuple[str, str] | None = Field(None, description="工单类型")
|
ticket_type: str | None = Field(None, description="工单类型", json_schema_extra={"q": "eq"})
|
||||||
assigned_id: int | tuple[str, int] | None = Field(None, description="处理人ID")
|
assigned_id: int | None = Field(None, description="处理人ID")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=3, description="状态(0:待处理 1:处理中 2:已完成 3:已关闭)")
|
status: int | None = Field(None, ge=0, le=3, description="状态(0:待处理 1:处理中 2:已完成 3:已关闭)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "TicketQueryParam":
|
|
||||||
if isinstance(self.title, str):
|
|
||||||
self.title = (QueueEnum.like.value, self.title)
|
|
||||||
if isinstance(self.ticket_type, str):
|
|
||||||
self.ticket_type = (QueueEnum.like.value, self.ticket_type)
|
|
||||||
if isinstance(self.assigned_id, int):
|
|
||||||
self.assigned_id = (QueueEnum.eq.value, self.assigned_id)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class TicketCommentCreateSchema(BaseModel):
|
class TicketCommentCreateSchema(BaseModel):
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ async def get_user_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:user:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:user:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[UserQueryParam, Query(description="用户查询参数")],
|
search: Annotated[UserQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await UserService(auth, db).page(
|
result_dict = await UserService(auth, db).page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
@@ -179,7 +179,7 @@ async def export_user_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:user:export"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:user:export"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[UserQueryParam, Query(description="用户查询参数")],
|
search: Annotated[UserQueryParam, Query()],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
user_list = await UserService(auth, db).get_list(search=search, order_by=page.order_by)
|
user_list = await UserService(auth, db).get_list(search=search, order_by=page.order_by)
|
||||||
user_export_result = UserService.export_list(user_list=[item.model_dump() for item in user_list])
|
user_export_result = UserService.export_list(user_list=[item.model_dump() for item in user_list])
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from pydantic import (
|
|||||||
|
|
||||||
from app.api.v1.module_platform.menu.schema import MenuTreeOutSchema
|
from app.api.v1.module_platform.menu.schema import MenuTreeOutSchema
|
||||||
from app.api.v1.module_system.role.schema import RoleOutSchema
|
from app.api.v1.module_system.role.schema import RoleOutSchema
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, CommonSchema, CoreUserSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, CommonSchema, CoreUserSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import email_validator, mobile_validator
|
from app.core.validator import email_validator, mobile_validator
|
||||||
|
|
||||||
@@ -262,29 +261,13 @@ class UserQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
|||||||
- 业务字段:用户名、名称、手机号、邮箱、部门、状态
|
- 业务字段:用户名、名称、手机号、邮箱、部门、状态
|
||||||
"""
|
"""
|
||||||
|
|
||||||
username: str | tuple[str, str] | None = Field(None, description="用户名")
|
username: str | None = Field(None, description="用户名")
|
||||||
name: str | tuple[str, str] | None = Field(None, description="名称")
|
name: str | None = Field(None, description="名称")
|
||||||
mobile: str | tuple[str, str] | None = Field(None, description="手机号", pattern=r"^1[3-9]\d{9}$")
|
mobile: str | None = Field(None, description="手机号", pattern=r"^1[3-9]\d{9}$")
|
||||||
email: str | tuple[str, str] | None = Field(
|
email: str | None = Field(
|
||||||
None,
|
None,
|
||||||
description="邮箱",
|
description="邮箱",
|
||||||
pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
|
pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
|
||||||
)
|
)
|
||||||
dept_id: int | tuple[str, int] | None = Field(None, description="部门ID")
|
dept_id: int | None = Field(None, description="部门ID")
|
||||||
status: int | tuple[str, int] | None = Field(None, description="是否可用")
|
status: int | None = Field(None, description="是否可用")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "UserQueryParam":
|
|
||||||
if isinstance(self.username, str):
|
|
||||||
self.username = (QueueEnum.like.value, self.username)
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.mobile, str):
|
|
||||||
self.mobile = (QueueEnum.like.value, self.mobile)
|
|
||||||
if isinstance(self.email, str):
|
|
||||||
self.email = (QueueEnum.like.value, self.email)
|
|
||||||
if isinstance(self.dept_id, int):
|
|
||||||
self.dept_id = (QueueEnum.eq.value, self.dept_id)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async def get_version_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[VersionQueryParam, Query(description="查询参数")],
|
search: Annotated[VersionQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
service = VersionService(auth, db)
|
service = VersionService(auth, db)
|
||||||
result = await service.page(page_no=page.page_no, page_size=page.page_size, search=search)
|
result = await service.page(page_no=page.page_no, page_size=page.page_size, search=search)
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ async def remove_job_controller(
|
|||||||
async def get_job_log_list_controller(
|
async def get_job_log_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:cronjob:job:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:cronjob:job:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[JobQueryParam, Query(description="查询参数")],
|
search: Annotated[JobQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await JobService(auth, db).get_job_log_page(
|
result_dict = await JobService(auth, db).get_job_log_page(
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ from pydantic import (
|
|||||||
ConfigDict,
|
ConfigDict,
|
||||||
Field,
|
Field,
|
||||||
field_validator,
|
field_validator,
|
||||||
model_validator,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -61,19 +59,9 @@ class JobOutSchema(JobCreateSchema, BaseSchema, UserBySchema, TenantBySchema):
|
|||||||
class JobQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class JobQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""执行日志查询参数"""
|
"""执行日志查询参数"""
|
||||||
|
|
||||||
job_id: str | tuple[str, str] | None = Field(None, description="任务ID")
|
job_id: str | None = Field(None, description="任务ID")
|
||||||
job_name: str | tuple[str, str] | None = Field(None, description="任务名称")
|
job_name: str | None = Field(None, description="任务名称")
|
||||||
trigger_type: str | tuple[str, str] | None = Field(None, description="触发方式")
|
trigger_type: str | None = Field(None, description="触发方式", json_schema_extra={"q": "eq"})
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=5, description="执行状态(0:待执行 1:执行中 2:成功 3:失败 4:超时 5:已取消)")
|
status: int | None = Field(None, ge=0, le=5, description="执行状态(0:待执行 1:执行中 2:成功 3:失败 4:超时 5:已取消)")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "JobQueryParam":
|
|
||||||
if self.job_id is not None:
|
|
||||||
self.job_id = (QueueEnum.eq.value, str(self.job_id))
|
|
||||||
if isinstance(self.job_name, str):
|
|
||||||
self.job_name = (QueueEnum.like.value, self.job_name)
|
|
||||||
if isinstance(self.trigger_type, str):
|
|
||||||
self.trigger_type = (QueueEnum.eq.value, self.trigger_type)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ async def get_obj_detail_controller(
|
|||||||
async def get_obj_list_controller(
|
async def get_obj_list_controller(
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:cronjob:node:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:cronjob:node:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[NodeQueryParam, Query(description="查询参数")],
|
search: Annotated[NodeQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
service = NodeService(auth, db)
|
service = NodeService(auth, db)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from pydantic import (
|
|||||||
model_validator,
|
model_validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import datetime_validator
|
from app.core.validator import datetime_validator
|
||||||
|
|
||||||
@@ -72,16 +71,8 @@ class NodeOutSchema(NodeCreateSchema, BaseSchema, UserBySchema, TenantBySchema):
|
|||||||
class NodeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class NodeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""节点查询参数"""
|
"""节点查询参数"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="节点名称")
|
name: str | None = Field(None, description="节点名称")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "NodeQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class NodeExecuteSchema(BaseModel):
|
class NodeExecuteSchema(BaseModel):
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ async def get_workflow_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:workflow:flow:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:workflow:flow:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[WorkflowQueryParam, Query(description="查询参数")],
|
search: Annotated[WorkflowQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
result_dict = await WorkflowService(auth, db).get_workflow_page(
|
result_dict = await WorkflowService(auth, db).get_workflow_page(
|
||||||
page_no=page.page_no,
|
page_no=page.page_no,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import Any
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import DateTimeStr
|
from app.core.validator import DateTimeStr
|
||||||
|
|
||||||
@@ -94,16 +93,8 @@ class WorkflowOutSchema(BaseSchema, UserBySchema, TenantBySchema):
|
|||||||
class WorkflowQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class WorkflowQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""工作流查询"""
|
"""工作流查询"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="流程名称")
|
name: str | None = Field(None, description="流程名称")
|
||||||
code: str | tuple[str, str] | None = Field(None, description="流程编码")
|
code: str | None = Field(None, description="流程编码")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "WorkflowQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.code, str):
|
|
||||||
self.code = (QueueEnum.like.value, self.code)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class WorkflowExecuteSchema(BaseModel):
|
class WorkflowExecuteSchema(BaseModel):
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ async def get_workflow_node_type_list_controller(
|
|||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:workflow:nodes:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["module_task:workflow:nodes:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[WorkflowNodeTypeQueryParam, Query(description="查询参数")],
|
search: Annotated[WorkflowNodeTypeQueryParam, Query()],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
service = WorkflowNodeTypeService(auth, db)
|
service = WorkflowNodeTypeService(auth, db)
|
||||||
result_dict = await service.get_page(
|
result_dict = await service.get_page(
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import re
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
|
|
||||||
|
|
||||||
@@ -65,22 +64,10 @@ class WorkflowNodeTypeOutSchema(WorkflowNodeTypeCreateSchema, BaseSchema, UserBy
|
|||||||
class WorkflowNodeTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class WorkflowNodeTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""查询"""
|
"""查询"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="名称")
|
name: str | None = Field(None, description="名称")
|
||||||
code: str | tuple[str, str] | None = Field(None, description="编码")
|
code: str | None = Field(None, description="编码", json_schema_extra={"q": "eq"})
|
||||||
category: str | tuple[str, str] | None = Field(None, description="分类")
|
category: str | None = Field(None, description="分类", json_schema_extra={"q": "eq"})
|
||||||
is_active: bool | tuple[str, bool] | None = Field(None, description="是否启用")
|
is_active: bool | None = Field(None, description="是否启用")
|
||||||
status: int | tuple[str, int] | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "WorkflowNodeTypeQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.code, str):
|
|
||||||
self.code = (QueueEnum.like.value, self.code)
|
|
||||||
if isinstance(self.category, str):
|
|
||||||
self.category = (QueueEnum.eq.value, self.category)
|
|
||||||
if isinstance(self.is_active, bool):
|
|
||||||
self.is_active = (QueueEnum.eq.value, self.is_active)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ class SchedulerUtil:
|
|||||||
scheduler.resume()
|
scheduler.resume()
|
||||||
|
|
||||||
# 注册系统级定时任务
|
# 注册系统级定时任务
|
||||||
from app.api.v1.module_platform.tenant.service import TenantService
|
|
||||||
from app.api.v1.module_platform.order.service import OrderService
|
from app.api.v1.module_platform.order.service import OrderService
|
||||||
|
from app.api.v1.module_platform.tenant.service import TenantService
|
||||||
from app.api.v1.module_system.log.service import OperationLogService
|
from app.api.v1.module_system.log.service import OperationLogService
|
||||||
|
|
||||||
cls.register_system_job(
|
cls.register_system_job(
|
||||||
|
|||||||
@@ -496,6 +496,12 @@ class CRUDBase[ModelType: ModelMixin, CreateSchemaType, UpdateSchemaType]:
|
|||||||
attr = getattr(self.model, key)
|
attr = getattr(self.model, key)
|
||||||
if isinstance(value, tuple):
|
if isinstance(value, tuple):
|
||||||
conditions.extend(self._resolve_condition(attr, value))
|
conditions.extend(self._resolve_condition(attr, value))
|
||||||
|
elif isinstance(value, str):
|
||||||
|
conditions.append(attr.like(f"%{value}%"))
|
||||||
|
elif isinstance(value, (int, bool)):
|
||||||
|
conditions.append(attr == value)
|
||||||
|
elif isinstance(value, list) and len(value) == 2:
|
||||||
|
conditions.append(attr.between(value[0], value[1]))
|
||||||
else:
|
else:
|
||||||
conditions.append(attr == value)
|
conditions.append(attr == value)
|
||||||
return conditions
|
return conditions
|
||||||
@@ -571,22 +577,26 @@ class CRUDBase[ModelType: ModelMixin, CreateSchemaType, UpdateSchemaType]:
|
|||||||
返回:
|
返回:
|
||||||
- 预加载选项列表
|
- 预加载选项列表
|
||||||
"""
|
"""
|
||||||
options: list[Any] = []
|
|
||||||
model_loader_options = getattr(self.model, "__loader_options__", [])
|
model_loader_options = getattr(self.model, "__loader_options__", [])
|
||||||
|
|
||||||
all_preloads: set[str | Any] = set(model_loader_options)
|
if preload == []:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 收集所有需要预加载的关系名
|
||||||
|
names: set[str] = set(model_loader_options)
|
||||||
if preload:
|
if preload:
|
||||||
for opt in preload:
|
for opt in preload:
|
||||||
if isinstance(opt, str):
|
if isinstance(opt, str):
|
||||||
all_preloads.add(opt)
|
names.add(opt)
|
||||||
elif preload == []:
|
|
||||||
all_preloads = set()
|
|
||||||
|
|
||||||
for opt in all_preloads:
|
# 字符串名 → selectinload
|
||||||
if isinstance(opt, str):
|
options: list[Any] = []
|
||||||
if hasattr(self.model, opt):
|
for name in names:
|
||||||
options.append(selectinload(getattr(self.model, opt)))
|
if hasattr(self.model, name):
|
||||||
else:
|
options.append(selectinload(getattr(self.model, name)))
|
||||||
options.append(opt)
|
|
||||||
|
# 非字符串预加载项直接追加(如递归 selectinload)
|
||||||
|
if preload:
|
||||||
|
options.extend(opt for opt in preload if not isinstance(opt, str))
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|||||||
@@ -178,53 +178,29 @@ class PaginationQueryParam(BaseModel):
|
|||||||
class BaseQueryParam(BaseModel):
|
class BaseQueryParam(BaseModel):
|
||||||
"""created_time + updated_time —— 子类自动继承"""
|
"""created_time + updated_time —— 子类自动继承"""
|
||||||
|
|
||||||
created_time: list[DateTimeStr] | tuple[str, tuple[DateTimeStr, DateTimeStr]] | None = Field(
|
created_time: list[DateTimeStr] | None = Field(
|
||||||
None,
|
None,
|
||||||
description="创建时间范围",
|
description="创建时间范围",
|
||||||
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
|
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
|
||||||
)
|
)
|
||||||
updated_time: list[DateTimeStr] | tuple[str, tuple[DateTimeStr, DateTimeStr]] | None = Field(
|
updated_time: list[DateTimeStr] | None = Field(
|
||||||
None,
|
None,
|
||||||
description="更新时间范围",
|
description="更新时间范围",
|
||||||
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
|
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "BaseQueryParam":
|
|
||||||
ct = self.created_time
|
|
||||||
if isinstance(ct, list) and len(ct) == 2:
|
|
||||||
self.created_time = ("between", (ct[0], ct[1]))
|
|
||||||
ut = self.updated_time
|
|
||||||
if isinstance(ut, list) and len(ut) == 2:
|
|
||||||
self.updated_time = ("between", (ut[0], ut[1]))
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class UserByQueryParam(BaseModel):
|
class UserByQueryParam(BaseModel):
|
||||||
"""created_id + updated_id —— 子类自动继承"""
|
"""created_id + updated_id —— 子类自动继承"""
|
||||||
|
|
||||||
created_id: int | tuple[str, int] | None = Field(None, description="创建人")
|
created_id: int | None = Field(None, description="创建人")
|
||||||
updated_id: int | tuple[str, int] | None = Field(None, description="更新人")
|
updated_id: int | None = Field(None, description="更新人")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "UserByQueryParam":
|
|
||||||
if isinstance(self.created_id, int):
|
|
||||||
self.created_id = ("eq", self.created_id)
|
|
||||||
if isinstance(self.updated_id, int):
|
|
||||||
self.updated_id = ("eq", self.updated_id)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class TenantByQueryParam(BaseModel):
|
class TenantByQueryParam(BaseModel):
|
||||||
"""tenant_id —— 子类自动继承"""
|
"""tenant_id —— 子类自动继承"""
|
||||||
|
|
||||||
tenant_id: int | tuple[str, int] | None = Field(None, description="租户ID")
|
tenant_id: int | None = Field(None, description="租户ID")
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "TenantByQueryParam":
|
|
||||||
if isinstance(self.tenant_id, int):
|
|
||||||
self.tenant_id = ("eq", self.tenant_id)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class OptionSchema(BaseModel):
|
class OptionSchema(BaseModel):
|
||||||
|
|||||||
@@ -58,5 +58,8 @@ def setup_logger() -> None:
|
|||||||
for name in ("apscheduler", "apscheduler.schedulers", "apscheduler.jobstores"):
|
for name in ("apscheduler", "apscheduler.schedulers", "apscheduler.jobstores"):
|
||||||
logging.getLogger(name).setLevel(logging.WARNING)
|
logging.getLogger(name).setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
# uvicorn.access 日志与 RequestLogMiddleware 重复,关闭以避免重复
|
||||||
|
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
|
||||||
setup_logger()
|
setup_logger()
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async def get_obj_detail_controller(
|
|||||||
async def get_obj_list_controller(
|
async def get_obj_list_controller(
|
||||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_example:demo:query"]))],
|
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_example:demo:query"]))],
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[DemoQueryParam, Query(description="查询参数")],
|
search: Annotated[DemoQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
service = DemoService(auth, db)
|
service = DemoService(auth, db)
|
||||||
@@ -93,7 +93,7 @@ async def batch_set_available_obj_controller(
|
|||||||
@DemoRouter.post("/export", summary="导出示例")
|
@DemoRouter.post("/export", summary="导出示例")
|
||||||
async def export_obj_list_controller(
|
async def export_obj_list_controller(
|
||||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_example:demo:export"]))],
|
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_example:demo:export"]))],
|
||||||
search: Annotated[DemoQueryParam, Query(description="查询参数")],
|
search: Annotated[DemoQueryParam, Query()],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> StreamingResponse:
|
) -> StreamingResponse:
|
||||||
service = DemoService(auth, db)
|
service = DemoService(auth, db)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from pydantic import (
|
|||||||
model_validator,
|
model_validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||||
from app.core.validator import DateStr, DateTimeStr, TimeStr
|
from app.core.validator import DateStr, DateTimeStr, TimeStr
|
||||||
|
|
||||||
@@ -78,16 +77,8 @@ class DemoOutSchema(DemoCreateSchema, BaseSchema, UserBySchema, TenantBySchema):
|
|||||||
class DemoQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
class DemoQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||||
"""示例查询参数(演示 Mixin 继承用法)"""
|
"""示例查询参数(演示 Mixin 继承用法)"""
|
||||||
|
|
||||||
name: str | tuple[str, str] | None = Field(None, description="名称")
|
name: str | None = Field(None, description="名称")
|
||||||
description: str | tuple[str, str] | None = Field(None, description="描述")
|
description: str | None = Field(None, description="描述")
|
||||||
status: int | tuple[str, int] | None = Field(None, description="是否启用")
|
status: int | None = Field(None, description="是否启用")
|
||||||
|
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "DemoQueryParam":
|
|
||||||
if isinstance(self.name, str):
|
|
||||||
self.name = (QueueEnum.like.value, self.name)
|
|
||||||
if isinstance(self.description, str):
|
|
||||||
self.description = (QueueEnum.like.value, self.description)
|
|
||||||
if isinstance(self.status, int):
|
|
||||||
self.status = (QueueEnum.eq.value, self.status)
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from app.api.v1.module_system.role.model import RoleModel
|
|||||||
from app.api.v1.module_system.user.model import UserModel, UserRolesModel
|
from app.api.v1.module_system.user.model import UserModel, UserRolesModel
|
||||||
from app.api.v1.module_system.versions.model import VersionModel
|
from app.api.v1.module_system.versions.model import VersionModel
|
||||||
from app.config.path_conf import SCRIPT_DIR
|
from app.config.path_conf import SCRIPT_DIR
|
||||||
from app.core.database import async_db_session, check_db, create_tables, drop_tables
|
from app.core.database import async_db_session, check_db, create_tables
|
||||||
from app.core.logger import logger
|
from app.core.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ def search_to_dict(search: Any, default: Any = None) -> dict | None:
|
|||||||
"""将 Pydantic 查询模型转为参数字典。
|
"""将 Pydantic 查询模型转为参数字典。
|
||||||
|
|
||||||
- search 为 None 时返回 default(默认 None)。
|
- search 为 None 时返回 default(默认 None)。
|
||||||
- search 非空时调用 vars() 提取字段字典。
|
- search 非空时调用 model_dump() 提取字段字典,排除 None 值。
|
||||||
|
- 自动将 json_schema_extra={"q": "eq"} 标记的字符串字段转为 ("eq", value) 元组。
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
- search: Pydantic 查询模型或 None。
|
- search: Pydantic 查询模型或 None。
|
||||||
@@ -96,7 +97,16 @@ def search_to_dict(search: Any, default: Any = None) -> dict | None:
|
|||||||
返回:
|
返回:
|
||||||
- dict | None: 查询参数字典或 None。
|
- dict | None: 查询参数字典或 None。
|
||||||
"""
|
"""
|
||||||
return vars(search) if search else default
|
if not search:
|
||||||
|
return default
|
||||||
|
d = search.model_dump(exclude_none=True)
|
||||||
|
for field_name, field_info in search.model_fields.items():
|
||||||
|
if field_name not in d or not isinstance(d[field_name], str):
|
||||||
|
continue
|
||||||
|
q_op = (field_info.json_schema_extra or {}).get("q")
|
||||||
|
if q_op == "eq":
|
||||||
|
d[field_name] = ("eq", d[field_name])
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
def get_parent_id_map(model_list: Sequence[DeclarativeBase]) -> dict[int, int]:
|
def get_parent_id_map(model_list: Sequence[DeclarativeBase]) -> dict[int, int]:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from fastapi import FastAPI
|
|||||||
from alembic import command
|
from alembic import command
|
||||||
from app.common.enums import EnvironmentEnum
|
from app.common.enums import EnvironmentEnum
|
||||||
from app.config.setting import settings
|
from app.config.setting import settings
|
||||||
from app.core.logger import logger
|
|
||||||
from app.utils.banner import worship
|
from app.utils.banner import worship
|
||||||
|
|
||||||
fastapiadmin_cli = typer.Typer()
|
fastapiadmin_cli = typer.Typer()
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ async def get_obj_detail_controller(
|
|||||||
)
|
)
|
||||||
async def get_obj_list_controller(
|
async def get_obj_list_controller(
|
||||||
page: Annotated[PaginationQueryParam, Depends()],
|
page: Annotated[PaginationQueryParam, Depends()],
|
||||||
search: Annotated[{{ class_name }}QueryParam, Depends()],
|
search: Annotated[{{ class_name }}QueryParam, Query()],
|
||||||
auth: Annotated[AuthSchema, Security(AuthPermission(["{{ permission_prefix }}:query"]))],
|
auth: Annotated[AuthSchema, Security(AuthPermission(["{{ permission_prefix }}:query"]))],
|
||||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
{% for import_stmt in schema_import_list %}
|
{% for import_stmt in schema_import_list %}
|
||||||
{{ import_stmt }}
|
{{ import_stmt }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
from app.common.enums import QueueEnum
|
|
||||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema, BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema, BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||||
|
|
||||||
class {{ class_name }}CreateSchema(BaseModel):
|
class {{ class_name }}CreateSchema(BaseModel):
|
||||||
@@ -54,16 +53,3 @@ class {{ class_name }}QueryParam(BaseQueryParam, UserByQueryParam, TenantByQuery
|
|||||||
{{ column.column_name }}: {{ column.python_type }} | None = Field(None, description="{{ column.column_comment }}")
|
{{ column.column_name }}: {{ column.python_type }} | None = Field(None, description="{{ column.column_comment }}")
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
@model_validator(mode="after")
|
|
||||||
def validate_query_params(self) -> "{{ class_name }}QueryParam":
|
|
||||||
{% for column in columns %}
|
|
||||||
{% if column.is_query and column.query_type == 'LIKE' and column.column_name not in ['created_time', 'updated_time', 'created_id', 'updated_id', 'tenant_id', 'is_deleted', 'deleted_time', 'deleted_id'] %}
|
|
||||||
if self.{{ column.column_name }}:
|
|
||||||
self.{{ column.column_name }} = (QueueEnum.like.value, self.{{ column.column_name }})
|
|
||||||
{% elif column.is_query and column.query_type == 'EQ' and column.column_name not in ['created_time', 'updated_time', 'created_id', 'updated_id', 'tenant_id', 'is_deleted', 'deleted_time', 'deleted_id'] %}
|
|
||||||
if self.{{ column.column_name }} is not None:
|
|
||||||
self.{{ column.column_name }} = (QueueEnum.eq.value, self.{{ column.column_name }})
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
return self
|
|
||||||
|
|||||||
@@ -181,6 +181,10 @@ async def _test_lifespan(app) -> AsyncGenerator[Any, None]:
|
|||||||
await db.execute(update(UserModel).where(UserModel.username == "admin").values(password=PwdUtil.hash_password("admin123")))
|
await db.execute(update(UserModel).where(UserModel.username == "admin").values(password=PwdUtil.hash_password("admin123")))
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
|
# 注册限流器(否则中间件访问 app.state.limiter 报 AttributeError)
|
||||||
|
from app.core.http_limit import limiter as _limiter
|
||||||
|
app.state.limiter = _limiter
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,9 @@ const onCreateEditor = (editor: IDomEditor) => {
|
|||||||
applyCustomIcons();
|
applyCustomIcons();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 图标重试定时器(提升到顶层以便 onUnmounted 访问)
|
||||||
|
let _iconTimerId: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
// 应用自定义图标(带重试机制)
|
// 应用自定义图标(带重试机制)
|
||||||
//
|
//
|
||||||
// 注意:递归 setTimeout 用于等待 wangEditor 工具栏 DOM 渲染完成。
|
// 注意:递归 setTimeout 用于等待 wangEditor 工具栏 DOM 渲染完成。
|
||||||
@@ -192,14 +195,13 @@ const applyCustomIcons = () => {
|
|||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
const maxRetries = 10;
|
const maxRetries = 10;
|
||||||
const retryDelay = 100;
|
const retryDelay = 100;
|
||||||
let timerId: ReturnType<typeof setTimeout> | null = null;
|
|
||||||
|
|
||||||
const tryApplyIcons = () => {
|
const tryApplyIcons = () => {
|
||||||
const editor = editorRef.value;
|
const editor = editorRef.value;
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
if (retryCount < maxRetries) {
|
if (retryCount < maxRetries) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
timerId = setTimeout(tryApplyIcons, retryDelay);
|
_iconTimerId = setTimeout(tryApplyIcons, retryDelay);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -209,7 +211,7 @@ const applyCustomIcons = () => {
|
|||||||
if (!editorContainer) {
|
if (!editorContainer) {
|
||||||
if (retryCount < maxRetries) {
|
if (retryCount < maxRetries) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
timerId = setTimeout(tryApplyIcons, retryDelay);
|
_iconTimerId = setTimeout(tryApplyIcons, retryDelay);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -224,7 +226,7 @@ const applyCustomIcons = () => {
|
|||||||
// 如果工具栏还没渲染完成,继续重试
|
// 如果工具栏还没渲染完成,继续重试
|
||||||
if (retryCount < maxRetries) {
|
if (retryCount < maxRetries) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
timerId = setTimeout(tryApplyIcons, retryDelay);
|
_iconTimerId = setTimeout(tryApplyIcons, retryDelay);
|
||||||
} else {
|
} else {
|
||||||
console.warn("工具栏渲染超时,无法应用自定义图标 - 编辑器实例:", editor.id);
|
console.warn("工具栏渲染超时,无法应用自定义图标 - 编辑器实例:", editor.id);
|
||||||
}
|
}
|
||||||
@@ -232,16 +234,16 @@ const applyCustomIcons = () => {
|
|||||||
|
|
||||||
// 使用 requestAnimationFrame 确保在下一帧执行
|
// 使用 requestAnimationFrame 确保在下一帧执行
|
||||||
requestAnimationFrame(tryApplyIcons);
|
requestAnimationFrame(tryApplyIcons);
|
||||||
|
|
||||||
// 组件卸载时清理挂起的重试定时器
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (timerId !== null) {
|
|
||||||
clearTimeout(timerId);
|
|
||||||
timerId = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 组件卸载时清理挂起的重试定时器(需在 setup 顶层注册)
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (_iconTimerId !== null) {
|
||||||
|
clearTimeout(_iconTimerId);
|
||||||
|
_iconTimerId = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 暴露编辑器实例和方法
|
// 暴露编辑器实例和方法
|
||||||
defineExpose({
|
defineExpose({
|
||||||
/** 获取编辑器实例 */
|
/** 获取编辑器实例 */
|
||||||
|
|||||||
@@ -244,7 +244,7 @@
|
|||||||
</ElForm>
|
</ElForm>
|
||||||
|
|
||||||
<div class="px-5 pb-4">
|
<div class="px-5 pb-4">
|
||||||
<ElButton text size="small" @click="router.push('/module_system/log')">
|
<ElButton text size="small" @click="router.push('/system/log')">
|
||||||
<FaSvgIcon icon="ri:history-line" class="mr-1" />查看登录日志
|
<FaSvgIcon icon="ri:history-line" class="mr-1" />查看登录日志
|
||||||
</ElButton>
|
</ElButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<FaDialog
|
<FaDialog
|
||||||
v-model="dialogVisible.visible"
|
v-model="dialogVisible.visible"
|
||||||
:title="dialogVisible.title"
|
:title="dialogVisible.title"
|
||||||
width="680px"
|
width="760px"
|
||||||
dialog-class="crud-embed-dialog"
|
dialog-class="crud-embed-dialog"
|
||||||
modal-class="crud-embed-dialog"
|
modal-class="crud-embed-dialog"
|
||||||
:form-mode="dialogVisible.type"
|
:form-mode="dialogVisible.type"
|
||||||
|
|||||||
Reference in New Issue
Block a user