From 3bf4a29844eb2ab7cd0da776f2267570d01df24d Mon Sep 17 00:00:00 2001
From: Github_lizhw <171332584@qq.com>
Date: Fri, 27 Sep 2024 22:54:32 +0800
Subject: [PATCH] =?UTF-8?q?system-tenant=20=E5=A4=9A=E5=BA=94=E7=94=A8?=
=?UTF-8?q?=E5=A4=9A=E7=A7=9F=E6=88=B7=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 6 +
ruoyi-admin/pom.xml | 5 +
.../src/main/resources/application.yml | 8 +
.../common/core/service/SaasDeptService.java | 18 +
.../common/core/service/SaasDictService.java | 67 ++
.../common/core/service/SaasOssService.java | 29 +
.../common/core/service/SaasUserService.java | 85 ++
ruoyi-modules/pom.xml | 1 +
ruoyi-modules/ruoyi-system-saas/pom.xml | 128 +++
.../monitor/Sys2LogininforController.java | 89 ++
.../monitor/Sys2OperlogController.java | 75 ++
.../monitor/Sys2UserOnlineController.java | 130 +++
.../system/Sys2ApplicationController.java | 105 +++
.../system/Sys2ClientController.java | 115 +++
.../system/Sys2ConfigController.java | 137 +++
.../controller/system/Sys2DeptController.java | 140 +++
.../system/Sys2DictDataController.java | 123 +++
.../system/Sys2DictTypeController.java | 125 +++
.../system/Sys2NoticeController.java | 90 ++
.../system/Sys2OssConfigController.java | 105 +++
.../controller/system/Sys2OssController.java | 108 +++
.../controller/system/Sys2PostController.java | 133 +++
.../system/Sys2ProfileController.java | 132 +++
.../controller/system/Sys2RoleController.java | 229 +++++
.../system/Sys2SocialController.java | 38 +
.../system/Sys2TenantController.java | 179 ++++
.../system/Sys2TenantPackageController.java | 142 +++
.../controller/system/Sys2UserController.java | 300 +++++++
.../system/SysSaasMenuController.java | 174 ++++
.../system/saas/domain/Sys2Application.java | 41 +
.../dromara/system/saas/domain/Sys2Cache.java | 47 +
.../system/saas/domain/Sys2Client.java | 77 ++
.../system/saas/domain/Sys2Config.java | 51 ++
.../dromara/system/saas/domain/Sys2Dept.java | 83 ++
.../system/saas/domain/Sys2DictData.java | 71 ++
.../system/saas/domain/Sys2DictType.java | 41 +
.../system/saas/domain/Sys2Logininfor.java | 85 ++
.../system/saas/domain/Sys2Notice.java | 51 ++
.../system/saas/domain/Sys2OperLog.java | 115 +++
.../dromara/system/saas/domain/Sys2Oss.java | 50 ++
.../system/saas/domain/Sys2OssConfig.java | 89 ++
.../dromara/system/saas/domain/Sys2Post.java | 61 ++
.../dromara/system/saas/domain/Sys2Role.java | 79 ++
.../system/saas/domain/Sys2RoleDept.java | 29 +
.../system/saas/domain/Sys2RoleMenu.java | 29 +
.../system/saas/domain/Sys2Social.java | 136 +++
.../system/saas/domain/Sys2Tenant.java | 103 +++
.../saas/domain/Sys2TenantApplication.java | 34 +
.../system/saas/domain/Sys2TenantPackage.java | 54 ++
.../dromara/system/saas/domain/Sys2User.java | 115 +++
.../system/saas/domain/Sys2UserOnline.java | 63 ++
.../system/saas/domain/Sys2UserPost.java | 29 +
.../system/saas/domain/Sys2UserRole.java | 29 +
.../system/saas/domain/SysSaasMenu.java | 196 ++++
.../saas/domain/bo/Sys2ApplicationBo.java | 42 +
.../system/saas/domain/bo/Sys2ClientBo.java | 80 ++
.../system/saas/domain/bo/Sys2ConfigBo.java | 59 ++
.../system/saas/domain/bo/Sys2DeptBo.java | 76 ++
.../system/saas/domain/bo/Sys2DictDataBo.java | 79 ++
.../system/saas/domain/bo/Sys2DictTypeBo.java | 50 ++
.../saas/domain/bo/Sys2LogininforBo.java | 87 ++
.../system/saas/domain/bo/Sys2NoticeBo.java | 61 ++
.../system/saas/domain/bo/Sys2OperLogBo.java | 127 +++
.../system/saas/domain/bo/Sys2OssBo.java | 49 +
.../saas/domain/bo/Sys2OssConfigBo.java | 109 +++
.../system/saas/domain/bo/Sys2PostBo.java | 75 ++
.../system/saas/domain/bo/Sys2RoleBo.java | 94 ++
.../system/saas/domain/bo/Sys2SocialBo.java | 142 +++
.../domain/bo/Sys2TenantApplicationBo.java | 32 +
.../system/saas/domain/bo/Sys2TenantBo.java | 114 +++
.../saas/domain/bo/Sys2TenantPackageBo.java | 59 ++
.../system/saas/domain/bo/Sys2UserBo.java | 125 +++
.../saas/domain/bo/Sys2UserPasswordBo.java | 29 +
.../saas/domain/bo/Sys2UserProfileBo.java | 53 ++
.../system/saas/domain/bo/SysSaasMenuBo.java | 110 +++
.../saas/domain/vo/Sys2ApplicationVo.java | 46 +
.../system/saas/domain/vo/Sys2ClientVo.java | 90 ++
.../system/saas/domain/vo/Sys2ConfigVo.java | 72 ++
.../system/saas/domain/vo/Sys2DeptVo.java | 102 +++
.../system/saas/domain/vo/Sys2DictDataVo.java | 88 ++
.../system/saas/domain/vo/Sys2DictTypeVo.java | 57 ++
.../saas/domain/vo/Sys2LogininforVo.java | 106 +++
.../system/saas/domain/vo/Sys2NoticeVo.java | 73 ++
.../system/saas/domain/vo/Sys2OperLogVo.java | 144 +++
.../saas/domain/vo/Sys2OssConfigVo.java | 97 ++
.../saas/domain/vo/Sys2OssUploadVo.java | 28 +
.../system/saas/domain/vo/Sys2OssVo.java | 72 ++
.../system/saas/domain/vo/Sys2PostVo.java | 91 ++
.../system/saas/domain/vo/Sys2RoleVo.java | 100 +++
.../system/saas/domain/vo/Sys2SocialVo.java | 144 +++
.../domain/vo/Sys2TenantApplicationVo.java | 38 +
.../saas/domain/vo/Sys2TenantPackageVo.java | 66 ++
.../system/saas/domain/vo/Sys2TenantVo.java | 115 +++
.../saas/domain/vo/Sys2UserExportVo.java | 94 ++
.../saas/domain/vo/Sys2UserImportVo.java | 76 ++
.../system/saas/domain/vo/Sys2UserInfoVo.java | 40 +
.../system/saas/domain/vo/Sys2UserVo.java | 142 +++
.../system/saas/domain/vo/SysSaasMenuVo.java | 119 +++
.../system/saas/domain/vo/TwoAvatarVo.java | 18 +
.../saas/domain/vo/TwoCacheListInfoVo.java | 23 +
.../saas/domain/vo/TwoDeptTreeSelectVo.java | 26 +
.../saas/domain/vo/TwoMenuTreeSelectVo.java | 26 +
.../system/saas/domain/vo/TwoMetaVo.java | 61 ++
.../system/saas/domain/vo/TwoProfileVo.java | 29 +
.../system/saas/domain/vo/TwoRouterVo.java | 62 ++
.../system/saas/domain/vo/TwoUserInfoVo.java | 30 +
.../saas/listener/SysUserImportListener.java | 119 +++
.../saas/mapper/Sys2ApplicationMapper.java | 17 +
.../system/saas/mapper/Sys2ClientMapper.java | 17 +
.../system/saas/mapper/Sys2ConfigMapper.java | 16 +
.../system/saas/mapper/Sys2DeptMapper.java | 48 +
.../saas/mapper/Sys2DictDataMapper.java | 25 +
.../saas/mapper/Sys2DictTypeMapper.java | 16 +
.../saas/mapper/Sys2LogininforMapper.java | 16 +
.../system/saas/mapper/Sys2NoticeMapper.java | 16 +
.../system/saas/mapper/Sys2OperLogMapper.java | 16 +
.../saas/mapper/Sys2OssConfigMapper.java | 18 +
.../system/saas/mapper/Sys2OssMapper.java | 15 +
.../system/saas/mapper/Sys2PostMapper.java | 38 +
.../saas/mapper/Sys2RoleDeptMapper.java | 15 +
.../system/saas/mapper/Sys2RoleMapper.java | 64 ++
.../saas/mapper/Sys2RoleMenuMapper.java | 15 +
.../system/saas/mapper/Sys2SocialMapper.java | 16 +
.../mapper/Sys2TenantApplicationMapper.java | 17 +
.../system/saas/mapper/Sys2TenantMapper.java | 16 +
.../saas/mapper/Sys2TenantPackageMapper.java | 16 +
.../system/saas/mapper/Sys2UserMapper.java | 93 ++
.../saas/mapper/Sys2UserPostMapper.java | 15 +
.../saas/mapper/Sys2UserRoleMapper.java | 19 +
.../system/saas/mapper/SysSaasMenuMapper.java | 78 ++
.../saas/runner/System2ApplicationRunner.java | 28 +
.../saas/service/ISys2ApplicationService.java | 68 ++
.../saas/service/ISys2ClientService.java | 59 ++
.../saas/service/ISys2ConfigService.java | 87 ++
.../saas/service/ISys2DataScopeService.java | 26 +
.../system/saas/service/ISys2DeptService.java | 125 +++
.../saas/service/ISys2DictDataService.java | 76 ++
.../saas/service/ISys2DictTypeService.java | 95 ++
.../saas/service/ISys2LogininforService.java | 47 +
.../saas/service/ISys2NoticeService.java | 67 ++
.../saas/service/ISys2OperLogService.java | 54 ++
.../saas/service/ISys2OssConfigService.java | 64 ++
.../system/saas/service/ISys2OssService.java | 80 ++
.../saas/service/ISys2PermissionService.java | 28 +
.../system/saas/service/ISys2PostService.java | 122 +++
.../system/saas/service/ISys2RoleService.java | 200 +++++
.../saas/service/ISys2SocialService.java | 53 ++
.../ISys2TenantApplicationService.java | 68 ++
.../service/ISys2TenantPackageService.java | 62 ++
.../saas/service/ISys2TenantService.java | 82 ++
.../system/saas/service/ISys2UserService.java | 222 +++++
.../saas/service/ISysSaasMenuService.java | 147 +++
.../impl/Sys2ApplicationServiceImpl.java | 130 +++
.../service/impl/Sys2ClientServiceImpl.java | 151 ++++
.../service/impl/Sys2ConfigServiceImpl.java | 219 +++++
.../impl/Sys2DataScopeServiceImpl.java | 76 ++
.../service/impl/Sys2DeptServiceImpl.java | 337 +++++++
.../service/impl/Sys2DictDataServiceImpl.java | 156 ++++
.../service/impl/Sys2DictTypeServiceImpl.java | 258 ++++++
.../impl/Sys2LogininforServiceImpl.java | 176 ++++
.../service/impl/Sys2NoticeServiceImpl.java | 124 +++
.../service/impl/Sys2OperLogServiceImpl.java | 146 +++
.../impl/Sys2OssConfigServiceImpl.java | 176 ++++
.../saas/service/impl/Sys2OssServiceImpl.java | 269 ++++++
.../impl/Sys2PermissionServiceImpl.java | 61 ++
.../service/impl/Sys2PostServiceImpl.java | 242 +++++
.../service/impl/Sys2RoleServiceImpl.java | 514 +++++++++++
.../impl/Sys2SensitiveServiceImpl.java | 47 +
.../service/impl/Sys2SocialServiceImpl.java | 112 +++
.../Sys2TenantApplicationServiceImpl.java | 127 +++
.../impl/Sys2TenantPackageServiceImpl.java | 157 ++++
.../service/impl/Sys2TenantServiceImpl.java | 372 ++++++++
.../service/impl/Sys2UserServiceImpl.java | 673 ++++++++++++++
.../service/impl/SysSaasMenuServiceImpl.java | 379 ++++++++
.../src/main/resources/mapper/package-info.md | 3 +
.../systemTenant/SysApplicationMapper.xml | 7 +
.../mapper/systemTenant/SysClientMapper.xml | 7 +
.../mapper/systemTenant/SysConfigMapper.xml | 7 +
.../mapper/systemTenant/SysDeptMapper.xml | 36 +
.../mapper/systemTenant/SysDictDataMapper.xml | 7 +
.../mapper/systemTenant/SysDictTypeMapper.xml | 7 +
.../systemTenant/SysLogininforMapper.xml | 7 +
.../mapper/systemTenant/SysNoticeMapper.xml | 7 +
.../mapper/systemTenant/SysOperLogMapper.xml | 7 +
.../systemTenant/SysOssConfigMapper.xml | 7 +
.../mapper/systemTenant/SysOssMapper.xml | 5 +
.../mapper/systemTenant/SysPostMapper.xml | 29 +
.../mapper/systemTenant/SysRoleDeptMapper.xml | 7 +
.../mapper/systemTenant/SysRoleMapper.xml | 59 ++
.../mapper/systemTenant/SysRoleMenuMapper.xml | 7 +
.../mapper/systemTenant/SysSaasMenuMapper.xml | 70 ++
.../mapper/systemTenant/SysSocialMapper.xml | 7 +
.../SysTenantApplicationMapper.xml | 7 +
.../mapper/systemTenant/SysTenantMapper.xml | 7 +
.../systemTenant/SysTenantPackageMapper.xml | 7 +
.../mapper/systemTenant/SysUserMapper.xml | 73 ++
.../mapper/systemTenant/SysUserPostMapper.xml | 7 +
.../mapper/systemTenant/SysUserRoleMapper.xml | 13 +
script/sql/ry_vue_5.X.sql | 10 +
script/sql/tenant/ry_vue_5.X.sql | 842 ++++++++++++++++++
200 files changed, 17456 insertions(+)
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDeptService.java
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDictService.java
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasOssService.java
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasUserService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/pom.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2LogininforController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2OperlogController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2UserOnlineController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ApplicationController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ClientController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ConfigController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DeptController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictDataController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictTypeController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2NoticeController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssConfigController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2PostController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ProfileController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2RoleController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2SocialController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantPackageController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2UserController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/SysSaasMenuController.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Application.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Cache.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Client.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Config.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Dept.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictData.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictType.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Logininfor.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Notice.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OperLog.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Oss.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OssConfig.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Post.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Role.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleDept.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleMenu.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Social.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Tenant.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantApplication.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantPackage.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2User.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserOnline.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserPost.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserRole.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/SysSaasMenu.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ApplicationBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ClientBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ConfigBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DeptBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictDataBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictTypeBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2LogininforBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2NoticeBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OperLogBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssConfigBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2PostBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2RoleBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2SocialBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantApplicationBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantPackageBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserPasswordBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserProfileBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/SysSaasMenuBo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ApplicationVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ClientVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ConfigVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DeptVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictDataVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictTypeVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2LogininforVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2NoticeVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OperLogVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssConfigVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssUploadVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2PostVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2RoleVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2SocialVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantApplicationVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantPackageVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserExportVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserImportVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserInfoVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/SysSaasMenuVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoAvatarVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoCacheListInfoVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoDeptTreeSelectVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoMenuTreeSelectVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoMetaVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoProfileVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoRouterVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoUserInfoVo.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/listener/SysUserImportListener.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2ApplicationMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2ClientMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2ConfigMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2DeptMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2DictDataMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2DictTypeMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2LogininforMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2NoticeMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2OperLogMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2OssConfigMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2OssMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2PostMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2RoleDeptMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2RoleMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2RoleMenuMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2SocialMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2TenantApplicationMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2TenantMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2TenantPackageMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2UserMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2UserPostMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/Sys2UserRoleMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/mapper/SysSaasMenuMapper.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/runner/System2ApplicationRunner.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2ApplicationService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2ClientService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2ConfigService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2DataScopeService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2DeptService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2DictDataService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2DictTypeService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2LogininforService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2NoticeService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2OperLogService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2OssConfigService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2OssService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2PermissionService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2PostService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2RoleService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2SocialService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2TenantApplicationService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2TenantPackageService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2TenantService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISys2UserService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/ISysSaasMenuService.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2ApplicationServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2ClientServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2ConfigServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2DataScopeServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2DeptServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2DictDataServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2DictTypeServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2LogininforServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2NoticeServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2OperLogServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2OssConfigServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2OssServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2PermissionServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2PostServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2RoleServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2SensitiveServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2SocialServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2TenantApplicationServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2TenantPackageServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2TenantServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/Sys2UserServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/service/impl/SysSaasMenuServiceImpl.java
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/package-info.md
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysApplicationMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysClientMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysConfigMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysDeptMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysDictDataMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysDictTypeMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysLogininforMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysNoticeMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysOperLogMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysOssConfigMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysOssMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysPostMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysRoleDeptMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysRoleMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysRoleMenuMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysSaasMenuMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysSocialMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysTenantApplicationMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysTenantMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysTenantPackageMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysUserMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysUserPostMapper.xml
create mode 100644 ruoyi-modules/ruoyi-system-saas/src/main/resources/mapper/systemTenant/SysUserRoleMapper.xml
create mode 100644 script/sql/tenant/ry_vue_5.X.sql
diff --git a/pom.xml b/pom.xml
index 5db785c8c..d7ee8d969 100644
--- a/pom.xml
+++ b/pom.xml
@@ -370,6 +370,12 @@
${revision}
+
+ org.dromara
+ ruoyi-system-saas
+ ${revision}
+
+
org.dromara
ruoyi-job
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index b7e3b30d9..7f9f4bd29 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -47,6 +47,11 @@
ruoyi-system
+
+ org.dromara
+ ruoyi-system-saas
+
+
org.dromara
ruoyi-job
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 16b245fb4..c72257f2e 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -125,6 +125,14 @@ tenant:
- sys_user_role
- sys_client
- sys_oss_config
+ - sys_saas_menu
+ - sys_saas_tenant
+ - sys_saas_tenant_package
+ - sys_saas_application
+ - sys_saas_role_dept
+ - sys_saas_role_menu
+ - sys_saas_user_post
+ - sys_saas_user_role
# MyBatisPlus配置
# https://baomidou.com/config/
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDeptService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDeptService.java
new file mode 100644
index 000000000..d06566cb3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDeptService.java
@@ -0,0 +1,18 @@
+package org.dromara.common.core.service;
+
+/**
+ * 通用 部门服务
+ *
+ * @author Lion Li
+ */
+public interface SaasDeptService {
+
+ /**
+ * 通过部门ID查询部门名称
+ *
+ * @param deptIds 部门ID串逗号分隔
+ * @return 部门名称串逗号分隔
+ */
+ String selectDeptNameByIds(String deptIds);
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDictService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDictService.java
new file mode 100644
index 000000000..1a724da6e
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasDictService.java
@@ -0,0 +1,67 @@
+package org.dromara.common.core.service;
+
+import java.util.Map;
+
+/**
+ * 通用 字典服务
+ *
+ * @author Lion Li
+ */
+public interface SaasDictService {
+
+ /**
+ * 分隔符
+ */
+ String SEPARATOR = ",";
+
+ /**
+ * 根据字典类型和字典值获取字典标签
+ *
+ * @param dictType 字典类型
+ * @param dictValue 字典值
+ * @return 字典标签
+ */
+ default String getDictLabel(String dictType, String dictValue) {
+ return getDictLabel(dictType, dictValue, SEPARATOR);
+ }
+
+ /**
+ * 根据字典类型和字典标签获取字典值
+ *
+ * @param dictType 字典类型
+ * @param dictLabel 字典标签
+ * @return 字典值
+ */
+ default String getDictValue(String dictType, String dictLabel) {
+ return getDictValue(dictType, dictLabel, SEPARATOR);
+ }
+
+ /**
+ * 根据字典类型和字典值获取字典标签
+ *
+ * @param dictType 字典类型
+ * @param dictValue 字典值
+ * @param separator 分隔符
+ * @return 字典标签
+ */
+ String getDictLabel(String dictType, String dictValue, String separator);
+
+ /**
+ * 根据字典类型和字典标签获取字典值
+ *
+ * @param dictType 字典类型
+ * @param dictLabel 字典标签
+ * @param separator 分隔符
+ * @return 字典值
+ */
+ String getDictValue(String dictType, String dictLabel, String separator);
+
+ /**
+ * 获取字典下所有的字典值与标签
+ *
+ * @param dictType 字典类型
+ * @return dictValue为key,dictLabel为值组成的Map
+ */
+ Map getAllDictByDictType(String dictType);
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasOssService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasOssService.java
new file mode 100644
index 000000000..4aa33f8bb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasOssService.java
@@ -0,0 +1,29 @@
+package org.dromara.common.core.service;
+
+import org.dromara.common.core.domain.dto.OssDTO;
+
+import java.util.List;
+
+/**
+ * 通用 OSS服务
+ *
+ * @author Lion Li
+ */
+public interface SaasOssService {
+
+ /**
+ * 通过ossId查询对应的url
+ *
+ * @param ossIds ossId串逗号分隔
+ * @return url串逗号分隔
+ */
+ String selectUrlByIds(String ossIds);
+
+ /**
+ * 通过ossId查询列表
+ *
+ * @param ossIds ossId串逗号分隔
+ * @return 列表
+ */
+ List selectByIds(String ossIds);
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasUserService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasUserService.java
new file mode 100644
index 000000000..1a3256c4c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SaasUserService.java
@@ -0,0 +1,85 @@
+package org.dromara.common.core.service;
+
+import org.dromara.common.core.domain.dto.UserDTO;
+
+import java.util.List;
+
+/**
+ * 通用 用户服务
+ *
+ * @author Lion Li
+ */
+public interface SaasUserService {
+
+ /**
+ * 通过用户ID查询用户账户
+ *
+ * @param userId 用户ID
+ * @return 用户账户
+ */
+ String selectUserNameById(Long userId);
+
+ /**
+ * 通过用户ID查询用户账户
+ *
+ * @param userId 用户ID
+ * @return 用户名称
+ */
+ String selectNicknameById(Long userId);
+
+ /**
+ * 通过用户ID查询用户账户
+ *
+ * @param userIds 用户ID 多个用逗号隔开
+ * @return 用户名称
+ */
+ String selectNicknameByIds(String userIds);
+
+ /**
+ * 通过用户ID查询用户手机号
+ *
+ * @param userId 用户id
+ * @return 用户手机号
+ */
+ String selectPhonenumberById(Long userId);
+
+ /**
+ * 通过用户ID查询用户邮箱
+ *
+ * @param userId 用户id
+ * @return 用户邮箱
+ */
+ String selectEmailById(Long userId);
+
+ /**
+ * 通过用户ID查询用户列表
+ *
+ * @param userIds 用户ids
+ * @return 用户列表
+ */
+ List selectListByIds(List userIds);
+
+ /**
+ * 通过角色ID查询用户ID
+ *
+ * @param roleIds 角色ids
+ * @return 用户ids
+ */
+ List selectUserIdsByRoleIds(List roleIds);
+
+ /**
+ * 通过角色ID查询用户
+ *
+ * @param roleIds 角色ids
+ * @return 用户
+ */
+ List selectUsersByRoleIds(List roleIds);
+
+ /**
+ * 通过部门ID查询用户
+ *
+ * @param deptIds 部门ids
+ * @return 用户
+ */
+ List selectUsersByDeptIds(List deptIds);
+}
diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml
index daff497a0..012c71e44 100644
--- a/ruoyi-modules/pom.xml
+++ b/ruoyi-modules/pom.xml
@@ -14,6 +14,7 @@
ruoyi-generator
ruoyi-job
ruoyi-system
+ ruoyi-system-saas
ruoyi-workflow
diff --git a/ruoyi-modules/ruoyi-system-saas/pom.xml b/ruoyi-modules/ruoyi-system-saas/pom.xml
new file mode 100644
index 000000000..f46d7794a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/pom.xml
@@ -0,0 +1,128 @@
+
+
+
+ org.dromara
+ ruoyi-modules
+ ${revision}
+
+ 4.0.0
+
+ ruoyi-system-saas
+
+
+ system-tenant 系统模块
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bootstrap
+
+
+
+
+
+ org.dromara
+ ruoyi-common-core
+
+
+
+ org.dromara
+ ruoyi-common-doc
+
+
+
+ org.dromara
+ ruoyi-common-mybatis
+
+
+
+ org.dromara
+ ruoyi-common-translation
+
+
+
+
+ org.dromara
+ ruoyi-common-oss
+
+
+
+ org.dromara
+ ruoyi-common-log
+
+
+
+
+ org.dromara
+ ruoyi-common-excel
+
+
+
+
+ org.dromara
+ ruoyi-common-sms
+
+
+
+ org.dromara
+ ruoyi-common-tenant
+
+
+
+ org.dromara
+ ruoyi-common-security
+
+
+
+ org.dromara
+ ruoyi-common-web
+
+
+
+ org.dromara
+ ruoyi-common-idempotent
+
+
+
+ org.dromara
+ ruoyi-common-sensitive
+
+
+
+ org.dromara
+ ruoyi-common-encrypt
+
+
+
+ org.dromara
+ ruoyi-common-websocket
+
+
+
+ org.dromara
+ ruoyi-common-sse
+
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2LogininforController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2LogininforController.java
new file mode 100644
index 000000000..4e53d365e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2LogininforController.java
@@ -0,0 +1,89 @@
+package org.dromara.system.saas.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.CacheConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2LogininforBo;
+import org.dromara.system.saas.domain.vo.Sys2LogininforVo;
+import org.dromara.system.saas.service.ISys2LogininforService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 系统访问记录
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor2/logininfor")
+public class Sys2LogininforController extends BaseController {
+
+ private final ISys2LogininforService logininforService;
+
+ /**
+ * 获取系统访问记录列表
+ */
+ @SaCheckPermission("monitor:logininfor:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2LogininforBo logininfor, PageQuery pageQuery) {
+ return logininforService.selectPageLogininforList(logininfor, pageQuery);
+ }
+
+ /**
+ * 导出系统访问记录列表
+ */
+ @Log(title = "登录日志", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("monitor:logininfor:export")
+ @PostMapping("/export")
+ public void export(Sys2LogininforBo logininfor, HttpServletResponse response) {
+ List list = logininforService.selectLogininforList(logininfor);
+ ExcelUtil.exportExcel(list, "登录日志", Sys2LogininforVo.class, response);
+ }
+
+ /**
+ * 批量删除登录日志
+ * @param infoIds 日志ids
+ */
+ @SaCheckPermission("monitor:logininfor:remove")
+ @Log(title = "登录日志", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{infoIds}")
+ public R remove(@PathVariable Long[] infoIds) {
+ return toAjax(logininforService.deleteLogininforByIds(infoIds));
+ }
+
+ /**
+ * 清理系统访问记录
+ */
+ @SaCheckPermission("monitor:logininfor:remove")
+ @Log(title = "登录日志", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public R clean() {
+ logininforService.cleanLogininfor();
+ return R.ok();
+ }
+
+ @SaCheckPermission("monitor:logininfor:unlock")
+ @Log(title = "账户解锁", businessType = BusinessType.OTHER)
+ @GetMapping("/unlock/{userName}")
+ public R unlock(@PathVariable("userName") String userName) {
+ String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName;
+ if (RedisUtils.hasKey(loginName)) {
+ RedisUtils.deleteObject(loginName);
+ }
+ return R.ok();
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2OperlogController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2OperlogController.java
new file mode 100644
index 000000000..5cb346e37
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2OperlogController.java
@@ -0,0 +1,75 @@
+package org.dromara.system.saas.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.system.saas.domain.bo.Sys2OperLogBo;
+import org.dromara.system.saas.domain.vo.Sys2OperLogVo;
+import org.dromara.system.saas.service.ISys2OperLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 操作日志记录
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor2/operlog")
+public class Sys2OperlogController extends BaseController {
+
+ private final ISys2OperLogService operLogService;
+
+ /**
+ * 获取操作日志记录列表
+ */
+ @SaCheckPermission("monitor:operlog:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2OperLogBo operLog, PageQuery pageQuery) {
+ return operLogService.selectPageOperLogList(operLog, pageQuery);
+ }
+
+ /**
+ * 导出操作日志记录列表
+ */
+ @Log(title = "操作日志", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("monitor:operlog:export")
+ @PostMapping("/export")
+ public void export(Sys2OperLogBo operLog, HttpServletResponse response) {
+ List list = operLogService.selectOperLogList(operLog);
+ ExcelUtil.exportExcel(list, "操作日志", Sys2OperLogVo.class, response);
+ }
+
+ /**
+ * 批量删除操作日志记录
+ * @param operIds 日志ids
+ */
+ @Log(title = "操作日志", businessType = BusinessType.DELETE)
+ @SaCheckPermission("monitor:operlog:remove")
+ @DeleteMapping("/{operIds}")
+ public R remove(@PathVariable Long[] operIds) {
+ return toAjax(operLogService.deleteOperLogByIds(operIds));
+ }
+
+ /**
+ * 清理操作日志记录
+ */
+ @Log(title = "操作日志", businessType = BusinessType.CLEAN)
+ @SaCheckPermission("monitor:operlog:remove")
+ @DeleteMapping("/clean")
+ public R clean() {
+ operLogService.cleanOperLog();
+ return R.ok();
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2UserOnlineController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2UserOnlineController.java
new file mode 100644
index 000000000..2e1e65920
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/monitor/Sys2UserOnlineController.java
@@ -0,0 +1,130 @@
+package org.dromara.system.saas.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.CacheConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.domain.dto.UserOnlineDTO;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.Sys2UserOnline;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 在线用户监控
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor2/online")
+public class Sys2UserOnlineController extends BaseController {
+
+ /**
+ * 获取在线用户监控列表
+ *
+ * @param ipaddr IP地址
+ * @param userName 用户名
+ */
+ @SaCheckPermission("monitor:online:list")
+ @GetMapping("/list")
+ public TableDataInfo list(String ipaddr, String userName) {
+ // 获取所有未过期的 token
+ List keys = StpUtil.searchTokenValue("", 0, -1, false);
+ List userOnlineDTOList = new ArrayList<>();
+ for (String key : keys) {
+ String token = StringUtils.substringAfterLast(key, ":");
+ // 如果已经过期则跳过
+ if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
+ continue;
+ }
+ userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token));
+ }
+ if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
+ userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+ StringUtils.equals(ipaddr, userOnline.getIpaddr()) &&
+ StringUtils.equals(userName, userOnline.getUserName())
+ );
+ } else if (StringUtils.isNotEmpty(ipaddr)) {
+ userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+ StringUtils.equals(ipaddr, userOnline.getIpaddr())
+ );
+ } else if (StringUtils.isNotEmpty(userName)) {
+ userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+ StringUtils.equals(userName, userOnline.getUserName())
+ );
+ }
+ Collections.reverse(userOnlineDTOList);
+ userOnlineDTOList.removeAll(Collections.singleton(null));
+ List userOnlineList = BeanUtil.copyToList(userOnlineDTOList, Sys2UserOnline.class);
+ return TableDataInfo.build(userOnlineList);
+ }
+
+ /**
+ * 强退用户
+ *
+ * @param tokenId token值
+ */
+ @SaCheckPermission("monitor:online:forceLogout")
+ @Log(title = "在线用户", businessType = BusinessType.FORCE)
+ @DeleteMapping("/{tokenId}")
+ public R forceLogout(@PathVariable String tokenId) {
+ try {
+ StpUtil.kickoutByTokenValue(tokenId);
+ } catch (NotLoginException ignored) {
+ }
+ return R.ok();
+ }
+
+ /**
+ * 获取当前用户登录在线设备
+ */
+ @GetMapping()
+ public TableDataInfo getInfo() {
+ // 获取指定账号 id 的 token 集合
+ List tokenIds = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString());
+ List userOnlineDTOList = tokenIds.stream()
+ .filter(token -> StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) >= -1)
+ .map(token -> (UserOnlineDTO) RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token))
+ .collect(Collectors.toList());
+ //复制和处理 Sys2UserOnline 对象列表
+ Collections.reverse(userOnlineDTOList);
+ userOnlineDTOList.removeAll(Collections.singleton(null));
+ List userOnlineList = BeanUtil.copyToList(userOnlineDTOList, Sys2UserOnline.class);
+ return TableDataInfo.build(userOnlineList);
+ }
+
+ /**
+ * 强退当前在线设备
+ *
+ * @param tokenId token值
+ */
+ @Log(title = "在线设备", businessType = BusinessType.FORCE)
+ @PostMapping("/{tokenId}")
+ public R remove(@PathVariable("tokenId") String tokenId) {
+ try {
+ // 获取指定账号 id 的 token 集合
+ List keys = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString());
+ keys.stream()
+ .filter(key -> key.equals(tokenId))
+ .findFirst()
+ .ifPresent(key -> StpUtil.kickoutByTokenValue(tokenId));
+ } catch (NotLoginException ignored) {
+ }
+ return R.ok();
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ApplicationController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ApplicationController.java
new file mode 100644
index 000000000..a9136beee
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ApplicationController.java
@@ -0,0 +1,105 @@
+package org.dromara.system.saas.controller.system;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.system.saas.domain.vo.Sys2ApplicationVo;
+import org.dromara.system.saas.domain.bo.Sys2ApplicationBo;
+import org.dromara.system.saas.service.ISys2ApplicationService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 应用
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/application")
+public class Sys2ApplicationController extends BaseController {
+
+ private final ISys2ApplicationService sysApplicationService;
+
+ /**
+ * 查询应用列表
+ */
+ @SaCheckPermission("system:application:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2ApplicationBo bo, PageQuery pageQuery) {
+ return sysApplicationService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出应用列表
+ */
+ @SaCheckPermission("system:application:export")
+ @Log(title = "应用", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(Sys2ApplicationBo bo, HttpServletResponse response) {
+ List list = sysApplicationService.queryList(bo);
+ ExcelUtil.exportExcel(list, "应用", Sys2ApplicationVo.class, response);
+ }
+
+ /**
+ * 获取应用详细信息
+ *
+ * @param applicationId 主键
+ */
+ @SaCheckPermission("system:application:query")
+ @GetMapping("/{applicationId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long applicationId) {
+ return R.ok(sysApplicationService.queryById(applicationId));
+ }
+
+ /**
+ * 新增应用
+ */
+ @SaCheckPermission("system:application:add")
+ @Log(title = "应用", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody Sys2ApplicationBo bo) {
+ return toAjax(sysApplicationService.insertByBo(bo));
+ }
+
+ /**
+ * 修改应用
+ */
+ @SaCheckPermission("system:application:edit")
+ @Log(title = "应用", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody Sys2ApplicationBo bo) {
+ return toAjax(sysApplicationService.updateByBo(bo));
+ }
+
+ /**
+ * 删除应用
+ *
+ * @param applicationIds 主键串
+ */
+ @SaCheckPermission("system:application:remove")
+ @Log(title = "应用", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{applicationIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] applicationIds) {
+ return toAjax(sysApplicationService.deleteWithValidByIds(List.of(applicationIds), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ClientController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ClientController.java
new file mode 100644
index 000000000..cc458a6c3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ClientController.java
@@ -0,0 +1,115 @@
+package org.dromara.system.saas.controller.system;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.system.saas.domain.bo.Sys2ClientBo;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.system.saas.domain.vo.Sys2ClientVo;
+import org.dromara.system.saas.service.ISys2ClientService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户端管理
+ *
+ * @author Michelle.Chung
+ * @date 2023-06-18
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/client")
+public class Sys2ClientController extends BaseController {
+
+ private final ISys2ClientService sysClientService;
+
+ /**
+ * 查询客户端管理列表
+ */
+ @SaCheckPermission("system:client:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2ClientBo bo, PageQuery pageQuery) {
+ return sysClientService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出客户端管理列表
+ */
+ @SaCheckPermission("system:client:export")
+ @Log(title = "客户端管理", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(Sys2ClientBo bo, HttpServletResponse response) {
+ List list = sysClientService.queryList(bo);
+ ExcelUtil.exportExcel(list, "客户端管理", Sys2ClientVo.class, response);
+ }
+
+ /**
+ * 获取客户端管理详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("system:client:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(sysClientService.queryById(id));
+ }
+
+ /**
+ * 新增客户端管理
+ */
+ @SaCheckPermission("system:client:add")
+ @Log(title = "客户端管理", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody Sys2ClientBo bo) {
+ return toAjax(sysClientService.insertByBo(bo));
+ }
+
+ /**
+ * 修改客户端管理
+ */
+ @SaCheckPermission("system:client:edit")
+ @Log(title = "客户端管理", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody Sys2ClientBo bo) {
+ return toAjax(sysClientService.updateByBo(bo));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckPermission("system:client:edit")
+ @Log(title = "客户端管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2ClientBo bo) {
+ return toAjax(sysClientService.updateUserStatus(bo.getClientId(), bo.getStatus()));
+ }
+
+ /**
+ * 删除客户端管理
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("system:client:remove")
+ @Log(title = "客户端管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(sysClientService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ConfigController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ConfigController.java
new file mode 100644
index 000000000..c7f4a2895
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ConfigController.java
@@ -0,0 +1,137 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2ConfigBo;
+import org.dromara.system.saas.domain.vo.Sys2ConfigVo;
+import org.dromara.system.saas.service.ISys2ConfigService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 参数配置 信息操作处理
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/config")
+public class Sys2ConfigController extends BaseController {
+
+ private final ISys2ConfigService configService;
+
+ /**
+ * 获取参数配置列表
+ */
+ @SaCheckPermission("system:config:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2ConfigBo config, PageQuery pageQuery) {
+ return configService.selectPageConfigList(config, pageQuery);
+ }
+
+ /**
+ * 导出参数配置列表
+ */
+ @Log(title = "参数管理", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:config:export")
+ @PostMapping("/export")
+ public void export(Sys2ConfigBo config, HttpServletResponse response) {
+ List list = configService.selectConfigList(config);
+ ExcelUtil.exportExcel(list, "参数数据", Sys2ConfigVo.class, response);
+ }
+
+ /**
+ * 根据参数编号获取详细信息
+ *
+ * @param configId 参数ID
+ */
+ @SaCheckPermission("system:config:query")
+ @GetMapping(value = "/{configId}")
+ public R getInfo(@PathVariable Long configId) {
+ return R.ok(configService.selectConfigById(configId));
+ }
+
+ /**
+ * 根据参数键名查询参数值
+ *
+ * @param configKey 参数Key
+ */
+ @GetMapping(value = "/configKey/{configKey}")
+ public R getConfigKey(@PathVariable String configKey) {
+ return R.ok("操作成功", configService.selectConfigByKey(configKey));
+ }
+
+ /**
+ * 新增参数配置
+ */
+ @SaCheckPermission("system:config:add")
+ @Log(title = "参数管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2ConfigBo config) {
+ if (!configService.checkConfigKeyUnique(config)) {
+ return R.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
+ }
+ configService.insertConfig(config);
+ return R.ok();
+ }
+
+ /**
+ * 修改参数配置
+ */
+ @SaCheckPermission("system:config:edit")
+ @Log(title = "参数管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2ConfigBo config) {
+ if (!configService.checkConfigKeyUnique(config)) {
+ return R.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
+ }
+ configService.updateConfig(config);
+ return R.ok();
+ }
+
+ /**
+ * 根据参数键名修改参数配置
+ */
+ @SaCheckPermission("system:config:edit")
+ @Log(title = "参数管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/updateByKey")
+ public R updateByKey(@RequestBody Sys2ConfigBo config) {
+ configService.updateConfig(config);
+ return R.ok();
+ }
+
+ /**
+ * 删除参数配置
+ *
+ * @param configIds 参数ID串
+ */
+ @SaCheckPermission("system:config:remove")
+ @Log(title = "参数管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{configIds}")
+ public R remove(@PathVariable Long[] configIds) {
+ configService.deleteConfigByIds(configIds);
+ return R.ok();
+ }
+
+ /**
+ * 刷新参数缓存
+ */
+ @SaCheckPermission("system:config:remove")
+ @Log(title = "参数管理", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public R refreshCache() {
+ configService.resetConfigCache();
+ return R.ok();
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DeptController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DeptController.java
new file mode 100644
index 000000000..acc314456
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DeptController.java
@@ -0,0 +1,140 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.convert.Convert;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2DeptBo;
+import org.dromara.system.saas.domain.vo.Sys2DeptVo;
+import org.dromara.system.saas.service.ISys2DeptService;
+import org.dromara.system.saas.service.ISys2PostService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 部门信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/dept")
+public class Sys2DeptController extends BaseController {
+
+ private final ISys2DeptService deptService;
+ private final ISys2PostService postService;
+
+ /**
+ * 获取部门列表
+ */
+ @SaCheckPermission("system:dept:list")
+ @GetMapping("/list")
+ public R> list(Sys2DeptBo dept) {
+ List depts = deptService.selectDeptList(dept);
+ return R.ok(depts);
+ }
+
+ /**
+ * 查询部门列表(排除节点)
+ *
+ * @param deptId 部门ID
+ */
+ @SaCheckPermission("system:dept:list")
+ @GetMapping("/list/exclude/{deptId}")
+ public R> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
+ List depts = deptService.selectDeptList(new Sys2DeptBo());
+ depts.removeIf(d -> d.getDeptId().equals(deptId)
+ || StringUtils.splitList(d.getAncestors()).contains(Convert.toStr(deptId)));
+ return R.ok(depts);
+ }
+
+ /**
+ * 根据部门编号获取详细信息
+ *
+ * @param deptId 部门ID
+ */
+ @SaCheckPermission("system:dept:query")
+ @GetMapping(value = "/{deptId}")
+ public R getInfo(@PathVariable Long deptId) {
+ deptService.checkDeptDataScope(deptId);
+ return R.ok(deptService.selectDeptById(deptId));
+ }
+
+ /**
+ * 新增部门
+ */
+ @SaCheckPermission("system:dept:add")
+ @Log(title = "部门管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2DeptBo dept) {
+ if (!deptService.checkDeptNameUnique(dept)) {
+ return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
+ }
+ return toAjax(deptService.insertDept(dept));
+ }
+
+ /**
+ * 修改部门
+ */
+ @SaCheckPermission("system:dept:edit")
+ @Log(title = "部门管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2DeptBo dept) {
+ Long deptId = dept.getDeptId();
+ deptService.checkDeptDataScope(deptId);
+ if (!deptService.checkDeptNameUnique(dept)) {
+ return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
+ } else if (dept.getParentId().equals(deptId)) {
+ return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
+ } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())) {
+ if (deptService.selectNormalChildrenDeptById(deptId) > 0) {
+ return R.fail("该部门包含未停用的子部门!");
+ } else if (deptService.checkDeptExistUser(deptId)) {
+ return R.fail("该部门下存在已分配用户,不能禁用!");
+ }
+ }
+ return toAjax(deptService.updateDept(dept));
+ }
+
+ /**
+ * 删除部门
+ *
+ * @param deptId 部门ID
+ */
+ @SaCheckPermission("system:dept:remove")
+ @Log(title = "部门管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{deptId}")
+ public R remove(@PathVariable Long deptId) {
+ if (deptService.hasChildByDeptId(deptId)) {
+ return R.warn("存在下级部门,不允许删除");
+ }
+ if (deptService.checkDeptExistUser(deptId)) {
+ return R.warn("部门存在用户,不允许删除");
+ }
+ if (postService.countPostByDeptId(deptId) > 0) {
+ return R.warn("部门存在岗位,不允许删除");
+ }
+ deptService.checkDeptDataScope(deptId);
+ return toAjax(deptService.deleteDeptById(deptId));
+ }
+
+ /**
+ * 获取部门选择框列表
+ *
+ * @param deptIds 部门ID串
+ */
+ @SaCheckPermission("system:dept:query")
+ @GetMapping("/optionselect")
+ public R> optionselect(@RequestParam(required = false) Long[] deptIds) {
+ return R.ok(deptService.selectDeptByIds(deptIds == null ? null : List.of(deptIds)));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictDataController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictDataController.java
new file mode 100644
index 000000000..05c6e2a28
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictDataController.java
@@ -0,0 +1,123 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ObjectUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.system.saas.domain.bo.Sys2DictDataBo;
+import org.dromara.system.saas.domain.vo.Sys2DictDataVo;
+import org.dromara.system.saas.service.ISys2DictDataService;
+import org.dromara.system.saas.service.ISys2DictTypeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 数据字典信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/dict/data")
+public class Sys2DictDataController extends BaseController {
+
+ private final ISys2DictDataService dictDataService;
+ private final ISys2DictTypeService dictTypeService;
+
+ /**
+ * 查询字典数据列表
+ */
+ @SaCheckPermission("system:dict:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2DictDataBo dictData, PageQuery pageQuery) {
+ return dictDataService.selectPageDictDataList(dictData, pageQuery);
+ }
+
+ /**
+ * 导出字典数据列表
+ */
+ @Log(title = "字典数据", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:dict:export")
+ @PostMapping("/export")
+ public void export(Sys2DictDataBo dictData, HttpServletResponse response) {
+ List list = dictDataService.selectDictDataList(dictData);
+ ExcelUtil.exportExcel(list, "字典数据", Sys2DictDataVo.class, response);
+ }
+
+ /**
+ * 查询字典数据详细
+ *
+ * @param dictCode 字典code
+ */
+ @SaCheckPermission("system:dict:query")
+ @GetMapping(value = "/{dictCode}")
+ public R getInfo(@PathVariable Long dictCode) {
+ return R.ok(dictDataService.selectDictDataById(dictCode));
+ }
+
+ /**
+ * 根据字典类型查询字典数据信息
+ *
+ * @param dictType 字典类型
+ */
+ @GetMapping(value = "/type/{dictType}")
+ public R> dictType(@PathVariable String dictType) {
+ List data = dictTypeService.selectDictDataByType(dictType);
+ if (ObjectUtil.isNull(data)) {
+ data = new ArrayList<>();
+ }
+ return R.ok(data);
+ }
+
+ /**
+ * 新增字典类型
+ */
+ @SaCheckPermission("system:dict:add")
+ @Log(title = "字典数据", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2DictDataBo dict) {
+ if (!dictDataService.checkDictDataUnique(dict)) {
+ return R.fail("新增字典数据'" + dict.getDictValue() + "'失败,字典键值已存在");
+ }
+ dictDataService.insertDictData(dict);
+ return R.ok();
+ }
+
+ /**
+ * 修改保存字典类型
+ */
+ @SaCheckPermission("system:dict:edit")
+ @Log(title = "字典数据", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2DictDataBo dict) {
+ if (!dictDataService.checkDictDataUnique(dict)) {
+ return R.fail("修改字典数据'" + dict.getDictValue() + "'失败,字典键值已存在");
+ }
+ dictDataService.updateDictData(dict);
+ return R.ok();
+ }
+
+ /**
+ * 删除字典类型
+ *
+ * @param dictCodes 字典code串
+ */
+ @SaCheckPermission("system:dict:remove")
+ @Log(title = "字典类型", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictCodes}")
+ public R remove(@PathVariable Long[] dictCodes) {
+ dictDataService.deleteDictDataByIds(dictCodes);
+ return R.ok();
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictTypeController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictTypeController.java
new file mode 100644
index 000000000..c620c8469
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2DictTypeController.java
@@ -0,0 +1,125 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2DictTypeBo;
+import org.dromara.system.saas.domain.vo.Sys2DictTypeVo;
+import org.dromara.system.saas.service.ISys2DictTypeService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 数据字典信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/dict/type")
+public class Sys2DictTypeController extends BaseController {
+
+ private final ISys2DictTypeService dictTypeService;
+
+ /**
+ * 查询字典类型列表
+ */
+ @SaCheckPermission("system:dict:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2DictTypeBo dictType, PageQuery pageQuery) {
+ return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
+ }
+
+ /**
+ * 导出字典类型列表
+ */
+ @Log(title = "字典类型", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:dict:export")
+ @PostMapping("/export")
+ public void export(Sys2DictTypeBo dictType, HttpServletResponse response) {
+ List list = dictTypeService.selectDictTypeList(dictType);
+ ExcelUtil.exportExcel(list, "字典类型", Sys2DictTypeVo.class, response);
+ }
+
+ /**
+ * 查询字典类型详细
+ *
+ * @param dictId 字典ID
+ */
+ @SaCheckPermission("system:dict:query")
+ @GetMapping(value = "/{dictId}")
+ public R getInfo(@PathVariable Long dictId) {
+ return R.ok(dictTypeService.selectDictTypeById(dictId));
+ }
+
+ /**
+ * 新增字典类型
+ */
+ @SaCheckPermission("system:dict:add")
+ @Log(title = "字典类型", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2DictTypeBo dict) {
+ if (!dictTypeService.checkDictTypeUnique(dict)) {
+ return R.fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
+ }
+ dictTypeService.insertDictType(dict);
+ return R.ok();
+ }
+
+ /**
+ * 修改字典类型
+ */
+ @SaCheckPermission("system:dict:edit")
+ @Log(title = "字典类型", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2DictTypeBo dict) {
+ if (!dictTypeService.checkDictTypeUnique(dict)) {
+ return R.fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
+ }
+ dictTypeService.updateDictType(dict);
+ return R.ok();
+ }
+
+ /**
+ * 删除字典类型
+ *
+ * @param dictIds 字典ID串
+ */
+ @SaCheckPermission("system:dict:remove")
+ @Log(title = "字典类型", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictIds}")
+ public R remove(@PathVariable Long[] dictIds) {
+ dictTypeService.deleteDictTypeByIds(dictIds);
+ return R.ok();
+ }
+
+ /**
+ * 刷新字典缓存
+ */
+ @SaCheckPermission("system:dict:remove")
+ @Log(title = "字典类型", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public R refreshCache() {
+ dictTypeService.resetDictCache();
+ return R.ok();
+ }
+
+ /**
+ * 获取字典选择框列表
+ */
+ @GetMapping("/optionselect")
+ public R> optionselect() {
+ List dictTypes = dictTypeService.selectDictTypeAll();
+ return R.ok(dictTypes);
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2NoticeController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2NoticeController.java
new file mode 100644
index 000000000..7f347ab5d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2NoticeController.java
@@ -0,0 +1,90 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.service.SaasDictService;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.sse.utils.SseMessageUtils;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2NoticeBo;
+import org.dromara.system.saas.domain.vo.Sys2NoticeVo;
+import org.dromara.system.saas.service.ISys2NoticeService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 公告 信息操作处理
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/notice")
+public class Sys2NoticeController extends BaseController {
+
+ private final ISys2NoticeService noticeService;
+ private final SaasDictService dictService;
+
+ /**
+ * 获取通知公告列表
+ */
+ @SaCheckPermission("system:notice:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2NoticeBo notice, PageQuery pageQuery) {
+ return noticeService.selectPageNoticeList(notice, pageQuery);
+ }
+
+ /**
+ * 根据通知公告编号获取详细信息
+ *
+ * @param noticeId 公告ID
+ */
+ @SaCheckPermission("system:notice:query")
+ @GetMapping(value = "/{noticeId}")
+ public R getInfo(@PathVariable Long noticeId) {
+ return R.ok(noticeService.selectNoticeById(noticeId));
+ }
+
+ /**
+ * 新增通知公告
+ */
+ @SaCheckPermission("system:notice:add")
+ @Log(title = "通知公告", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2NoticeBo notice) {
+ int rows = noticeService.insertNotice(notice);
+ if (rows <= 0) {
+ return R.fail();
+ }
+ String type = dictService.getDictLabel("sys2_notice_type", notice.getNoticeType());
+ SseMessageUtils.publishAll("[" + type + "] " + notice.getNoticeTitle());
+ return R.ok();
+ }
+
+ /**
+ * 修改通知公告
+ */
+ @SaCheckPermission("system:notice:edit")
+ @Log(title = "通知公告", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2NoticeBo notice) {
+ return toAjax(noticeService.updateNotice(notice));
+ }
+
+ /**
+ * 删除通知公告
+ *
+ * @param noticeIds 公告ID串
+ */
+ @SaCheckPermission("system:notice:remove")
+ @Log(title = "通知公告", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{noticeIds}")
+ public R remove(@PathVariable Long[] noticeIds) {
+ return toAjax(noticeService.deleteNoticeByIds(noticeIds));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssConfigController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssConfigController.java
new file mode 100644
index 000000000..bba31e630
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssConfigController.java
@@ -0,0 +1,105 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.core.validate.QueryGroup;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.system.saas.domain.bo.Sys2OssConfigBo;
+import org.dromara.system.saas.domain.vo.Sys2OssConfigVo;
+import org.dromara.system.saas.service.ISys2OssConfigService;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 对象存储配置
+ *
+ * @author Lion Li
+ * @author 孤舟烟雨
+ * @date 2021-08-13
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/resource2/oss/config")
+public class Sys2OssConfigController extends BaseController {
+
+ private final ISys2OssConfigService ossConfigService;
+
+ /**
+ * 查询对象存储配置列表
+ */
+ @SaCheckPermission("system:ossConfig:list")
+ @GetMapping("/list")
+ public TableDataInfo list(@Validated(QueryGroup.class) Sys2OssConfigBo bo, PageQuery pageQuery) {
+ return ossConfigService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 获取对象存储配置详细信息
+ *
+ * @param ossConfigId OSS配置ID
+ */
+ @SaCheckPermission("system:ossConfig:list")
+ @GetMapping("/{ossConfigId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long ossConfigId) {
+ return R.ok(ossConfigService.queryById(ossConfigId));
+ }
+
+ /**
+ * 新增对象存储配置
+ */
+ @SaCheckPermission("system:ossConfig:add")
+ @Log(title = "对象存储配置", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody Sys2OssConfigBo bo) {
+ return toAjax(ossConfigService.insertByBo(bo));
+ }
+
+ /**
+ * 修改对象存储配置
+ */
+ @SaCheckPermission("system:ossConfig:edit")
+ @Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody Sys2OssConfigBo bo) {
+ return toAjax(ossConfigService.updateByBo(bo));
+ }
+
+ /**
+ * 删除对象存储配置
+ *
+ * @param ossConfigIds OSS配置ID串
+ */
+ @SaCheckPermission("system:ossConfig:remove")
+ @Log(title = "对象存储配置", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ossConfigIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ossConfigIds) {
+ return toAjax(ossConfigService.deleteWithValidByIds(List.of(ossConfigIds), true));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckPermission("system:ossConfig:edit")
+ @Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2OssConfigBo bo) {
+ return toAjax(ossConfigService.updateOssConfigStatus(bo));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssController.java
new file mode 100644
index 000000000..d46055ea5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2OssController.java
@@ -0,0 +1,108 @@
+package org.dromara.system.saas.controller.system;
+
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ObjectUtil;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.QueryGroup;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.system.saas.domain.bo.Sys2OssBo;
+import org.dromara.system.saas.domain.vo.Sys2OssUploadVo;
+import org.dromara.system.saas.domain.vo.Sys2OssVo;
+import org.dromara.system.saas.service.ISys2OssService;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 文件上传 控制层
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/resource2/oss")
+public class Sys2OssController extends BaseController {
+
+ private final ISys2OssService ossService;
+
+ /**
+ * 查询OSS对象存储列表
+ */
+ @SaCheckPermission("system:oss:list")
+ @GetMapping("/list")
+ public TableDataInfo list(@Validated(QueryGroup.class) Sys2OssBo bo, PageQuery pageQuery) {
+ return ossService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 查询OSS对象基于id串
+ *
+ * @param ossIds OSS对象ID串
+ */
+ @SaCheckPermission("system:oss:list")
+ @GetMapping("/listByIds/{ossIds}")
+ public R> listByIds(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ossIds) {
+ List list = ossService.listByIds(Arrays.asList(ossIds));
+ return R.ok(list);
+ }
+
+ /**
+ * 上传OSS对象存储
+ *
+ * @param file 文件
+ */
+ @SaCheckPermission("system:oss:upload")
+ @Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
+ @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public R upload(@RequestPart("file") MultipartFile file) {
+ if (ObjectUtil.isNull(file)) {
+ return R.fail("上传文件不能为空");
+ }
+ Sys2OssVo oss = ossService.upload(file);
+ Sys2OssUploadVo uploadVo = new Sys2OssUploadVo();
+ uploadVo.setUrl(oss.getUrl());
+ uploadVo.setFileName(oss.getOriginalName());
+ uploadVo.setOssId(oss.getOssId().toString());
+ return R.ok(uploadVo);
+ }
+
+ /**
+ * 下载OSS对象
+ *
+ * @param ossId OSS对象ID
+ */
+ @SaCheckPermission("system:oss:download")
+ @GetMapping("/download/{ossId}")
+ public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
+ ossService.download(ossId, response);
+ }
+
+ /**
+ * 删除OSS对象存储
+ *
+ * @param ossIds OSS对象ID串
+ */
+ @SaCheckPermission("system:oss:remove")
+ @Log(title = "OSS对象存储", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ossIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ossIds) {
+ return toAjax(ossService.deleteWithValidByIds(List.of(ossIds), true));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2PostController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2PostController.java
new file mode 100644
index 000000000..836b293ae
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2PostController.java
@@ -0,0 +1,133 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ObjectUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2PostBo;
+import org.dromara.system.saas.domain.vo.Sys2PostVo;
+import org.dromara.system.saas.service.ISys2PostService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 岗位信息操作处理
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/post")
+public class Sys2PostController extends BaseController {
+
+ private final ISys2PostService postService;
+
+ /**
+ * 获取岗位列表
+ */
+ @SaCheckPermission("system:post:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2PostBo post, PageQuery pageQuery) {
+ return postService.selectPagePostList(post, pageQuery);
+ }
+
+ /**
+ * 导出岗位列表
+ */
+ @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:post:export")
+ @PostMapping("/export")
+ public void export(Sys2PostBo post, HttpServletResponse response) {
+ List list = postService.selectPostList(post);
+ ExcelUtil.exportExcel(list, "岗位数据", Sys2PostVo.class, response);
+ }
+
+ /**
+ * 根据岗位编号获取详细信息
+ *
+ * @param postId 岗位ID
+ */
+ @SaCheckPermission("system:post:query")
+ @GetMapping(value = "/{postId}")
+ public R getInfo(@PathVariable Long postId) {
+ return R.ok(postService.selectPostById(postId));
+ }
+
+ /**
+ * 新增岗位
+ */
+ @SaCheckPermission("system:post:add")
+ @Log(title = "岗位管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2PostBo post) {
+ if (!postService.checkPostNameUnique(post)) {
+ return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
+ } else if (!postService.checkPostCodeUnique(post)) {
+ return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
+ }
+ return toAjax(postService.insertPost(post));
+ }
+
+ /**
+ * 修改岗位
+ */
+ @SaCheckPermission("system:post:edit")
+ @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2PostBo post) {
+ if (!postService.checkPostNameUnique(post)) {
+ return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
+ } else if (!postService.checkPostCodeUnique(post)) {
+ return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
+ } else if (UserConstants.POST_DISABLE.equals(post.getStatus())
+ && postService.countUserPostById(post.getPostId()) > 0) {
+ return R.fail("该岗位下存在已分配用户,不能禁用!");
+ }
+ return toAjax(postService.updatePost(post));
+ }
+
+ /**
+ * 删除岗位
+ *
+ * @param postIds 岗位ID串
+ */
+ @SaCheckPermission("system:post:remove")
+ @Log(title = "岗位管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{postIds}")
+ public R remove(@PathVariable Long[] postIds) {
+ return toAjax(postService.deletePostByIds(postIds));
+ }
+
+ /**
+ * 获取岗位选择框列表
+ *
+ * @param postIds 岗位ID串
+ * @param deptId 部门id
+ */
+ @SaCheckPermission("system:post:query")
+ @GetMapping("/optionselect")
+ public R> optionselect(@RequestParam(required = false) Long[] postIds, @RequestParam(required = false) Long deptId) {
+ List list = new ArrayList<>();
+ if (ObjectUtil.isNotNull(deptId)) {
+ Sys2PostBo post = new Sys2PostBo();
+ post.setDeptId(deptId);
+ list = postService.selectPostList(post);
+ } else if (postIds != null) {
+ list = postService.selectPostByIds(List.of(postIds));
+ }
+ return R.ok(list);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ProfileController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ProfileController.java
new file mode 100644
index 000000000..a45b75644
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2ProfileController.java
@@ -0,0 +1,132 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.secure.BCrypt;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.io.FileUtil;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.core.utils.file.MimeTypeUtils;
+import org.dromara.common.encrypt.annotation.ApiEncrypt;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.helper.DataPermissionHelper;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2UserBo;
+import org.dromara.system.saas.domain.bo.Sys2UserPasswordBo;
+import org.dromara.system.saas.domain.bo.Sys2UserProfileBo;
+import org.dromara.system.saas.domain.vo.TwoAvatarVo;
+import org.dromara.system.saas.domain.vo.TwoProfileVo;
+import org.dromara.system.saas.domain.vo.Sys2OssVo;
+import org.dromara.system.saas.domain.vo.Sys2UserVo;
+import org.dromara.system.saas.service.ISys2OssService;
+import org.dromara.system.saas.service.ISys2UserService;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Arrays;
+
+/**
+ * 个人信息 业务处理
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/user/profile")
+public class Sys2ProfileController extends BaseController {
+
+ private final ISys2UserService userService;
+ private final ISys2OssService ossService;
+
+ /**
+ * 个人信息
+ */
+ @GetMapping
+ public R profile() {
+ Sys2UserVo user = userService.selectUserById(LoginHelper.getUserId());
+ TwoProfileVo twoProfileVo = new TwoProfileVo();
+ twoProfileVo.setUser(user);
+ twoProfileVo.setRoleGroup(userService.selectUserRoleGroup(user.getUserId()));
+ twoProfileVo.setPostGroup(userService.selectUserPostGroup(user.getUserId()));
+ return R.ok(twoProfileVo);
+ }
+
+ /**
+ * 修改用户信息
+ */
+ @RepeatSubmit
+ @Log(title = "个人信息", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R updateProfile(@Validated @RequestBody Sys2UserProfileBo profile) {
+ Sys2UserBo user = BeanUtil.toBean(profile, Sys2UserBo.class);
+ user.setUserId(LoginHelper.getUserId());
+ String username = LoginHelper.getUsername();
+ if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
+ return R.fail("修改用户'" + username + "'失败,手机号码已存在");
+ }
+ if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
+ return R.fail("修改用户'" + username + "'失败,邮箱账号已存在");
+ }
+ int rows = DataPermissionHelper.ignore(() -> userService.updateUserProfile(user));
+ if (rows > 0) {
+ return R.ok();
+ }
+ return R.fail("修改个人信息异常,请联系管理员");
+ }
+
+ /**
+ * 重置密码
+ *
+ * @param bo 新旧密码
+ */
+ @RepeatSubmit
+ @ApiEncrypt
+ @Log(title = "个人信息", businessType = BusinessType.UPDATE)
+ @PutMapping("/updatePwd")
+ public R updatePwd(@Validated @RequestBody Sys2UserPasswordBo bo) {
+ Sys2UserVo user = userService.selectUserById(LoginHelper.getUserId());
+ String password = user.getPassword();
+ if (!BCrypt.checkpw(bo.getOldPassword(), password)) {
+ return R.fail("修改密码失败,旧密码错误");
+ }
+ if (BCrypt.checkpw(bo.getNewPassword(), password)) {
+ return R.fail("新密码不能与旧密码相同");
+ }
+
+ if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword())) > 0) {
+ return R.ok();
+ }
+ return R.fail("修改密码异常,请联系管理员");
+ }
+
+ /**
+ * 头像上传
+ *
+ * @param avatarfile 用户头像
+ */
+ @RepeatSubmit
+ @Log(title = "用户头像", businessType = BusinessType.UPDATE)
+ @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public R avatar(@RequestPart("avatarfile") MultipartFile avatarfile) {
+ if (!avatarfile.isEmpty()) {
+ String extension = FileUtil.extName(avatarfile.getOriginalFilename());
+ if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
+ return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
+ }
+ Sys2OssVo oss = ossService.upload(avatarfile);
+ String avatar = oss.getUrl();
+ if (userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())) {
+ TwoAvatarVo twoAvatarVo = new TwoAvatarVo();
+ twoAvatarVo.setImgUrl(avatar);
+ return R.ok(twoAvatarVo);
+ }
+ }
+ return R.fail("上传图片异常,请联系管理员");
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2RoleController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2RoleController.java
new file mode 100644
index 000000000..89cd85517
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2RoleController.java
@@ -0,0 +1,229 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.Sys2UserRole;
+import org.dromara.system.saas.domain.bo.Sys2DeptBo;
+import org.dromara.system.saas.domain.bo.Sys2RoleBo;
+import org.dromara.system.saas.domain.bo.Sys2UserBo;
+import org.dromara.system.saas.domain.vo.TwoDeptTreeSelectVo;
+import org.dromara.system.saas.domain.vo.Sys2RoleVo;
+import org.dromara.system.saas.domain.vo.Sys2UserVo;
+import org.dromara.system.saas.service.ISys2DeptService;
+import org.dromara.system.saas.service.ISys2RoleService;
+import org.dromara.system.saas.service.ISys2UserService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 角色信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/role")
+public class Sys2RoleController extends BaseController {
+
+ private final ISys2RoleService roleService;
+ private final ISys2UserService userService;
+ private final ISys2DeptService deptService;
+
+ /**
+ * 获取角色信息列表
+ */
+ @SaCheckPermission("system:role:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2RoleBo role, PageQuery pageQuery) {
+ return roleService.selectPageRoleList(role, pageQuery);
+ }
+
+ /**
+ * 导出角色信息列表
+ */
+ @Log(title = "角色管理", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:role:export")
+ @PostMapping("/export")
+ public void export(Sys2RoleBo role, HttpServletResponse response) {
+ List list = roleService.selectRoleList(role);
+ ExcelUtil.exportExcel(list, "角色数据", Sys2RoleVo.class, response);
+ }
+
+ /**
+ * 根据角色编号获取详细信息
+ *
+ * @param roleId 角色ID
+ */
+ @SaCheckPermission("system:role:query")
+ @GetMapping(value = "/{roleId}")
+ public R getInfo(@PathVariable Long roleId) {
+ roleService.checkRoleDataScope(roleId);
+ return R.ok(roleService.selectRoleById(roleId));
+ }
+
+ /**
+ * 新增角色
+ */
+ @SaCheckPermission("system:role:add")
+ @Log(title = "角色管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2RoleBo role) {
+ roleService.checkRoleAllowed(role);
+ if (!roleService.checkRoleNameUnique(role)) {
+ return R.fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
+ } else if (!roleService.checkRoleKeyUnique(role)) {
+ return R.fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
+ }
+ return toAjax(roleService.insertRole(role));
+
+ }
+
+ /**
+ * 修改保存角色
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2RoleBo role) {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ if (!roleService.checkRoleNameUnique(role)) {
+ return R.fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
+ } else if (!roleService.checkRoleKeyUnique(role)) {
+ return R.fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
+ }
+
+ if (roleService.updateRole(role) > 0) {
+ roleService.cleanOnlineUserByRole(role.getRoleId());
+ return R.ok();
+ }
+ return R.fail("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
+ }
+
+ /**
+ * 修改保存数据权限
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/dataScope")
+ public R dataScope(@RequestBody Sys2RoleBo role) {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ return toAjax(roleService.authDataScope(role));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2RoleBo role) {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ return toAjax(roleService.updateRoleStatus(role.getRoleId(), role.getStatus()));
+ }
+
+ /**
+ * 删除角色
+ *
+ * @param roleIds 角色ID串
+ */
+ @SaCheckPermission("system:role:remove")
+ @Log(title = "角色管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{roleIds}")
+ public R remove(@PathVariable Long[] roleIds) {
+ return toAjax(roleService.deleteRoleByIds(roleIds));
+ }
+
+ /**
+ * 获取角色选择框列表
+ *
+ * @param roleIds 角色ID串
+ */
+ @SaCheckPermission("system:role:query")
+ @GetMapping("/optionselect")
+ public R> optionselect(@RequestParam(required = false) Long[] roleIds) {
+ return R.ok(roleService.selectRoleByIds(roleIds == null ? null : List.of(roleIds)));
+ }
+
+ /**
+ * 查询已分配用户角色列表
+ */
+ @SaCheckPermission("system:role:list")
+ @GetMapping("/authUser/allocatedList")
+ public TableDataInfo allocatedList(Sys2UserBo user, PageQuery pageQuery) {
+ return userService.selectAllocatedList(user, pageQuery);
+ }
+
+ /**
+ * 查询未分配用户角色列表
+ */
+ @SaCheckPermission("system:role:list")
+ @GetMapping("/authUser/unallocatedList")
+ public TableDataInfo unallocatedList(Sys2UserBo user, PageQuery pageQuery) {
+ return userService.selectUnallocatedList(user, pageQuery);
+ }
+
+ /**
+ * 取消授权用户
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancel")
+ public R cancelAuthUser(@RequestBody Sys2UserRole userRole) {
+ return toAjax(roleService.deleteAuthUser(userRole));
+ }
+
+ /**
+ * 批量取消授权用户
+ *
+ * @param roleId 角色ID
+ * @param userIds 用户ID串
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancelAll")
+ public R cancelAuthUserAll(Long roleId, Long[] userIds) {
+ return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 批量选择用户授权
+ *
+ * @param roleId 角色ID
+ * @param userIds 用户ID串
+ */
+ @SaCheckPermission("system:role:edit")
+ @Log(title = "角色管理", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/selectAll")
+ public R selectAuthUserAll(Long roleId, Long[] userIds) {
+ roleService.checkRoleDataScope(roleId);
+ return toAjax(roleService.insertAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 获取对应角色部门树列表
+ *
+ * @param roleId 角色ID
+ */
+ @SaCheckPermission("system:role:list")
+ @GetMapping(value = "/deptTree/{roleId}")
+ public R roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
+ TwoDeptTreeSelectVo selectVo = new TwoDeptTreeSelectVo();
+ selectVo.setCheckedKeys(deptService.selectDeptListByRoleId(roleId));
+ selectVo.setDepts(deptService.selectDeptTreeList(new Sys2DeptBo()));
+ return R.ok(selectVo);
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2SocialController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2SocialController.java
new file mode 100644
index 000000000..f81a7cdca
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2SocialController.java
@@ -0,0 +1,38 @@
+package org.dromara.system.saas.controller.system;
+
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.vo.Sys2SocialVo;
+import org.dromara.system.saas.service.ISys2SocialService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 社会化关系
+ *
+ * @author thiszhc
+ * @date 2023-06-16
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/social")
+public class Sys2SocialController extends BaseController {
+
+ private final ISys2SocialService socialUserService;
+
+ /**
+ * 查询社会化关系列表
+ */
+ @GetMapping("/list")
+ public R> list() {
+ return R.ok(socialUserService.queryListByUserId(LoginHelper.getUserId()));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantController.java
new file mode 100644
index 000000000..df71785b0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantController.java
@@ -0,0 +1,179 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.baomidou.lock.annotation.Lock4j;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.TenantConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.encrypt.annotation.ApiEncrypt;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2TenantBo;
+import org.dromara.system.saas.domain.vo.Sys2TenantVo;
+import org.dromara.system.saas.service.ISys2TenantService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 租户管理
+ *
+ * @author Michelle.Chung
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/tenant")
+@ConditionalOnProperty(value = "tenant.enable", havingValue = "true")
+public class Sys2TenantController extends BaseController {
+
+ private final ISys2TenantService tenantService;
+
+ /**
+ * 查询租户列表
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2TenantBo bo, PageQuery pageQuery) {
+ return tenantService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出租户列表
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:export")
+ @Log(title = "租户", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(Sys2TenantBo bo, HttpServletResponse response) {
+ List list = tenantService.queryList(bo);
+ ExcelUtil.exportExcel(list, "租户", Sys2TenantVo.class, response);
+ }
+
+ /**
+ * 获取租户详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(tenantService.queryById(id));
+ }
+
+ /**
+ * 新增租户
+ */
+ @ApiEncrypt
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:add")
+ @Log(title = "租户", businessType = BusinessType.INSERT)
+ @Lock4j
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody Sys2TenantBo bo) {
+ if (!tenantService.checkCompanyNameUnique(bo)) {
+ return R.fail("新增租户'" + bo.getCompanyName() + "'失败,企业名称已存在");
+ }
+ return toAjax(TenantHelper.ignore(() -> tenantService.insertByBo(bo)));
+ }
+
+ /**
+ * 修改租户
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:edit")
+ @Log(title = "租户", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody Sys2TenantBo bo) {
+ tenantService.checkTenantAllowed(bo.getTenantId());
+ if (!tenantService.checkCompanyNameUnique(bo)) {
+ return R.fail("修改租户'" + bo.getCompanyName() + "'失败,公司名称已存在");
+ }
+ return toAjax(tenantService.updateByBo(bo));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:edit")
+ @Log(title = "租户", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2TenantBo bo) {
+ tenantService.checkTenantAllowed(bo.getTenantId());
+ return toAjax(tenantService.updateTenantStatus(bo));
+ }
+
+ /**
+ * 删除租户
+ *
+ * @param ids 主键串
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:remove")
+ @Log(title = "租户", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(tenantService.deleteWithValidByIds(List.of(ids), true));
+ }
+
+ /**
+ * 动态切换租户
+ *
+ * @param tenantId 租户ID
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @GetMapping("/dynamic/{tenantId}")
+ public R dynamicTenant(@NotBlank(message = "租户ID不能为空") @PathVariable String tenantId) {
+ TenantHelper.setDynamic(tenantId, true);
+ return R.ok();
+ }
+
+ /**
+ * 清除动态租户
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @GetMapping("/dynamic/clear")
+ public R dynamicClear() {
+ TenantHelper.clearDynamic();
+ return R.ok();
+ }
+
+
+ /**
+ * 同步租户套餐
+ *
+ * @param tenantId 租户id
+ * @param packageId 套餐id
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenant:edit")
+ @Log(title = "租户", businessType = BusinessType.UPDATE)
+ @GetMapping("/syncTenantPackage")
+ public R syncTenantPackage(@NotBlank(message = "租户ID不能为空") String tenantId,
+ @NotNull(message = "套餐ID不能为空") Long packageId) {
+ return toAjax(TenantHelper.ignore(() -> tenantService.syncTenantPackage(tenantId, packageId)));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantPackageController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantPackageController.java
new file mode 100644
index 000000000..764fc9b94
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2TenantPackageController.java
@@ -0,0 +1,142 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import org.dromara.common.core.constant.TenantConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2TenantPackageBo;
+import org.dromara.system.saas.domain.vo.Sys2TenantPackageVo;
+import org.dromara.system.saas.service.ISys2TenantPackageService;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 租户套餐管理
+ *
+ * @author Michelle.Chung
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/tenant/package")
+@ConditionalOnProperty(value = "tenant.enable", havingValue = "true")
+public class Sys2TenantPackageController extends BaseController {
+
+ private final ISys2TenantPackageService tenantPackageService;
+
+ /**
+ * 查询租户套餐列表
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2TenantPackageBo bo, PageQuery pageQuery) {
+ return tenantPackageService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 查询租户套餐下拉选列表
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:list")
+ @GetMapping("/selectList")
+ public R> selectList() {
+ return R.ok(tenantPackageService.selectList());
+ }
+
+ /**
+ * 导出租户套餐列表
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:export")
+ @Log(title = "租户套餐", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(Sys2TenantPackageBo bo, HttpServletResponse response) {
+ List list = tenantPackageService.queryList(bo);
+ ExcelUtil.exportExcel(list, "租户套餐", Sys2TenantPackageVo.class, response);
+ }
+
+ /**
+ * 获取租户套餐详细信息
+ *
+ * @param packageId 主键
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:query")
+ @GetMapping("/{packageId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long packageId) {
+ return R.ok(tenantPackageService.queryById(packageId));
+ }
+
+ /**
+ * 新增租户套餐
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:add")
+ @Log(title = "租户套餐", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody Sys2TenantPackageBo bo) {
+ if (!tenantPackageService.checkPackageNameUnique(bo)) {
+ return R.fail("新增套餐'" + bo.getPackageName() + "'失败,套餐名称已存在");
+ }
+ return toAjax(tenantPackageService.insertByBo(bo));
+ }
+
+ /**
+ * 修改租户套餐
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:edit")
+ @Log(title = "租户套餐", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody Sys2TenantPackageBo bo) {
+ if (!tenantPackageService.checkPackageNameUnique(bo)) {
+ return R.fail("修改套餐'" + bo.getPackageName() + "'失败,套餐名称已存在");
+ }
+ return toAjax(tenantPackageService.updateByBo(bo));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:edit")
+ @Log(title = "租户套餐", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2TenantPackageBo bo) {
+ return toAjax(tenantPackageService.updatePackageStatus(bo));
+ }
+
+ /**
+ * 删除租户套餐
+ *
+ * @param packageIds 主键串
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("system:tenantPackage:remove")
+ @Log(title = "租户套餐", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{packageIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] packageIds) {
+ return toAjax(tenantPackageService.deleteWithValidByIds(List.of(packageIds), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2UserController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2UserController.java
new file mode 100644
index 000000000..7563236c4
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/Sys2UserController.java
@@ -0,0 +1,300 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.secure.BCrypt;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.domain.model.LoginUser;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.encrypt.annotation.ApiEncrypt;
+import org.dromara.common.excel.core.ExcelResult;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.bo.Sys2DeptBo;
+import org.dromara.system.saas.domain.bo.Sys2PostBo;
+import org.dromara.system.saas.domain.bo.Sys2RoleBo;
+import org.dromara.system.saas.domain.bo.Sys2UserBo;
+import org.dromara.system.saas.domain.vo.*;
+import org.dromara.system.saas.listener.SysUserImportListener;
+import org.dromara.system.saas.service.*;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 用户信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system2/user")
+public class Sys2UserController extends BaseController {
+
+ private final ISys2UserService userService;
+ private final ISys2RoleService roleService;
+ private final ISys2PostService postService;
+ private final ISys2DeptService deptService;
+ private final ISys2TenantService tenantService;
+
+ /**
+ * 获取用户列表
+ */
+ @SaCheckPermission("system:user:list")
+ @GetMapping("/list")
+ public TableDataInfo list(Sys2UserBo user, PageQuery pageQuery) {
+ return userService.selectPageUserList(user, pageQuery);
+ }
+
+ /**
+ * 导出用户列表
+ */
+ @Log(title = "用户管理", businessType = BusinessType.EXPORT)
+ @SaCheckPermission("system:user:export")
+ @PostMapping("/export")
+ public void export(Sys2UserBo user, HttpServletResponse response) {
+ List list = userService.selectUserExportList(user);
+ ExcelUtil.exportExcel(list, "用户数据", Sys2UserExportVo.class, response);
+ }
+
+ /**
+ * 导入数据
+ *
+ * @param file 导入文件
+ * @param updateSupport 是否更新已存在数据
+ */
+ @Log(title = "用户管理", businessType = BusinessType.IMPORT)
+ @SaCheckPermission("system:user:import")
+ @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public R importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
+ ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), Sys2UserImportVo.class, new SysUserImportListener(updateSupport));
+ return R.ok(result.getAnalysis());
+ }
+
+ /**
+ * 获取导入模板
+ */
+ @PostMapping("/importTemplate")
+ public void importTemplate(HttpServletResponse response) {
+ ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", Sys2UserImportVo.class, response);
+ }
+
+ /**
+ * 获取用户信息
+ *
+ * @return 用户信息
+ */
+ @GetMapping("/getInfo")
+ public R getInfo() {
+ TwoUserInfoVo twoUserInfoVo = new TwoUserInfoVo();
+ LoginUser loginUser = LoginHelper.getLoginUser();
+ if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
+ // 超级管理员 如果重新加载用户信息需清除动态租户
+ TenantHelper.clearDynamic();
+ }
+ Sys2UserVo user = userService.selectUserById(loginUser.getUserId());
+ if (ObjectUtil.isNull(user)) {
+ return R.fail("没有权限访问用户数据!");
+ }
+ twoUserInfoVo.setUser(user);
+ twoUserInfoVo.setPermissions(loginUser.getMenuPermission());
+ twoUserInfoVo.setRoles(loginUser.getRolePermission());
+ return R.ok(twoUserInfoVo);
+ }
+
+ /**
+ * 根据用户编号获取详细信息
+ *
+ * @param userId 用户ID
+ */
+ @SaCheckPermission("system:user:query")
+ @GetMapping(value = {"/", "/{userId}"})
+ public R getInfo(@PathVariable(value = "userId", required = false) Long userId) {
+ userService.checkUserDataScope(userId);
+ Sys2UserInfoVo userInfoVo = new Sys2UserInfoVo();
+ Sys2RoleBo roleBo = new Sys2RoleBo();
+ roleBo.setStatus(UserConstants.ROLE_NORMAL);
+ List roles = roleService.selectRoleList(roleBo);
+ userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin()));
+ if (ObjectUtil.isNotNull(userId)) {
+ Sys2UserVo sysUser = userService.selectUserById(userId);
+ userInfoVo.setUser(sysUser);
+ userInfoVo.setRoleIds(roleService.selectRoleListByUserId(userId));
+ Long deptId = sysUser.getDeptId();
+ if (ObjectUtil.isNotNull(deptId)) {
+ Sys2PostBo postBo = new Sys2PostBo();
+ postBo.setDeptId(deptId);
+ userInfoVo.setPosts(postService.selectPostList(postBo));
+ userInfoVo.setPostIds(postService.selectPostListByUserId(userId));
+ }
+ }
+ return R.ok(userInfoVo);
+ }
+
+ /**
+ * 新增用户
+ */
+ @SaCheckPermission("system:user:add")
+ @Log(title = "用户管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody Sys2UserBo user) {
+ deptService.checkDeptDataScope(user.getDeptId());
+ if (!userService.checkUserNameUnique(user)) {
+ return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
+ } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
+ return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
+ } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
+ return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
+ }
+ if (TenantHelper.isEnable()) {
+ if (!tenantService.checkAccountBalance(TenantHelper.getTenantId())) {
+ return R.fail("当前租户下用户名额不足,请联系管理员");
+ }
+ }
+ user.setPassword(BCrypt.hashpw(user.getPassword()));
+ return toAjax(userService.insertUser(user));
+ }
+
+ /**
+ * 修改用户
+ */
+ @SaCheckPermission("system:user:edit")
+ @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody Sys2UserBo user) {
+ userService.checkUserAllowed(user.getUserId());
+ userService.checkUserDataScope(user.getUserId());
+ deptService.checkDeptDataScope(user.getDeptId());
+ if (!userService.checkUserNameUnique(user)) {
+ return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
+ } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
+ return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
+ } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
+ return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
+ }
+ return toAjax(userService.updateUser(user));
+ }
+
+ /**
+ * 删除用户
+ *
+ * @param userIds 角色ID串
+ */
+ @SaCheckPermission("system:user:remove")
+ @Log(title = "用户管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{userIds}")
+ public R remove(@PathVariable Long[] userIds) {
+ if (ArrayUtil.contains(userIds, LoginHelper.getUserId())) {
+ return R.fail("当前用户不能删除");
+ }
+ return toAjax(userService.deleteUserByIds(userIds));
+ }
+
+ /**
+ * 根据用户ID串批量获取用户基础信息
+ *
+ * @param userIds 用户ID串
+ * @param deptId 部门ID
+ */
+ @SaCheckPermission("system:user:query")
+ @GetMapping("/optionselect")
+ public R> optionselect(@RequestParam(required = false) Long[] userIds,
+ @RequestParam(required = false) Long deptId) {
+ return R.ok(userService.selectUserByIds(userIds == null ? null : List.of(userIds), deptId));
+ }
+
+ /**
+ * 重置密码
+ */
+ @ApiEncrypt
+ @SaCheckPermission("system:user:resetPwd")
+ @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/resetPwd")
+ public R resetPwd(@RequestBody Sys2UserBo user) {
+ userService.checkUserAllowed(user.getUserId());
+ userService.checkUserDataScope(user.getUserId());
+ user.setPassword(BCrypt.hashpw(user.getPassword()));
+ return toAjax(userService.resetUserPwd(user.getUserId(), user.getPassword()));
+ }
+
+ /**
+ * 状态修改
+ */
+ @SaCheckPermission("system:user:edit")
+ @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public R changeStatus(@RequestBody Sys2UserBo user) {
+ userService.checkUserAllowed(user.getUserId());
+ userService.checkUserDataScope(user.getUserId());
+ return toAjax(userService.updateUserStatus(user.getUserId(), user.getStatus()));
+ }
+
+ /**
+ * 根据用户编号获取授权角色
+ *
+ * @param userId 用户ID
+ */
+ @SaCheckPermission("system:user:query")
+ @GetMapping("/authRole/{userId}")
+ public R authRole(@PathVariable Long userId) {
+ userService.checkUserDataScope(userId);
+ Sys2UserVo user = userService.selectUserById(userId);
+ List roles = roleService.selectRolesAuthByUserId(userId);
+ Sys2UserInfoVo userInfoVo = new Sys2UserInfoVo();
+ userInfoVo.setUser(user);
+ userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin()));
+ return R.ok(userInfoVo);
+ }
+
+ /**
+ * 用户授权角色
+ *
+ * @param userId 用户Id
+ * @param roleIds 角色ID串
+ */
+ @SaCheckPermission("system:user:edit")
+ @Log(title = "用户管理", businessType = BusinessType.GRANT)
+ @PutMapping("/authRole")
+ public R insertAuthRole(Long userId, Long[] roleIds) {
+ userService.checkUserDataScope(userId);
+ userService.insertUserAuth(userId, roleIds);
+ return R.ok();
+ }
+
+ /**
+ * 获取部门树列表
+ */
+ @SaCheckPermission("system:user:list")
+ @GetMapping("/deptTree")
+ public R>> deptTree(Sys2DeptBo dept) {
+ return R.ok(deptService.selectDeptTreeList(dept));
+ }
+
+ /**
+ * 获取部门下的所有用户信息
+ */
+ @SaCheckPermission("system:user:list")
+ @GetMapping("/list/dept/{deptId}")
+ public R> listByDept(@PathVariable @NotNull Long deptId) {
+ return R.ok(userService.selectUserListByDept(deptId));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/SysSaasMenuController.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/SysSaasMenuController.java
new file mode 100644
index 000000000..f29c38e41
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/controller/system/SysSaasMenuController.java
@@ -0,0 +1,174 @@
+package org.dromara.system.saas.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
+import cn.hutool.core.lang.tree.Tree;
+import org.dromara.common.core.constant.TenantConstants;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.saas.domain.SysSaasMenu;
+import org.dromara.system.saas.domain.bo.SysSaasMenuBo;
+import org.dromara.system.saas.domain.vo.TwoMenuTreeSelectVo;
+import org.dromara.system.saas.domain.vo.TwoRouterVo;
+import org.dromara.system.saas.domain.vo.SysSaasMenuVo;
+import org.dromara.system.saas.service.ISysSaasMenuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 菜单信息
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/systemSaas/menu")
+public class SysSaasMenuController extends BaseController {
+
+ private final ISysSaasMenuService menuService;
+
+ /**
+ * 获取路由信息
+ *
+ * @return 路由信息
+ */
+ @GetMapping("/getRouters")
+ public R> getRouters() {
+ List menus = menuService.selectMenuTreeByUserId(LoginHelper.getUserId());
+ return R.ok(menuService.buildMenus(menus));
+ }
+
+ /**
+ * 获取菜单列表
+ */
+ @SaCheckRole(value = {
+ TenantConstants.SUPER_ADMIN_ROLE_KEY,
+ TenantConstants.TENANT_ADMIN_ROLE_KEY
+ }, mode = SaMode.OR)
+ @SaCheckPermission("systemSaas:menu:list")
+ @GetMapping("/list")
+ public R> list(SysSaasMenuBo menu) {
+ List menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
+ return R.ok(menus);
+ }
+
+ /**
+ * 根据菜单编号获取详细信息
+ *
+ * @param menuId 菜单ID
+ */
+ @SaCheckRole(value = {
+ TenantConstants.SUPER_ADMIN_ROLE_KEY,
+ TenantConstants.TENANT_ADMIN_ROLE_KEY
+ }, mode = SaMode.OR)
+ @SaCheckPermission("systemSaas:menu:query")
+ @GetMapping(value = "/{menuId}")
+ public R getInfo(@PathVariable Long menuId) {
+ return R.ok(menuService.selectMenuById(menuId));
+ }
+
+ /**
+ * 获取菜单下拉树列表
+ */
+ @SaCheckPermission("systemSaas:menu:query")
+ @GetMapping("/treeselect")
+ public R>> treeselect(SysSaasMenuBo menu) {
+ List menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
+ return R.ok(menuService.buildMenuTreeSelect(menus));
+ }
+
+ /**
+ * 加载对应角色菜单列表树
+ *
+ * @param roleId 角色ID
+ */
+ @SaCheckPermission("systemSaas:menu:query")
+ @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+ public R roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
+ List menus = menuService.selectMenuList(LoginHelper.getUserId());
+ TwoMenuTreeSelectVo selectVo = new TwoMenuTreeSelectVo();
+ selectVo.setCheckedKeys(menuService.selectMenuListByRoleId(roleId));
+ selectVo.setMenus(menuService.buildMenuTreeSelect(menus));
+ return R.ok(selectVo);
+ }
+
+ /**
+ * 加载对应租户套餐菜单列表树
+ *
+ * @param packageId 租户套餐ID
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("systemSaas:menu:query")
+ @GetMapping(value = "/tenantPackageMenuTreeselect/{packageId}")
+ public R tenantPackageMenuTreeselect(@PathVariable("packageId") Long packageId) {
+ List menus = menuService.selectMenuList(LoginHelper.getUserId());
+ TwoMenuTreeSelectVo selectVo = new TwoMenuTreeSelectVo();
+ selectVo.setCheckedKeys(menuService.selectMenuListByPackageId(packageId));
+ selectVo.setMenus(menuService.buildMenuTreeSelect(menus));
+ return R.ok(selectVo);
+ }
+
+ /**
+ * 新增菜单
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("systemSaas:menu:add")
+ @Log(title = "菜单管理", businessType = BusinessType.INSERT)
+ @PostMapping
+ public R add(@Validated @RequestBody SysSaasMenuBo menu) {
+ if (!menuService.checkMenuNameUnique(menu)) {
+ return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+ } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
+ return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
+ }
+ return toAjax(menuService.insertMenu(menu));
+ }
+
+ /**
+ * 修改菜单
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("systemSaas:menu:edit")
+ @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public R edit(@Validated @RequestBody SysSaasMenuBo menu) {
+ if (!menuService.checkMenuNameUnique(menu)) {
+ return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+ } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
+ return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
+ } else if (menu.getMenuId().equals(menu.getParentId())) {
+ return R.fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
+ }
+ return toAjax(menuService.updateMenu(menu));
+ }
+
+ /**
+ * 删除菜单
+ *
+ * @param menuId 菜单ID
+ */
+ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+ @SaCheckPermission("systemSaas:menu:remove")
+ @Log(title = "菜单管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{menuId}")
+ public R remove(@PathVariable("menuId") Long menuId) {
+ if (menuService.hasChildByMenuId(menuId)) {
+ return R.warn("存在子菜单,不允许删除");
+ }
+ if (menuService.checkMenuExistRole(menuId)) {
+ return R.warn("菜单已分配,不允许删除");
+ }
+ return toAjax(menuService.deleteMenuById(menuId));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Application.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Application.java
new file mode 100644
index 000000000..97d4b94f8
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Application.java
@@ -0,0 +1,41 @@
+package org.dromara.system.saas.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 应用对象 sys_saas_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_saas_application")
+public class Sys2Application extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "application_id")
+ private Long applicationId;
+
+ /**
+ * 应用名称
+ */
+ private String applicationName;
+
+ /**
+ * 应用code
+ */
+ private String applicationCode;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Cache.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Cache.java
new file mode 100644
index 000000000..297e8b973
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Cache.java
@@ -0,0 +1,47 @@
+package org.dromara.system.saas.domain;
+
+import org.dromara.common.core.utils.StringUtils;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 缓存信息
+ *
+ * @author Lion Li
+ */
+@Data
+@NoArgsConstructor
+public class Sys2Cache {
+
+ /**
+ * 缓存名称
+ */
+ private String cacheName = "";
+
+ /**
+ * 缓存键名
+ */
+ private String cacheKey = "";
+
+ /**
+ * 缓存内容
+ */
+ private String cacheValue = "";
+
+ /**
+ * 备注
+ */
+ private String remark = "";
+
+ public Sys2Cache(String cacheName, String remark) {
+ this.cacheName = cacheName;
+ this.remark = remark;
+ }
+
+ public Sys2Cache(String cacheName, String cacheKey, String cacheValue) {
+ this.cacheName = StringUtils.replace(cacheName, ":", "");
+ this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
+ this.cacheValue = cacheValue;
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Client.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Client.java
new file mode 100644
index 000000000..46fadb82e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Client.java
@@ -0,0 +1,77 @@
+package org.dromara.system.saas.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 授权管理对象 sys2_client
+ *
+ * @author Michelle.Chung
+ * @date 2023-05-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_client")
+public class Sys2Client extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 客户端id
+ */
+ private String clientId;
+
+ /**
+ * 客户端key
+ */
+ private String clientKey;
+
+ /**
+ * 客户端秘钥
+ */
+ private String clientSecret;
+
+ /**
+ * 授权类型
+ */
+ private String grantType;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * token活跃超时时间
+ */
+ private Long activeTimeout;
+
+ /**
+ * token固定超时时间
+ */
+ private Long timeout;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Config.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Config.java
new file mode 100644
index 000000000..6d756de07
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Config.java
@@ -0,0 +1,51 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 参数配置表 sys2_config
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_config")
+public class Sys2Config extends TenantEntity {
+
+ /**
+ * 参数主键
+ */
+ @TableId(value = "config_id")
+ private Long configId;
+
+ /**
+ * 参数名称
+ */
+ private String configName;
+
+ /**
+ * 参数键名
+ */
+ private String configKey;
+
+ /**
+ * 参数键值
+ */
+ private String configValue;
+
+ /**
+ * 系统内置(Y是 N否)
+ */
+ private String configType;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Dept.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Dept.java
new file mode 100644
index 000000000..f38ca5e55
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Dept.java
@@ -0,0 +1,83 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.tenant.core.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 部门表 sys2_dept
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_dept")
+public class Sys2Dept extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 部门ID
+ */
+ @TableId(value = "dept_id")
+ private Long deptId;
+
+ /**
+ * 父部门ID
+ */
+ private Long parentId;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+
+ /**
+ * 部门类别编码
+ */
+ private String deptCategory;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 负责人
+ */
+ private Long leader;
+
+ /**
+ * 联系电话
+ */
+ private String phone;
+
+ /**
+ * 邮箱
+ */
+ private String email;
+
+ /**
+ * 部门状态:0正常,1停用
+ */
+ private String status;
+
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+ /**
+ * 祖级列表
+ */
+ private String ancestors;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictData.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictData.java
new file mode 100644
index 000000000..d1dfb1e80
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictData.java
@@ -0,0 +1,71 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 字典数据表 sys2_dict_data
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_dict_data")
+public class Sys2DictData extends TenantEntity {
+
+ /**
+ * 字典编码
+ */
+ @TableId(value = "dict_code")
+ private Long dictCode;
+
+ /**
+ * 字典排序
+ */
+ private Integer dictSort;
+
+ /**
+ * 字典标签
+ */
+ private String dictLabel;
+
+ /**
+ * 字典键值
+ */
+ private String dictValue;
+
+ /**
+ * 字典类型
+ */
+ private String dictType;
+
+ /**
+ * 样式属性(其他样式扩展)
+ */
+ private String cssClass;
+
+ /**
+ * 表格字典样式
+ */
+ private String listClass;
+
+ /**
+ * 是否默认(Y是 N否)
+ */
+ private String isDefault;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ public boolean getDefault() {
+ return UserConstants.YES.equals(this.isDefault);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictType.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictType.java
new file mode 100644
index 000000000..c3475ee25
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2DictType.java
@@ -0,0 +1,41 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 字典类型表 sys2_dict_type
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_dict_type")
+public class Sys2DictType extends TenantEntity {
+
+ /**
+ * 字典主键
+ */
+ @TableId(value = "dict_id")
+ private Long dictId;
+
+ /**
+ * 字典名称
+ */
+ private String dictName;
+
+ /**
+ * 字典类型
+ */
+ private String dictType;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Logininfor.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Logininfor.java
new file mode 100644
index 000000000..0e780673e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Logininfor.java
@@ -0,0 +1,85 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 系统访问记录表 sys2_logininfor
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_logininfor")
+public class Sys2Logininfor implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * ID
+ */
+ @TableId(value = "info_id")
+ private Long infoId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 用户账号
+ */
+ private String userName;
+
+ /**
+ * 客户端
+ */
+ private String clientKey;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * 登录状态 0成功 1失败
+ */
+ private String status;
+
+ /**
+ * 登录IP地址
+ */
+ private String ipaddr;
+
+ /**
+ * 登录地点
+ */
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ private String os;
+
+ /**
+ * 提示消息
+ */
+ private String msg;
+
+ /**
+ * 访问时间
+ */
+ private Date loginTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Notice.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Notice.java
new file mode 100644
index 000000000..048966fe0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Notice.java
@@ -0,0 +1,51 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * 通知公告表 sys2_notice
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_notice")
+public class Sys2Notice extends TenantEntity {
+
+ /**
+ * 公告ID
+ */
+ @TableId(value = "notice_id")
+ private Long noticeId;
+
+ /**
+ * 公告标题
+ */
+ private String noticeTitle;
+
+ /**
+ * 公告类型(1通知 2公告)
+ */
+ private String noticeType;
+
+ /**
+ * 公告内容
+ */
+ private String noticeContent;
+
+ /**
+ * 公告状态(0正常 1关闭)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OperLog.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OperLog.java
new file mode 100644
index 000000000..29b874b09
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OperLog.java
@@ -0,0 +1,115 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 操作日志记录表 oper_log
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_oper_log")
+public class Sys2OperLog implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 日志主键
+ */
+ @TableId(value = "oper_id")
+ private Long operId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 操作模块
+ */
+ private String title;
+
+ /**
+ * 业务类型(0其它 1新增 2修改 3删除)
+ */
+ private Integer businessType;
+
+ /**
+ * 请求方法
+ */
+ private String method;
+
+ /**
+ * 请求方式
+ */
+ private String requestMethod;
+
+ /**
+ * 操作类别(0其它 1后台用户 2手机端用户)
+ */
+ private Integer operatorType;
+
+ /**
+ * 操作人员
+ */
+ private String operName;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+
+ /**
+ * 请求url
+ */
+ private String operUrl;
+
+ /**
+ * 操作地址
+ */
+ private String operIp;
+
+ /**
+ * 操作地点
+ */
+ private String operLocation;
+
+ /**
+ * 请求参数
+ */
+ private String operParam;
+
+ /**
+ * 返回参数
+ */
+ private String jsonResult;
+
+ /**
+ * 操作状态(0正常 1异常)
+ */
+ private Integer status;
+
+ /**
+ * 错误消息
+ */
+ private String errorMsg;
+
+ /**
+ * 操作时间
+ */
+ private Date operTime;
+
+ /**
+ * 消耗时间
+ */
+ private Long costTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Oss.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Oss.java
new file mode 100644
index 000000000..23e7db46e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Oss.java
@@ -0,0 +1,50 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * OSS对象存储对象
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_oss")
+public class Sys2Oss extends TenantEntity {
+
+ /**
+ * 对象存储主键
+ */
+ @TableId(value = "oss_id")
+ private Long ossId;
+
+ /**
+ * 文件名
+ */
+ private String fileName;
+
+ /**
+ * 原名
+ */
+ private String originalName;
+
+ /**
+ * 文件后缀名
+ */
+ private String fileSuffix;
+
+ /**
+ * URL地址
+ */
+ private String url;
+
+ /**
+ * 服务商
+ */
+ private String service;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OssConfig.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OssConfig.java
new file mode 100644
index 000000000..b0151895b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2OssConfig.java
@@ -0,0 +1,89 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+/**
+ * 对象存储配置对象 sys2_oss_config
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_oss_config")
+public class Sys2OssConfig extends BaseEntity {
+
+ /**
+ * 主键
+ */
+ @TableId(value = "oss_config_id")
+ private Long ossConfigId;
+
+ /**
+ * 配置key
+ */
+ private String configKey;
+
+ /**
+ * accessKey
+ */
+ private String accessKey;
+
+ /**
+ * 秘钥
+ */
+ private String secretKey;
+
+ /**
+ * 桶名称
+ */
+ private String bucketName;
+
+ /**
+ * 前缀
+ */
+ private String prefix;
+
+ /**
+ * 访问站点
+ */
+ private String endpoint;
+
+ /**
+ * 自定义域名
+ */
+ private String domain;
+
+ /**
+ * 是否https(0否 1是)
+ */
+ private String isHttps;
+
+ /**
+ * 域
+ */
+ private String region;
+
+ /**
+ * 是否默认(0=是,1=否)
+ */
+ private String status;
+
+ /**
+ * 扩展字段
+ */
+ private String ext1;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ private String accessPolicy;
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Post.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Post.java
new file mode 100644
index 000000000..f0e75bbc3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Post.java
@@ -0,0 +1,61 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 岗位表 sys2_post
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_post")
+public class Sys2Post extends TenantEntity {
+
+ /**
+ * 岗位序号
+ */
+ @TableId(value = "post_id")
+ private Long postId;
+
+ /**
+ * 部门id
+ */
+ private Long deptId;
+
+ /**
+ * 岗位编码
+ */
+ private String postCode;
+
+ /**
+ * 岗位名称
+ */
+ private String postName;
+
+ /**
+ * 岗位类别编码
+ */
+ private String postCategory;
+
+ /**
+ * 岗位排序
+ */
+ private Integer postSort;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Role.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Role.java
new file mode 100644
index 000000000..8bdd4f642
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Role.java
@@ -0,0 +1,79 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 角色表 sys2_role
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_role")
+public class Sys2Role extends TenantEntity {
+
+ /**
+ * 角色ID
+ */
+ @TableId(value = "role_id")
+ private Long roleId;
+
+ /**
+ * 角色名称
+ */
+ private String roleName;
+
+ /**
+ * 角色权限
+ */
+ private String roleKey;
+
+ /**
+ * 角色排序
+ */
+ private Integer roleSort;
+
+ /**
+ * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
+ */
+ private String dataScope;
+
+ /**
+ * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)
+ */
+ private Boolean menuCheckStrictly;
+
+ /**
+ * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )
+ */
+ private Boolean deptCheckStrictly;
+
+ /**
+ * 角色状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ public Sys2Role(Long roleId) {
+ this.roleId = roleId;
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleDept.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleDept.java
new file mode 100644
index 000000000..4c943f87a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleDept.java
@@ -0,0 +1,29 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 角色和部门关联 sys2_role_dept
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_role_dept")
+public class Sys2RoleDept {
+
+ /**
+ * 角色ID
+ */
+ @TableId(type = IdType.INPUT)
+ private Long roleId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleMenu.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleMenu.java
new file mode 100644
index 000000000..168875d85
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2RoleMenu.java
@@ -0,0 +1,29 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 角色和菜单关联 sys2_role_menu
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_role_menu")
+public class Sys2RoleMenu {
+
+ /**
+ * 角色ID
+ */
+ @TableId(type = IdType.INPUT)
+ private Long roleId;
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Social.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Social.java
new file mode 100644
index 000000000..7e6d20841
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Social.java
@@ -0,0 +1,136 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.tenant.core.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 社会化关系对象 sys2_social
+ *
+ * @author thiszhc
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_social")
+public class Sys2Social extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 的唯一ID
+ */
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 用户的 open id
+ */
+ private String openId;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Tenant.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Tenant.java
new file mode 100644
index 000000000..d90533f8c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2Tenant.java
@@ -0,0 +1,103 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 租户对象 sys2_tenant
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_tenant")
+public class Sys2Tenant extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 联系人
+ */
+ private String contactUserName;
+
+ /**
+ * 联系电话
+ */
+ private String contactPhone;
+
+ /**
+ * 企业名称
+ */
+ private String companyName;
+
+ /**
+ * 统一社会信用代码
+ */
+ private String licenseNumber;
+
+ /**
+ * 地址
+ */
+ private String address;
+
+ /**
+ * 域名
+ */
+ private String domain;
+
+ /**
+ * 企业简介
+ */
+ private String intro;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 租户套餐编号
+ */
+ private Long packageId;
+
+ /**
+ * 过期时间
+ */
+ private Date expireTime;
+
+ /**
+ * 用户数量(-1不限制)
+ */
+ private Long accountCount;
+
+ /**
+ * 租户状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantApplication.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantApplication.java
new file mode 100644
index 000000000..1ce038915
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantApplication.java
@@ -0,0 +1,34 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 租户和应用关联对象 sys2_tenant_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@TableName("sys2_tenant_application")
+public class Sys2TenantApplication implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 租户id
+ */
+ @TableId(value = "tenant_id")
+ private Long tenantId;
+
+ /**
+ * 应用ID
+ */
+ private Long applicationId;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantPackage.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantPackage.java
new file mode 100644
index 000000000..d3e4c94ed
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2TenantPackage.java
@@ -0,0 +1,54 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.io.Serial;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+/**
+ * 租户套餐对象 sys2_tenant_package
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_tenant_package")
+public class Sys2TenantPackage extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 租户套餐id
+ */
+ @TableId(value = "package_id")
+ private Long packageId;
+ /**
+ * 套餐名称
+ */
+ private String packageName;
+ /**
+ * 关联菜单id
+ */
+ private String menuIds;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)
+ */
+ private Boolean menuCheckStrictly;
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2User.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2User.java
new file mode 100644
index 000000000..642c2f0a6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2User.java
@@ -0,0 +1,115 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.tenant.core.TenantEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 用户对象 sys2_user
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys2_user")
+public class Sys2User extends TenantEntity {
+
+ /**
+ * 用户ID
+ */
+ @TableId(value = "user_id")
+ private Long userId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 用户账号
+ */
+ private String userName;
+
+ /**
+ * 用户昵称
+ */
+ private String nickName;
+
+ /**
+ * 用户类型(sys2_user系统用户)
+ */
+ private String userType;
+
+ /**
+ * 用户邮箱
+ */
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ private String phonenumber;
+
+ /**
+ * 用户性别
+ */
+ private String sex;
+
+ /**
+ * 用户头像
+ */
+ private Long avatar;
+
+ /**
+ * 密码
+ */
+ @TableField(
+ insertStrategy = FieldStrategy.NOT_EMPTY,
+ updateStrategy = FieldStrategy.NOT_EMPTY,
+ whereStrategy = FieldStrategy.NOT_EMPTY
+ )
+ private String password;
+
+ /**
+ * 帐号状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 删除标志(0代表存在 2代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+ /**
+ * 最后登录IP
+ */
+ private String loginIp;
+
+ /**
+ * 最后登录时间
+ */
+ private Date loginDate;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+ public Sys2User(Long userId) {
+ this.userId = userId;
+ }
+
+ public boolean isSuperAdmin() {
+ return UserConstants.SUPER_ADMIN_ID.equals(this.userId);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserOnline.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserOnline.java
new file mode 100644
index 000000000..7ab8bca64
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserOnline.java
@@ -0,0 +1,63 @@
+package org.dromara.system.saas.domain;
+
+import lombok.Data;
+
+/**
+ * 当前在线会话
+ *
+ * @author Lion Li
+ */
+@Data
+public class Sys2UserOnline {
+
+ /**
+ * 会话编号
+ */
+ private String tokenId;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+
+ /**
+ * 用户名称
+ */
+ private String userName;
+
+ /**
+ * 客户端
+ */
+ private String clientKey;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * 登录IP地址
+ */
+ private String ipaddr;
+
+ /**
+ * 登录地址
+ */
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ private String os;
+
+ /**
+ * 登录时间
+ */
+ private Long loginTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserPost.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserPost.java
new file mode 100644
index 000000000..5502f807f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserPost.java
@@ -0,0 +1,29 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 用户和岗位关联 sys2_user_post
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_user_post")
+public class Sys2UserPost {
+
+ /**
+ * 用户ID
+ */
+ @TableId(type = IdType.INPUT)
+ private Long userId;
+
+ /**
+ * 岗位ID
+ */
+ private Long postId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserRole.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserRole.java
new file mode 100644
index 000000000..cd7d26faf
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/Sys2UserRole.java
@@ -0,0 +1,29 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 用户和角色关联 sys2_user_role
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys2_user_role")
+public class Sys2UserRole {
+
+ /**
+ * 用户ID
+ */
+ @TableId(type = IdType.INPUT)
+ private Long userId;
+
+ /**
+ * 角色ID
+ */
+ private Long roleId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/SysSaasMenu.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/SysSaasMenu.java
new file mode 100644
index 000000000..0e7138087
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/SysSaasMenu.java
@@ -0,0 +1,196 @@
+package org.dromara.system.saas.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.dromara.common.core.constant.Constants;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 菜单权限表 sys_saas_menu
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_saas_menu")
+public class SysSaasMenu extends BaseEntity {
+
+ /**
+ * 应用id
+ */
+ @TableId(value = "application_id")
+ private Long applicationId;
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+ /**
+ * 父菜单ID
+ */
+ private Long parentId;
+
+ /**
+ * 菜单名称
+ */
+ private String menuName;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 路由地址
+ */
+ private String path;
+
+ /**
+ * 组件路径
+ */
+ private String component;
+
+ /**
+ * 路由参数
+ */
+ private String queryParam;
+
+ /**
+ * 是否为外链(0是 1否)
+ */
+ private String isFrame;
+
+ /**
+ * 是否缓存(0缓存 1不缓存)
+ */
+ private String isCache;
+
+ /**
+ * 类型(M目录 C菜单 F按钮)
+ */
+ private String menuType;
+
+ /**
+ * 显示状态(0显示 1隐藏)
+ */
+ private String visible;
+
+ /**
+ * 菜单状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 权限字符串
+ */
+ private String perms;
+
+ /**
+ * 菜单图标
+ */
+ private String icon;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 父菜单名称
+ */
+ @TableField(exist = false)
+ private String parentName;
+
+ /**
+ * 子菜单
+ */
+ @TableField(exist = false)
+ private List children = new ArrayList<>();
+
+ /**
+ * 获取路由名称
+ */
+ public String getRouteName() {
+ String routerName = StringUtils.capitalize(path);
+ // 非外链并且是一级目录(类型为目录)
+ if (isMenuFrame()) {
+ routerName = StringUtils.EMPTY;
+ }
+ return routerName;
+ }
+
+ /**
+ * 获取路由地址
+ */
+ public String getRouterPath() {
+ String routerPath = this.path;
+ // 内链打开外网方式
+ if (getParentId() != 0L && isInnerLink()) {
+ routerPath = innerLinkReplaceEach(routerPath);
+ }
+ // 非外链并且是一级目录(类型为目录)
+ if (0L == getParentId() && UserConstants.TYPE_DIR.equals(getMenuType())
+ && UserConstants.NO_FRAME.equals(getIsFrame())) {
+ routerPath = "/" + this.path;
+ }
+ // 非外链并且是一级目录(类型为菜单)
+ else if (isMenuFrame()) {
+ routerPath = "/";
+ }
+ return routerPath;
+ }
+
+ /**
+ * 获取组件信息
+ */
+ public String getComponentInfo() {
+ String component = UserConstants.LAYOUT;
+ if (StringUtils.isNotEmpty(this.component) && !isMenuFrame()) {
+ component = this.component;
+ } else if (StringUtils.isEmpty(this.component) && getParentId() != 0L && isInnerLink()) {
+ component = UserConstants.INNER_LINK;
+ } else if (StringUtils.isEmpty(this.component) && isParentView()) {
+ component = UserConstants.PARENT_VIEW;
+ }
+ return component;
+ }
+
+ /**
+ * 是否为菜单内部跳转
+ */
+ public boolean isMenuFrame() {
+ return getParentId() == 0L && UserConstants.TYPE_MENU.equals(menuType) && isFrame.equals(UserConstants.NO_FRAME);
+ }
+
+ /**
+ * 是否为内链组件
+ */
+ public boolean isInnerLink() {
+ return isFrame.equals(UserConstants.NO_FRAME) && StringUtils.ishttp(path);
+ }
+
+ /**
+ * 是否为parent_view组件
+ */
+ public boolean isParentView() {
+ return getParentId() != 0L && UserConstants.TYPE_DIR.equals(menuType);
+ }
+
+ /**
+ * 内链域名特殊字符替换
+ */
+ public static String innerLinkReplaceEach(String path) {
+ return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":"},
+ new String[]{"", "", "", "/", "/"});
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ApplicationBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ApplicationBo.java
new file mode 100644
index 000000000..062e99dc7
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ApplicationBo.java
@@ -0,0 +1,42 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.system.saas.domain.Sys2Application;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 应用业务对象 sys_saas_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Application.class, reverseConvertGenerate = false)
+public class Sys2ApplicationBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ @NotNull(message = "id不能为空", groups = { EditGroup.class })
+ private Long applicationId;
+
+ /**
+ * 应用名称
+ */
+ @NotBlank(message = "应用名称不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String applicationName;
+
+ /**
+ * 应用code
+ */
+ @NotBlank(message = "应用code不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String applicationCode;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ClientBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ClientBo.java
new file mode 100644
index 000000000..751c28a13
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ClientBo.java
@@ -0,0 +1,80 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.system.saas.domain.Sys2Client;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+import java.util.List;
+
+/**
+ * 授权管理业务对象 sys2_client
+ *
+ * @author Michelle.Chung
+ * @date 2023-05-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Client.class, reverseConvertGenerate = false)
+public class Sys2ClientBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ @NotNull(message = "id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 客户端id
+ */
+ private String clientId;
+
+ /**
+ * 客户端key
+ */
+ @NotBlank(message = "客户端key不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String clientKey;
+
+ /**
+ * 客户端秘钥
+ */
+ @NotBlank(message = "客户端秘钥不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String clientSecret;
+
+ /**
+ * 授权类型
+ */
+ @NotNull(message = "授权类型不能为空", groups = { AddGroup.class, EditGroup.class })
+ private List grantTypeList;
+
+ /**
+ * 授权类型
+ */
+ private String grantType;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * token活跃超时时间
+ */
+ private Long activeTimeout;
+
+ /**
+ * token固定超时时间
+ */
+ private Long timeout;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ConfigBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ConfigBo.java
new file mode 100644
index 000000000..ed5483d0d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2ConfigBo.java
@@ -0,0 +1,59 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Config;
+
+/**
+ * 参数配置业务对象 sys2_config
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Config.class, reverseConvertGenerate = false)
+public class Sys2ConfigBo extends BaseEntity {
+
+ /**
+ * 参数主键
+ */
+ private Long configId;
+
+ /**
+ * 参数名称
+ */
+ @NotBlank(message = "参数名称不能为空")
+ @Size(min = 0, max = 100, message = "参数名称不能超过{max}个字符")
+ private String configName;
+
+ /**
+ * 参数键名
+ */
+ @NotBlank(message = "参数键名不能为空")
+ @Size(min = 0, max = 100, message = "参数键名长度不能超过{max}个字符")
+ private String configKey;
+
+ /**
+ * 参数键值
+ */
+ @NotBlank(message = "参数键值不能为空")
+ @Size(min = 0, max = 500, message = "参数键值长度不能超过{max}个字符")
+ private String configValue;
+
+ /**
+ * 系统内置(Y是 N否)
+ */
+ private String configType;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DeptBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DeptBo.java
new file mode 100644
index 000000000..47c7767c0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DeptBo.java
@@ -0,0 +1,76 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Dept;
+
+/**
+ * 部门业务对象 sys2_dept
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Dept.class, reverseConvertGenerate = false)
+public class Sys2DeptBo extends BaseEntity {
+
+ /**
+ * 部门id
+ */
+ private Long deptId;
+
+ /**
+ * 父部门ID
+ */
+ private Long parentId;
+
+ /**
+ * 部门名称
+ */
+ @NotBlank(message = "部门名称不能为空")
+ @Size(min = 0, max = 30, message = "部门名称长度不能超过{max}个字符")
+ private String deptName;
+
+ /**
+ * 部门类别编码
+ */
+ @Size(min = 0, max = 100, message = "部门类别编码长度不能超过{max}个字符")
+ private String deptCategory;
+
+ /**
+ * 显示顺序
+ */
+ @NotNull(message = "显示顺序不能为空")
+ private Integer orderNum;
+
+ /**
+ * 负责人
+ */
+ private Long leader;
+
+ /**
+ * 联系电话
+ */
+ @Size(min = 0, max = 11, message = "联系电话长度不能超过{max}个字符")
+ private String phone;
+
+ /**
+ * 邮箱
+ */
+ @Email(message = "邮箱格式不正确")
+ @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
+ private String email;
+
+ /**
+ * 部门状态(0正常 1停用)
+ */
+ private String status;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictDataBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictDataBo.java
new file mode 100644
index 000000000..84aeba191
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictDataBo.java
@@ -0,0 +1,79 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2DictData;
+
+/**
+ * 字典数据业务对象 sys2_dict_data
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2DictData.class, reverseConvertGenerate = false)
+public class Sys2DictDataBo extends BaseEntity {
+
+ /**
+ * 字典编码
+ */
+ private Long dictCode;
+
+ /**
+ * 字典排序
+ */
+ private Integer dictSort;
+
+ /**
+ * 字典标签
+ */
+ @NotBlank(message = "字典标签不能为空")
+ @Size(min = 0, max = 100, message = "字典标签长度不能超过{max}个字符")
+ private String dictLabel;
+
+ /**
+ * 字典键值
+ */
+ @NotBlank(message = "字典键值不能为空")
+ @Size(min = 0, max = 100, message = "字典键值长度不能超过{max}个字符")
+ private String dictValue;
+
+ /**
+ * 字典类型
+ */
+ @NotBlank(message = "字典类型不能为空")
+ @Size(min = 0, max = 100, message = "字典类型长度不能超过{max}个字符")
+ private String dictType;
+
+ /**
+ * 样式属性(其他样式扩展)
+ */
+ @Size(min = 0, max = 100, message = "样式属性长度不能超过{max}个字符")
+ private String cssClass;
+
+ /**
+ * 表格回显样式
+ */
+ private String listClass;
+
+ /**
+ * 是否默认(Y是 N否)
+ */
+ private String isDefault;
+
+ /**
+ * 创建部门
+ */
+ private Long createDept;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictTypeBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictTypeBo.java
new file mode 100644
index 000000000..d29785b2c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2DictTypeBo.java
@@ -0,0 +1,50 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.core.constant.RegexConstants;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2DictType;
+
+/**
+ * 字典类型业务对象 sys2_dict_type
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2DictType.class, reverseConvertGenerate = false)
+public class Sys2DictTypeBo extends BaseEntity {
+
+ /**
+ * 字典主键
+ */
+ private Long dictId;
+
+ /**
+ * 字典名称
+ */
+ @NotBlank(message = "字典名称不能为空")
+ @Size(min = 0, max = 100, message = "字典类型名称长度不能超过{max}个字符")
+ private String dictName;
+
+ /**
+ * 字典类型
+ */
+ @NotBlank(message = "字典类型不能为空")
+ @Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符")
+ @Pattern(regexp = RegexConstants.DICTIONARY_TYPE, message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
+ private String dictType;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2LogininforBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2LogininforBo.java
new file mode 100644
index 000000000..335bd608b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2LogininforBo.java
@@ -0,0 +1,87 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.system.saas.domain.Sys2Logininfor;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 系统访问记录业务对象 sys2_logininfor
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@AutoMapper(target = Sys2Logininfor.class, reverseConvertGenerate = false)
+public class Sys2LogininforBo {
+
+ /**
+ * 访问ID
+ */
+ private Long infoId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 用户账号
+ */
+ private String userName;
+
+ /**
+ * 客户端
+ */
+ private String clientKey;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * 登录IP地址
+ */
+ private String ipaddr;
+
+ /**
+ * 登录地点
+ */
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ private String os;
+
+ /**
+ * 登录状态(0成功 1失败)
+ */
+ private String status;
+
+ /**
+ * 提示消息
+ */
+ private String msg;
+
+ /**
+ * 访问时间
+ */
+ private Date loginTime;
+
+ /**
+ * 请求参数
+ */
+ private Map params = new HashMap<>();
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2NoticeBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2NoticeBo.java
new file mode 100644
index 000000000..14268a07f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2NoticeBo.java
@@ -0,0 +1,61 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.core.xss.Xss;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Notice;
+
+/**
+ * 通知公告业务对象 sys2_notice
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Notice.class, reverseConvertGenerate = false)
+public class Sys2NoticeBo extends BaseEntity {
+
+ /**
+ * 公告ID
+ */
+ private Long noticeId;
+
+ /**
+ * 公告标题
+ */
+ @Xss(message = "公告标题不能包含脚本字符")
+ @NotBlank(message = "公告标题不能为空")
+ @Size(min = 0, max = 50, message = "公告标题不能超过{max}个字符")
+ private String noticeTitle;
+
+ /**
+ * 公告类型(1通知 2公告)
+ */
+ private String noticeType;
+
+ /**
+ * 公告内容
+ */
+ private String noticeContent;
+
+ /**
+ * 公告状态(0正常 1关闭)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 创建人名称
+ */
+ private String createByName;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OperLogBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OperLogBo.java
new file mode 100644
index 000000000..7496b0f54
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OperLogBo.java
@@ -0,0 +1,127 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.common.log.event.OperLogEvent;
+import org.dromara.system.saas.domain.Sys2OperLog;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.github.linpeilie.annotations.AutoMappers;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 操作日志记录业务对象 sys2_oper_log
+ *
+ * @author Michelle.Chung
+ * @date 2023-02-07
+ */
+
+@Data
+@AutoMappers({
+ @AutoMapper(target = Sys2OperLog.class, reverseConvertGenerate = false),
+ @AutoMapper(target = OperLogEvent.class)
+})
+public class Sys2OperLogBo {
+
+ /**
+ * 日志主键
+ */
+ private Long operId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 模块标题
+ */
+ private String title;
+
+ /**
+ * 业务类型(0其它 1新增 2修改 3删除)
+ */
+ private Integer businessType;
+
+ /**
+ * 业务类型数组
+ */
+ private Integer[] businessTypes;
+
+ /**
+ * 方法名称
+ */
+ private String method;
+
+ /**
+ * 请求方式
+ */
+ private String requestMethod;
+
+ /**
+ * 操作类别(0其它 1后台用户 2手机端用户)
+ */
+ private Integer operatorType;
+
+ /**
+ * 操作人员
+ */
+ private String operName;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+
+ /**
+ * 请求URL
+ */
+ private String operUrl;
+
+ /**
+ * 主机地址
+ */
+ private String operIp;
+
+ /**
+ * 操作地点
+ */
+ private String operLocation;
+
+ /**
+ * 请求参数
+ */
+ private String operParam;
+
+ /**
+ * 返回参数
+ */
+ private String jsonResult;
+
+ /**
+ * 操作状态(0正常 1异常)
+ */
+ private Integer status;
+
+ /**
+ * 错误消息
+ */
+ private String errorMsg;
+
+ /**
+ * 操作时间
+ */
+ private Date operTime;
+
+ /**
+ * 消耗时间
+ */
+ private Long costTime;
+
+ /**
+ * 请求参数
+ */
+ private Map params = new HashMap<>();
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssBo.java
new file mode 100644
index 000000000..9c3680001
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssBo.java
@@ -0,0 +1,49 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Oss;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * OSS对象存储分页查询对象 sys2_oss
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Oss.class, reverseConvertGenerate = false)
+public class Sys2OssBo extends BaseEntity {
+
+ /**
+ * ossId
+ */
+ private Long ossId;
+
+ /**
+ * 文件名
+ */
+ private String fileName;
+
+ /**
+ * 原名
+ */
+ private String originalName;
+
+ /**
+ * 文件后缀名
+ */
+ private String fileSuffix;
+
+ /**
+ * URL地址
+ */
+ private String url;
+
+ /**
+ * 服务商
+ */
+ private String service;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssConfigBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssConfigBo.java
new file mode 100644
index 000000000..dce191b31
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2OssConfigBo.java
@@ -0,0 +1,109 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2OssConfig;
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 对象存储配置业务对象 sys2_oss_config
+ *
+ * @author Lion Li
+ * @author 孤舟烟雨
+ * @date 2021-08-13
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2OssConfig.class, reverseConvertGenerate = false)
+public class Sys2OssConfigBo extends BaseEntity {
+
+ /**
+ * 主键
+ */
+ @NotNull(message = "主键不能为空", groups = {EditGroup.class})
+ private Long ossConfigId;
+
+ /**
+ * 配置key
+ */
+ @NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class})
+ @Size(min = 2, max = 100, message = "configKey长度必须介于{min}和{max} 之间")
+ private String configKey;
+
+ /**
+ * accessKey
+ */
+ @NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class})
+ @Size(min = 2, max = 100, message = "accessKey长度必须介于{min}和{max} 之间")
+ private String accessKey;
+
+ /**
+ * 秘钥
+ */
+ @NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class})
+ @Size(min = 2, max = 100, message = "secretKey长度必须介于{min}和{max} 之间")
+ private String secretKey;
+
+ /**
+ * 桶名称
+ */
+ @NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class})
+ @Size(min = 2, max = 100, message = "bucketName长度必须介于{min}和{max}之间")
+ private String bucketName;
+
+ /**
+ * 前缀
+ */
+ private String prefix;
+
+ /**
+ * 访问站点
+ */
+ @NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class})
+ @Size(min = 2, max = 100, message = "endpoint长度必须介于{min}和{max}之间")
+ private String endpoint;
+
+ /**
+ * 自定义域名
+ */
+ private String domain;
+
+ /**
+ * 是否https(Y=是,N=否)
+ */
+ private String isHttps;
+
+ /**
+ * 是否默认(0=是,1=否)
+ */
+ private String status;
+
+ /**
+ * 域
+ */
+ private String region;
+
+ /**
+ * 扩展字段
+ */
+ private String ext1;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ @NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class})
+ private String accessPolicy;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2PostBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2PostBo.java
new file mode 100644
index 000000000..7e9628533
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2PostBo.java
@@ -0,0 +1,75 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Post;
+
+/**
+ * 岗位信息业务对象 sys2_post
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Post.class, reverseConvertGenerate = false)
+public class Sys2PostBo extends BaseEntity {
+
+ /**
+ * 岗位ID
+ */
+ private Long postId;
+
+ /**
+ * 部门id(单部门)
+ */
+ @NotNull(message = "部门id不能为空")
+ private Long deptId;
+
+ /**
+ * 归属部门id(部门树)
+ */
+ private Long belongDeptId;
+
+ /**
+ * 岗位编码
+ */
+ @NotBlank(message = "岗位编码不能为空")
+ @Size(min = 0, max = 64, message = "岗位编码长度不能超过{max}个字符")
+ private String postCode;
+
+ /**
+ * 岗位名称
+ */
+ @NotBlank(message = "岗位名称不能为空")
+ @Size(min = 0, max = 50, message = "岗位名称长度不能超过{max}个字符")
+ private String postName;
+
+ /**
+ * 岗位类别编码
+ */
+ @Size(min = 0, max = 100, message = "类别编码长度不能超过{max}个字符")
+ private String postCategory;
+
+ /**
+ * 显示顺序
+ */
+ @NotNull(message = "显示顺序不能为空")
+ private Integer postSort;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2RoleBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2RoleBo.java
new file mode 100644
index 000000000..c37ea65de
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2RoleBo.java
@@ -0,0 +1,94 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2Role;
+
+/**
+ * 角色信息业务对象 sys2_role
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Role.class, reverseConvertGenerate = false)
+public class Sys2RoleBo extends BaseEntity {
+
+ /**
+ * 角色ID
+ */
+ private Long roleId;
+
+ /**
+ * 角色名称
+ */
+ @NotBlank(message = "角色名称不能为空")
+ @Size(min = 0, max = 30, message = "角色名称长度不能超过{max}个字符")
+ private String roleName;
+
+ /**
+ * 角色权限字符串
+ */
+ @NotBlank(message = "角色权限字符串不能为空")
+ @Size(min = 0, max = 100, message = "权限字符长度不能超过{max}个字符")
+ private String roleKey;
+
+ /**
+ * 显示顺序
+ */
+ @NotNull(message = "显示顺序不能为空")
+ private Integer roleSort;
+
+ /**
+ * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)
+ */
+ private String dataScope;
+
+ /**
+ * 菜单树选择项是否关联显示
+ */
+ private Boolean menuCheckStrictly;
+
+ /**
+ * 部门树选择项是否关联显示
+ */
+ private Boolean deptCheckStrictly;
+
+ /**
+ * 角色状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 菜单组
+ */
+ private Long[] menuIds;
+
+ /**
+ * 部门组(数据权限)
+ */
+ private Long[] deptIds;
+
+ public Sys2RoleBo(Long roleId) {
+ this.roleId = roleId;
+ }
+
+ public boolean isSuperAdmin() {
+ return UserConstants.SUPER_ADMIN_ID.equals(this.roleId);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2SocialBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2SocialBo.java
new file mode 100644
index 000000000..72f1e0c0a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2SocialBo.java
@@ -0,0 +1,142 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.tenant.core.TenantEntity;
+import org.dromara.system.saas.domain.Sys2Social;
+
+/**
+ * 社会化关系业务对象 sys2_social
+ *
+ * @author Lion Li
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Social.class, reverseConvertGenerate = false)
+public class Sys2SocialBo extends TenantEntity {
+
+ /**
+ * 主键
+ */
+ @NotNull(message = "主键不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 认证唯一ID
+ */
+ @NotBlank(message = "认证唯一ID不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ @NotBlank(message = "用户来源不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ @NotBlank(message = "用户的授权令牌不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 平台唯一id
+ */
+ private String openId;
+
+ /**
+ * 用户的 ID
+ */
+ @NotBlank(message = "用户的ID不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long userId;
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantApplicationBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantApplicationBo.java
new file mode 100644
index 000000000..5a14a7881
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantApplicationBo.java
@@ -0,0 +1,32 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.system.saas.domain.Sys2TenantApplication;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 租户和应用关联业务对象 sys2_tenant_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2TenantApplication.class, reverseConvertGenerate = false)
+public class Sys2TenantApplicationBo extends BaseEntity {
+
+ @NotNull(message = "租户ID不能为空", groups = {EditGroup.class})
+ private Long tenantId;
+
+ /**
+ * 应用ID
+ */
+ @NotNull(message = "应用ID不能为空", groups = {EditGroup.class})
+ private Long applicationId;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantBo.java
new file mode 100644
index 000000000..19a1456b6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantBo.java
@@ -0,0 +1,114 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.system.saas.domain.Sys2Tenant;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+import java.util.Date;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+/**
+ * 租户业务对象 sys2_tenant
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2Tenant.class, reverseConvertGenerate = false)
+public class Sys2TenantBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ @NotNull(message = "id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 联系人
+ */
+ @NotBlank(message = "联系人不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String contactUserName;
+
+ /**
+ * 联系电话
+ */
+ @NotBlank(message = "联系电话不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String contactPhone;
+
+ /**
+ * 企业名称
+ */
+ @NotBlank(message = "企业名称不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String companyName;
+
+ /**
+ * 用户名(创建系统用户)
+ */
+ @NotBlank(message = "用户名不能为空", groups = { AddGroup.class })
+ private String username;
+
+ /**
+ * 密码(创建系统用户)
+ */
+ @NotBlank(message = "密码不能为空", groups = { AddGroup.class })
+ private String password;
+
+ /**
+ * 统一社会信用代码
+ */
+ private String licenseNumber;
+
+ /**
+ * 地址
+ */
+ private String address;
+
+ /**
+ * 域名
+ */
+ private String domain;
+
+ /**
+ * 企业简介
+ */
+ private String intro;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 租户套餐编号
+ */
+ @NotNull(message = "租户套餐不能为空", groups = { AddGroup.class })
+ private Long packageId;
+
+ /**
+ * 过期时间
+ */
+ private Date expireTime;
+
+ /**
+ * 用户数量(-1不限制)
+ */
+ private Long accountCount;
+
+ /**
+ * 租户状态(0正常 1停用)
+ */
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantPackageBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantPackageBo.java
new file mode 100644
index 000000000..3f9b81205
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2TenantPackageBo.java
@@ -0,0 +1,59 @@
+package org.dromara.system.saas.domain.bo;
+
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.system.saas.domain.Sys2TenantPackage;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.github.linpeilie.annotations.AutoMapping;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+/**
+ * 租户套餐业务对象 sys2_tenant_package
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2TenantPackage.class, reverseConvertGenerate = false)
+public class Sys2TenantPackageBo extends BaseEntity {
+
+ /**
+ * 租户套餐id
+ */
+ @NotNull(message = "租户套餐id不能为空", groups = { EditGroup.class })
+ private Long packageId;
+
+ /**
+ * 套餐名称
+ */
+ @NotBlank(message = "套餐名称不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String packageName;
+
+ /**
+ * 关联菜单id
+ */
+ @AutoMapping(target = "menuIds", expression = "java(org.dromara.common.core.utils.StringUtils.join(source.getMenuIds(), \",\"))")
+ private Long[] menuIds;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 菜单树选择项是否关联显示
+ */
+ private Boolean menuCheckStrictly;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserBo.java
new file mode 100644
index 000000000..c4db816bd
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserBo.java
@@ -0,0 +1,125 @@
+package org.dromara.system.saas.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.core.xss.Xss;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.Sys2User;
+
+/**
+ * 用户信息业务对象 sys2_user
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Sys2User.class, reverseConvertGenerate = false)
+public class Sys2UserBo extends BaseEntity {
+
+ /**
+ * 应用id
+ */
+ @NotBlank(message = "不能为空")
+ private Long applicationId;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 用户账号
+ */
+ @Xss(message = "用户账号不能包含脚本字符")
+ @NotBlank(message = "用户账号不能为空")
+ @Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
+ private String userName;
+
+ /**
+ * 用户昵称
+ */
+ @Xss(message = "用户昵称不能包含脚本字符")
+ @NotBlank(message = "用户昵称不能为空")
+ @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
+ private String nickName;
+
+ /**
+ * 用户类型(sys2_user系统用户)
+ */
+ private String userType;
+
+ /**
+ * 用户邮箱
+ */
+ @Email(message = "邮箱格式不正确")
+ @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ private String phonenumber;
+
+ /**
+ * 用户性别(0男 1女 2未知)
+ */
+ private String sex;
+
+ /**
+ * 密码
+ */
+ private String password;
+
+ /**
+ * 帐号状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 角色组
+ */
+ @Size(min = 1, message = "用户角色不能为空")
+ private Long[] roleIds;
+
+ /**
+ * 岗位组
+ */
+ private Long[] postIds;
+
+ /**
+ * 数据权限 当前角色ID
+ */
+ private Long roleId;
+
+ /**
+ * 排除不查询的用户(工作流用)
+ */
+ private String excludeUserIds;
+
+ public Sys2UserBo(Long userId) {
+ this.userId = userId;
+ }
+
+ public boolean isSuperAdmin() {
+ return UserConstants.SUPER_ADMIN_ID.equals(this.userId);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserPasswordBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserPasswordBo.java
new file mode 100644
index 000000000..2eae6017d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserPasswordBo.java
@@ -0,0 +1,29 @@
+package org.dromara.system.saas.domain.bo;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 用户密码修改bo
+ */
+@Data
+public class Sys2UserPasswordBo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 旧密码
+ */
+ @NotBlank(message = "旧密码不能为空")
+ private String oldPassword;
+
+ /**
+ * 新密码
+ */
+ @NotBlank(message = "新密码不能为空")
+ private String newPassword;
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserProfileBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserProfileBo.java
new file mode 100644
index 000000000..d799d9ff0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/Sys2UserProfileBo.java
@@ -0,0 +1,53 @@
+package org.dromara.system.saas.domain.bo;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.dromara.common.core.constant.RegexConstants;
+import org.dromara.common.core.xss.Xss;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.sensitive.annotation.Sensitive;
+import org.dromara.common.sensitive.core.SensitiveStrategy;
+
+/**
+ * 个人信息业务处理
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class Sys2UserProfileBo extends BaseEntity {
+
+ /**
+ * 用户昵称
+ */
+ @Xss(message = "用户昵称不能包含脚本字符")
+ @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
+ private String nickName;
+
+ /**
+ * 用户邮箱
+ */
+ @Sensitive(strategy = SensitiveStrategy.EMAIL)
+ @Email(message = "邮箱格式不正确")
+ @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ @Pattern(regexp = RegexConstants.MOBILE, message = "手机号格式不正确")
+ @Sensitive(strategy = SensitiveStrategy.PHONE)
+ private String phonenumber;
+
+ /**
+ * 用户性别(0男 1女 2未知)
+ */
+ private String sex;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/SysSaasMenuBo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/SysSaasMenuBo.java
new file mode 100644
index 000000000..a229f2f1b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/bo/SysSaasMenuBo.java
@@ -0,0 +1,110 @@
+package org.dromara.system.saas.domain.bo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.core.constant.RegexConstants;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.system.saas.domain.SysSaasMenu;
+
+/**
+ * 菜单权限业务对象 sys_saas_menu
+ *
+ * @author Michelle.Chung
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = SysSaasMenu.class, reverseConvertGenerate = false)
+public class SysSaasMenuBo extends BaseEntity {
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+ /**
+ * 父菜单ID
+ */
+ private Long parentId;
+
+ /**
+ * 菜单名称
+ */
+ @NotBlank(message = "菜单名称不能为空")
+ @Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符")
+ private String menuName;
+
+ /**
+ * 显示顺序
+ */
+ @NotNull(message = "显示顺序不能为空")
+ private Integer orderNum;
+
+ /**
+ * 路由地址
+ */
+ @Size(min = 0, max = 200, message = "路由地址不能超过{max}个字符")
+ private String path;
+
+ /**
+ * 组件路径
+ */
+ @Size(min = 0, max = 200, message = "组件路径不能超过{max}个字符")
+ private String component;
+
+ /**
+ * 路由参数
+ */
+ private String queryParam;
+
+ /**
+ * 是否为外链(0是 1否)
+ */
+ private String isFrame;
+
+ /**
+ * 是否缓存(0缓存 1不缓存)
+ */
+ private String isCache;
+
+ /**
+ * 菜单类型(M目录 C菜单 F按钮)
+ */
+ @NotBlank(message = "菜单类型不能为空")
+ private String menuType;
+
+ /**
+ * 显示状态(0显示 1隐藏)
+ */
+ private String visible;
+
+ /**
+ * 菜单状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 权限标识
+ */
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ @Size(min = 0, max = 100, message = "权限标识长度不能超过{max}个字符")
+ @Pattern(regexp = RegexConstants.PERMISSION_STRING, message = "权限标识必须符合 tool:build:list 格式")
+ private String perms;
+
+ /**
+ * 菜单图标
+ */
+ private String icon;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ApplicationVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ApplicationVo.java
new file mode 100644
index 000000000..b892df21f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ApplicationVo.java
@@ -0,0 +1,46 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.system.saas.domain.Sys2Application;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 应用视图对象 sys_saas_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Application.class)
+public class Sys2ApplicationVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private Long applicationId;
+
+ /**
+ * 应用名称
+ */
+ @ExcelProperty(value = "应用名称")
+ private String applicationName;
+
+ /**
+ * 应用code
+ */
+ @ExcelProperty(value = "应用code")
+ private String applicationCode;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ClientVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ClientVo.java
new file mode 100644
index 000000000..5d5b35616
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ClientVo.java
@@ -0,0 +1,90 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.system.saas.domain.Sys2Client;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * 授权管理视图对象 sys2_client
+ *
+ * @author Michelle.Chung
+ * @date 2023-05-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Client.class)
+public class Sys2ClientVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private Long id;
+
+ /**
+ * 客户端id
+ */
+ @ExcelProperty(value = "客户端id")
+ private String clientId;
+
+ /**
+ * 客户端key
+ */
+ @ExcelProperty(value = "客户端key")
+ private String clientKey;
+
+ /**
+ * 客户端秘钥
+ */
+ @ExcelProperty(value = "客户端秘钥")
+ private String clientSecret;
+
+ /**
+ * 授权类型
+ */
+ @ExcelProperty(value = "授权类型")
+ private List grantTypeList;
+
+ /**
+ * 授权类型
+ */
+ private String grantType;
+
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+
+ /**
+ * token活跃超时时间
+ */
+ @ExcelProperty(value = "token活跃超时时间")
+ private Long activeTimeout;
+
+ /**
+ * token固定超时时间
+ */
+ @ExcelProperty(value = "token固定超时时间")
+ private Long timeout;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ConfigVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ConfigVo.java
new file mode 100644
index 000000000..0c2a644ef
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2ConfigVo.java
@@ -0,0 +1,72 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2Config;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 参数配置视图对象 sys2_config
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Config.class)
+public class Sys2ConfigVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 参数主键
+ */
+ @ExcelProperty(value = "参数主键")
+ private Long configId;
+
+ /**
+ * 参数名称
+ */
+ @ExcelProperty(value = "参数名称")
+ private String configName;
+
+ /**
+ * 参数键名
+ */
+ @ExcelProperty(value = "参数键名")
+ private String configKey;
+
+ /**
+ * 参数键值
+ */
+ @ExcelProperty(value = "参数键值")
+ private String configValue;
+
+ /**
+ * 系统内置(Y是 N否)
+ */
+ @ExcelProperty(value = "系统内置", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_yes_no")
+ private String configType;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DeptVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DeptVo.java
new file mode 100644
index 000000000..c84d315b1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DeptVo.java
@@ -0,0 +1,102 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2Dept;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 部门视图对象 sys2_dept
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Dept.class)
+public class Sys2DeptVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 部门id
+ */
+ @ExcelProperty(value = "部门id")
+ private Long deptId;
+
+ /**
+ * 父部门id
+ */
+ private Long parentId;
+
+ /**
+ * 父部门名称
+ */
+ private String parentName;
+
+ /**
+ * 祖级列表
+ */
+ private String ancestors;
+
+ /**
+ * 部门名称
+ */
+ @ExcelProperty(value = "部门名称")
+ private String deptName;
+
+ /**
+ * 部门类别编码
+ */
+ @ExcelProperty(value = "部门类别编码")
+ private String deptCategory;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 负责人ID
+ */
+ private Long leader;
+
+ /**
+ * 负责人
+ */
+ @ExcelProperty(value = "负责人")
+ private String leaderName;
+
+ /**
+ * 联系电话
+ */
+ @ExcelProperty(value = "联系电话")
+ private String phone;
+
+ /**
+ * 邮箱
+ */
+ @ExcelProperty(value = "邮箱")
+ private String email;
+
+ /**
+ * 部门状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "部门状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_normal_disable")
+ private String status;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictDataVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictDataVo.java
new file mode 100644
index 000000000..c79c58be1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictDataVo.java
@@ -0,0 +1,88 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2DictData;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 字典数据视图对象 sys2_dict_data
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2DictData.class)
+public class Sys2DictDataVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 字典编码
+ */
+ @ExcelProperty(value = "字典编码")
+ private Long dictCode;
+
+ /**
+ * 字典排序
+ */
+ @ExcelProperty(value = "字典排序")
+ private Integer dictSort;
+
+ /**
+ * 字典标签
+ */
+ @ExcelProperty(value = "字典标签")
+ private String dictLabel;
+
+ /**
+ * 字典键值
+ */
+ @ExcelProperty(value = "字典键值")
+ private String dictValue;
+
+ /**
+ * 字典类型
+ */
+ @ExcelProperty(value = "字典类型")
+ private String dictType;
+
+ /**
+ * 样式属性(其他样式扩展)
+ */
+ private String cssClass;
+
+ /**
+ * 表格回显样式
+ */
+ private String listClass;
+
+ /**
+ * 是否默认(Y是 N否)
+ */
+ @ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_yes_no")
+ private String isDefault;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictTypeVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictTypeVo.java
new file mode 100644
index 000000000..e0ad7cc09
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2DictTypeVo.java
@@ -0,0 +1,57 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.system.saas.domain.Sys2DictType;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 字典类型视图对象 sys2_dict_type
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2DictType.class)
+public class Sys2DictTypeVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 字典主键
+ */
+ @ExcelProperty(value = "字典主键")
+ private Long dictId;
+
+ /**
+ * 字典名称
+ */
+ @ExcelProperty(value = "字典名称")
+ private String dictName;
+
+ /**
+ * 字典类型
+ */
+ @ExcelProperty(value = "字典类型")
+ private String dictType;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2LogininforVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2LogininforVo.java
new file mode 100644
index 000000000..f3c5ed2fc
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2LogininforVo.java
@@ -0,0 +1,106 @@
+package org.dromara.system.saas.domain.vo;
+
+import java.util.Date;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2Logininfor;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+
+/**
+ * 系统访问记录视图对象 sys2_logininfor
+ *
+ * @author Michelle.Chung
+ * @date 2023-02-07
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Logininfor.class)
+public class Sys2LogininforVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 访问ID
+ */
+ @ExcelProperty(value = "序号")
+ private Long infoId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 用户账号
+ */
+ @ExcelProperty(value = "用户账号")
+ private String userName;
+
+ /**
+ * 客户端
+ */
+ @ExcelProperty(value = "客户端")
+ private String clientKey;
+
+ /**
+ * 设备类型
+ */
+ @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_device_type")
+ private String deviceType;
+
+ /**
+ * 登录状态(0成功 1失败)
+ */
+ @ExcelProperty(value = "登录状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_common_status")
+ private String status;
+
+ /**
+ * 登录IP地址
+ */
+ @ExcelProperty(value = "登录地址")
+ private String ipaddr;
+
+ /**
+ * 登录地点
+ */
+ @ExcelProperty(value = "登录地点")
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ @ExcelProperty(value = "浏览器")
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ @ExcelProperty(value = "操作系统")
+ private String os;
+
+
+ /**
+ * 提示消息
+ */
+ @ExcelProperty(value = "提示消息")
+ private String msg;
+
+ /**
+ * 访问时间
+ */
+ @ExcelProperty(value = "访问时间")
+ private Date loginTime;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2NoticeVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2NoticeVo.java
new file mode 100644
index 000000000..dd334ebd4
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2NoticeVo.java
@@ -0,0 +1,73 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.system.saas.domain.Sys2Notice;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 通知公告视图对象 sys2_notice
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@AutoMapper(target = Sys2Notice.class)
+public class Sys2NoticeVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 公告ID
+ */
+ private Long noticeId;
+
+ /**
+ * 公告标题
+ */
+ private String noticeTitle;
+
+ /**
+ * 公告类型(1通知 2公告)
+ */
+ private String noticeType;
+
+ /**
+ * 公告内容
+ */
+ private String noticeContent;
+
+ /**
+ * 公告状态(0正常 1关闭)
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 创建者
+ */
+ private Long createBy;
+
+ /**
+ * 创建人名称
+ */
+ @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
+ private String createByName;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OperLogVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OperLogVo.java
new file mode 100644
index 000000000..607cc0b1d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OperLogVo.java
@@ -0,0 +1,144 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2OperLog;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 操作日志记录视图对象 sys2_oper_log
+ *
+ * @author Michelle.Chung
+ * @date 2023-02-07
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2OperLog.class)
+public class Sys2OperLogVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 日志主键
+ */
+ @ExcelProperty(value = "日志主键")
+ private Long operId;
+
+ /**
+ * 租户编号
+ */
+ private String tenantId;
+
+ /**
+ * 模块标题
+ */
+ @ExcelProperty(value = "操作模块")
+ private String title;
+
+ /**
+ * 业务类型(0其它 1新增 2修改 3删除)
+ */
+ @ExcelProperty(value = "业务类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_oper_type")
+ private Integer businessType;
+
+ /**
+ * 业务类型数组
+ */
+ private Integer[] businessTypes;
+
+ /**
+ * 方法名称
+ */
+ @ExcelProperty(value = "请求方法")
+ private String method;
+
+ /**
+ * 请求方式
+ */
+ @ExcelProperty(value = "请求方式")
+ private String requestMethod;
+
+ /**
+ * 操作类别(0其它 1后台用户 2手机端用户)
+ */
+ @ExcelProperty(value = "操作类别", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "0=其它,1=后台用户,2=手机端用户")
+ private Integer operatorType;
+
+ /**
+ * 操作人员
+ */
+ @ExcelProperty(value = "操作人员")
+ private String operName;
+
+ /**
+ * 部门名称
+ */
+ @ExcelProperty(value = "部门名称")
+ private String deptName;
+
+ /**
+ * 请求URL
+ */
+ @ExcelProperty(value = "请求地址")
+ private String operUrl;
+
+ /**
+ * 主机地址
+ */
+ @ExcelProperty(value = "操作地址")
+ private String operIp;
+
+ /**
+ * 操作地点
+ */
+ @ExcelProperty(value = "操作地点")
+ private String operLocation;
+
+ /**
+ * 请求参数
+ */
+ @ExcelProperty(value = "请求参数")
+ private String operParam;
+
+ /**
+ * 返回参数
+ */
+ @ExcelProperty(value = "返回参数")
+ private String jsonResult;
+
+ /**
+ * 操作状态(0正常 1异常)
+ */
+ @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_common_status")
+ private Integer status;
+
+ /**
+ * 错误消息
+ */
+ @ExcelProperty(value = "错误消息")
+ private String errorMsg;
+
+ /**
+ * 操作时间
+ */
+ @ExcelProperty(value = "操作时间")
+ private Date operTime;
+
+ /**
+ * 消耗时间
+ */
+ @ExcelProperty(value = "消耗时间")
+ private Long costTime;
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssConfigVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssConfigVo.java
new file mode 100644
index 000000000..137f3f3e0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssConfigVo.java
@@ -0,0 +1,97 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import org.dromara.system.saas.domain.Sys2OssConfig;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 对象存储配置视图对象 sys2_oss_config
+ *
+ * @author Lion Li
+ * @author 孤舟烟雨
+ * @date 2021-08-13
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2OssConfig.class)
+public class Sys2OssConfigVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ private Long ossConfigId;
+
+ /**
+ * 配置key
+ */
+ private String configKey;
+
+ /**
+ * accessKey
+ */
+ private String accessKey;
+
+ /**
+ * 秘钥
+ */
+ private String secretKey;
+
+ /**
+ * 桶名称
+ */
+ private String bucketName;
+
+ /**
+ * 前缀
+ */
+ private String prefix;
+
+ /**
+ * 访问站点
+ */
+ private String endpoint;
+
+ /**
+ * 自定义域名
+ */
+ private String domain;
+
+ /**
+ * 是否https(Y=是,N=否)
+ */
+ private String isHttps;
+
+ /**
+ * 域
+ */
+ private String region;
+
+ /**
+ * 是否默认(0=是,1=否)
+ */
+ private String status;
+
+ /**
+ * 扩展字段
+ */
+ private String ext1;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ private String accessPolicy;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssUploadVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssUploadVo.java
new file mode 100644
index 000000000..82d40d872
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssUploadVo.java
@@ -0,0 +1,28 @@
+package org.dromara.system.saas.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 上传对象信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class Sys2OssUploadVo {
+
+ /**
+ * URL地址
+ */
+ private String url;
+
+ /**
+ * 文件名
+ */
+ private String fileName;
+
+ /**
+ * 对象存储主键
+ */
+ private String ossId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssVo.java
new file mode 100644
index 000000000..ce3d24973
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2OssVo.java
@@ -0,0 +1,72 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.system.saas.domain.Sys2Oss;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * OSS对象存储视图对象 sys2_oss
+ *
+ * @author Lion Li
+ */
+@Data
+@AutoMapper(target = Sys2Oss.class)
+public class Sys2OssVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 对象存储主键
+ */
+ private Long ossId;
+
+ /**
+ * 文件名
+ */
+ private String fileName;
+
+ /**
+ * 原名
+ */
+ private String originalName;
+
+ /**
+ * 文件后缀名
+ */
+ private String fileSuffix;
+
+ /**
+ * URL地址
+ */
+ private String url;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 上传人
+ */
+ private Long createBy;
+
+ /**
+ * 上传人名称
+ */
+ @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
+ private String createByName;
+
+ /**
+ * 服务商
+ */
+ private String service;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2PostVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2PostVo.java
new file mode 100644
index 000000000..dfbde3cbd
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2PostVo.java
@@ -0,0 +1,91 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.system.saas.domain.Sys2Post;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 岗位信息视图对象 sys2_post
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Post.class)
+public class Sys2PostVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 岗位ID
+ */
+ @ExcelProperty(value = "岗位序号")
+ private Long postId;
+
+ /**
+ * 部门id
+ */
+ @ExcelProperty(value = "部门id")
+ private Long deptId;
+
+ /**
+ * 岗位编码
+ */
+ @ExcelProperty(value = "岗位编码")
+ private String postCode;
+
+ /**
+ * 岗位名称
+ */
+ @ExcelProperty(value = "岗位名称")
+ private String postName;
+
+ /**
+ * 岗位类别编码
+ */
+ @ExcelProperty(value = "类别编码")
+ private String postCategory;
+
+ /**
+ * 显示顺序
+ */
+ @ExcelProperty(value = "岗位排序")
+ private Integer postSort;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_normal_disable")
+ private String status;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+ /**
+ * 部门名
+ */
+ @Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "deptId")
+ private String deptName;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2RoleVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2RoleVo.java
new file mode 100644
index 000000000..80cbc4e75
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2RoleVo.java
@@ -0,0 +1,100 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.core.constant.UserConstants;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2Role;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 角色信息视图对象 sys2_role
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Role.class)
+public class Sys2RoleVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 角色ID
+ */
+ @ExcelProperty(value = "角色序号")
+ private Long roleId;
+
+ /**
+ * 角色名称
+ */
+ @ExcelProperty(value = "角色名称")
+ private String roleName;
+
+ /**
+ * 角色权限字符串
+ */
+ @ExcelProperty(value = "角色权限")
+ private String roleKey;
+
+ /**
+ * 显示顺序
+ */
+ @ExcelProperty(value = "角色排序")
+ private Integer roleSort;
+
+ /**
+ * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)
+ */
+ @ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
+ private String dataScope;
+
+ /**
+ * 菜单树选择项是否关联显示
+ */
+ @ExcelProperty(value = "菜单树选择项是否关联显示")
+ private Boolean menuCheckStrictly;
+
+ /**
+ * 部门树选择项是否关联显示
+ */
+ @ExcelProperty(value = "部门树选择项是否关联显示")
+ private Boolean deptCheckStrictly;
+
+ /**
+ * 角色状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_normal_disable")
+ private String status;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+ /**
+ * 用户是否存在此角色标识 默认不存在
+ */
+ private boolean flag = false;
+
+ public boolean isSuperAdmin() {
+ return UserConstants.SUPER_ADMIN_ID.equals(this.roleId);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2SocialVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2SocialVo.java
new file mode 100644
index 000000000..fe62c83d6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2SocialVo.java
@@ -0,0 +1,144 @@
+package org.dromara.system.saas.domain.vo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.system.saas.domain.Sys2Social;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 社会化关系视图对象 sys2_social
+ *
+ * @author thiszhc
+ */
+@Data
+@AutoMapper(target = Sys2Social.class)
+public class Sys2SocialVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 租户ID
+ */
+ private String tenantId;
+
+ /**
+ * 的唯一ID
+ */
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 用户的 open id
+ */
+ private String openId;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantApplicationVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantApplicationVo.java
new file mode 100644
index 000000000..71e8532e0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantApplicationVo.java
@@ -0,0 +1,38 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.system.saas.domain.Sys2TenantApplication;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 租户和应用关联视图对象 sys2_tenant_application
+ *
+ * @author Lion Li
+ * @date 2024-09-22
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2TenantApplication.class)
+public class Sys2TenantApplicationVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+
+ @ExcelProperty(value = "应用ID")
+ private Long tenantId;
+
+ /**
+ * 应用ID
+ */
+ @ExcelProperty(value = "应用ID")
+ private Long applicationId;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantPackageVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantPackageVo.java
new file mode 100644
index 000000000..bc842253e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantPackageVo.java
@@ -0,0 +1,66 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2TenantPackage;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 租户套餐视图对象 sys2_tenant_package
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2TenantPackage.class)
+public class Sys2TenantPackageVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 租户套餐id
+ */
+ @ExcelProperty(value = "租户套餐id")
+ private Long packageId;
+
+ /**
+ * 套餐名称
+ */
+ @ExcelProperty(value = "套餐名称")
+ private String packageName;
+
+ /**
+ * 关联菜单id
+ */
+ @ExcelProperty(value = "关联菜单id")
+ private String menuIds;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 菜单树选择项是否关联显示
+ */
+ @ExcelProperty(value = "菜单树选择项是否关联显示")
+ private Boolean menuCheckStrictly;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantVo.java
new file mode 100644
index 000000000..75c373a6a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2TenantVo.java
@@ -0,0 +1,115 @@
+package org.dromara.system.saas.domain.vo;
+
+import java.util.Date;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.system.saas.domain.Sys2Tenant;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 租户视图对象 sys2_tenant
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Sys2Tenant.class)
+public class Sys2TenantVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private Long id;
+
+ /**
+ * 租户编号
+ */
+ @ExcelProperty(value = "租户编号")
+ private String tenantId;
+
+ /**
+ * 联系人
+ */
+ @ExcelProperty(value = "联系人")
+ private String contactUserName;
+
+ /**
+ * 联系电话
+ */
+ @ExcelProperty(value = "联系电话")
+ private String contactPhone;
+
+ /**
+ * 企业名称
+ */
+ @ExcelProperty(value = "企业名称")
+ private String companyName;
+
+ /**
+ * 统一社会信用代码
+ */
+ @ExcelProperty(value = "统一社会信用代码")
+ private String licenseNumber;
+
+ /**
+ * 地址
+ */
+ @ExcelProperty(value = "地址")
+ private String address;
+
+ /**
+ * 域名
+ */
+ @ExcelProperty(value = "域名")
+ private String domain;
+
+ /**
+ * 企业简介
+ */
+ @ExcelProperty(value = "企业简介")
+ private String intro;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 租户套餐编号
+ */
+ @ExcelProperty(value = "租户套餐编号")
+ private Long packageId;
+
+ /**
+ * 过期时间
+ */
+ @ExcelProperty(value = "过期时间")
+ private Date expireTime;
+
+ /**
+ * 用户数量(-1不限制)
+ */
+ @ExcelProperty(value = "用户数量")
+ private Long accountCount;
+
+ /**
+ * 租户状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "租户状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+ private String status;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserExportVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserExportVo.java
new file mode 100644
index 000000000..4d32efa28
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserExportVo.java
@@ -0,0 +1,94 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 用户对象导出VO
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+public class Sys2UserExportVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ @ExcelProperty(value = "用户序号")
+ private Long userId;
+
+ /**
+ * 用户账号
+ */
+ @ExcelProperty(value = "登录名称")
+ private String userName;
+
+ /**
+ * 用户昵称
+ */
+ @ExcelProperty(value = "用户名称")
+ private String nickName;
+
+ /**
+ * 用户邮箱
+ */
+ @ExcelProperty(value = "用户邮箱")
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ @ExcelProperty(value = "手机号码")
+ private String phonenumber;
+
+ /**
+ * 用户性别
+ */
+ @ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_user_sex")
+ private String sex;
+
+ /**
+ * 帐号状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_normal_disable")
+ private String status;
+
+ /**
+ * 最后登录IP
+ */
+ @ExcelProperty(value = "最后登录IP")
+ private String loginIp;
+
+ /**
+ * 最后登录时间
+ */
+ @ExcelProperty(value = "最后登录时间")
+ private Date loginDate;
+
+ /**
+ * 部门名称
+ */
+ @ExcelProperty(value = "部门名称")
+ private String deptName;
+
+ /**
+ * 负责人
+ */
+ @ExcelProperty(value = "部门负责人")
+ private String leaderName;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserImportVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserImportVo.java
new file mode 100644
index 000000000..e6a888bd3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserImportVo.java
@@ -0,0 +1,76 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 用户对象导入VO
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+// @Accessors(chain = true) // 导入不允许使用 会找不到set方法
+public class Sys2UserImportVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ @ExcelProperty(value = "用户序号")
+ private Long userId;
+
+ /**
+ * 部门ID
+ */
+ @ExcelProperty(value = "部门编号")
+ private Long deptId;
+
+ /**
+ * 用户账号
+ */
+ @ExcelProperty(value = "登录名称")
+ private String userName;
+
+ /**
+ * 用户昵称
+ */
+ @ExcelProperty(value = "用户名称")
+ private String nickName;
+
+ /**
+ * 用户邮箱
+ */
+ @ExcelProperty(value = "用户邮箱")
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ @ExcelProperty(value = "手机号码")
+ private String phonenumber;
+
+ /**
+ * 用户性别
+ */
+ @ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_user_sex")
+ private String sex;
+
+ /**
+ * 帐号状态(0正常 1停用)
+ */
+ @ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "sys2_normal_disable")
+ private String status;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserInfoVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserInfoVo.java
new file mode 100644
index 000000000..674c5b04b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserInfoVo.java
@@ -0,0 +1,40 @@
+package org.dromara.system.saas.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 用户信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class Sys2UserInfoVo {
+
+ /**
+ * 用户信息
+ */
+ private Sys2UserVo user;
+
+ /**
+ * 角色ID列表
+ */
+ private List roleIds;
+
+ /**
+ * 角色列表
+ */
+ private List roles;
+
+ /**
+ * 岗位ID列表
+ */
+ private List postIds;
+
+ /**
+ * 岗位列表
+ */
+ private List posts;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserVo.java
new file mode 100644
index 000000000..4af26ca59
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/Sys2UserVo.java
@@ -0,0 +1,142 @@
+package org.dromara.system.saas.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.dromara.common.sensitive.annotation.Sensitive;
+import org.dromara.common.sensitive.core.SensitiveStrategy;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.system.saas.domain.Sys2User;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * 用户信息视图对象 sys2_user
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@AutoMapper(target = Sys2User.class)
+public class Sys2UserVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 租户ID
+ */
+ private String tenantId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 用户账号
+ */
+ private String userName;
+
+ /**
+ * 用户昵称
+ */
+ private String nickName;
+
+ /**
+ * 用户类型(sys2_user系统用户)
+ */
+ private String userType;
+
+ /**
+ * 用户邮箱
+ */
+ @Sensitive(strategy = SensitiveStrategy.EMAIL, perms = "system:user:edit")
+ private String email;
+
+ /**
+ * 手机号码
+ */
+ @Sensitive(strategy = SensitiveStrategy.PHONE, perms = "system:user:edit")
+ private String phonenumber;
+
+ /**
+ * 用户性别(0男 1女 2未知)
+ */
+ private String sex;
+
+ /**
+ * 头像地址
+ */
+ @Translation(type = TransConstant.OSS_ID_TO_URL)
+ private Long avatar;
+
+ /**
+ * 密码
+ */
+ @JsonIgnore
+ @JsonProperty
+ private String password;
+
+ /**
+ * 帐号状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 最后登录IP
+ */
+ private String loginIp;
+
+ /**
+ * 最后登录时间
+ */
+ private Date loginDate;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 部门名
+ */
+ @Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "deptId")
+ private String deptName;
+
+ /**
+ * 角色对象
+ */
+ private List roles;
+
+ /**
+ * 角色组
+ */
+ private Long[] roleIds;
+
+ /**
+ * 岗位组
+ */
+ private Long[] postIds;
+
+ /**
+ * 数据权限 当前角色ID
+ */
+ private Long roleId;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/SysSaasMenuVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/SysSaasMenuVo.java
new file mode 100644
index 000000000..8e3052cd3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/SysSaasMenuVo.java
@@ -0,0 +1,119 @@
+package org.dromara.system.saas.domain.vo;
+
+import org.dromara.system.saas.domain.SysSaasMenu;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * 菜单权限视图对象 sys_saas_menu
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@AutoMapper(target = SysSaasMenu.class)
+public class SysSaasMenuVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+ /**
+ * 应用id
+ */
+ private Long applicationId;
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+ /**
+ * 菜单名称
+ */
+ private String menuName;
+
+ /**
+ * 父菜单ID
+ */
+ private Long parentId;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 路由地址
+ */
+ private String path;
+
+ /**
+ * 组件路径
+ */
+ private String component;
+
+ /**
+ * 路由参数
+ */
+ private String queryParam;
+
+ /**
+ * 是否为外链(0是 1否)
+ */
+ private String isFrame;
+
+ /**
+ * 是否缓存(0缓存 1不缓存)
+ */
+ private String isCache;
+
+ /**
+ * 菜单类型(A应用 M目录 C菜单 F按钮 A应用)
+ */
+ private String menuType;
+
+ /**
+ * 显示状态(0显示 1隐藏)
+ */
+ private String visible;
+
+ /**
+ * 菜单状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 权限标识
+ */
+ private String perms;
+
+ /**
+ * 菜单图标
+ */
+ private String icon;
+
+ /**
+ * 创建部门
+ */
+ private Long createDept;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 子菜单
+ */
+ private List children = new ArrayList<>();
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoAvatarVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoAvatarVo.java
new file mode 100644
index 000000000..595c9651e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoAvatarVo.java
@@ -0,0 +1,18 @@
+package org.dromara.system.saas.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 用户头像信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class TwoAvatarVo {
+
+ /**
+ * 头像地址
+ */
+ private String imgUrl;
+
+}
diff --git a/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoCacheListInfoVo.java b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoCacheListInfoVo.java
new file mode 100644
index 000000000..87752f19e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system-saas/src/main/java/org/dromara/system/saas/domain/vo/TwoCacheListInfoVo.java
@@ -0,0 +1,23 @@
+package org.dromara.system.saas.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * 缓存监控列表信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class TwoCacheListInfoVo {
+
+ private Properties info;
+
+ private Long dbSize;
+
+ private List