diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 40b2684..50cb958 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Path, Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService from utils.log_util import logger @@ -14,7 +15,7 @@ cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[PreAuthDepen @cache_controller.get( '', - response_model=CacheMonitorModel, + response_model=DataResponseModel[CacheMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_info(request: Request) -> Response: @@ -27,7 +28,7 @@ async def get_monitor_cache_info(request: Request) -> Response: @cache_controller.get( '/getNames', - response_model=list[CacheInfoModel], + response_model=DataResponseModel[list[CacheInfoModel]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_name(request: Request) -> Response: @@ -40,7 +41,7 @@ async def get_monitor_cache_name(request: Request) -> Response: @cache_controller.get( '/getKeys/{cache_name}', - response_model=list[str], + response_model=DataResponseModel[list[str]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Path(description='缓存名称')]) -> Response: @@ -53,7 +54,7 @@ async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Pat @cache_controller.get( '/getValue/{cache_name}/{cache_key}', - response_model=CacheInfoModel, + response_model=DataResponseModel[CacheInfoModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_value( @@ -83,6 +84,7 @@ async def clear_monitor_cache_name( @cache_controller.delete( '/clearCacheKey/{cache_key}', + response_model= ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response: @@ -94,6 +96,7 @@ async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Pa @cache_controller.delete( '/clearCacheAll', + response_model= ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_all(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index f1ef6c4..2eb6358 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -4,6 +4,7 @@ from datetime import timedelta from fastapi import APIRouter, Request, Response from common.enums import RedisInitKeyConfig +from common.vo import DynamicResponseModel from module_admin.entity.vo.login_vo import CaptchaCode from module_admin.service.captcha_service import CaptchaService from utils.log_util import logger @@ -12,7 +13,10 @@ from utils.response_util import ResponseUtil captcha_controller = APIRouter() -@captcha_controller.get('/captchaImage') +@captcha_controller.get( + '/captchaImage', + response_model=DynamicResponseModel[CaptchaCode], +) async def get_captcha_image(request: Request) -> Response: captcha_enabled = ( await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index 9d37c8f..182bd8e 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -1,8 +1,11 @@ from typing import Annotated from fastapi import APIRouter, BackgroundTasks, File, Query, Request, Response, UploadFile +from fastapi.responses import StreamingResponse from common.aspect.pre_auth import PreAuthDependency +from common.vo import DynamicResponseModel +from module_admin.entity.vo.common_vo import UploadResponseModel from module_admin.service.common_service import CommonService from utils.log_util import logger from utils.response_util import ResponseUtil @@ -10,7 +13,10 @@ from utils.response_util import ResponseUtil common_controller = APIRouter(prefix='/common', dependencies=[PreAuthDependency()]) -@common_controller.post('/upload') +@common_controller.post( + '/upload', + response_model=DynamicResponseModel[UploadResponseModel], +) async def common_upload(request: Request, file: Annotated[UploadFile, File(...)]) -> Response: upload_result = await CommonService.upload_service(request, file) logger.info('上传成功') @@ -18,7 +24,18 @@ async def common_upload(request: Request, file: Annotated[UploadFile, File(...)] return ResponseUtil.success(model_content=upload_result.result) -@common_controller.get('/download') +@common_controller.get( + '/download', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, +) async def common_download( request: Request, background_tasks: BackgroundTasks, @@ -31,7 +48,18 @@ async def common_download( return ResponseUtil.streaming(data=download_result.result) -@common_controller.get('/download/resource') +@common_controller.get( + '/download/resource', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, +) async def common_download_resource(request: Request, resource: Annotated[str, Query()]) -> Response: download_resource_result = await CommonService.download_resource_services(resource) logger.info(download_resource_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 2befefb..2515cb5 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -146,6 +147,15 @@ async def query_system_config(request: Request, config_key: str) -> Response: @config_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回参数列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:config:export')], ) @Log(title='参数管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index 542e869..8136dcd 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dept_service import DeptService @@ -22,7 +23,7 @@ dept_controller = APIRouter(prefix='/system/dept', dependencies=[PreAuthDependen @dept_controller.get( '/list/exclude/{dept_id}', - response_model=list[DeptModel], + response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_tree_for_edit_option( @@ -40,7 +41,7 @@ async def get_system_dept_tree_for_edit_option( @dept_controller.get( '/list', - response_model=list[DeptModel], + response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_list( @@ -57,6 +58,7 @@ async def get_system_dept_list( @dept_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:add')], ) @ValidateFields(validate_model='add_dept') @@ -74,11 +76,12 @@ async def add_system_dept( add_dept_result = await DeptService.add_dept_services(query_db, add_dept) logger.info(add_dept_result.message) - return ResponseUtil.success(data=add_dept_result) + return ResponseUtil.success(msg=add_dept_result.message) @dept_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:edit')], ) @ValidateFields(validate_model='edit_dept') @@ -102,6 +105,7 @@ async def edit_system_dept( @dept_controller.delete( '/{dept_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:remove')], ) @Log(title='部门管理', business_type=BusinessType.DELETE) @@ -128,7 +132,7 @@ async def delete_system_dept( @dept_controller.get( '/{dept_id}', - response_model=DeptModel, + response_model=DataResponseModel[DeptModel], dependencies=[UserInterfaceAuthDependency('system:dept:query')], ) async def query_detail_system_dept( diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 310d00a..d7b9803 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -155,6 +156,15 @@ async def query_detail_system_dict_type( @dict_controller.post( '/type/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回字典类型列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:dict:export')], ) @Log(title='字典类型', business_type=BusinessType.EXPORT) @@ -290,6 +300,15 @@ async def query_detail_system_dict_data( @dict_controller.post( '/data/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回字典数据列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:dict:export')], ) @Log(title='字典数据', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index 34735d2..33a4bda 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -169,6 +170,15 @@ async def query_detail_system_job( @job_controller.post( '/job/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回定时任务列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:job:export')], ) @Log(title='定时任务', business_type=BusinessType.EXPORT) @@ -240,6 +250,15 @@ async def delete_system_job_log( @job_controller.post( '/jobLog/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回定时任务日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:job:export')], ) @Log(title='定时任务调度日志', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index adb497f..e0a36b4 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -1,6 +1,7 @@ from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log @@ -82,6 +83,15 @@ async def delete_system_operation_log( @log_controller.post( '/operlog/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回操作日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:operlog:export')], ) @Log(title='操作日志', business_type=BusinessType.EXPORT) @@ -174,6 +184,15 @@ async def unlock_system_user( @log_controller.post( '/logininfor/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回登录日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:export')], ) @Log(title='登录日志', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 4dbb055..7ac208a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -10,9 +10,9 @@ from common.annotation.log_annotation import Log from common.aspect.db_seesion import DBSessionDependency from common.aspect.pre_auth import CurrentUserDependency from common.enums import BusinessType, RedisInitKeyConfig -from common.vo import CrudResponseModel +from common.vo import CrudResponseModel, DataResponseModel, DynamicResponseModel, ResponseBaseModel from config.env import AppConfig, JwtConfig -from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister +from module_admin.entity.vo.login_vo import RouterModel, Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme from module_admin.service.user_service import UserService @@ -22,7 +22,10 @@ from utils.response_util import ResponseUtil login_controller = APIRouter() -@login_controller.post('/login', response_model=Token) +@login_controller.post( + '/login', + response_model=DynamicResponseModel[Token], +) @Log(title='用户登录', business_type=BusinessType.OTHER, log_type='login') async def login( request: Request, @@ -78,7 +81,10 @@ async def login( return ResponseUtil.success(msg='登录成功', dict_content={'token': access_token}) -@login_controller.get('/getInfo', response_model=CurrentUserModel) +@login_controller.get( + '/getInfo', + response_model=DynamicResponseModel[CurrentUserModel], +) async def get_login_user_info( request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()] ) -> Response: @@ -87,7 +93,10 @@ async def get_login_user_info( return ResponseUtil.success(model_content=current_user) -@login_controller.get('/getRouters') +@login_controller.get( + '/getRouters', + response_model=DataResponseModel[list[RouterModel]], +) async def get_login_user_routers( request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()], @@ -99,7 +108,10 @@ async def get_login_user_routers( return ResponseUtil.success(data=user_routers) -@login_controller.post('/register', response_model=CrudResponseModel) +@login_controller.post( + '/register', + response_model=DataResponseModel[CrudResponseModel], +) async def register_user( request: Request, user_register: UserRegister, @@ -141,7 +153,10 @@ async def register_user( # return ResponseUtil.error(msg=str(e)) -@login_controller.post('/logout') +@login_controller.post( + '/logout', + response_model=ResponseBaseModel, +) async def logout(request: Request, token: Annotated[Optional[str], Depends(oauth2_scheme)]) -> Response: payload = jwt.decode( token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False} diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index fd157d1..ec97f1b 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -10,7 +10,9 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel +from common.vo import DataResponseModel, DynamicResponseModel, ResponseBaseModel +from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel +from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.menu_service import MenuService from utils.log_util import logger @@ -19,7 +21,10 @@ from utils.response_util import ResponseUtil menu_controller = APIRouter(prefix='/system/menu', dependencies=[PreAuthDependency()]) -@menu_controller.get('/treeselect') +@menu_controller.get( + '/treeselect', + response_model=DataResponseModel[list[MenuTreeModel]], +) async def get_system_menu_tree( request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()], @@ -31,7 +36,10 @@ async def get_system_menu_tree( return ResponseUtil.success(data=menu_query_result) -@menu_controller.get('/roleMenuTreeselect/{role_id}') +@menu_controller.get( + '/roleMenuTreeselect/{role_id}', + response_model=DynamicResponseModel[RoleMenuQueryModel], +) async def get_system_role_menu_tree( request: Request, role_id: Annotated[int, Path(description='角色ID')], @@ -46,7 +54,7 @@ async def get_system_role_menu_tree( @menu_controller.get( '/list', - response_model=list[MenuModel], + response_model=DataResponseModel[list[MenuModel]], dependencies=[UserInterfaceAuthDependency('system:menu:list')], ) async def get_system_menu_list( @@ -63,6 +71,7 @@ async def get_system_menu_list( @menu_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:add')], ) @ValidateFields(validate_model='add_menu') @@ -85,6 +94,7 @@ async def add_system_menu( @menu_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:edit')], ) @ValidateFields(validate_model='edit_menu') @@ -105,6 +115,7 @@ async def edit_system_menu( @menu_controller.delete( '/{menu_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:remove')], ) @Log(title='菜单管理', business_type=BusinessType.DELETE) @@ -122,7 +133,7 @@ async def delete_system_menu( @menu_controller.get( '/{menu_id}', - response_model=MenuModel, + response_model=DataResponseModel[MenuModel], dependencies=[UserInterfaceAuthDependency('system:menu:query')], ) async def query_detail_system_menu( diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index adfce48..3ea466c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -118,6 +119,15 @@ async def query_detail_system_post( @post_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回岗位列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:post:export')], ) @Log(title='岗位管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index f3ca39e..9d3ea2a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,10 +12,16 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel +from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeptModel -from module_admin.entity.vo.role_vo import AddRoleModel, DeleteRoleModel, RoleModel, RolePageQueryModel -from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserModel, UserRolePageQueryModel +from module_admin.entity.vo.role_vo import ( + AddRoleModel, + DeleteRoleModel, + RoleDeptQueryModel, + RoleModel, + RolePageQueryModel, +) +from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserInfoModel, UserRolePageQueryModel from module_admin.service.dept_service import DeptService from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService @@ -27,6 +34,7 @@ role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependen @role_controller.get( '/deptTree/{role_id}', + response_model=DynamicResponseModel[RoleDeptQueryModel], dependencies=[UserInterfaceAuthDependency('system:role:query')], ) async def get_system_role_dept_tree( @@ -188,6 +196,15 @@ async def query_detail_system_role( @role_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回角色列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:role:export')], ) @Log(title='角色管理', business_type=BusinessType.EXPORT) @@ -238,7 +255,7 @@ async def reset_system_role_status( @role_controller.get( '/authUser/allocatedList', - response_model=PageResponseModel[UserModel], + response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_allocated_user_list( @@ -257,7 +274,7 @@ async def get_system_allocated_user_list( @role_controller.get( '/authUser/unallocatedList', - response_model=PageResponseModel[UserModel], + response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_unallocated_user_list( diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index acbcdf1..0c20659 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -2,6 +2,7 @@ from fastapi import APIRouter, Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.vo import DataResponseModel from module_admin.entity.vo.server_vo import ServerMonitorModel from module_admin.service.server_service import ServerService from utils.log_util import logger @@ -12,7 +13,7 @@ server_controller = APIRouter(prefix='/monitor/server', dependencies=[PreAuthDep @server_controller.get( '', - response_model=ServerMonitorModel, + response_model=DataResponseModel[ServerMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:server:list')], ) async def get_monitor_server_info(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index 1ac0810..36467af 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -4,6 +4,7 @@ from typing import Annotated, Literal, Optional, Union import aiofiles from fastapi import APIRouter, File, Form, Path, Query, Request, Response, UploadFile +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -15,9 +16,10 @@ from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from config.env import UploadConfig -from module_admin.entity.vo.dept_vo import DeptModel +from module_admin.entity.vo.dept_vo import DeptModel, DeptTreeModel from module_admin.entity.vo.user_vo import ( AddUserModel, + AvatarModel, CrudUserRoleModel, CurrentUserModel, DeleteUserModel, @@ -31,6 +33,7 @@ from module_admin.entity.vo.user_vo import ( UserProfileModel, UserRoleQueryModel, UserRoleResponseModel, + UserRowModel, ) from module_admin.service.dept_service import DeptService from module_admin.service.role_service import RoleService @@ -46,6 +49,7 @@ user_controller = APIRouter(prefix='/system/user', dependencies=[PreAuthDependen @user_controller.get( '/deptTree', + response_model=DataResponseModel[list[DeptTreeModel]], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) async def get_system_dept_tree( @@ -61,7 +65,7 @@ async def get_system_dept_tree( @user_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[UserRowModel], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) async def get_system_user_list( @@ -247,12 +251,12 @@ async def query_detail_system_user_profile( @user_controller.get( '/{user_id}', - response_model=DataResponseModel[UserDetailModel], + response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @user_controller.get( '/', - response_model=UserDetailModel, + response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) async def query_detail_system_user( @@ -270,7 +274,10 @@ async def query_detail_system_user( return ResponseUtil.success(model_content=detail_user_result) -@user_controller.post('/profile/avatar') +@user_controller.post( + '/profile/avatar', + response_model=DynamicResponseModel[AvatarModel], +) @Log(title='个人信息', business_type=BusinessType.UPDATE) async def change_system_user_profile_avatar( request: Request, @@ -301,7 +308,7 @@ async def change_system_user_profile_avatar( edit_user_result = await UserService.edit_user_services(query_db, edit_user) logger.info(edit_user_result.message) - return ResponseUtil.success(dict_content={'imgUrl': edit_user.avatar}, msg=edit_user_result.message) + return ResponseUtil.success(model_content=AvatarModel(imgUrl=edit_user.avatar), msg=edit_user_result.message) return ResponseUtil.failure(msg='上传图片异常,请联系管理员') @@ -382,6 +389,15 @@ async def batch_import_system_user( @user_controller.post( '/importTemplate', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回导入用户模板excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:user:import')], ) async def export_system_user_template( @@ -395,6 +411,15 @@ async def export_system_user_template( @user_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回用户列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:user:export')], ) @Log(title='用户管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py index 930f820..7b7afa8 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py @@ -62,6 +62,19 @@ class DeptQueryModel(DeptModel): end_time: Optional[str] = Field(default=None, description='结束时间') +class DeptTreeModel(BaseModel): + """ + 部门树模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + id: int = Field(description='部门id') + label: str = Field(description='部门名称') + parent_id: int = Field(description='父部门id') + children: Optional[list['DeptTreeModel']] = Field(default=None, description='子部门树') + + class DeleteDeptModel(BaseModel): """ 删除部门模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py index b58500c..7b5212a 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py @@ -77,6 +77,19 @@ class MenuQueryModel(MenuModel): end_time: Optional[str] = Field(default=None, description='结束时间') +class MenuTreeModel(BaseModel): + """ + 菜单树模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + id: int = Field(description='菜单id') + label: str = Field(description='菜单名称') + parent_id: int = Field(description='父菜单id') + children: Optional[list['MenuTreeModel']] = Field(default=None, description='子菜单树') + + class DeleteMenuModel(BaseModel): """ 删除菜单模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py index 887b0f9..0ac0f4e 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py @@ -91,6 +91,14 @@ class UserModel(BaseModel): self.get_phonenumber() +class UserRowModel(UserModel): + """ + 用户列表行数据模型 + """ + + dept: Optional[DeptModel] = Field(default=None, description='部门信息') + + class UserRoleModel(BaseModel): """ 用户和角色关联表对应pydantic模型 @@ -156,6 +164,16 @@ class UserProfileModel(BaseModel): role_group: Union[str, None] = Field(description='角色信息') +class AvatarModel(BaseModel): + """ + 上传头像响应模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + img_url: str = Field(description='头像地址') + + class UserQueryModel(UserModel): """ 用户管理不分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index d36b2f4..b939c41 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -8,7 +8,7 @@ from common.vo import CrudResponseModel from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.dept_dao import DeptDao from module_admin.entity.do.dept_do import SysDept -from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel +from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptTreeModel from utils.common_util import CamelCaseUtil @@ -20,7 +20,7 @@ class DeptService: @classmethod async def get_dept_tree_services( cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str - ) -> list[dict[str, Any]]: + ) -> list[dict[str,Any]]: """ 获取部门树信息service @@ -30,7 +30,8 @@ class DeptService: :return: 部门树信息对象 """ dept_list_result = await DeptDao.get_dept_list_for_tree(query_db, page_object, data_scope_sql) - dept_tree_result = cls.list_to_tree(dept_list_result) + dept_tree_model_result = cls.list_to_tree(dept_list_result) + dept_tree_result = [dept.model_dump(exclude_unset=True, by_alias=True) for dept in dept_tree_model_result] return dept_tree_result @@ -205,7 +206,7 @@ class DeptService: return result @classmethod - def list_to_tree(cls, permission_list: Sequence[SysDept]) -> list[dict[str, Any]]: + def list_to_tree(cls, permission_list: Sequence[SysDept]) -> list[DeptTreeModel]: """ 工具方法:根据部门列表信息生成树形嵌套数据 @@ -213,25 +214,25 @@ class DeptService: :return: 部门树形嵌套数据 """ _permission_list = [ - {'id': item.dept_id, 'label': item.dept_name, 'parentId': item.parent_id} for item in permission_list + DeptTreeModel(id=item.dept_id, label=item.dept_name, parentId=item.parent_id) for item in permission_list ] # 转成id为key的字典 - mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) + mapping: dict[int, DeptTreeModel] = dict(zip([i.id for i in _permission_list], _permission_list)) # 树容器 - container: list[dict[str, Any]] = [] + container: list[DeptTreeModel] = [] for d in _permission_list: # 如果找不到父级项,则是根节点 - parent = mapping.get(d['parentId']) + parent = mapping.get(d.parent_id) if parent is None: container.append(d) else: - children: list[dict[str, Any]] = parent.get('children') + children: list[DeptTreeModel] = parent.children if not children: children = [] children.append(d) - parent.update({'children': children}) + parent.children = children return container diff --git a/ruoyi-fastapi-backend/module_admin/service/menu_service.py b/ruoyi-fastapi-backend/module_admin/service/menu_service.py index 1767b69..224e384 100644 --- a/ruoyi-fastapi-backend/module_admin/service/menu_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/menu_service.py @@ -9,7 +9,7 @@ from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.menu_dao import MenuDao from module_admin.dao.role_dao import RoleDao from module_admin.entity.do.menu_do import SysMenu -from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel +from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from utils.common_util import CamelCaseUtil @@ -35,7 +35,8 @@ class MenuService: menu_list_result = await MenuDao.get_menu_list_for_tree( query_db, current_user.user.user_id, current_user.user.role ) - menu_tree_result = cls.list_to_tree(menu_list_result) + menu_tree_model_result = cls.list_to_tree(menu_list_result) + menu_tree_result = [menu.model_dump(exclude_unset=True, by_alias=True) for menu in menu_tree_model_result] return menu_tree_result @@ -185,7 +186,7 @@ class MenuService: return result @classmethod - def list_to_tree(cls, permission_list: Sequence[SysMenu]) -> list[dict[str, Any]]: + def list_to_tree(cls, permission_list: Sequence[SysMenu]) -> list[MenuTreeModel]: """ 工具方法:根据菜单列表信息生成树形嵌套数据 @@ -193,24 +194,24 @@ class MenuService: :return: 菜单树形嵌套数据 """ _permission_list = [ - {'id': item.menu_id, 'label': item.menu_name, 'parentId': item.parent_id} for item in permission_list + MenuTreeModel(id=item.menu_id, label=item.menu_name, parentId=item.parent_id) for item in permission_list ] # 转成id为key的字典 - mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) + mapping: dict[int, MenuTreeModel] = dict(zip([i.id for i in _permission_list], _permission_list)) # 树容器 - container: list[dict[str, Any]] = [] + container: list[MenuTreeModel] = [] for d in _permission_list: # 如果找不到父级项,则是根节点 - parent = mapping.get(d['parentId']) + parent = mapping.get(d.parent_id) if parent is None: container.append(d) else: - children: list[dict[str, Any]] = parent.get('children') + children: list[MenuTreeModel] = parent.children if not children: children = [] children.append(d) - parent.update({'children': children}) + parent.children = children return container diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index c960197..e41c53a 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -318,7 +318,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_allocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - allocated_list = PageModel( + allocated_list = PageModel[UserInfoModel]( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], @@ -343,7 +343,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_unallocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - unallocated_list = PageModel( + unallocated_list = PageModel[UserInfoModel]( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index 9a8bc3c..1d88d03 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -29,6 +29,7 @@ from module_admin.entity.vo.user_vo import ( UserRoleModel, UserRoleQueryModel, UserRoleResponseModel, + UserRowModel, ) from module_admin.service.config_service import ConfigService from module_admin.service.dept_service import DeptService @@ -47,7 +48,7 @@ class UserService: @classmethod async def get_user_list_services( cls, query_db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageModel, list[dict[str, Any]]]: + ) -> Union[PageModel[UserRowModel], list[dict[str, Any]]]: """ 获取用户列表信息service @@ -59,7 +60,7 @@ class UserService: """ query_result = await UserDao.get_user_list(query_db, query_object, data_scope_sql, is_page) if is_page: - user_list_result = PageModel( + user_list_result = PageModel[UserRowModel]( **{ **query_result.model_dump(by_alias=True), 'rows': [{**row[0], 'dept': row[1]} for row in query_result.rows], diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index faab42b..43dd6c4 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -10,10 +11,17 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import RoleInterfaceAuthDependency, UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from common.vo import PageResponseModel +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from config.env import GenConfig from module_admin.entity.vo.user_vo import CurrentUserModel -from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel +from module_generator.entity.vo.gen_vo import ( + DeleteGenTableModel, + EditGenTableModel, + GenTableDbRowModel, + GenTableDetailModel, + GenTablePageQueryModel, + GenTableRowModel, +) from module_generator.service.gen_service import GenTableColumnService, GenTableService from utils.common_util import bytes2file_response from utils.log_util import logger @@ -24,7 +32,7 @@ gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency() @gen_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[GenTableRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_table_list( @@ -41,7 +49,7 @@ async def get_gen_table_list( @gen_controller.get( '/db/list', - response_model=PageResponseModel, + response_model=PageResponseModel[GenTableDbRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_db_table_list( @@ -58,6 +66,7 @@ async def get_gen_db_table_list( @gen_controller.post( '/importTable', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:import')], ) @Log(title='代码生成', business_type=BusinessType.IMPORT) @@ -77,6 +86,7 @@ async def import_gen_table( @gen_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) @ValidateFields(validate_model='edit_gen_table') @@ -98,6 +108,7 @@ async def edit_gen_table( @gen_controller.delete( '/{table_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:remove')], ) @Log(title='代码生成', business_type=BusinessType.DELETE) @@ -115,6 +126,7 @@ async def delete_gen_table( @gen_controller.post( '/createTable', + response_model=ResponseBaseModel, dependencies=[RoleInterfaceAuthDependency('admin')], ) @Log(title='创建表', business_type=BusinessType.OTHER) @@ -132,6 +144,15 @@ async def create_table( @gen_controller.get( '/batchGenCode', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回生成的代码文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('tool:gen:code')], ) @Log(title='代码生成', business_type=BusinessType.GENCODE) @@ -149,6 +170,7 @@ async def batch_gen_code( @gen_controller.get( '/genCode/{table_name}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:code')], ) @Log(title='代码生成', business_type=BusinessType.GENCODE) @@ -168,6 +190,7 @@ async def gen_code_local( @gen_controller.get( '/{table_id}', + response_model=DataResponseModel[GenTableDetailModel], dependencies=[UserInterfaceAuthDependency('tool:gen:query')], ) async def query_detail_gen_table( @@ -186,6 +209,7 @@ async def query_detail_gen_table( @gen_controller.get( '/preview/{table_id}', + response_model=DataResponseModel[dict[str, str]], dependencies=[UserInterfaceAuthDependency('tool:gen:preview')], ) async def preview_code( @@ -201,6 +225,7 @@ async def preview_code( @gen_controller.get( '/synchDb/{table_name}', + response_model=DataResponseModel[str], dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) @Log(title='代码生成', business_type=BusinessType.UPDATE) diff --git a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py index c43b227..4e4a67e 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py +++ b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py @@ -81,6 +81,27 @@ class GenTableBaseModel(BaseModel): self.get_function_author() +class GenTableRowModel(GenTableBaseModel): + """ + 代码生成业务表行数据模型 + """ + + columns: Optional[list['GenTableColumnBaseModel']] = Field(default=None, description='表列信息') + + +class GenTableDbRowModel(BaseModel): + """ + 代码生成业务表数据库行数据模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + table_name: Optional[str] = Field(default=None, description='表名称') + table_comment: Optional[str] = Field(default=None, description='表描述') + create_time: Optional[datetime] = Field(default=None, description='创建时间') + update_time: Optional[datetime] = Field(default=None, description='更新时间') + + class GenTableModel(GenTableBaseModel): """ 代码生成业务表模型 @@ -145,6 +166,18 @@ class GenTablePageQueryModel(GenTableQueryModel): page_size: int = Field(default=10, description='每页记录数') +class GenTableDetailModel(BaseModel): + """ + 代码生成业务表详情模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + info: Optional[GenTableModel] = Field(default=None, description='业务表信息') + rows: Optional[list['GenTableColumnModel']] = Field(default=None, description='表列信息') + tables: Optional[list['GenTableModel']] = Field(default=None, description='所有业务表信息') + + class DeleteGenTableModel(BaseModel): """ 删除代码生成业务表模型 diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index 56c2dd7..51c44d3 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -14,6 +14,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -150,6 +151,15 @@ async def query_detail_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回{{ functionName }}列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:export')], ) @Log(title='{{ functionName }}', business_type=BusinessType.EXPORT)