From 7553ccf14db5c96c1138024abe26f66e7cd0d969 Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Sat, 18 Jan 2025 23:33:37 +0800 Subject: [PATCH] Update return schema of query interface (#492) * Update return model of query interface * Update tree data return type hints * Update code generation and task return types * Fix inconsistency between ORM query result and schema --- backend/app/admin/api/v1/auth/auth.py | 8 ++--- backend/app/admin/api/v1/auth/captcha.py | 12 ++++--- backend/app/admin/api/v1/log/login_log.py | 7 ++-- backend/app/admin/api/v1/log/opera_log.py | 7 ++-- backend/app/admin/api/v1/oauth2/github.py | 4 +-- backend/app/admin/api/v1/oauth2/linux_do.py | 4 +-- backend/app/admin/api/v1/sys/api.py | 12 +++---- backend/app/admin/api/v1/sys/casbin.py | 33 ++++++++++--------- backend/app/admin/api/v1/sys/config.py | 31 ++++++++--------- backend/app/admin/api/v1/sys/data_rule.py | 20 ++++++----- backend/app/admin/api/v1/sys/dept.py | 12 +++---- backend/app/admin/api/v1/sys/dict_data.py | 12 +++---- backend/app/admin/api/v1/sys/dict_type.py | 8 ++--- backend/app/admin/api/v1/sys/menu.py | 14 ++++---- backend/app/admin/api/v1/sys/notice.py | 10 +++--- backend/app/admin/api/v1/sys/role.py | 22 ++++++------- backend/app/admin/api/v1/sys/user.py | 16 ++++----- backend/app/admin/crud/crud_config.py | 6 ++-- backend/app/admin/crud/crud_data_rule.py | 3 +- backend/app/admin/crud/crud_dict_data.py | 4 +-- backend/app/admin/crud/crud_role.py | 4 +-- backend/app/admin/crud/crud_user.py | 12 +++---- backend/app/admin/schema/api.py | 2 +- backend/app/admin/schema/captcha.py | 10 ++++++ backend/app/admin/schema/casbin_rule.py | 2 +- backend/app/admin/schema/config.py | 10 +++--- backend/app/admin/schema/data_rule.py | 2 +- backend/app/admin/schema/dept.py | 2 +- backend/app/admin/schema/dict_data.py | 6 ++-- backend/app/admin/schema/dict_type.py | 2 +- backend/app/admin/schema/login_log.py | 2 +- backend/app/admin/schema/menu.py | 2 +- backend/app/admin/schema/notice.py | 2 +- backend/app/admin/schema/opera_log.py | 2 +- backend/app/admin/schema/role.py | 10 +++--- backend/app/admin/schema/user.py | 18 +++++----- backend/app/admin/service/config_service.py | 12 +++---- .../app/admin/service/data_rule_service.py | 4 +-- backend/app/generator/api/v1/gen.py | 10 +++--- backend/app/generator/api/v1/gen_business.py | 13 ++++---- backend/app/generator/api/v1/gen_model.py | 10 +++--- backend/app/generator/schema/gen_business.py | 6 ++-- backend/app/generator/schema/gen_model.py | 2 +- backend/app/generator/service/gen_service.py | 6 ++-- backend/app/task/api/v1/task.py | 10 +++--- backend/app/task/schema/task.py | 12 +++++++ backend/app/task/service/task_service.py | 13 ++++---- backend/common/dataclasses.py | 13 -------- backend/common/pagination.py | 14 ++++---- backend/common/response/response_schema.py | 12 +++---- backend/common/schema.py | 1 + backend/common/security/permission.py | 4 +-- backend/templates/py/api.jinja | 10 +++--- backend/templates/py/schema.jinja | 2 +- backend/utils/serializers.py | 4 +-- 55 files changed, 257 insertions(+), 234 deletions(-) create mode 100644 backend/app/admin/schema/captcha.py diff --git a/backend/app/admin/api/v1/auth/auth.py b/backend/app/admin/api/v1/auth/auth.py index 3b9f808a..a3a27782 100644 --- a/backend/app/admin/api/v1/auth/auth.py +++ b/backend/app/admin/api/v1/auth/auth.py @@ -7,10 +7,10 @@ from fastapi_limiter.depends import RateLimiter from starlette.background import BackgroundTasks -from backend.app.admin.schema.token import GetSwaggerToken +from backend.app.admin.schema.token import GetLoginToken, GetNewToken, GetSwaggerToken from backend.app.admin.schema.user import AuthLoginParam from backend.app.admin.service.auth_service import auth_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth router = APIRouter() @@ -30,13 +30,13 @@ async def swagger_login(obj: Annotated[HTTPBasicCredentials, Depends()]) -> GetS ) async def user_login( request: Request, response: Response, obj: AuthLoginParam, background_tasks: BackgroundTasks -) -> ResponseModel: +) -> ResponseSchemaModel[GetLoginToken]: data = await auth_service.login(request=request, response=response, obj=obj, background_tasks=background_tasks) return response_base.success(data=data) @router.post('/token/new', summary='创建新 token', dependencies=[DependsJwtAuth]) -async def create_new_token(request: Request, response: Response) -> ResponseModel: +async def create_new_token(request: Request, response: Response) -> ResponseSchemaModel[GetNewToken]: data = await auth_service.new_token(request=request, response=response) return response_base.success(data=data) diff --git a/backend/app/admin/api/v1/auth/captcha.py b/backend/app/admin/api/v1/auth/captcha.py index 4582074f..6b5288dc 100644 --- a/backend/app/admin/api/v1/auth/captcha.py +++ b/backend/app/admin/api/v1/auth/captcha.py @@ -6,7 +6,8 @@ from starlette.concurrency import run_in_threadpool from backend.app.admin.conf import admin_settings -from backend.common.response.response_schema import ResponseModel, response_base +from backend.app.admin.schema.captcha import GetCaptchaDetail +from backend.common.response.response_schema import ResponseSchemaModel, response_base from backend.database.redis import redis_client router = APIRouter() @@ -17,7 +18,7 @@ summary='获取登录验证码', dependencies=[Depends(RateLimiter(times=5, seconds=10))], ) -async def get_captcha(request: Request) -> ResponseModel: +async def get_captcha(request: Request) -> ResponseSchemaModel[GetCaptchaDetail]: """ 此接口可能存在性能损耗,尽管是异步接口,但是验证码生成是IO密集型任务,使用线程池尽量减少性能损耗 """ @@ -25,6 +26,9 @@ async def get_captcha(request: Request) -> ResponseModel: img, code = await run_in_threadpool(img_captcha, img_byte=img_type) ip = request.state.ip await redis_client.set( - f'{admin_settings.CAPTCHA_LOGIN_REDIS_PREFIX}:{ip}', code, ex=admin_settings.CAPTCHA_LOGIN_EXPIRE_SECONDS + f'{admin_settings.CAPTCHA_LOGIN_REDIS_PREFIX}:{ip}', + code, + ex=admin_settings.CAPTCHA_LOGIN_EXPIRE_SECONDS, ) - return response_base.success(data={'image_type': img_type, 'image': img}) + data = GetCaptchaDetail(image_type=img_type, image=img) + return response_base.success(data=data) diff --git a/backend/app/admin/api/v1/log/login_log.py b/backend/app/admin/api/v1/log/login_log.py index 7a7e865a..13e246b7 100644 --- a/backend/app/admin/api/v1/log/login_log.py +++ b/backend/app/admin/api/v1/log/login_log.py @@ -4,9 +4,10 @@ from fastapi import APIRouter, Depends, Query +from backend.app.admin.schema.login_log import GetLoginLogDetail from backend.app.admin.service.login_log_service import login_log_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -28,7 +29,7 @@ async def get_pagination_login_logs( username: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, ip: Annotated[str | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetLoginLogDetail]]: log_select = await login_log_service.get_select(username=username, status=status, ip=ip) page_data = await paging_data(db, log_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/log/opera_log.py b/backend/app/admin/api/v1/log/opera_log.py index c90a12de..4b7b8c41 100644 --- a/backend/app/admin/api/v1/log/opera_log.py +++ b/backend/app/admin/api/v1/log/opera_log.py @@ -4,9 +4,10 @@ from fastapi import APIRouter, Depends, Query +from backend.app.admin.schema.opera_log import GetOperaLogDetail from backend.app.admin.service.opera_log_service import opera_log_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -28,7 +29,7 @@ async def get_pagination_opera_logs( username: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, ip: Annotated[str | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetOperaLogDetail]]: log_select = await opera_log_service.get_select(username=username, status=status, ip=ip) page_data = await paging_data(db, log_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/oauth2/github.py b/backend/app/admin/api/v1/oauth2/github.py index 7293fd78..7a054173 100644 --- a/backend/app/admin/api/v1/oauth2/github.py +++ b/backend/app/admin/api/v1/oauth2/github.py @@ -8,7 +8,7 @@ from backend.app.admin.conf import admin_settings from backend.app.admin.service.oauth2_service import oauth2_service from backend.common.enums import UserSocialType -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseSchemaModel, response_base router = APIRouter() @@ -17,7 +17,7 @@ @router.get('', summary='获取 Github 授权链接') -async def github_auth2() -> ResponseModel: +async def github_auth2() -> ResponseSchemaModel[str]: auth_url = await _github_client.get_authorization_url(redirect_uri=admin_settings.OAUTH2_GITHUB_REDIRECT_URI) return response_base.success(data=auth_url) diff --git a/backend/app/admin/api/v1/oauth2/linux_do.py b/backend/app/admin/api/v1/oauth2/linux_do.py index a305579f..41257fc6 100644 --- a/backend/app/admin/api/v1/oauth2/linux_do.py +++ b/backend/app/admin/api/v1/oauth2/linux_do.py @@ -8,7 +8,7 @@ from backend.app.admin.conf import admin_settings from backend.app.admin.service.oauth2_service import oauth2_service from backend.common.enums import UserSocialType -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseSchemaModel, response_base router = APIRouter() @@ -20,7 +20,7 @@ @router.get('', summary='获取 Linux Do 授权链接') -async def linux_do_auth2() -> ResponseModel: +async def linux_do_auth2() -> ResponseSchemaModel[str]: auth_url = await _linux_do_client.get_authorization_url(redirect_uri=admin_settings.OAUTH2_LINUX_DO_REDIRECT_URI) return response_base.success(data=auth_url) diff --git a/backend/app/admin/api/v1/sys/api.py b/backend/app/admin/api/v1/sys/api.py index 999694b0..6acc691b 100644 --- a/backend/app/admin/api/v1/sys/api.py +++ b/backend/app/admin/api/v1/sys/api.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, Path, Query, Request -from backend.app.admin.schema.api import CreateApiParam, UpdateApiParam +from backend.app.admin.schema.api import CreateApiParam, GetApiDetail, UpdateApiParam from backend.app.admin.service.api_service import api_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -17,13 +17,13 @@ @router.get('/all', summary='获取所有接口', dependencies=[DependsJwtAuth]) -async def get_all_apis() -> ResponseModel: +async def get_all_apis() -> ResponseSchemaModel[list[GetApiDetail]]: data = await api_service.get_all() return response_base.success(data=data) @router.get('/{pk}', summary='获取接口详情', dependencies=[DependsJwtAuth]) -async def get_api(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_api(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetApiDetail]: api = await api_service.get(pk=pk) return response_base.success(data=api) @@ -42,7 +42,7 @@ async def get_pagination_apis( name: Annotated[str | None, Query()] = None, method: Annotated[str | None, Query()] = None, path: Annotated[str | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetApiDetail]]: api_select = await api_service.get_select(request=request, name=name, method=method, path=path) page_data = await paging_data(db, api_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/casbin.py b/backend/app/admin/api/v1/sys/casbin.py index 7d4eb0d0..d63dfed5 100644 --- a/backend/app/admin/api/v1/sys/casbin.py +++ b/backend/app/admin/api/v1/sys/casbin.py @@ -11,12 +11,13 @@ DeleteAllPoliciesParam, DeletePolicyParam, DeleteUserRoleParam, + GetPolicyDetail, UpdatePoliciesParam, UpdatePolicyParam, ) from backend.app.admin.service.casbin_service import casbin_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -37,14 +38,16 @@ async def get_pagination_casbin( db: CurrentSession, ptype: Annotated[str | None, Query(description='策略类型, p / g')] = None, sub: Annotated[str | None, Query(description='用户 uuid / 角色')] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetPolicyDetail]]: casbin_select = await casbin_service.get_casbin_list(ptype=ptype, sub=sub) page_data = await paging_data(db, casbin_select) return response_base.success(data=page_data) @router.get('/policies', summary='获取所有P权限策略', dependencies=[DependsJwtAuth]) -async def get_all_policies(role: Annotated[int | None, Query(description='角色ID')] = None) -> ResponseModel: +async def get_all_policies( + role: Annotated[int | None, Query(description='角色ID')] = None, +) -> ResponseSchemaModel[list[GetPolicyDetail]]: policies = await casbin_service.get_policy_list(role=role) return response_base.success(data=policies) @@ -57,7 +60,7 @@ async def get_all_policies(role: Annotated[int | None, Query(description='角色 DependsRBAC, ], ) -async def create_policy(p: CreatePolicyParam) -> ResponseModel: +async def create_policy(p: CreatePolicyParam) -> ResponseSchemaModel[bool]: """ p 策略: @@ -79,7 +82,7 @@ async def create_policy(p: CreatePolicyParam) -> ResponseModel: DependsRBAC, ], ) -async def create_policies(ps: list[CreatePolicyParam]) -> ResponseModel: +async def create_policies(ps: list[CreatePolicyParam]) -> ResponseSchemaModel[bool]: data = await casbin_service.create_policies(ps=ps) return response_base.success(data=data) @@ -92,7 +95,7 @@ async def create_policies(ps: list[CreatePolicyParam]) -> ResponseModel: DependsRBAC, ], ) -async def update_policy(obj: UpdatePolicyParam) -> ResponseModel: +async def update_policy(obj: UpdatePolicyParam) -> ResponseSchemaModel[bool]: data = await casbin_service.update_policy(obj=obj) return response_base.success(data=data) @@ -105,7 +108,7 @@ async def update_policy(obj: UpdatePolicyParam) -> ResponseModel: DependsRBAC, ], ) -async def update_policies(obj: UpdatePoliciesParam) -> ResponseModel: +async def update_policies(obj: UpdatePoliciesParam) -> ResponseSchemaModel[bool]: data = await casbin_service.update_policies(obj=obj) return response_base.success(data=data) @@ -118,7 +121,7 @@ async def update_policies(obj: UpdatePoliciesParam) -> ResponseModel: DependsRBAC, ], ) -async def delete_policy(p: DeletePolicyParam) -> ResponseModel: +async def delete_policy(p: DeletePolicyParam) -> ResponseSchemaModel[bool]: data = await casbin_service.delete_policy(p=p) return response_base.success(data=data) @@ -131,7 +134,7 @@ async def delete_policy(p: DeletePolicyParam) -> ResponseModel: DependsRBAC, ], ) -async def delete_policies(ps: list[DeletePolicyParam]) -> ResponseModel: +async def delete_policies(ps: list[DeletePolicyParam]) -> ResponseSchemaModel[bool]: data = await casbin_service.delete_policies(ps=ps) return response_base.success(data=data) @@ -152,7 +155,7 @@ async def delete_all_policies(sub: DeleteAllPoliciesParam) -> ResponseModel: @router.get('/groups', summary='获取所有G权限策略', dependencies=[DependsJwtAuth]) -async def get_all_groups() -> ResponseModel: +async def get_all_groups() -> ResponseSchemaModel[list]: data = await casbin_service.get_group_list() return response_base.success(data=data) @@ -165,7 +168,7 @@ async def get_all_groups() -> ResponseModel: DependsRBAC, ], ) -async def create_group(g: CreateUserRoleParam) -> ResponseModel: +async def create_group(g: CreateUserRoleParam) -> ResponseSchemaModel[bool]: """ g 策略 (**依赖 p 策略**): @@ -187,7 +190,7 @@ async def create_group(g: CreateUserRoleParam) -> ResponseModel: DependsRBAC, ], ) -async def create_groups(gs: list[CreateUserRoleParam]) -> ResponseModel: +async def create_groups(gs: list[CreateUserRoleParam]) -> ResponseSchemaModel[bool]: data = await casbin_service.create_groups(gs=gs) return response_base.success(data=data) @@ -200,7 +203,7 @@ async def create_groups(gs: list[CreateUserRoleParam]) -> ResponseModel: DependsRBAC, ], ) -async def delete_group(g: DeleteUserRoleParam) -> ResponseModel: +async def delete_group(g: DeleteUserRoleParam) -> ResponseSchemaModel[bool]: data = await casbin_service.delete_group(g=g) return response_base.success(data=data) @@ -213,7 +216,7 @@ async def delete_group(g: DeleteUserRoleParam) -> ResponseModel: DependsRBAC, ], ) -async def delete_groups(gs: list[DeleteUserRoleParam]) -> ResponseModel: +async def delete_groups(gs: list[DeleteUserRoleParam]) -> ResponseSchemaModel[bool]: data = await casbin_service.delete_groups(gs=gs) return response_base.success(data=data) diff --git a/backend/app/admin/api/v1/sys/config.py b/backend/app/admin/api/v1/sys/config.py index 6f51885a..a13de7de 100644 --- a/backend/app/admin/api/v1/sys/config.py +++ b/backend/app/admin/api/v1/sys/config.py @@ -5,13 +5,14 @@ from fastapi import APIRouter, Depends, Path, Query from backend.app.admin.schema.config import ( - CreateAnyConfigParam, - SaveConfigParam, - UpdateAnyConfigParam, + CreateConfigParam, + GetConfigDetail, + SaveBuiltInConfigParam, + UpdateConfigParam, ) from backend.app.admin.service.config_service import config_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -21,7 +22,7 @@ @router.get('/website', summary='获取网站配置信息', dependencies=[DependsJwtAuth]) -async def get_website_config() -> ResponseModel: +async def get_website_config() -> ResponseSchemaModel[GetConfigDetail]: config = await config_service.get_built_in_config('website') return response_base.success(data=config) @@ -34,13 +35,13 @@ async def get_website_config() -> ResponseModel: DependsRBAC, ], ) -async def save_website_config(objs: list[SaveConfigParam]) -> ResponseModel: +async def save_website_config(objs: list[SaveBuiltInConfigParam]) -> ResponseModel: await config_service.save_built_in_config(objs, 'website') return response_base.success() @router.get('/protocol', summary='获取用户协议', dependencies=[DependsJwtAuth]) -async def get_protocol_config() -> ResponseModel: +async def get_protocol_config() -> ResponseSchemaModel[GetConfigDetail]: config = await config_service.get_built_in_config('protocol') return response_base.success(data=config) @@ -53,13 +54,13 @@ async def get_protocol_config() -> ResponseModel: DependsRBAC, ], ) -async def save_protocol_config(objs: list[SaveConfigParam]) -> ResponseModel: +async def save_protocol_config(objs: list[SaveBuiltInConfigParam]) -> ResponseModel: await config_service.save_built_in_config(objs, 'protocol') return response_base.success() @router.get('/policy', summary='获取用户政策', dependencies=[DependsJwtAuth]) -async def get_policy_config() -> ResponseModel: +async def get_policy_config() -> ResponseSchemaModel[GetConfigDetail]: config = await config_service.get_built_in_config('policy') return response_base.success(data=config) @@ -72,13 +73,13 @@ async def get_policy_config() -> ResponseModel: DependsRBAC, ], ) -async def save_policy_config(objs: list[SaveConfigParam]) -> ResponseModel: +async def save_policy_config(objs: list[SaveBuiltInConfigParam]) -> ResponseModel: await config_service.save_built_in_config(objs, 'policy') return response_base.success() @router.get('/{pk}', summary='获取系统参数配置详情', dependencies=[DependsJwtAuth]) -async def get_config(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_config(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetConfigDetail]: config = await config_service.get(pk) return response_base.success(data=config) @@ -95,7 +96,7 @@ async def get_pagination_config( db: CurrentSession, name: Annotated[str | None, Query()] = None, type: Annotated[str | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetConfigDetail]]: config_select = await config_service.get_select(name=name, type=type) page_data = await paging_data(db, config_select) return response_base.success(data=page_data) @@ -109,7 +110,7 @@ async def get_pagination_config( DependsRBAC, ], ) -async def create_config(obj: CreateAnyConfigParam) -> ResponseModel: +async def create_config(obj: CreateConfigParam) -> ResponseModel: await config_service.create(obj=obj) return response_base.success() @@ -122,7 +123,7 @@ async def create_config(obj: CreateAnyConfigParam) -> ResponseModel: DependsRBAC, ], ) -async def update_config(pk: Annotated[int, Path(...)], obj: UpdateAnyConfigParam) -> ResponseModel: +async def update_config(pk: Annotated[int, Path(...)], obj: UpdateConfigParam) -> ResponseModel: count = await config_service.update(pk=pk, obj=obj) if count > 0: return response_base.success() diff --git a/backend/app/admin/api/v1/sys/data_rule.py b/backend/app/admin/api/v1/sys/data_rule.py index 7901f5fa..54a1eb7b 100644 --- a/backend/app/admin/api/v1/sys/data_rule.py +++ b/backend/app/admin/api/v1/sys/data_rule.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, Path, Query, Request -from backend.app.admin.schema.data_rule import CreateDataRuleParam, GetDataRuleListDetails, UpdateDataRuleParam +from backend.app.admin.schema.data_rule import CreateDataRuleParam, GetDataRuleDetail, UpdateDataRuleParam from backend.app.admin.service.data_rule_service import data_rule_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -18,28 +18,28 @@ @router.get('/models', summary='获取支持过滤的数据库模型', dependencies=[DependsJwtAuth]) -async def get_data_rule_models() -> ResponseModel: +async def get_data_rule_models() -> ResponseSchemaModel[list[str]]: models = await data_rule_service.get_models() return response_base.success(data=models) @router.get('/model/{model}/columns', summary='获取支持过滤的数据库模型列', dependencies=[DependsJwtAuth]) -async def get_data_rule_model_columns(model: Annotated[str, Path()]) -> ResponseModel: +async def get_data_rule_model_columns(model: Annotated[str, Path()]) -> ResponseSchemaModel[list[str]]: models = await data_rule_service.get_columns(model=model) return response_base.success(data=models) @router.get('/all', summary='获取所有数据规则', dependencies=[DependsJwtAuth]) -async def get_all_data_rule() -> ResponseModel: +async def get_all_data_rule() -> ResponseSchemaModel[list[GetDataRuleDetail]]: data_rules = await data_rule_service.get_all() data = select_list_serialize(data_rules) return response_base.success(data=data) @router.get('/{pk}', summary='获取数据权限规则详情', dependencies=[DependsJwtAuth]) -async def get_data_rule(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_data_rule(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDataRuleDetail]: data_rule = await data_rule_service.get(pk=pk) - data = GetDataRuleListDetails(**select_as_dict(data_rule)) + data = GetDataRuleDetail(**select_as_dict(data_rule)) return response_base.success(data=data) @@ -51,7 +51,9 @@ async def get_data_rule(pk: Annotated[int, Path(...)]) -> ResponseModel: DependsPagination, ], ) -async def get_pagination_data_rule(db: CurrentSession, name: Annotated[str | None, Query()] = None) -> ResponseModel: +async def get_pagination_data_rule( + db: CurrentSession, name: Annotated[str | None, Query()] = None +) -> ResponseSchemaModel[PageData[GetDataRuleDetail]]: data_rule_select = await data_rule_service.get_select(name=name) page_data = await paging_data(db, data_rule_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/dept.py b/backend/app/admin/api/v1/sys/dept.py index 123293ed..27506337 100644 --- a/backend/app/admin/api/v1/sys/dept.py +++ b/backend/app/admin/api/v1/sys/dept.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Annotated +from typing import Annotated, Any from fastapi import APIRouter, Depends, Path, Query, Request -from backend.app.admin.schema.dept import CreateDeptParam, GetDeptListDetails, UpdateDeptParam +from backend.app.admin.schema.dept import CreateDeptParam, GetDeptDetail, UpdateDeptParam from backend.app.admin.service.dept_service import dept_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -16,9 +16,9 @@ @router.get('/{pk}', summary='获取部门详情', dependencies=[DependsJwtAuth]) -async def get_dept(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_dept(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDeptDetail]: dept = await dept_service.get(pk=pk) - data = GetDeptListDetails(**select_as_dict(dept)) + data = GetDeptDetail(**select_as_dict(dept)) return response_base.success(data=data) @@ -28,7 +28,7 @@ async def get_all_depts_tree( leader: Annotated[str | None, Query()] = None, phone: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[list[dict[str, Any]]]: dept = await dept_service.get_dept_tree(name=name, leader=leader, phone=phone, status=status) return response_base.success(data=dept) diff --git a/backend/app/admin/api/v1/sys/dict_data.py b/backend/app/admin/api/v1/sys/dict_data.py index 979d7fb5..495de3a8 100644 --- a/backend/app/admin/api/v1/sys/dict_data.py +++ b/backend/app/admin/api/v1/sys/dict_data.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, Path, Query -from backend.app.admin.schema.dict_data import CreateDictDataParam, GetDictDataListDetails, UpdateDictDataParam +from backend.app.admin.schema.dict_data import CreateDictDataParam, GetDictDataDetail, UpdateDictDataParam from backend.app.admin.service.dict_data_service import dict_data_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -18,9 +18,9 @@ @router.get('/{pk}', summary='获取字典详情', dependencies=[DependsJwtAuth]) -async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDictDataDetail]: dict_data = await dict_data_service.get(pk=pk) - data = GetDictDataListDetails(**select_as_dict(dict_data)) + data = GetDictDataDetail(**select_as_dict(dict_data)) return response_base.success(data=data) @@ -37,7 +37,7 @@ async def get_pagination_dict_datas( label: Annotated[str | None, Query()] = None, value: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetDictDataDetail]]: dict_data_select = await dict_data_service.get_select(label=label, value=value, status=status) page_data = await paging_data(db, dict_data_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/dict_type.py b/backend/app/admin/api/v1/sys/dict_type.py index d2914d02..30ec3fdd 100644 --- a/backend/app/admin/api/v1/sys/dict_type.py +++ b/backend/app/admin/api/v1/sys/dict_type.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, Path, Query -from backend.app.admin.schema.dict_type import CreateDictTypeParam, UpdateDictTypeParam +from backend.app.admin.schema.dict_type import CreateDictTypeParam, GetDictTypeDetail, UpdateDictTypeParam from backend.app.admin.service.dict_type_service import dict_type_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -29,7 +29,7 @@ async def get_pagination_dict_types( name: Annotated[str | None, Query()] = None, code: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetDictTypeDetail]]: dict_type_select = await dict_type_service.get_select(name=name, code=code, status=status) page_data = await paging_data(db, dict_type_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/menu.py b/backend/app/admin/api/v1/sys/menu.py index a08ababc..bd994d0c 100644 --- a/backend/app/admin/api/v1/sys/menu.py +++ b/backend/app/admin/api/v1/sys/menu.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Annotated +from typing import Annotated, Any from fastapi import APIRouter, Depends, Path, Query, Request -from backend.app.admin.schema.menu import CreateMenuParam, GetMenuListDetails, UpdateMenuParam +from backend.app.admin.schema.menu import CreateMenuParam, GetMenuDetail, UpdateMenuParam from backend.app.admin.service.menu_service import menu_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -16,22 +16,22 @@ @router.get('/sidebar', summary='获取用户菜单展示树', dependencies=[DependsJwtAuth]) -async def get_user_sidebar_tree(request: Request) -> ResponseModel: +async def get_user_sidebar_tree(request: Request) -> ResponseSchemaModel[list[dict[str, Any]]]: menu = await menu_service.get_user_menu_tree(request=request) return response_base.success(data=menu) @router.get('/{pk}', summary='获取菜单详情', dependencies=[DependsJwtAuth]) -async def get_menu(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_menu(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetMenuDetail]: menu = await menu_service.get(pk=pk) - data = GetMenuListDetails(**select_as_dict(menu)) + data = GetMenuDetail(**select_as_dict(menu)) return response_base.success(data=data) @router.get('', summary='获取所有菜单展示树', dependencies=[DependsJwtAuth]) async def get_all_menus( title: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None -) -> ResponseModel: +) -> ResponseSchemaModel[list[dict[str, Any]]]: menu = await menu_service.get_menu_tree(title=title, status=status) return response_base.success(data=menu) diff --git a/backend/app/admin/api/v1/sys/notice.py b/backend/app/admin/api/v1/sys/notice.py index 95e6e4dc..a2726f48 100644 --- a/backend/app/admin/api/v1/sys/notice.py +++ b/backend/app/admin/api/v1/sys/notice.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, Path, Query -from backend.app.admin.schema.notice import CreateNoticeParam, UpdateNoticeParam +from backend.app.admin.schema.notice import CreateNoticeParam, GetNoticeDetail, UpdateNoticeParam from backend.app.admin.service.notice_service import notice_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -17,7 +17,7 @@ @router.get('/{pk}', summary='获取通知公告详情', dependencies=[DependsJwtAuth]) -async def get_notice(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_notice(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetNoticeDetail]: notice = await notice_service.get(pk=pk) return response_base.success(data=notice) @@ -30,7 +30,7 @@ async def get_notice(pk: Annotated[int, Path(...)]) -> ResponseModel: DependsPagination, ], ) -async def get_pagination_notice(db: CurrentSession) -> ResponseModel: +async def get_pagination_notice(db: CurrentSession) -> ResponseSchemaModel[PageData[GetNoticeDetail]]: notice_select = await notice_service.get_select() page_data = await paging_data(db, notice_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/role.py b/backend/app/admin/api/v1/sys/role.py index cdb356f9..a7439f2d 100644 --- a/backend/app/admin/api/v1/sys/role.py +++ b/backend/app/admin/api/v1/sys/role.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Annotated +from typing import Annotated, Any from fastapi import APIRouter, Depends, Path, Query, Request from backend.app.admin.schema.role import ( CreateRoleParam, - GetRoleListDetails, + GetRoleDetail, UpdateRoleMenuParam, UpdateRoleParam, UpdateRoleRuleParam, @@ -14,8 +14,8 @@ from backend.app.admin.service.data_rule_service import data_rule_service from backend.app.admin.service.menu_service import menu_service from backend.app.admin.service.role_service import role_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -26,35 +26,35 @@ @router.get('/all', summary='获取所有角色', dependencies=[DependsJwtAuth]) -async def get_all_roles() -> ResponseModel: +async def get_all_roles() -> ResponseSchemaModel[list[GetRoleDetail]]: roles = await role_service.get_all() data = select_list_serialize(roles) return response_base.success(data=data) @router.get('/{pk}/all', summary='获取用户所有角色', dependencies=[DependsJwtAuth]) -async def get_user_all_roles(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_user_all_roles(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[GetRoleDetail]]: roles = await role_service.get_by_user(pk=pk) data = select_list_serialize(roles) return response_base.success(data=data) @router.get('/{pk}/menus', summary='获取角色所有菜单', dependencies=[DependsJwtAuth]) -async def get_role_all_menus(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_role_all_menus(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[dict[str, Any]]]: menu = await menu_service.get_role_menu_tree(pk=pk) return response_base.success(data=menu) @router.get('/{pk}/rules', summary='获取角色所有数据规则', dependencies=[DependsJwtAuth]) -async def get_role_all_rules(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_role_all_rules(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[int]]: rule = await data_rule_service.get_role_rules(pk=pk) return response_base.success(data=rule) @router.get('/{pk}', summary='获取角色详情', dependencies=[DependsJwtAuth]) -async def get_role(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_role(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetRoleDetail]: role = await role_service.get(pk=pk) - data = GetRoleListDetails(**select_as_dict(role)) + data = GetRoleDetail(**select_as_dict(role)) return response_base.success(data=data) @@ -70,7 +70,7 @@ async def get_pagination_roles( db: CurrentSession, name: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, -) -> ResponseModel: +) -> ResponseSchemaModel[PageData[GetRoleDetail]]: role_select = await role_service.get_select(name=name, status=status) page_data = await paging_data(db, role_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/api/v1/sys/user.py b/backend/app/admin/api/v1/sys/user.py index 961821ca..90306340 100644 --- a/backend/app/admin/api/v1/sys/user.py +++ b/backend/app/admin/api/v1/sys/user.py @@ -8,7 +8,7 @@ AddUserParam, AvatarParam, GetCurrentUserInfoDetail, - GetUserInfoListDetails, + GetUserInfoDetail, RegisterUserParam, ResetPasswordParam, UpdateUserParam, @@ -16,7 +16,7 @@ ) from backend.app.admin.service.user_service import user_service from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -33,10 +33,10 @@ async def register_user(obj: RegisterUserParam) -> ResponseModel: @router.post('/add', summary='添加用户', dependencies=[DependsRBAC]) -async def add_user(request: Request, obj: AddUserParam) -> ResponseModel: +async def add_user(request: Request, obj: AddUserParam) -> ResponseSchemaModel[GetUserInfoDetail]: await user_service.add(request=request, obj=obj) current_user = await user_service.get_userinfo(username=obj.username) - data = GetUserInfoListDetails(**select_as_dict(current_user)) + data = GetUserInfoDetail(**select_as_dict(current_user)) return response_base.success(data=data) @@ -49,15 +49,15 @@ async def password_reset(request: Request, obj: ResetPasswordParam) -> ResponseM @router.get('/me', summary='获取当前用户信息', dependencies=[DependsJwtAuth], response_model_exclude={'password'}) -async def get_current_user(request: Request) -> ResponseModel: +async def get_current_user(request: Request) -> ResponseSchemaModel[GetUserInfoDetail]: data = GetCurrentUserInfoDetail(**request.user.model_dump()) return response_base.success(data=data) @router.get('/{username}', summary='查看用户信息', dependencies=[DependsJwtAuth]) -async def get_user(username: Annotated[str, Path(...)]) -> ResponseModel: +async def get_user(username: Annotated[str, Path(...)]) -> ResponseSchemaModel[GetUserInfoDetail]: current_user = await user_service.get_userinfo(username=username) - data = GetUserInfoListDetails(**select_as_dict(current_user)) + data = GetUserInfoDetail(**select_as_dict(current_user)) return response_base.success(data=data) @@ -106,7 +106,7 @@ async def get_pagination_users( username: Annotated[str | None, Query()] = None, phone: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None, -): +) -> ResponseModel: user_select = await user_service.get_select(dept=dept, username=username, phone=phone, status=status) page_data = await paging_data(db, user_select) return response_base.success(data=page_data) diff --git a/backend/app/admin/crud/crud_config.py b/backend/app/admin/crud/crud_config.py index 2a02632a..9e6eda2e 100644 --- a/backend/app/admin/crud/crud_config.py +++ b/backend/app/admin/crud/crud_config.py @@ -8,7 +8,7 @@ from backend.app.admin.conf import admin_settings from backend.app.admin.model import Config -from backend.app.admin.schema.config import CreateAnyConfigParam, UpdateAnyConfigParam +from backend.app.admin.schema.config import CreateConfigParam, UpdateConfigParam class CRUDConfig(CRUDPlus[Config]): @@ -72,7 +72,7 @@ async def get_list(self, name: str = None, type: str = None) -> Select: filters.update(type__like=f'%{type}%') return await self.select_order('created_time', 'desc', **filters) - async def create(self, db: AsyncSession, obj_in: CreateAnyConfigParam) -> None: + async def create(self, db: AsyncSession, obj_in: CreateConfigParam) -> None: """ 创建 Config @@ -82,7 +82,7 @@ async def create(self, db: AsyncSession, obj_in: CreateAnyConfigParam) -> None: """ await self.create_model(db, obj_in) - async def update(self, db: AsyncSession, pk: int, obj_in: UpdateAnyConfigParam) -> int: + async def update(self, db: AsyncSession, pk: int, obj_in: UpdateConfigParam) -> int: """ 更新 Config diff --git a/backend/app/admin/crud/crud_data_rule.py b/backend/app/admin/crud/crud_data_rule.py index 8ef9e489..2a65800a 100644 --- a/backend/app/admin/crud/crud_data_rule.py +++ b/backend/app/admin/crud/crud_data_rule.py @@ -4,6 +4,7 @@ from sqlalchemy import Select, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import noload from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import DataRule @@ -27,7 +28,7 @@ async def get_list(self, name: str = None) -> Select: :return: """ - stmt = select(self.model).order_by(desc(self.model.created_time)) + stmt = select(self.model).options(noload(self.model.roles)).order_by(desc(self.model.created_time)) where_list = [] if name is not None: where_list.append(self.model.name.like(f'%{name}%')) diff --git a/backend/app/admin/crud/crud_dict_data.py b/backend/app/admin/crud/crud_dict_data.py index 1c5141d5..aa6dfafe 100644 --- a/backend/app/admin/crud/crud_dict_data.py +++ b/backend/app/admin/crud/crud_dict_data.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from sqlalchemy import Select, and_, desc, select from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import noload, selectinload from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import DictData @@ -29,7 +29,7 @@ async def get_list(self, label: str = None, value: str = None, status: int = Non :param status: :return: """ - stmt = select(self.model).options(selectinload(self.model.type)).order_by(desc(self.model.sort)) + stmt = select(self.model).options(noload(self.model.type)).order_by(desc(self.model.sort)) where_list = [] if label is not None: where_list.append(self.model.label.like(f'%{label}%')) diff --git a/backend/app/admin/crud/crud_role.py b/backend/app/admin/crud/crud_role.py index db31036c..a46d0776 100644 --- a/backend/app/admin/crud/crud_role.py +++ b/backend/app/admin/crud/crud_role.py @@ -3,7 +3,7 @@ from typing import Sequence from sqlalchemy import Select, desc, select -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import noload, selectinload from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import DataRule, Menu, Role, User @@ -73,7 +73,7 @@ async def get_list(self, name: str = None, status: int = None) -> Select: """ stmt = ( select(self.model) - .options(selectinload(self.model.menus), selectinload(self.model.rules)) + .options(noload(self.model.users), noload(self.model.menus), noload(self.model.rules)) .order_by(desc(self.model.created_time)) ) where_list = [] diff --git a/backend/app/admin/crud/crud_user.py b/backend/app/admin/crud/crud_user.py index 9d7fda0e..1c0a06f1 100644 --- a/backend/app/admin/crud/crud_user.py +++ b/backend/app/admin/crud/crud_user.py @@ -4,11 +4,11 @@ from sqlalchemy import and_, desc, select from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import noload, selectinload from sqlalchemy.sql import Select from sqlalchemy_crud_plus import CRUDPlus -from backend.app.admin.model import Role, User +from backend.app.admin.model import Dept, Role, User from backend.app.admin.schema.user import ( AddUserParam, AvatarParam, @@ -185,11 +185,9 @@ async def get_list(self, dept: int = None, username: str = None, phone: str = No stmt = ( select(self.model) .options( - selectinload(self.model.dept), - selectinload(self.model.roles).options( - selectinload(Role.menus), - selectinload(Role.rules), - ), + selectinload(self.model.dept).options(noload(Dept.parent), noload(Dept.children), noload(Dept.users)), + noload(self.model.socials), + selectinload(self.model.roles).options(noload(Role.users), noload(Role.menus), noload(Role.rules)), ) .order_by(desc(self.model.join_time)) ) diff --git a/backend/app/admin/schema/api.py b/backend/app/admin/schema/api.py index 0f69b653..8237e00e 100644 --- a/backend/app/admin/schema/api.py +++ b/backend/app/admin/schema/api.py @@ -23,7 +23,7 @@ class UpdateApiParam(ApiSchemaBase): pass -class GetApiListDetails(ApiSchemaBase): +class GetApiDetail(ApiSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/captcha.py b/backend/app/admin/schema/captcha.py new file mode 100644 index 00000000..71ea24ca --- /dev/null +++ b/backend/app/admin/schema/captcha.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from pydantic import Field + +from backend.common.schema import SchemaBase + + +class GetCaptchaDetail(SchemaBase): + image_type: str = Field(description='图片类型') + image: str = Field(description='图片内容') diff --git a/backend/app/admin/schema/casbin_rule.py b/backend/app/admin/schema/casbin_rule.py index 241c5993..8a569e11 100644 --- a/backend/app/admin/schema/casbin_rule.py +++ b/backend/app/admin/schema/casbin_rule.py @@ -40,7 +40,7 @@ class DeleteUserRoleParam(CreateUserRoleParam): pass -class GetPolicyListDetails(SchemaBase): +class GetPolicyDetail(SchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/config.py b/backend/app/admin/schema/config.py index 7f5231dc..ff9a85d9 100644 --- a/backend/app/admin/schema/config.py +++ b/backend/app/admin/schema/config.py @@ -7,13 +7,13 @@ from backend.common.schema import SchemaBase -class SaveConfigParam(SchemaBase): +class SaveBuiltInConfigParam(SchemaBase): name: str key: str value: str -class AnyConfigSchemaBase(SchemaBase): +class ConfigSchemaBase(SchemaBase): name: str type: str | None key: str @@ -22,15 +22,15 @@ class AnyConfigSchemaBase(SchemaBase): remark: str | None -class CreateAnyConfigParam(AnyConfigSchemaBase): +class CreateConfigParam(ConfigSchemaBase): pass -class UpdateAnyConfigParam(AnyConfigSchemaBase): +class UpdateConfigParam(ConfigSchemaBase): pass -class GetAnyConfigListDetails(AnyConfigSchemaBase): +class GetConfigDetail(ConfigSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/data_rule.py b/backend/app/admin/schema/data_rule.py index 495b5f0b..80f8211b 100644 --- a/backend/app/admin/schema/data_rule.py +++ b/backend/app/admin/schema/data_rule.py @@ -25,7 +25,7 @@ class UpdateDataRuleParam(DataRuleSchemaBase): pass -class GetDataRuleListDetails(DataRuleSchemaBase): +class GetDataRuleDetail(DataRuleSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/dept.py b/backend/app/admin/schema/dept.py index fac9f89d..c8186076 100644 --- a/backend/app/admin/schema/dept.py +++ b/backend/app/admin/schema/dept.py @@ -26,7 +26,7 @@ class UpdateDeptParam(DeptSchemaBase): pass -class GetDeptListDetails(DeptSchemaBase): +class GetDeptDetail(DeptSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/dict_data.py b/backend/app/admin/schema/dict_data.py index d3b4afb4..d02258bf 100644 --- a/backend/app/admin/schema/dict_data.py +++ b/backend/app/admin/schema/dict_data.py @@ -4,7 +4,7 @@ from pydantic import ConfigDict, Field -from backend.app.admin.schema.dict_type import GetDictTypeListDetails +from backend.app.admin.schema.dict_type import GetDictTypeDetail from backend.common.enums import StatusType from backend.common.schema import SchemaBase @@ -26,10 +26,10 @@ class UpdateDictDataParam(DictDataSchemaBase): pass -class GetDictDataListDetails(DictDataSchemaBase): +class GetDictDataDetail(DictDataSchemaBase): model_config = ConfigDict(from_attributes=True) id: int - type: GetDictTypeListDetails + type: GetDictTypeDetail | None = None created_time: datetime updated_time: datetime | None = None diff --git a/backend/app/admin/schema/dict_type.py b/backend/app/admin/schema/dict_type.py index ea7ea3e6..42fe4916 100644 --- a/backend/app/admin/schema/dict_type.py +++ b/backend/app/admin/schema/dict_type.py @@ -23,7 +23,7 @@ class UpdateDictTypeParam(DictTypeSchemaBase): pass -class GetDictTypeListDetails(DictTypeSchemaBase): +class GetDictTypeDetail(DictTypeSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/login_log.py b/backend/app/admin/schema/login_log.py index f134ef2f..50218e8c 100644 --- a/backend/app/admin/schema/login_log.py +++ b/backend/app/admin/schema/login_log.py @@ -31,7 +31,7 @@ class UpdateLoginLogParam(LoginLogSchemaBase): pass -class GetLoginLogListDetails(LoginLogSchemaBase): +class GetLoginLogDetail(LoginLogSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/menu.py b/backend/app/admin/schema/menu.py index e095924e..0d4d49e4 100644 --- a/backend/app/admin/schema/menu.py +++ b/backend/app/admin/schema/menu.py @@ -32,7 +32,7 @@ class UpdateMenuParam(MenuSchemaBase): pass -class GetMenuListDetails(MenuSchemaBase): +class GetMenuDetail(MenuSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/notice.py b/backend/app/admin/schema/notice.py index e9070268..34e29df4 100644 --- a/backend/app/admin/schema/notice.py +++ b/backend/app/admin/schema/notice.py @@ -25,7 +25,7 @@ class UpdateNoticeParam(NoticeSchemaBase): pass -class GetNoticeListDetails(NoticeSchemaBase): +class GetNoticeDetail(NoticeSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/opera_log.py b/backend/app/admin/schema/opera_log.py index a990712b..0791c488 100644 --- a/backend/app/admin/schema/opera_log.py +++ b/backend/app/admin/schema/opera_log.py @@ -38,7 +38,7 @@ class UpdateOperaLogParam(OperaLogSchemaBase): pass -class GetOperaLogListDetails(OperaLogSchemaBase): +class GetOperaLogDetail(OperaLogSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/admin/schema/role.py b/backend/app/admin/schema/role.py index 126424f0..a89c4b76 100644 --- a/backend/app/admin/schema/role.py +++ b/backend/app/admin/schema/role.py @@ -4,8 +4,8 @@ from pydantic import ConfigDict, Field -from backend.app.admin.schema.data_rule import GetDataRuleListDetails -from backend.app.admin.schema.menu import GetMenuListDetails +from backend.app.admin.schema.data_rule import GetDataRuleDetail +from backend.app.admin.schema.menu import GetMenuDetail from backend.common.enums import StatusType from backend.common.schema import SchemaBase @@ -32,11 +32,11 @@ class UpdateRoleRuleParam(SchemaBase): rules: list[int] -class GetRoleListDetails(RoleSchemaBase): +class GetRoleDetail(RoleSchemaBase): model_config = ConfigDict(from_attributes=True) id: int created_time: datetime updated_time: datetime | None = None - menus: list[GetMenuListDetails] - rules: list[GetDataRuleListDetails | None] = [] + menus: list[GetMenuDetail | None] = [] + rules: list[GetDataRuleDetail | None] = [] diff --git a/backend/app/admin/schema/user.py b/backend/app/admin/schema/user.py index 749495cc..cbd33996 100644 --- a/backend/app/admin/schema/user.py +++ b/backend/app/admin/schema/user.py @@ -5,8 +5,8 @@ from pydantic import ConfigDict, EmailStr, Field, HttpUrl, model_validator from typing_extensions import Self -from backend.app.admin.schema.dept import GetDeptListDetails -from backend.app.admin.schema.role import GetRoleListDetails +from backend.app.admin.schema.dept import GetDeptDetail +from backend.app.admin.schema.role import GetRoleDetail from backend.common.enums import StatusType from backend.common.schema import CustomPhoneNumber, SchemaBase @@ -67,18 +67,18 @@ class GetUserInfoNoRelationDetail(UserInfoSchemaBase): last_login_time: datetime | None = None -class GetUserInfoListDetails(GetUserInfoNoRelationDetail): +class GetUserInfoDetail(GetUserInfoNoRelationDetail): model_config = ConfigDict(from_attributes=True) - dept: GetDeptListDetails | None = None - roles: list[GetRoleListDetails] + dept: GetDeptDetail | None = None + roles: list[GetRoleDetail] -class GetCurrentUserInfoDetail(GetUserInfoListDetails): +class GetCurrentUserInfoDetail(GetUserInfoDetail): model_config = ConfigDict(from_attributes=True) - dept: GetDeptListDetails | str | None = None - roles: list[GetRoleListDetails] | list[str] | None = None + dept: GetDeptDetail | str | None = None + roles: list[GetRoleDetail] | list[str] | None = None @model_validator(mode='after') def handel(self) -> Self: @@ -92,7 +92,7 @@ def handel(self) -> Self: return self -class CurrentUserIns(GetUserInfoListDetails): +class CurrentUserIns(GetUserInfoDetail): model_config = ConfigDict(from_attributes=True) diff --git a/backend/app/admin/service/config_service.py b/backend/app/admin/service/config_service.py index 2e45f6fc..8af41dda 100644 --- a/backend/app/admin/service/config_service.py +++ b/backend/app/admin/service/config_service.py @@ -8,9 +8,9 @@ from backend.app.admin.crud.crud_config import config_dao from backend.app.admin.model import Config from backend.app.admin.schema.config import ( - CreateAnyConfigParam, - SaveConfigParam, - UpdateAnyConfigParam, + CreateConfigParam, + SaveBuiltInConfigParam, + UpdateConfigParam, ) from backend.common.exception import errors from backend.database.db import async_db_session @@ -23,7 +23,7 @@ async def get_built_in_config(type: str) -> Sequence[Config]: return await config_dao.get_by_type(db, type) @staticmethod - async def save_built_in_config(objs: list[SaveConfigParam], type: str) -> None: + async def save_built_in_config(objs: list[SaveBuiltInConfigParam], type: str) -> None: async with async_db_session.begin() as db: for obj in objs: config = await config_dao.get_by_key_and_type(db, obj.key, type) @@ -47,7 +47,7 @@ async def get_select(*, name: str = None, type: str = None) -> Select: return await config_dao.get_list(name=name, type=type) @staticmethod - async def create(*, obj: CreateAnyConfigParam) -> None: + async def create(*, obj: CreateConfigParam) -> None: async with async_db_session.begin() as db: if obj.type in admin_settings.CONFIG_BUILT_IN_TYPES: raise errors.ForbiddenError(msg='非法类型参数') @@ -57,7 +57,7 @@ async def create(*, obj: CreateAnyConfigParam) -> None: await config_dao.create(db, obj) @staticmethod - async def update(*, pk: int, obj: UpdateAnyConfigParam) -> int: + async def update(*, pk: int, obj: UpdateConfigParam) -> int: async with async_db_session.begin() as db: config = await config_dao.get(db, pk) if not config: diff --git a/backend/app/admin/service/data_rule_service.py b/backend/app/admin/service/data_rule_service.py index 63e9aa9e..f29cc1eb 100644 --- a/backend/app/admin/service/data_rule_service.py +++ b/backend/app/admin/service/data_rule_service.py @@ -35,11 +35,11 @@ async def get_role_rules(*, pk: int) -> list[int]: return rule_ids @staticmethod - async def get_models() -> list: + async def get_models() -> list[str]: return list(settings.DATA_PERMISSION_MODELS.keys()) @staticmethod - async def get_columns(model: str): + async def get_columns(model: str) -> list[str]: if model not in settings.DATA_PERMISSION_MODELS: raise errors.NotFoundError(msg='数据模型不存在') model_ins = dynamic_import(settings.DATA_PERMISSION_MODELS[model]) diff --git a/backend/app/generator/api/v1/gen.py b/backend/app/generator/api/v1/gen.py index 6a978d01..b9270af8 100644 --- a/backend/app/generator/api/v1/gen.py +++ b/backend/app/generator/api/v1/gen.py @@ -8,7 +8,7 @@ from backend.app.generator.conf import generator_settings from backend.app.generator.schema.gen import ImportParam from backend.app.generator.service.gen_service import gen_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -17,7 +17,9 @@ @router.get('/tables', summary='获取数据库表') -async def get_all_tables(table_schema: Annotated[str, Query(..., description='数据库名')] = 'fba') -> ResponseModel: +async def get_all_tables( + table_schema: Annotated[str, Query(..., description='数据库名')] = 'fba', +) -> ResponseSchemaModel[list[str]]: data = await gen_service.get_tables(table_schema=table_schema) return response_base.success(data=data) @@ -36,13 +38,13 @@ async def import_table(obj: ImportParam) -> ResponseModel: @router.get('/preview/{pk}', summary='生成代码预览', dependencies=[DependsJwtAuth]) -async def preview_code(pk: Annotated[int, Path(..., description='业务ID')]) -> ResponseModel: +async def preview_code(pk: Annotated[int, Path(..., description='业务ID')]) -> ResponseSchemaModel[dict[str, bytes]]: data = await gen_service.preview(pk=pk) return response_base.success(data=data) @router.get('/generate/{pk}/path', summary='获取代码生成路径', dependencies=[DependsJwtAuth]) -async def generate_path(pk: Annotated[int, Path(..., description='业务ID')]): +async def generate_path(pk: Annotated[int, Path(..., description='业务ID')]) -> ResponseSchemaModel[list[str]]: data = await gen_service.get_generate_path(pk=pk) return response_base.success(data=data) diff --git a/backend/app/generator/api/v1/gen_business.py b/backend/app/generator/api/v1/gen_business.py index 07506075..0171b30b 100644 --- a/backend/app/generator/api/v1/gen_business.py +++ b/backend/app/generator/api/v1/gen_business.py @@ -6,12 +6,13 @@ from backend.app.generator.schema.gen_business import ( CreateGenBusinessParam, - GetGenBusinessListDetails, + GetGenBusinessDetail, UpdateGenBusinessParam, ) +from backend.app.generator.schema.gen_model import GetGenModelDetail from backend.app.generator.service.gen_business_service import gen_business_service from backend.app.generator.service.gen_model_service import gen_model_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -21,21 +22,21 @@ @router.get('/all', summary='获取所有代码生成业务', dependencies=[DependsJwtAuth]) -async def get_all_businesses() -> ResponseModel: +async def get_all_businesses() -> ResponseSchemaModel[list[GetGenBusinessDetail]]: businesses = await gen_business_service.get_all() data = select_list_serialize(businesses) return response_base.success(data=data) @router.get('/{pk}', summary='获取代码生成业务详情', dependencies=[DependsJwtAuth]) -async def get_business(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_business(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetGenBusinessDetail]: business = await gen_business_service.get(pk=pk) - data = GetGenBusinessListDetails(**select_as_dict(business)) + data = GetGenBusinessDetail(**select_as_dict(business)) return response_base.success(data=data) @router.get('/{pk}/models', summary='获取代码生成业务所有模型', dependencies=[DependsJwtAuth]) -async def get_business_models(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_business_all_models(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[GetGenModelDetail]]: models = await gen_model_service.get_by_business(business_id=pk) data = select_list_serialize(models) return response_base.success(data=data) diff --git a/backend/app/generator/api/v1/gen_model.py b/backend/app/generator/api/v1/gen_model.py index db778661..b0bc6be7 100644 --- a/backend/app/generator/api/v1/gen_model.py +++ b/backend/app/generator/api/v1/gen_model.py @@ -4,9 +4,9 @@ from fastapi import APIRouter, Depends, Path -from backend.app.generator.schema.gen_model import CreateGenModelParam, GetGenModelListDetails, UpdateGenModelParam +from backend.app.generator.schema.gen_model import CreateGenModelParam, GetGenModelDetail, UpdateGenModelParam from backend.app.generator.service.gen_model_service import gen_model_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -16,15 +16,15 @@ @router.get('/types', summary='获取代码生成模型列类型', dependencies=[DependsJwtAuth]) -async def get_model_types() -> ResponseModel: +async def get_model_types() -> ResponseSchemaModel[list[str]]: model_types = await gen_model_service.get_types() return response_base.success(data=model_types) @router.get('/{pk}', summary='获取代码生成模型详情', dependencies=[DependsJwtAuth]) -async def get_model(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_model(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetGenModelDetail]: model = await gen_model_service.get(pk=pk) - data = GetGenModelListDetails(**select_as_dict(model)) + data = GetGenModelDetail(**select_as_dict(model)) return response_base.success(data=data) diff --git a/backend/app/generator/schema/gen_business.py b/backend/app/generator/schema/gen_business.py index 404b6bfc..f09d24c2 100644 --- a/backend/app/generator/schema/gen_business.py +++ b/backend/app/generator/schema/gen_business.py @@ -5,7 +5,7 @@ from pydantic import ConfigDict, Field, model_validator from typing_extensions import Self -from backend.app.generator.schema.gen_model import GetGenModelListDetails +from backend.app.generator.schema.gen_model import GetGenModelDetail from backend.common.schema import SchemaBase @@ -36,10 +36,10 @@ class UpdateGenBusinessParam(GenBusinessSchemaBase): pass -class GetGenBusinessListDetails(GenBusinessSchemaBase): +class GetGenBusinessDetail(GenBusinessSchemaBase): model_config = ConfigDict(from_attributes=True) id: int created_time: datetime updated_time: datetime | None = None - gen_model: list[GetGenModelListDetails] | None = None + gen_model: list[GetGenModelDetail] | None = None diff --git a/backend/app/generator/schema/gen_model.py b/backend/app/generator/schema/gen_model.py index d75bd9de..524f96fa 100644 --- a/backend/app/generator/schema/gen_model.py +++ b/backend/app/generator/schema/gen_model.py @@ -31,7 +31,7 @@ class UpdateGenModelParam(GenModelSchemaBase): pass -class GetGenModelListDetails(GenModelSchemaBase): +class GetGenModelDetail(GenModelSchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/app/generator/service/gen_service.py b/backend/app/generator/service/gen_service.py index 47ac5069..2a712fd6 100644 --- a/backend/app/generator/service/gen_service.py +++ b/backend/app/generator/service/gen_service.py @@ -69,7 +69,7 @@ async def import_business_and_model(*, obj: ImportParam) -> None: await gen_model_dao.create(db, CreateGenModelParam(**model_data), pd_type=pd_type) @staticmethod - async def render_tpl_code(*, business: GenBusiness) -> dict: + async def render_tpl_code(*, business: GenBusiness) -> dict[str, str]: gen_models = await gen_model_service.get_by_business(business_id=business.id) if not gen_models: raise errors.NotFoundError(msg='代码生成模型表为空') @@ -79,7 +79,7 @@ async def render_tpl_code(*, business: GenBusiness) -> dict: tpl_code_map[tpl_path] = await gen_template.get_template(tpl_path).render_async(**gen_vars) return tpl_code_map - async def preview(self, *, pk: int) -> dict: + async def preview(self, *, pk: int) -> dict[str, bytes]: async with async_db_session() as db: business = await gen_business_dao.get(db, pk) if not business: @@ -91,7 +91,7 @@ async def preview(self, *, pk: int) -> dict: } @staticmethod - async def get_generate_path(*, pk: int) -> list: + async def get_generate_path(*, pk: int) -> list[str]: async with async_db_session() as db: business = await gen_business_dao.get(db, pk) if not business: diff --git a/backend/app/task/api/v1/task.py b/backend/app/task/api/v1/task.py index 63a2927a..de27ef7d 100644 --- a/backend/app/task/api/v1/task.py +++ b/backend/app/task/api/v1/task.py @@ -4,9 +4,9 @@ from fastapi import APIRouter, Depends, Path -from backend.app.task.schema.task import RunParam +from backend.app.task.schema.task import RunParam, TaskResult from backend.app.task.service.task_service import task_service -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -15,7 +15,7 @@ @router.get('', summary='获取可执行任务', dependencies=[DependsJwtAuth]) -async def get_all_tasks() -> ResponseModel: +async def get_all_tasks() -> ResponseSchemaModel[list[str]]: tasks = await task_service.get_list() return response_base.success(data=tasks) @@ -27,7 +27,7 @@ async def get_all_tasks() -> ResponseModel: description='此接口被视为作废,建议使用 flower 查看任务详情', dependencies=[DependsJwtAuth], ) -async def get_task_detail(tid: Annotated[str, Path(description='任务ID')]) -> ResponseModel: +async def get_task_detail(tid: Annotated[str, Path(description='任务ID')]) -> ResponseSchemaModel[TaskResult]: status = task_service.get_detail(tid=tid) return response_base.success(data=status) @@ -53,6 +53,6 @@ async def revoke_task(tid: Annotated[str, Path(description='任务ID')]) -> Resp DependsRBAC, ], ) -async def run_task(obj: RunParam) -> ResponseModel: +async def run_task(obj: RunParam) -> ResponseSchemaModel[str]: task = task_service.run(obj=obj) return response_base.success(data=task) diff --git a/backend/app/task/schema/task.py b/backend/app/task/schema/task.py index f4ab1dc4..850e5860 100644 --- a/backend/app/task/schema/task.py +++ b/backend/app/task/schema/task.py @@ -9,3 +9,15 @@ class RunParam(SchemaBase): name: str = Field(description='任务名称') args: list | None = Field(default=None, description='任务函数位置参数') kwargs: dict | None = Field(default=None, description='任务函数关键字参数') + + +class TaskResult(SchemaBase): + result: str + traceback: str + status: str + name: str + args: list | None + kwargs: dict | None + worker: str + retries: int | None + queue: str | None diff --git a/backend/app/task/service/task_service.py b/backend/app/task/service/task_service.py index 2c797472..a9f74054 100644 --- a/backend/app/task/service/task_service.py +++ b/backend/app/task/service/task_service.py @@ -1,25 +1,26 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - from celery.exceptions import NotRegistered from celery.result import AsyncResult from starlette.concurrency import run_in_threadpool from backend.app.task.celery import celery_app -from backend.app.task.schema.task import RunParam -from backend.common.dataclasses import TaskResult +from backend.app.task.schema.task import RunParam, TaskResult +from backend.common.exception import errors from backend.common.exception.errors import NotFoundError class TaskService: @staticmethod - async def get_list(): + async def get_list() -> list[str]: registered_tasks = await run_in_threadpool(celery_app.control.inspect().registered) + if not registered_tasks: + raise errors.ForbiddenError(msg='celery 服务未启动') tasks = list(registered_tasks.values())[0] return tasks @staticmethod - def get_detail(*, tid: str): + def get_detail(*, tid: str) -> TaskResult: try: result = AsyncResult(id=tid, app=celery_app) except NotRegistered: @@ -45,7 +46,7 @@ def revoke(*, tid: str): result.revoke(terminate=True) @staticmethod - def run(*, obj: RunParam): + def run(*, obj: RunParam) -> str: task: AsyncResult = celery_app.send_task(name=obj.name, args=obj.args, kwargs=obj.kwargs) return task.task_id diff --git a/backend/common/dataclasses.py b/backend/common/dataclasses.py index eb622d46..124d1d37 100644 --- a/backend/common/dataclasses.py +++ b/backend/common/dataclasses.py @@ -52,16 +52,3 @@ class AccessToken: class RefreshToken: refresh_token: str refresh_token_expire_time: datetime - - -@dataclasses.dataclass -class TaskResult: - result: str - traceback: str - status: str - name: str - args: list | None - kwargs: dict | None - worker: str - retries: int | None - queue: str | None diff --git a/backend/common/pagination.py b/backend/common/pagination.py index 4800f19a..82340806 100644 --- a/backend/common/pagination.py +++ b/backend/common/pagination.py @@ -84,22 +84,20 @@ class PageData(_PageDetails, Generic[SchemaT]): E.g. :: - @router.get('/test', response_model=ResponseSchemaModel[PageData[GetApiListDetails]]) + @router.get('/test', response_model=ResponseSchemaModel[PageData[GetApiDetail]]) def test(): - return ResponseSchemaModel[PageData[GetApiListDetails]](data=GetApiListDetails(...)) + return ResponseSchemaModel[PageData[GetApiDetail]](data=GetApiDetail(...)) @router.get('/test') - def test() -> ResponseSchemaModel[PageData[GetApiListDetails]]: - return ResponseSchemaModel[PageData[GetApiListDetails]](data=GetApiListDetails(...)) + def test() -> ResponseSchemaModel[PageData[GetApiDetail]]: + return ResponseSchemaModel[PageData[GetApiDetail]](data=GetApiDetail(...)) @router.get('/test') - def test() -> ResponseSchemaModel[PageData[GetApiListDetails]]: + def test() -> ResponseSchemaModel[PageData[GetApiDetail]]: res = CustomResponseCode.HTTP_200 - return ResponseSchemaModel[PageData[GetApiListDetails]]( - code=res.code, msg=res.msg, data=GetApiListDetails(...) - ) + return ResponseSchemaModel[PageData[GetApiDetail]](code=res.code, msg=res.msg, data=GetApiDetail(...)) """ items: Sequence[SchemaT] diff --git a/backend/common/response/response_schema.py b/backend/common/response/response_schema.py index 9f3193c6..64ca4617 100644 --- a/backend/common/response/response_schema.py +++ b/backend/common/response/response_schema.py @@ -49,20 +49,20 @@ class ResponseSchemaModel(ResponseModel, Generic[SchemaT]): E.g. :: - @router.get('/test', response_model=ResponseSchemaModel[GetApiListDetails]) + @router.get('/test', response_model=ResponseSchemaModel[GetApiDetail]) def test(): - return ResponseSchemaModel[GetApiListDetails](data=GetApiListDetails(...)) + return ResponseSchemaModel[GetApiDetail](data=GetApiDetail(...)) @router.get('/test') - def test() -> ResponseSchemaModel[GetApiListDetails]: - return ResponseSchemaModel[GetApiListDetails](data=GetApiListDetails(...)) + def test() -> ResponseSchemaModel[GetApiDetail]: + return ResponseSchemaModel[GetApiDetail](data=GetApiDetail(...)) @router.get('/test') - def test() -> ResponseSchemaModel[GetApiListDetails]: + def test() -> ResponseSchemaModel[GetApiDetail]: res = CustomResponseCode.HTTP_200 - return ResponseSchemaModel[GetApiListDetails](code=res.code, msg=res.msg, data=GetApiListDetails(...)) + return ResponseSchemaModel[GetApiDetail](code=res.code, msg=res.msg, data=GetApiDetail(...)) """ data: SchemaT diff --git a/backend/common/schema.py b/backend/common/schema.py index 464f9594..00b54425 100644 --- a/backend/common/schema.py +++ b/backend/common/schema.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + from pydantic import BaseModel, ConfigDict, EmailStr, validate_email from pydantic_extra_types.phone_numbers import PhoneNumber diff --git a/backend/common/security/permission.py b/backend/common/security/permission.py index 9f023353..9df72fd7 100644 --- a/backend/common/security/permission.py +++ b/backend/common/security/permission.py @@ -12,7 +12,7 @@ from backend.utils.import_parse import dynamic_import if TYPE_CHECKING: - from backend.app.admin.schema.data_rule import GetDataRuleListDetails + from backend.app.admin.schema.data_rule import GetDataRuleDetail class RequestPermission: @@ -47,7 +47,7 @@ def filter_data_permission(request: Request) -> ColumnElement[bool]: data_rules = [] for role in request.user.roles: data_rules.extend(role.rules) - user_data_rules: list[GetDataRuleListDetails] = list(dict.fromkeys(data_rules)) + user_data_rules: list[GetDataRuleDetail] = list(dict.fromkeys(data_rules)) # 超级管理员和无规则用户不做过滤 if request.user.is_superuser or not user_data_rules: diff --git a/backend/templates/py/api.jinja b/backend/templates/py/api.jinja index 24f3ed3d..9c579809 100644 --- a/backend/templates/py/api.jinja +++ b/backend/templates/py/api.jinja @@ -2,10 +2,10 @@ # -*- coding: utf-8 -*- from typing import Annotated -from backend.app.{{ app_name }}.schema.{{ table_name_en }} import Create{{ schema_name }}Param, Update{{ schema_name }}Param +from backend.app.{{ app_name }}.schema.{{ table_name_en }} import Create{{ schema_name }}Param, Get{{ schema_name }}Detail, Update{{ schema_name }}Param from backend.app.{{ app_name }}.service.{{ table_name_en }}_service import {{ table_name_en }}_service -from backend.common.pagination import DependsPagination, paging_data -from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.pagination import DependsPagination, PageData, paging_data +from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC @@ -16,7 +16,7 @@ router = APIRouter() @router.get('/{pk}', summary='获取{{ table_simple_name_zh }}详情', dependencies=[DependsJwtAuth]) -async def get_{{ table_name_en }}(pk: Annotated[int, Path(...)]) -> ResponseModel: +async def get_{{ table_name_en }}(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[Get{{ schema_name }}Detail]: {{ table_name_en }} = await {{ table_name_en }}_service.get(pk=pk) return response_base.success(data={{ table_name_en }}) @@ -29,7 +29,7 @@ async def get_{{ table_name_en }}(pk: Annotated[int, Path(...)]) -> ResponseMode DependsPagination, ], ) -async def get_pagination_{{ table_name_en }}(db: CurrentSession) -> ResponseModel: +async def get_pagination_{{ table_name_en }}(db: CurrentSession) -> ResponseSchemaModel[PageData[Get{{ schema_name }}Detail]]: {{ table_name_en }}_select = await {{ table_name_en }}_service.get_select() page_data = await paging_data(db, {{ table_name_en }}_select) return response_base.success(data=page_data) diff --git a/backend/templates/py/schema.jinja b/backend/templates/py/schema.jinja index a50af192..6a1eb20b 100644 --- a/backend/templates/py/schema.jinja +++ b/backend/templates/py/schema.jinja @@ -22,7 +22,7 @@ class Update{{ schema_name }}Param({{ schema_name }}SchemaBase): pass -class Get{{ schema_name }}ListDetails({{ schema_name }}SchemaBase): +class Get{{ schema_name }}Detail({{ schema_name }}SchemaBase): model_config = ConfigDict(from_attributes=True) id: int diff --git a/backend/utils/serializers.py b/backend/utils/serializers.py index 54b48538..9d9cd6e2 100644 --- a/backend/utils/serializers.py +++ b/backend/utils/serializers.py @@ -30,7 +30,7 @@ def select_columns_serialize(row: R) -> dict: return result -def select_list_serialize(row: Sequence[R]) -> list: +def select_list_serialize(row: Sequence[R]) -> list[dict[str, Any]]: """ Serialize SQLAlchemy select list @@ -59,7 +59,7 @@ def select_as_dict(row: R, use_alias: bool = False) -> dict: del result['_sa_instance_state'] else: result = {} - mapper = class_mapper(row.__class__) + mapper = class_mapper(row.__class__) # type: ignore for prop in mapper.iterate_properties: if isinstance(prop, (ColumnProperty, SynonymProperty)): key = prop.key