diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 8c3f27f..36079d1 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -37,6 +37,11 @@
             <artifactId>postgresql</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-tenant</artifactId>
+        </dependency>
+
         <!-- system模块-->
         <dependency>
             <groupId>com.ruoyi</groupId>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
index 30b6e19..a2b8024 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
@@ -1,31 +1,38 @@
 package com.ruoyi.web.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.mybatisflex.core.query.QueryWrapper;
-import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.UserConstants;
 import com.ruoyi.common.core.core.domain.AjaxResult;
 import com.ruoyi.common.core.core.domain.model.LoginUser;
+import com.ruoyi.common.core.utils.*;
+import com.ruoyi.common.encrypt.annotation.ApiEncrypt;
+import com.ruoyi.common.json.utils.JsonUtils;
 import com.ruoyi.common.security.utils.LoginHelper;
-import com.ruoyi.system.domain.SysMenu;
-import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.tenant.helper.TenantHelper;
+import com.ruoyi.system.domain.bo.SysTenantBo;
+import com.ruoyi.system.domain.vo.SysTenantVo;
 import com.ruoyi.system.domain.vo.SysUserVo;
 import com.ruoyi.system.service.*;
+import com.ruoyi.web.domain.vo.LoginTenantVo;
 import com.ruoyi.web.domain.vo.LoginVo;
+import com.ruoyi.web.domain.vo.TenantListVo;
 import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import com.ruoyi.common.core.core.domain.R;
 import com.ruoyi.common.core.core.domain.model.LoginBody;
 import com.ruoyi.common.core.core.domain.model.RegisterBody;
-import com.ruoyi.common.core.utils.MessageUtils;
-import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.system.domain.SysClient;
 import com.ruoyi.web.service.IAuthStrategy;
 import com.ruoyi.web.service.SysLoginService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.net.URL;
 import java.util.List;
 import java.util.Set;
 
@@ -42,29 +49,27 @@ import static com.ruoyi.system.domain.table.SysClientTableDef.SYS_CLIENT;
 @Validated
 @RequiredArgsConstructor
 @RestController
+@RequestMapping("/auth")
 public class AuthController {
 
     @Resource
-    private final SysLoginService loginService;
+    private  SysLoginService loginService;
     @Resource
-    private final ISysClientService clientService;
+    private  ISysClientService clientService;
     @Resource
-    private final ISysUserService sysUserService;
-    @Resource
-    private final ISysPermissionService permissionService;
-    @Resource
-    private ISysMenuService menuService;
+    private ISysTenantService tenantService;
 
     /**
      * 登录方法
      *
-     * @param loginBody 登录信息
+     * @param body 登录信息
      * @return 结果
      */
+    @ApiEncrypt
     @PostMapping("/login")
-    public R<LoginVo> login(@RequestBody LoginBody loginBody) {
-
-        AjaxResult ajax = AjaxResult.success();
+    public R<LoginVo> login(@RequestBody String body) {
+        LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
+        ValidatorUtils.validate(loginBody);
         // 授权类型和客户端id
         String clientId = loginBody.getClientId();
         String grantType = loginBody.getGrantType();
@@ -74,53 +79,14 @@ public class AuthController {
         if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) {
             log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
             return R.fail(MessageUtils.message("auth.grant.type.error"));
+        } else if (!UserConstants.NORMAL.equals(client.getStatus())) {
+            return R.fail(MessageUtils.message("auth.grant.type.blocked"));
         }
-
-        // TODO:校验租户
-        //loginService.checkTenant(loginBody.getTenantId());
+        // 校验租户
+        loginService.checkTenant(loginBody.getTenantId());
 
         // 登录
-        return R.ok(IAuthStrategy.login(loginBody, client));
-    }
-
-    /**
-     * 获取用户信息
-     *
-     * @return 用户信息
-     */
-    @GetMapping("/getInfo")
-    public AjaxResult getInfo() {
-
-        LoginUser loginUser = LoginHelper.getLoginUser();
-
-        //TODO:多租户 超级管理员 如果重新加载用户信息需清除动态租户
-
-        SysUserVo user = sysUserService.selectUserById(loginUser.getUserId());
-        // 角色集合
-        Set<String> roles = permissionService.getRolePermission(user.getUserId());
-        // 权限集合
-        Set<String> permissions = permissionService.getMenuPermission(user.getUserId());
-
-        AjaxResult ajax = AjaxResult.success();
-        ajax.put("user", user);
-        ajax.put("roles", roles);
-        ajax.put("permissions", permissions);
-        return ajax;
-    }
-
-    /**
-     * 获取路由信息
-     *
-     * @return 路由信息
-     */
-    @GetMapping("/getRouters")
-    public AjaxResult getRouters()
-    {
-        LoginUser loginUser = LoginHelper.getLoginUser();
-        // 用户信息
-        SysUserVo user = sysUserService.selectUserById(loginUser.getUserId());
-        List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
-        return AjaxResult.success(menuService.buildMenus(menus));
+        return R.ok(IAuthStrategy.login(body, client, grantType));
     }
 
     /**
@@ -135,7 +101,7 @@ public class AuthController {
     /**
      * 用户注册
      */
-    @PostMapping("LoginHelper.getUserId()")
+    @PostMapping("/register")
     public R<Void> register(@Validated @RequestBody RegisterBody user) {
         //if (!configService.selectRegisterEnabled(user.getTenantId())) // TODO:注册代码
         {
@@ -145,5 +111,32 @@ public class AuthController {
 //        return R.ok();
     }
 
+    /**
+     * 登录页面租户下拉框
+     *
+     * @return 租户列表
+     */
+    @GetMapping("/tenant/list")
+    public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
+        List<SysTenantVo> tenantList = tenantService.selectList(new SysTenantBo());
+        List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
+        // 获取域名
+        String host;
+        String referer = request.getHeader("referer");
+        if (StringUtils.isNotBlank(referer)) {
+            // 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试
+            host = referer.split("//")[1].split("/")[0];
+        } else {
+            host = new URL(request.getRequestURL().toString()).getHost();
+        }
+        // 根据域名进行筛选
+        List<TenantListVo> list = StreamUtils.filter(voList, vo ->
+            StringUtils.equals(vo.getDomain(), host));
+        // 返回对象
+        LoginTenantVo vo = new LoginTenantVo();
+        vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
+        return R.ok(vo);
+    }
+
 
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
index 91fb8b1..a9b0c4b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
@@ -8,7 +8,6 @@ import cn.hutool.captcha.generator.CodeGenerator;
 import cn.hutool.core.util.IdUtil;
 import com.ruoyi.common.core.annotation.RateLimiter;
 import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.core.domain.AjaxResult;
 import com.ruoyi.common.core.enums.LimitType;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.utils.reflect.ReflectUtils;
@@ -32,6 +31,7 @@ import com.ruoyi.common.web.config.properties.CaptchaProperties;
  * 验证码操作处理
  *
  * @author ruoyi
+ * @author 数据小王子
  */
 @SaIgnore
 @Slf4j
@@ -46,13 +46,13 @@ public class CaptchaController
      * 生成验证码
      */
     @RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
-    @GetMapping("/captchaImage")
-    public AjaxResult getCode() {
+    @GetMapping("/auth/code")
+    public R<CaptchaVo> getCode() {
         CaptchaVo captchaVo = new CaptchaVo();
         boolean captchaEnabled = captchaProperties.getEnable();
         if (!captchaEnabled) {
             captchaVo.setCaptchaEnabled(false);
-            return AjaxResult.success(captchaVo);
+            return R.ok(captchaVo);
         }
         // 保存验证码信息
         String uuid = IdUtil.simpleUUID();
@@ -75,8 +75,6 @@ public class CaptchaController
 
         captchaVo.setUuid(uuid);
         captchaVo.setImg(captcha.getImageBase64());
-        return AjaxResult.success(captchaVo);
-
-
+        return R.ok(captchaVo);
     }
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java
new file mode 100644
index 0000000..521797a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java
@@ -0,0 +1,20 @@
+package com.ruoyi.web.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 登录租户对象
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class LoginTenantVo {
+
+    /**
+     * 租户对象列表
+     */
+    private List<TenantListVo> voList;
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/TenantListVo.java b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/TenantListVo.java
new file mode 100644
index 0000000..e3da6c7
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/TenantListVo.java
@@ -0,0 +1,22 @@
+package com.ruoyi.web.domain.vo;
+
+import com.ruoyi.system.domain.vo.SysTenantVo;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+/**
+ * 租户列表
+ *
+ * @author Lion Li
+ */
+@Data
+@AutoMapper(target = SysTenantVo.class)
+public class TenantListVo {
+
+    private String tenantId;
+
+    private String companyName;
+
+    private String domain;
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
index 8835ced..ed11904 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
@@ -20,27 +20,19 @@ public interface IAuthStrategy {
     /**
      * 登录
      */
-    static LoginVo login(LoginBody loginBody, SysClient client) {
+    static LoginVo login(String body, SysClient client, String grantType) {
         // 授权类型和客户端id
-        String clientId = loginBody.getClientId();
-        String grantType = loginBody.getGrantType();
         String beanName = grantType + BASE_NAME;
         if (!SpringUtils.containsBean(beanName)) {
             throw new ServiceException("授权类型不正确!");
         }
         IAuthStrategy instance = SpringUtils.getBean(beanName);
-        instance.validate(loginBody);
-        return instance.login(clientId, loginBody, client);
+        return instance.login(body,client);
     }
 
-    /**
-     * 参数校验
-     */
-    void validate(LoginBody loginBody);
-
     /**
      * 登录
      */
-    LoginVo login(String clientId, LoginBody loginBody, SysClient client);
+    LoginVo login(String body, SysClient client);
 
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
index de81f4b..5887eca 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
@@ -4,20 +4,25 @@ import cn.dev33.satoken.exception.NotLoginException;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
+import com.mybatisflex.core.tenant.TenantManager;
 import com.ruoyi.common.core.constant.*;
 import com.ruoyi.common.core.core.domain.dto.RoleDTO;
 import com.ruoyi.common.core.enums.LoginType;
+import com.ruoyi.common.core.enums.TenantStatus;
 import com.ruoyi.common.core.exception.user.*;
 import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.SpringUtils;
 import com.ruoyi.common.log.event.LogininforEvent;
 import com.ruoyi.common.redis.utils.RedisUtils;
 import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.tenant.exception.TenantException;
 import com.ruoyi.common.tenant.helper.TenantHelper;
 import com.ruoyi.system.domain.SysUser;
 import com.ruoyi.system.domain.bo.SysUserBo;
+import com.ruoyi.system.domain.vo.SysTenantVo;
 import com.ruoyi.system.domain.vo.SysUserVo;
 import com.ruoyi.system.service.ISysPermissionService;
+import com.ruoyi.system.service.ISysTenantService;
 import jakarta.annotation.Resource;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -30,6 +35,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.beans.factory.annotation.Value;
 
 import java.time.Duration;
+import java.util.Date;
 import java.util.List;
 import java.util.function.Supplier;
 
@@ -37,6 +43,7 @@ import java.util.function.Supplier;
  * 登录校验方法
  *
  * @author ruoyi
+ * @author 数据小王子
  */
 @RequiredArgsConstructor
 @Slf4j
@@ -49,11 +56,15 @@ public class SysLoginService {
     @Value("${user.password.lockTime}")
     private Integer lockTime;
 
-    private final ISysPermissionService permissionService;
+    @Resource
+    private ISysPermissionService permissionService;
 
     @Resource
     private ISysUserService userService;
 
+    @Resource
+    private ISysTenantService tenantService;
+
     /**
      * 登录校验
      */
@@ -91,17 +102,28 @@ public class SysLoginService {
     /**
      * 校验租户
      *
-     * @param tenantId 租户ID
+     * @param tenantId 租户编号
      */
-    public void checkTenant(String tenantId) {
-        if (!TenantHelper.isEnable()) {
-            return;
-        }
+    public void checkTenant(Long tenantId) {
         if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
             return;
         }
+        if (ObjectUtil.isNull(tenantId)) {
+            throw new TenantException("tenant.number.not.blank");
+        }
+        SysTenantVo tenant = tenantService.selectById(tenantId);
 
-        //TODO:完善heckTenant功能
+        if (ObjectUtil.isNull(tenant)) {
+            log.info("登录租户:{} 不存在.", tenantId);
+            throw new TenantException("tenant.not.exists");
+        } else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
+            log.info("登录租户:{} 已被停用.", tenantId);
+            throw new TenantException("tenant.blocked");
+        } else if (ObjectUtil.isNotNull(tenant.getExpireTime())
+            && new Date().after(tenant.getExpireTime())) {
+            log.info("登录租户:{} 已超过有效期.", tenantId);
+            throw new TenantException("tenant.expired");
+        }
     }
 
     /**
@@ -164,7 +186,7 @@ public class SysLoginService {
             if (ObjectUtil.isNull(loginUser)) {
                 return;
             }
-            if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
+            if (LoginHelper.isSuperAdmin()) {
                 // 超级管理员 登出清除动态租户
                 TenantHelper.clearDynamic();
             }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
index 4746825..79201ef 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
@@ -4,6 +4,9 @@ import cn.dev33.satoken.stp.SaLoginModel;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.ruoyi.common.core.core.domain.AjaxResult;
+import com.ruoyi.common.core.core.domain.model.EmailLoginBody;
+import com.ruoyi.common.json.utils.JsonUtils;
+import com.ruoyi.common.tenant.helper.TenantHelper;
 import com.ruoyi.system.domain.vo.SysUserVo;
 import com.ruoyi.system.service.ISysUserService;
 import com.ruoyi.web.domain.vo.LoginVo;
@@ -43,18 +46,12 @@ public class EmailAuthStrategy implements IAuthStrategy {
 
     @Resource
     private final SysLoginService loginService;
-
     @Resource
     private ISysUserService userService;
-//    private final SysUserMapper userMapper;
-
     @Override
-    public void validate(LoginBody loginBody) {
-        ValidatorUtils.validate(loginBody, EmailGroup.class);
-    }
-
-    @Override
-    public LoginVo login(String clientId, LoginBody loginBody, SysClient client) {
+    public LoginVo login(String body, SysClient client) {
+        EmailLoginBody loginBody = JsonUtils.parseObject(body, EmailLoginBody.class);
+        ValidatorUtils.validate(loginBody);
         Long tenantId = loginBody.getTenantId();
         String email = loginBody.getEmail();
         String emailCode = loginBody.getEmailCode();
@@ -65,25 +62,26 @@ public class EmailAuthStrategy implements IAuthStrategy {
         loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode));
         // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
         LoginUser loginUser = loginService.buildLoginUser(user);
+        loginUser.setClientKey(client.getClientKey());
+        loginUser.setDeviceType(client.getDeviceType());
         SaLoginModel model = new SaLoginModel();
         model.setDevice(client.getDeviceType());
         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
         // 例如: 后台用户30分钟过期 app用户1天过期
         model.setTimeout(client.getTimeout());
         model.setActiveTimeout(client.getActiveTimeout());
-        model.setExtra(LoginHelper.CLIENT_KEY, clientId);
+        model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
         // 生成token
         LoginHelper.login(loginUser, model);
 
-        loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        loginService.recordLoginInfo(user.getUserId());
+//        loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+//        loginService.recordLoginInfo(user.getUserId());
 
         LoginVo loginVo = new LoginVo();
         loginVo.setAccessToken(StpUtil.getTokenValue());
         loginVo.setExpireIn(StpUtil.getTokenTimeout());
-        loginVo.setClientId(clientId);
+        loginVo.setClientId(client.getClientId());
         return loginVo;
-//        return StpUtil.getTokenValue();
     }
 
     /**
@@ -99,22 +97,18 @@ public class EmailAuthStrategy implements IAuthStrategy {
     }
 
     private SysUserVo loadUserByEmail(Long tenantId, String email) {
-//        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-//            .select(SysUser::getEmail, SysUser::getStatus)
-//            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
-//            .eq(SysUser::getEmail, email));
-        SysUserVo user =userService.selectUserByEmail(email);
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", email);
-            throw new UserException("user.not.exists", email);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", email);
-            throw new UserException("user.blocked", email);
-        }
-//        if (TenantHelper.isEnable()) {
-//            return userMapper.selectTenantUserByEmail(email, tenantId);
-//        }
-        return user;
+        return TenantHelper.dynamic(tenantId, () -> {
+            SysUserVo user =userService.selectUserByEmail(email);
+            if (ObjectUtil.isNull(user)) {
+                log.info("登录用户:{} 不存在.", email);
+                throw new UserException("user.not.exists", email);
+            } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+                log.info("登录用户:{} 已被停用.", email);
+                throw new UserException("user.blocked", email);
+            }
+            return user;
+        });
+
     }
 
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
index 7126463..4b9e5ec 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
@@ -4,14 +4,15 @@ import cn.dev33.satoken.secure.BCrypt;
 import cn.dev33.satoken.stp.SaLoginModel;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.core.core.domain.AjaxResult;
+import com.ruoyi.common.core.core.domain.model.PasswordLoginBody;
+import com.ruoyi.common.json.utils.JsonUtils;
+import com.ruoyi.common.tenant.helper.TenantHelper;
 import com.ruoyi.system.service.ISysUserService;
 import jakarta.annotation.Resource;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import com.ruoyi.common.core.constant.Constants;
 import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.core.domain.model.LoginBody;
 import com.ruoyi.common.core.core.domain.model.LoginUser;
 import com.ruoyi.common.core.enums.LoginType;
 import com.ruoyi.common.core.enums.UserStatus;
@@ -21,14 +22,11 @@ import com.ruoyi.common.core.exception.user.UserException;
 import com.ruoyi.common.core.utils.MessageUtils;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.utils.ValidatorUtils;
-import com.ruoyi.common.core.validate.auth.PasswordGroup;
 import com.ruoyi.common.redis.utils.RedisUtils;
 import com.ruoyi.common.security.utils.LoginHelper;
 import com.ruoyi.common.web.config.properties.CaptchaProperties;
 import com.ruoyi.system.domain.SysClient;
-import com.ruoyi.system.domain.SysUser;
 import com.ruoyi.system.domain.vo.SysUserVo;
-import com.ruoyi.system.mapper.SysUserMapper;
 import com.ruoyi.web.domain.vo.LoginVo;
 import com.ruoyi.web.service.IAuthStrategy;
 import com.ruoyi.web.service.SysLoginService;
@@ -45,18 +43,15 @@ import org.springframework.stereotype.Service;
 public class PasswordAuthStrategy implements IAuthStrategy {
 
     private final CaptchaProperties captchaProperties;
-    private final SysLoginService loginService;
-
+    @Resource
+    private SysLoginService loginService;
     @Resource
     private ISysUserService userService;
 
     @Override
-    public void validate(LoginBody loginBody) {
-        ValidatorUtils.validate(loginBody, PasswordGroup.class);
-    }
-
-    @Override
-    public LoginVo login(String clientId, LoginBody loginBody, SysClient client) {
+    public LoginVo login(String body, SysClient client) {
+        PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class);
+        ValidatorUtils.validate(loginBody);
         Long tenantId = loginBody.getTenantId();
         String username = loginBody.getUsername();
         String password = loginBody.getPassword();
@@ -73,13 +68,15 @@ public class PasswordAuthStrategy implements IAuthStrategy {
         loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
         // 此处可根据登录用户的数据不同 自行创建 loginUser
         LoginUser loginUser = loginService.buildLoginUser(user);
+        loginUser.setClientKey(client.getClientKey());
+        loginUser.setDeviceType(client.getDeviceType());
         SaLoginModel model = new SaLoginModel();
         model.setDevice(client.getDeviceType());
         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
         // 例如: 后台用户30分钟过期 app用户1天过期
         model.setTimeout(client.getTimeout());
         model.setActiveTimeout(client.getActiveTimeout());
-        model.setExtra(LoginHelper.CLIENT_KEY, clientId);
+        model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
         // 生成token
         LoginHelper.login(loginUser, model);
 
@@ -89,11 +86,9 @@ public class PasswordAuthStrategy implements IAuthStrategy {
         LoginVo loginVo = new LoginVo();
         loginVo.setAccessToken(StpUtil.getTokenValue());
         loginVo.setExpireIn(StpUtil.getTokenTimeout());
-        loginVo.setClientId(clientId);
+        loginVo.setClientId(client.getClientId());
+
         return loginVo;
-
-        //return StpUtil.getTokenValue();
-
     }
 
     /**
@@ -118,19 +113,16 @@ public class PasswordAuthStrategy implements IAuthStrategy {
     }
 
     private SysUserVo loadUserByUsername(Long tenantId, String username) {
-        //TODO:以后根据tenantId条件过滤查询:
-        SysUserVo user = userService.selectUserByUserName(username);
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", username);
-            throw new UserException("user.not.exists", username);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", username);
-            throw new UserException("user.blocked", username);
-        }
-//        if (TenantHelper.isEnable()) {
-//            return userMapper.selectTenantUserByUserName(username, tenantId);
-//        }
-        return user;
+
+            SysUserVo user = userService.selectTenantUserByUserName(username,tenantId);
+            if (ObjectUtil.isNull(user)) {
+                log.info("登录用户:{} 不存在.", username);
+                throw new UserException("user.not.exists", username);
+            } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+                log.info("登录用户:{} 已被停用.", username);
+                throw new UserException("user.blocked", username);
+            }
+            return user;
     }
 
 }
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index a71140e..e792ca4 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -91,7 +91,7 @@ redisson:
 --- # 监控中心客户端配置
 spring.boot.admin.client:
   # 增加客户端开关
-  enabled: true
+  enabled: false
   url: http://localhost:9090/admin
   instance:
     service-host-type: IP
@@ -102,7 +102,7 @@ spring.boot.admin.client:
 powerjob:
   worker:
     # 如何开启调度中心请查看文档教程
-    enabled: true
+    enabled: false
     # 需要先在 powerjob 登录页执行应用注册后才能使用
     app-name: ruoyi-worker
     # 28080 端口 随着主应用端口飘逸 避免集群冲突
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 9e260b9..1b0454b 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -146,7 +146,7 @@ mybatis-flex:
     # 默认的逻辑删除字段
     logic-delete-column: del_flag
     # 默认的多租户字段
-    #tenant-column: tenant_id
+    tenant-column: tenant_id
     # 默认的乐观锁字段
     version-column: version
 
@@ -295,11 +295,6 @@ security:
     - /captcha/get
     - /captcha/check
 
-# 多租户配置
-tenant:
-  # 是否开启
-  enable: false
-
 --- # Actuator 监控端点的配置项
 management:
   endpoints:
diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties
index 5c9f422..cce11c8 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -29,6 +29,7 @@ user.notfound=请重新登录
 user.forcelogout=管理员强制退出,请重新登录
 user.unknown.error=未知错误,请重新登录
 auth.grant.type.error=认证权限类型错误
+auth.grant.type.blocked=认证权限类型已禁用
 auth.grant.type.not.blank=认证权限类型不能为空
 auth.clientid.not.blank=认证客户端id不能为空
 ##文件上传消息
@@ -49,7 +50,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
 email.code.not.blank=邮箱验证码不能为空
 email.code.retry.limit.count=邮箱验证码输入错误{0}次
 email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
-xcx.code.not.blank=小程序code不能为空
+xcx.code.not.blank=小程序[code]不能为空
+social.source.not.blank=第三方登录平台[source]不能为空
+social.code.not.blank=第三方登录平台[code]不能为空
+social.state.not.blank=第三方登录平台[state]不能为空
 ##租户
 tenant.number.not.blank=租户编号不能为空
 tenant.not.exists=对不起, 您的租户不存在,请联系管理员
diff --git a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
index 2ab82a6..f948c4a 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
@@ -29,6 +29,7 @@ user.notfound=Please login again
 user.forcelogout=The administrator is forced to exit,please login again
 user.unknown.error=Unknown error, please login again
 auth.grant.type.error=Auth grant type error
+auth.grant.type.blocked=Auth grant type disabled
 auth.grant.type.not.blank=Auth grant type cannot be blank
 auth.clientid.not.blank=Auth clientid cannot be blank
 ##文件上传消息
@@ -49,7 +50,10 @@ sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {
 email.code.not.blank=Email code cannot be blank
 email.code.retry.limit.count=Email code input error {0} times
 email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
-xcx.code.not.blank=Mini program code cannot be blank
+xcx.code.not.blank=Mini program [code] cannot be blank
+social.source.not.blank=Social login platform [source] cannot be blank
+social.code.not.blank=Social login platform [code] cannot be blank
+social.state.not.blank=Social login platform [state] cannot be blank
 ##租户
 tenant.number.not.blank=Tenant number cannot be blank
 tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator
diff --git a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
index 5c9f422..cce11c8 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
@@ -29,6 +29,7 @@ user.notfound=请重新登录
 user.forcelogout=管理员强制退出,请重新登录
 user.unknown.error=未知错误,请重新登录
 auth.grant.type.error=认证权限类型错误
+auth.grant.type.blocked=认证权限类型已禁用
 auth.grant.type.not.blank=认证权限类型不能为空
 auth.clientid.not.blank=认证客户端id不能为空
 ##文件上传消息
@@ -49,7 +50,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
 email.code.not.blank=邮箱验证码不能为空
 email.code.retry.limit.count=邮箱验证码输入错误{0}次
 email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
-xcx.code.not.blank=小程序code不能为空
+xcx.code.not.blank=小程序[code]不能为空
+social.source.not.blank=第三方登录平台[source]不能为空
+social.code.not.blank=第三方登录平台[code]不能为空
+social.state.not.blank=第三方登录平台[state]不能为空
 ##租户
 tenant.number.not.blank=租户编号不能为空
 tenant.not.exists=对不起, 您的租户不存在,请联系管理员
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
index 49bafa0..69d9207 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
@@ -4,7 +4,7 @@ import io.jsonwebtoken.Claims;
 
 /**
  * 通用常量信息
- * 
+ *
  * @author ruoyi
  */
 public class Constants
@@ -63,7 +63,7 @@ public class Constants
      * 登录失败
      */
     public static final String LOGIN_FAIL = "Error";
- 
+
     /**
      * 验证码有效期(分钟)
      */
@@ -80,68 +80,14 @@ public class Constants
     public static final String TOKEN = "token";
 
     /**
-     * 令牌前缀
+     * 顶级部门id
      */
-    public static final String TOKEN_PREFIX = "Bearer ";
-
-    /**
-     * 令牌前缀
-     */
-    public static final String LOGIN_USER_KEY = "login_user_key";
-
-    /**
-     * 用户ID
-     */
-    public static final String JWT_USERID = "userid";
-
-    /**
-     * 用户名称
-     */
-    public static final String JWT_USERNAME = Claims.SUBJECT;
-
-    /**
-     * 用户头像
-     */
-    public static final String JWT_AVATAR = "avatar";
-
-    /**
-     * 创建时间
-     */
-    public static final String JWT_CREATED = "created";
-
-    /**
-     * 用户权限
-     */
-    public static final String JWT_AUTHORITIES = "authorities";
+    public static final Long TOP_PARENT_ID = 0L;
 
     /**
      * 资源映射路径 前缀
      */
     public static final String RESOURCE_PREFIX = "/profile";
 
-    /**
-     * RMI 远程方法调用
-     */
-    public static final String LOOKUP_RMI = "rmi:";
 
-    /**
-     * LDAP 远程方法调用
-     */
-    public static final String LOOKUP_LDAP = "ldap:";
-
-    /**
-     * LDAPS 远程方法调用
-     */
-    public static final String LOOKUP_LDAPS = "ldaps:";
-
-    /**
-     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
-     */
-    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
-
-    /**
-     * 定时任务违规的字符
-     */
-    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
-            "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
 }
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java
index 5f6cc42..0b85852 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java
@@ -5,120 +5,188 @@ package com.ruoyi.common.core.constant;
  *
  * @author ruoyi
  */
-public class GenConstants
-{
-    /** 单表(增删改查) */
+public class GenConstants {
+    /**
+     * 单表(增删改查)
+     */
     public static final String TPL_CRUD = "crud";
 
-    /** 树表(增删改查) */
+    /**
+     * 树表(增删改查)
+     */
     public static final String TPL_TREE = "tree";
 
-    /** 主子表(增删改查) */
+    /**
+     * 主子表(增删改查)
+     */
     public static final String TPL_SUB = "sub";
 
-    /** 树编码字段 */
+    /**
+     * 树编码字段
+     */
     public static final String TREE_CODE = "treeCode";
 
-    /** 树父编码字段 */
+    /**
+     * 树父编码字段
+     */
     public static final String TREE_PARENT_CODE = "treeParentCode";
 
-    /** 树名称字段 */
+    /**
+     * 树名称字段
+     */
     public static final String TREE_NAME = "treeName";
 
-    /** 上级菜单ID字段 */
+    /**
+     * 上级菜单ID字段
+     */
     public static final String PARENT_MENU_ID = "parentMenuId";
 
-    /** 上级菜单名称字段 */
+    /**
+     * 上级菜单名称字段
+     */
     public static final String PARENT_MENU_NAME = "parentMenuName";
 
-    /** 数据库字符串类型 */
-    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2","character","character varying" };
+    /**
+     * 数据库字符串类型
+     */
+    public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "enum", "set", "nchar", "nvarchar", "varchar2", "nvarchar2", "character", "character varying"};
 
-    /** 数据库文本类型 */
-    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext", "binary", "varbinary", "blob",
-        "ntext", "image", "bytea" };
+    /**
+     * 数据库文本类型
+     */
+    public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext", "binary", "varbinary", "blob",
+        "ntext", "image", "bytea"};
 
-    /** 数据库时间类型 */
-    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp","timestamp without time zone","year", "interval",
-        "smalldatetime", "datetime2", "datetimeoffset" };
+    /**
+     * 数据库时间类型
+     */
+    public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp", "timestamp without time zone", "year", "interval",
+        "smalldatetime", "datetime2", "datetimeoffset"};
 
-    /** 数据库数字类型 */
-    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+    /**
+     * 数据库数字类型
+     */
+    public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
         "bit", "bigint", "float", "double", "decimal", "numeric", "real", "double precision",
-        "smallserial", "serial", "bigserial", "money", "smallmoney" };
+        "smallserial", "serial", "bigserial", "money", "smallmoney"};
 
     /**
      * BO对象 不需要添加字段
      */
-    public static final String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time",  "update_by", "update_time" };
+    public static final String[] COLUMNNAME_NOT_ADD = {"tenant_id", "version", "del_flag", "create_by", "create_time", "update_by", "update_time"};
 
-    /** BO对象 不需要编辑字段 */
-    public static final String[] COLUMNNAME_NOT_EDIT = { "create_by", "create_time",  "update_by",  "update_time" };
+    /**
+     * BO对象 不需要编辑字段
+     */
+    public static final String[] COLUMNNAME_NOT_EDIT = {"tenant_id", "version", "del_flag", "create_by", "create_time", "update_by", "update_time"};
 
-    /** VO对象 不需要显示的列表字段 */
-    public static final String[] COLUMNNAME_NOT_LIST = { "create_by", "create_time", "update_by",  "update_time" };
+    /**
+     * VO对象 不需要显示的列表字段
+     */
+    public static final String[] COLUMNNAME_NOT_LIST = {"tenant_id", "version", "del_flag", "create_by", "create_time", "update_by", "update_time"};
 
-    /** BO对象 不需要查询字段 */
-    public static final String[] COLUMNNAME_NOT_QUERY = { "create_by", "create_time", "update_by",
-            "update_time", "del_flag", "remark", "version" };
+    /**
+     * BO对象 不需要查询字段
+     */
+    public static final String[] COLUMNNAME_NOT_QUERY = {"tenant_id", "version", "del_flag", "create_by", "create_time", "update_by", "update_time",  "remark", "id"};
 
-    /** Entity基类字段 */
-    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime"};
+    /**
+     * Entity基类字段
+     */
+    public static final String[] BASE_ENTITY = {"tenant_id", "createBy", "createTime", "updateBy", "updateTime"};
 
-    /** Tree基类字段 */
-    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
+    /**
+     * Tree基类字段
+     */
+    public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"};
 
-    /** 文本框 */
+    /**
+     * 文本框
+     */
     public static final String HTML_INPUT = "input";
 
-    /** 文本域 */
+    /**
+     * 文本域
+     */
     public static final String HTML_TEXTAREA = "textarea";
 
-    /** 下拉框 */
+    /**
+     * 下拉框
+     */
     public static final String HTML_SELECT = "select";
 
-    /** 单选框 */
+    /**
+     * 单选框
+     */
     public static final String HTML_RADIO = "radio";
 
-    /** 复选框 */
+    /**
+     * 复选框
+     */
     public static final String HTML_CHECKBOX = "checkbox";
 
-    /** 日期控件 */
+    /**
+     * 日期控件
+     */
     public static final String HTML_DATETIME = "datetime";
 
-    /** 图片上传控件 */
+    /**
+     * 图片上传控件
+     */
     public static final String HTML_IMAGE_UPLOAD = "imageUpload";
 
-    /** 文件上传控件 */
+    /**
+     * 文件上传控件
+     */
     public static final String HTML_FILE_UPLOAD = "fileUpload";
 
-    /** 富文本控件 */
+    /**
+     * 富文本控件
+     */
     public static final String HTML_EDITOR = "editor";
 
-    /** 字符串类型 */
+    /**
+     * 字符串类型
+     */
     public static final String TYPE_STRING = "String";
 
-    /** 整型 */
+    /**
+     * 整型
+     */
     public static final String TYPE_INTEGER = "Integer";
 
-    /** 长整型 */
+    /**
+     * 长整型
+     */
     public static final String TYPE_LONG = "Long";
 
-    /** 浮点型 */
+    /**
+     * 浮点型
+     */
     public static final String TYPE_DOUBLE = "Double";
 
-    /** 高精度计算类型 */
+    /**
+     * 高精度计算类型
+     */
     public static final String TYPE_BIGDECIMAL = "BigDecimal";
 
-    /** 时间类型 */
+    /**
+     * 时间类型
+     */
     public static final String TYPE_DATE = "Date";
 
-    /** 模糊查询 */
+    /**
+     * 模糊查询
+     */
     public static final String QUERY_LIKE = "LIKE";
 
-    /** 相等查询 */
+    /**
+     * 相等查询
+     */
     public static final String QUERY_EQ = "EQ";
 
-    /** 需要 */
+    /**
+     * 需要
+     */
     public static final String REQUIRE = "1";
 }
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java
index 6411ba4..0609731 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java
@@ -4,6 +4,7 @@ package com.ruoyi.common.core.constant;
  * 租户常量信息
  *
  * @author Lion Li
+ * @author 数据小王子
  */
 public interface TenantConstants {
 
@@ -25,21 +26,21 @@ public interface TenantConstants {
     /**
      * 超级管理员角色 roleKey
      */
-    String SUPER_ADMIN_ROLE_KEY = "superadmin";
+    String SUPER_ADMIN_ROLE_KEY = "SuperAminRole";
 
     /**
      * 租户管理员角色 roleKey
      */
-    String TENANT_ADMIN_ROLE_KEY = "admin";
+    String TENANT_ADMIN_ROLE_KEY = "AdminRole";
 
     /**
      * 租户管理员角色名称
      */
-    String TENANT_ADMIN_ROLE_NAME = "管理员";
+    String TENANT_ADMIN_ROLE_NAME = "管理员角色";
 
     /**
      * 默认租户ID
      */
-    String DEFAULT_TENANT_ID = "000000";
+    Long DEFAULT_TENANT_ID = 0L;
 
 }
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/EmailLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/EmailLoginBody.java
index 189a4c9..e47b22d 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/EmailLoginBody.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/EmailLoginBody.java
@@ -11,13 +11,7 @@ import lombok.Data;
  */
 
 @Data
-public class EmailLoginBody {
-
-    /**
-     * 租户ID
-     */
-    @NotBlank(message = "{tenant.number.not.blank}")
-    private String tenantId;
+public class EmailLoginBody extends LoginBody {
 
     /**
      * 邮箱
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/LoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/LoginUser.java
index 3de891a..2d05c5d 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/LoginUser.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/LoginUser.java
@@ -111,6 +111,16 @@ public class LoginUser
      */
     private Long roleId;
 
+    /**
+     * 客户端
+     */
+    private String clientKey;
+
+    /**
+     * 设备类型
+     */
+    private String deviceType;
+
     /**
      * 获取登录id
      */
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/PasswordLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/PasswordLoginBody.java
new file mode 100644
index 0000000..8fc772a
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/PasswordLoginBody.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.core.core.domain.model;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.hibernate.validator.constraints.Length;
+
+import static com.ruoyi.common.core.constant.UserConstants.*;
+
+/**
+ * 密码登录对象
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PasswordLoginBody extends LoginBody {
+
+    /**
+     * 用户名
+     */
+    @NotBlank(message = "{user.username.not.blank}")
+    @Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
+    private String username;
+
+    /**
+     * 用户密码
+     */
+    @NotBlank(message = "{user.password.not.blank}")
+    @Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
+    private String password;
+
+}
diff --git a/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/config/MyBatisFlexConfig.java b/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/config/MyBatisFlexConfig.java
index 47dd64b..aab2a89 100644
--- a/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/config/MyBatisFlexConfig.java
+++ b/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/config/MyBatisFlexConfig.java
@@ -1,11 +1,9 @@
 package com.ruoyi.common.orm.config;
 
-import com.mybatisflex.annotation.KeyType;
 import com.mybatisflex.core.FlexGlobalConfig;
 import com.mybatisflex.core.audit.AuditManager;
 import com.mybatisflex.core.audit.ConsoleMessageCollector;
 import com.mybatisflex.core.datasource.DataSourceDecipher;
-import com.mybatisflex.core.keygen.KeyGenerators;
 import com.mybatisflex.core.mybatis.FlexConfiguration;
 import com.mybatisflex.spring.boot.ConfigurationCustomizer;
 import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
diff --git a/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/core/domain/BaseEntity.java b/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/core/domain/BaseEntity.java
index 70c4cf9..8128aa8 100644
--- a/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/core/domain/BaseEntity.java
+++ b/ruoyi-common/ruoyi-common-orm/src/main/java/com/ruoyi/common/orm/core/domain/BaseEntity.java
@@ -24,11 +24,10 @@ public class BaseEntity implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
-//    /**
-//     * 租户编号
-//     */
-//    @Column(ignore = true)
-//    private Long tenantId;
+    /**
+     * 租户编号
+     */
+    private Long tenantId;
 
     /**
      * 搜索值
@@ -37,12 +36,6 @@ public class BaseEntity implements Serializable {
     @Column(ignore = true)
     private String searchValue;
 
-    /**
-     * 创建部门
-     */
-    @Column(ignore = true)
-    private Long createDept;
-
     /**
      * 创建者
      */
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/LoginHelper.java
index f8e06f3..4f63c75 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/LoginHelper.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/LoginHelper.java
@@ -58,7 +58,6 @@ public class LoginHelper {
             model.setExtra(TENANT_KEY, loginUser.getTenantId())
                 .setExtra(USER_KEY, loginUser.getUserId())
                 .setExtra(DEPT_KEY, loginUser.getDeptId()));
-        //StpUtil.getSession().set(LOGIN_USER_KEY, loginUser);
         StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
     }
 
diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java
index 4344f36..6da2e0b 100644
--- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java
+++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java
@@ -11,13 +11,10 @@ import com.ruoyi.common.tenant.core.TenantSaTokenDao;
 import com.ruoyi.common.tenant.handle.MyTenantFactory;
 import com.ruoyi.common.tenant.handle.TenantKeyPrefixHandler;
 import com.ruoyi.common.tenant.manager.TenantSpringCacheManager;
-import com.ruoyi.common.tenant.properties.TenantProperties;
 import org.redisson.config.ClusterServersConfig;
 import org.redisson.config.SingleServerConfig;
 import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.cache.CacheManager;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Primary;
@@ -28,12 +25,9 @@ import org.springframework.context.annotation.Primary;
  * @author Lion Li
  * @author 数据小王子
  */
-@EnableConfigurationProperties(TenantProperties.class)
 @AutoConfiguration(after = {RedisConfig.class, MyBatisFlexConfig.class})
-@ConditionalOnProperty(value = "tenant.enable", havingValue = "true")
 public class TenantConfig {
 
-
     /**
      * 多租户工厂,用于获取当前租户ID
      */
diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java
index 3f935f6..0907041 100644
--- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java
+++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java
@@ -2,7 +2,6 @@ package com.ruoyi.common.tenant.helper;
 
 import cn.dev33.satoken.context.SaHolder;
 import cn.dev33.satoken.spring.SpringMVCUtil;
-import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.ttl.TransmittableThreadLocal;
 import com.mybatisflex.core.tenant.TenantManager;
@@ -10,8 +9,6 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.utils.SpringUtils;
-import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.redis.utils.RedisUtils;
 import com.ruoyi.common.security.utils.LoginHelper;
 
@@ -31,13 +28,6 @@ public class TenantHelper {
 
     private static final ThreadLocal<Long> TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>();
 
-    /**
-     * 租户功能是否启用
-     */
-    public static boolean isEnable() {
-        return Convert.toBool(SpringUtils.getProperty("tenant.enable"), false);
-    }
-
     /**
      * 开启忽略租户(开启后需手动调用 {@link #disableIgnore()} 关闭)
      */
@@ -109,7 +99,6 @@ public class TenantHelper {
         if (ObjectUtil.isNotNull(tenantId)) {
             return tenantId;
         }
-        System.out.println("####################:RedisUtils.getCacheObject("+cacheKey+")="+RedisUtils.getCacheObject(cacheKey));
         if (ObjectUtil.isNotNull(RedisUtils.getCacheObject(cacheKey))) {
             tenantId = Long.valueOf(RedisUtils.getCacheObject(cacheKey));
         }
@@ -164,9 +153,6 @@ public class TenantHelper {
      * 获取当前租户id(动态租户优先)
      */
     public static Long getTenantId() {
-        if (!isEnable()) {
-            return null;
-        }
         Long tenantId = TenantHelper.getDynamic();
         if (ObjectUtil.isNull(tenantId)) {
             tenantId = LoginHelper.getTenantId();
diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/properties/TenantProperties.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/properties/TenantProperties.java
deleted file mode 100644
index 4cd4fa0..0000000
--- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/properties/TenantProperties.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.ruoyi.common.tenant.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import java.util.List;
-
-/**
- * 租户 配置属性
- *
- * @author Lion Li
- */
-@Data
-@ConfigurationProperties(prefix = "tenant")
-public class TenantProperties {
-
-    /**
-     * 是否启用
-     */
-    private Boolean enable;
-
-}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
index 6c32184..abd0cdf 100644
--- a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
@@ -1,18 +1,22 @@
 package com.ruoyi.generator.domain;
 
 import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.mybatisflex.annotation.Column;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.Table;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
 import org.apache.commons.lang3.ArrayUtils;
 import com.ruoyi.common.core.constant.GenConstants;
-import com.ruoyi.common.orm.core.domain.BaseEntity;
 import com.ruoyi.common.core.utils.StringUtils;
 
 /**
@@ -22,9 +26,8 @@ import com.ruoyi.common.core.utils.StringUtils;
  * @author 数据小王子
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
 @Table(value = "gen_table")
-public class GenTable extends BaseEntity
+public class GenTable implements Serializable
 {
     @Serial
     private static final long serialVersionUID = 1L;
@@ -119,9 +122,38 @@ public class GenTable extends BaseEntity
     @Column(ignore = true)
     private String parentMenuName;
 
+    /**
+     * 创建者
+     */
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
     /** 备注   */
     private String remark;
 
+    /**
+     * 请求参数
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @Column(ignore = true)
+    private Map<String, Object> params = new HashMap<>();
+
     public boolean isSub()
     {
         return isSub(this.tplCategory);
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
index 42deb37..da55fa3 100644
--- a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
@@ -1,14 +1,15 @@
 package com.ruoyi.generator.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.Table;
 import jakarta.validation.constraints.NotBlank;
-import com.ruoyi.common.orm.core.domain.BaseEntity;
 import com.ruoyi.common.core.utils.StringUtils;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
 
 /**
  * 代码生成业务字段表 gen_table_column
@@ -17,9 +18,8 @@ import java.io.Serial;
  * @author 数据小王子
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
 @Table(value = "gen_table_column")
-public class GenTableColumn extends BaseEntity
+public class GenTableColumn implements Serializable
 {
     @Serial
     private static final long serialVersionUID = 1L;
@@ -80,6 +80,28 @@ public class GenTableColumn extends BaseEntity
     /** 排序 */
     private Integer sort;
 
+    /**
+     * 创建者
+     */
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
     public String getCapJavaField()
     {
         return StringUtils.capitalize(javaField);
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java
index 0e43436..fc7f783 100644
--- a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java
@@ -1,9 +1,11 @@
 package com.ruoyi.generator.service;
 
+import java.util.Date;
 import java.util.List;
 
 import com.mybatisflex.core.query.QueryWrapper;
 import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
+import com.ruoyi.common.security.utils.LoginHelper;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import com.ruoyi.common.core.core.text.Convert;
@@ -54,7 +56,13 @@ public class GenTableColumnServiceImpl extends BaseServiceImpl<GenTableColumnMap
 	@Override
 	public int insertGenTableColumn(GenTableColumn genTableColumn)
 	{
-	    //return genTableColumnMapper.insertGenTableColumn(genTableColumn);
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        genTableColumn.setCreateBy(loginUserId);
+        genTableColumn.setCreateTime(createTime);
+        genTableColumn.setUpdateBy(loginUserId);
+        genTableColumn.setUpdateTime(createTime);
+
         return genTableColumnMapper.insertSelective(genTableColumn);
 	}
 
@@ -67,6 +75,11 @@ public class GenTableColumnServiceImpl extends BaseServiceImpl<GenTableColumnMap
 	@Override
 	public int updateGenTableColumn(GenTableColumn genTableColumn)
 	{
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        genTableColumn.setUpdateBy(loginUserId);
+        genTableColumn.setUpdateTime(createTime);
+
 	    return genTableColumnMapper.update(genTableColumn);
 	}
 
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
index 917c861..20d9729 100644
--- a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
@@ -16,6 +16,7 @@ import com.ruoyi.common.core.utils.DateUtils;
 import com.ruoyi.common.orm.core.page.PageQuery;
 import com.ruoyi.common.orm.core.page.TableDataInfo;
 import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
+import com.ruoyi.common.security.utils.LoginHelper;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
@@ -170,11 +171,19 @@ public class GenTableServiceImpl extends BaseServiceImpl<GenTableMapper, GenTabl
     {
         String options = JSON.toJSONString(genTable.getParams());
         genTable.setOptions(options);
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        genTable.setUpdateBy(loginUserId);
+        genTable.setUpdateTime(createTime);
+
         boolean updated = this.updateById(genTable);
         if (updated)
         {
             for (GenTableColumn genTableColumn : genTable.getColumns())
             {
+                genTableColumn.setUpdateBy(loginUserId);
+                genTableColumn.setUpdateTime(createTime);
                 genTableColumnMapper.update(genTableColumn);
             }
         }
@@ -209,6 +218,15 @@ public class GenTableServiceImpl extends BaseServiceImpl<GenTableMapper, GenTabl
             {
                 String tableName = table.getTableName();
                 GenUtils.initTable(table);
+
+                Long loginUserId = LoginHelper.getUserId();
+                Date createTime = new Date();
+                table.setCreateBy(loginUserId);
+                table.setCreateTime(createTime);
+                table.setUpdateBy(loginUserId);
+                table.setUpdateTime(createTime);
+
+
                 boolean saved = this.save(table);
                 if (saved)
                 {
@@ -217,6 +235,10 @@ public class GenTableServiceImpl extends BaseServiceImpl<GenTableMapper, GenTabl
                     for (GenTableColumn column : genTableColumns)
                     {
                         GenUtils.initColumnField(column, table);
+                        column.setCreateBy(loginUserId);
+                        column.setCreateTime(createTime);
+                        column.setUpdateBy(loginUserId);
+                        column.setUpdateTime(createTime);
                         genTableColumnMapper.insertSelective(column);
                     }
                 }
@@ -337,6 +359,9 @@ public class GenTableServiceImpl extends BaseServiceImpl<GenTableMapper, GenTabl
     @Transactional
     public void synchDb(String tableName)
     {
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+
         GenTable table = genTableMapper.selectGenTableByName(tableName);
         List<GenTableColumn> tableColumns = table.getColumns();
         Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
@@ -368,10 +393,17 @@ public class GenTableServiceImpl extends BaseServiceImpl<GenTableMapper, GenTabl
                     column.setIsRequired(prevColumn.getIsRequired());
                     column.setHtmlType(prevColumn.getHtmlType());
                 }
+                column.setUpdateBy(loginUserId);
+                column.setUpdateTime(createTime);
                 genTableColumnMapper.update(column);
             }
             else
             {
+                column.setCreateBy(loginUserId);
+                column.setCreateTime(createTime);
+                column.setUpdateBy(loginUserId);
+                column.setUpdateTime(createTime);
+
                 genTableColumnMapper.insertSelective(column);
             }
         });
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
index 91e77a3..c12b9dc 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
@@ -3,7 +3,9 @@ package com.ruoyi.system.controller.system;
 import java.util.List;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
 import cn.hutool.core.lang.tree.Tree;
+import com.ruoyi.common.core.constant.TenantConstants;
 import com.ruoyi.common.core.core.domain.R;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
@@ -100,6 +102,22 @@ public class SysMenuController extends BaseController
         return R.ok(selectVo);
     }
 
+    /**
+     * 加载对应租户套餐菜单列表树
+     *
+     * @param packageId 租户套餐ID
+     */
+    @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
+    @SaCheckPermission("system:menu:query")
+    @GetMapping(value = "/tenantPackageMenuTreeselect/{packageId}")
+    public R<MenuTreeSelectVo> tenantPackageMenuTreeselect(@PathVariable("packageId") Long packageId) {
+        List<SysMenuVo> menus = menuService.selectMenuList(LoginHelper.getUserId());
+        MenuTreeSelectVo selectVo = new MenuTreeSelectVo();
+        selectVo.setCheckedKeys(menuService.selectMenuListByPackageId(packageId));
+        selectVo.setMenus(menuService.buildMenuTreeSelect(menus));
+        return R.ok(selectVo);
+    }
+
     /**
      * 新增菜单
      */
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
index 647c492..624880d 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
@@ -117,7 +117,7 @@ public class SysUserController extends BaseController {
     public R<UserInfoVo> getInfo() {
         UserInfoVo userInfoVo = new UserInfoVo();
         LoginUser loginUser = LoginHelper.getLoginUser();
-        if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
+        if (LoginHelper.isSuperAdmin()) {
             // 超级管理员 如果重新加载用户信息需清除动态租户
             TenantHelper.clearDynamic();
         }
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysClient.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysClient.java
index 77c8ac9..3eedd04 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysClient.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysClient.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.Table;
 import com.ruoyi.common.orm.core.domain.BaseEntity;
@@ -7,6 +8,8 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
 
 /**
  * 授权管理对象 sys_client
@@ -14,9 +17,8 @@ import java.io.Serial;
  * @author dataprince数据小王子
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
 @Table(value = "sys_client")
-public class SysClient extends BaseEntity {
+public class SysClient implements Serializable {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -72,5 +74,25 @@ public class SysClient extends BaseEntity {
      */
     private Integer delFlag;
 
+    /**
+     * 创建者
+     */
+    private Long createBy;
 
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
 }
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
index 549e027..275acc4 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
@@ -1,6 +1,5 @@
 package com.ruoyi.system.domain;
 
-import com.mybatisflex.annotation.Column;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.Table;
 import lombok.Data;
@@ -23,12 +22,6 @@ public class SysConfig extends BaseEntity
     @Id
     private Long configId;
 
-    /**
-     * 租户编号
-     */
-    @Column(tenantId = true)
-    private Long tenantId;
-
     /** 参数名称 */
     private String configName;
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
index 57c1b11..02249c1 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
@@ -38,7 +38,7 @@ public class SysDept extends BaseEntity
     private String orderNum;
 
     /** 负责人 */
-    private String leader;//TODO:修改为Long类型?
+    private String leader;
 
     /** 联系电话 */
     private String phone;
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
index bbe152f..c4e0bac 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
@@ -7,6 +7,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.mybatisflex.annotation.Column;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.Table;
 import lombok.Data;
@@ -27,10 +28,24 @@ public class SysLogininfor implements Serializable
     @Id
     private Long infoId;
 
+    /**
+     * 租户编号
+     */
+    private Long tenantId;
+
     /** 用户账号 */
-    //@Excel(name = "用户账号")
     private String userName;
 
+    /**
+     * 客户端
+     */
+    private String clientKey;
+
+    /**
+     * 设备类型
+     */
+    private String deviceType;
+
     /** 登录状态 0成功 1失败 */
     private String status;
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
index 5349f26..93fa046 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
@@ -1,8 +1,12 @@
 package com.ruoyi.system.domain;
 
+import java.io.Serial;
+import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.mybatisflex.annotation.Column;
 import com.mybatisflex.annotation.Id;
 import com.mybatisflex.annotation.KeyType;
@@ -20,11 +24,11 @@ import com.ruoyi.common.orm.core.domain.BaseEntity;
  * @author ruoyi
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
 @Table(value = "sys_menu")
-public class SysMenu extends BaseEntity
+public class SysMenu  implements Serializable
 {
-
+    @Serial
+    private static final long serialVersionUID = 1L;
 
     /** 菜单ID */
     @Id
@@ -73,6 +77,28 @@ public class SysMenu extends BaseEntity
     /** 菜单图标 */
     private String icon;
 
+    /**
+     * 创建者
+     */
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
     /** 备注   */
     private String remark;
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
index 97e648f..2a3d831 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
@@ -30,6 +30,11 @@ public class SysOperLog implements Serializable
     @Id
     private Long operId;
 
+    /**
+     * 租户编号
+     */
+    private Long tenantId;
+
     /** 操作模块 */
     private String title;
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
index 868e48a..3bd6d68 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
@@ -38,7 +38,7 @@ public class SysRole extends BaseEntity {
     /**
      * 角色排序
      */
-    private String roleSort;
+    private Integer roleSort;
 
     /**
      * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
index cf4595b..16fdf36 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
@@ -25,11 +25,6 @@ public class SysUser extends BaseEntity
     @Id
     private Long userId;
 
-    /**
-     * 租户编号
-     */
-    private Long tenantId;
-
     /** 部门ID */
     private Long deptId;
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysClientBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysClientBo.java
index 624274d..a83af6e 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysClientBo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysClientBo.java
@@ -9,6 +9,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 
+import java.io.Serializable;
 import java.util.List;
 
 /**
@@ -17,9 +18,8 @@ import java.util.List;
  * @author Michelle.Chung
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
 @AutoMapper(target = SysClient.class, reverseConvertGenerate = false)
-public class SysClientBo extends BaseEntity {
+public class SysClientBo implements Serializable {
 
     /**
      * id
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysLogininforBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysLogininforBo.java
index b5330f6..377a811 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysLogininforBo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysLogininforBo.java
@@ -4,6 +4,8 @@ import com.ruoyi.system.domain.SysLogininfor;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
 
+import java.io.Serial;
+import java.io.Serializable;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -16,7 +18,10 @@ import java.util.Map;
 
 @Data
 @AutoMapper(target = SysLogininfor.class, reverseConvertGenerate = false)
-public class SysLogininforBo {
+public class SysLogininforBo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
 
     /**
      * 访问ID
@@ -33,6 +38,16 @@ public class SysLogininforBo {
      */
     private String userName;
 
+    /**
+     * 客户端
+     */
+    private String clientKey;
+
+    /**
+     * 设备类型
+     */
+    private String deviceType;
+
     /**
      * 登录IP地址
      */
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysMenuBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysMenuBo.java
index d647afe..05905c5 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysMenuBo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysMenuBo.java
@@ -10,6 +10,8 @@ import jakarta.validation.constraints.Size;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import java.io.Serializable;
+
 /**
  * 菜单权限业务对象 sys_menu
  *
@@ -17,9 +19,8 @@ import lombok.EqualsAndHashCode;
  */
 
 @Data
-@EqualsAndHashCode(callSuper = true)
 @AutoMapper(target = SysMenu.class, reverseConvertGenerate = false)
-public class SysMenuBo extends BaseEntity {
+public class SysMenuBo implements Serializable {
 
     /**
      * 菜单ID
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysLogininforVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysLogininforVo.java
index 6512a71..8886789 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysLogininforVo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysLogininforVo.java
@@ -33,6 +33,7 @@ public class SysLogininforVo implements Serializable {
     @ExcelProperty(value = "序号")
     private Long infoId;
 
+
     /**
      * 租户编号
      */
@@ -44,6 +45,19 @@ public class SysLogininforVo implements Serializable {
     @ExcelProperty(value = "用户账号")
     private String userName;
 
+    /**
+     * 客户端
+     */
+    @ExcelProperty(value = "客户端")
+    private String clientKey;
+
+    /**
+     * 设备类型
+     */
+    @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_device_type")
+    private String deviceType;
+
     /**
      * 登录状态(0成功 1失败)
      */
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOperLogVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOperLogVo.java
index 3c67c73..6999da9 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOperLogVo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOperLogVo.java
@@ -36,7 +36,7 @@ public class SysOperLogVo implements Serializable {
     /**
      * 租户编号
      */
-    private String tenantId;
+    private Long tenantId;
 
     /**
      * 模块标题
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserVo.java
index 57dc66f..b4a546b 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserVo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserVo.java
@@ -2,9 +2,11 @@ package com.ruoyi.system.domain.vo;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.mybatisflex.annotation.Column;
 import com.mybatisflex.annotation.ColumnMask;
 import com.mybatisflex.annotation.RelationOneToOne;
 import com.mybatisflex.core.mask.Masks;
+import com.ruoyi.common.orm.core.domain.BaseEntity;
 import com.ruoyi.system.domain.SysUser;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
@@ -22,7 +24,7 @@ import java.util.List;
  */
 @Data
 @AutoMapper(target = SysUser.class)
-public class SysUserVo implements Serializable {
+public class SysUserVo extends BaseEntity {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -32,11 +34,6 @@ public class SysUserVo implements Serializable {
      */
     private Long userId;
 
-    /**
-     * 租户ID
-     */
-    private Long tenantId;
-
     /**
      * 部门ID
      */
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
index 9cfc1db..f38e852 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
@@ -66,6 +66,14 @@ public interface ISysMenuService extends IBaseService<SysMenu>
      */
     List<Long> selectMenuListByRoleId(Long roleId);
 
+    /**
+     * 根据租户套餐ID查询菜单树信息
+     *
+     * @param packageId 租户套餐ID
+     * @return 选中菜单列表
+     */
+    List<Long> selectMenuListByPackageId(Long packageId);
+
     /**
      * 构建前端路由所需要的菜单
      *
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
index 07408d4..7709bb5 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
@@ -11,11 +11,13 @@ import com.ruoyi.system.domain.bo.SysNoticeBo;
 import com.ruoyi.system.domain.bo.SysRoleBo;
 import com.ruoyi.system.domain.vo.SysNoticeVo;
 import com.ruoyi.system.domain.vo.SysRoleVo;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 角色业务层
  *
  * @author ruoyi
+ * @author 数据小王子
  */
 public interface ISysRoleService extends IBaseService<SysRole>
 {
@@ -66,14 +68,6 @@ public interface ISysRoleService extends IBaseService<SysRole>
      */
     List<SysRoleVo> selectRoleAll();
 
-    /**
-     * 根据用户ID获取角色选择框列表
-     *
-     * @param userId 用户ID
-     * @return 选中角色ID列表
-     */
-    List<Long> selectRoleListByUserId(Long userId);
-
     /**
      * 通过角色ID查询角色
      *
@@ -112,14 +106,6 @@ public interface ISysRoleService extends IBaseService<SysRole>
      */
     void checkRoleDataScope(Long roleId);
 
-//    /**
-//     * 通过角色ID查询角色使用数量
-//     *
-//     * @param roleId 角色ID
-//     * @return 结果
-//     */
-//    int countUserRoleByRoleId(Long roleId);
-
     /**
      * 新增保存角色信息
      *
@@ -128,6 +114,14 @@ public interface ISysRoleService extends IBaseService<SysRole>
      */
     boolean insertRole(SysRoleBo roleBo);
 
+    /**
+     * 新增角色菜单信息
+     *
+     * @param role 角色对象
+     * @return true 保存成功,false 保存失败
+     */
+    boolean insertRoleMenu(SysRole role);
+
     /**
      * 修改保存角色信息
      *
@@ -152,14 +146,6 @@ public interface ISysRoleService extends IBaseService<SysRole>
      */
     boolean authDataScope(SysRoleBo roleBo);
 
-//    /**
-//     * 通过角色ID删除角色
-//     *
-//     * @param roleId 角色ID
-//     * @return 结果
-//     */
-//    int deleteRoleById(Long roleId);
-
     /**
      * 批量删除角色信息
      *
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index 00a5a74..068727d 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -57,6 +57,15 @@ public interface ISysUserService extends IBaseService<SysUser>
      */
     SysUserVo selectUserByUserName(String userName);
 
+    /**
+     * 登录时通过用户名、租户编号查询用户(不走Mybatis-Flex租户插件)
+     *
+     * @param userName 用户名
+     * @param tenantId 租户编号
+     * @return 用户对象信息
+     */
+    SysUserVo selectTenantUserByUserName(String userName,Long tenantId);
+
     /**
      * 通过邮箱查询用户
      *
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysClientServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysClientServiceImpl.java
index c18eeb4..83d1983 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysClientServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysClientServiceImpl.java
@@ -8,6 +8,7 @@ import com.mybatisflex.core.util.UpdateEntity;
 import com.ruoyi.common.core.utils.MapstructUtils;
 import com.ruoyi.common.orm.core.page.PageQuery;
 import com.ruoyi.common.orm.core.page.TableDataInfo;
+import com.ruoyi.common.security.utils.LoginHelper;
 import com.ruoyi.system.domain.bo.SysClientBo;
 import com.ruoyi.system.domain.vo.SysClientVo;
 import jakarta.annotation.Resource;
@@ -18,6 +19,7 @@ import com.ruoyi.system.mapper.SysClientMapper;
 import com.mybatisflex.spring.service.impl.ServiceImpl;
 
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 
 import static com.ruoyi.system.domain.table.SysClientTableDef.SYS_CLIENT;
@@ -85,6 +87,14 @@ public class SysClientServiceImpl extends ServiceImpl<SysClientMapper, SysClient
         String clientKey = sysClientBo.getClientKey();
         String clientSecret = sysClientBo.getClientSecret();
         sysClient.setClientId(SecureUtil.md5(clientKey + clientSecret));
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        sysClient.setCreateBy(loginUserId);
+        sysClient.setCreateTime(createTime);
+        sysClient.setUpdateBy(loginUserId);
+        sysClient.setUpdateTime(createTime);
+
         return this.save(sysClient);
     }
 
@@ -95,6 +105,12 @@ public class SysClientServiceImpl extends ServiceImpl<SysClientMapper, SysClient
     public Boolean update(SysClientBo sysClientBo) {
         SysClient sysClient = MapstructUtils.convert(sysClientBo, SysClient.class);
         sysClient.setGrantType(String.join(",", sysClientBo.getGrantTypeList()));
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        sysClient.setUpdateBy(loginUserId);
+        sysClient.setUpdateTime(createTime);
+
         return this.updateById(sysClient);
     }
 
@@ -104,7 +120,14 @@ public class SysClientServiceImpl extends ServiceImpl<SysClientMapper, SysClient
     @Override
     public boolean updateStatus(Long id, String status) {
         SysClient sysClient = UpdateEntity.of(SysClient.class, id);
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        sysClient.setUpdateBy(loginUserId);
+        sysClient.setUpdateTime(createTime);
+
         sysClient.setStatus(status);
+
         return clientMapper.update(sysClient) > 0;
     }
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
index 16f471f..db13524 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
@@ -5,6 +5,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.useragent.UserAgent;
 import cn.hutool.http.useragent.UserAgentUtil;
 import com.mybatisflex.core.paginate.Page;
@@ -18,8 +19,12 @@ import com.ruoyi.common.log.event.LogininforEvent;
 import com.ruoyi.common.orm.core.page.PageQuery;
 import com.ruoyi.common.orm.core.page.TableDataInfo;
 import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
+import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.system.domain.SysClient;
 import com.ruoyi.system.domain.bo.SysLogininforBo;
 import com.ruoyi.system.domain.vo.SysLogininforVo;
+import com.ruoyi.system.service.ISysClientService;
+import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -45,6 +50,9 @@ import static com.ruoyi.system.domain.table.SysLogininforTableDef.SYS_LOGININFOR
 @Service
 public class SysLogininforServiceImpl extends BaseServiceImpl<SysLogininforMapper, SysLogininfor> implements ISysLogininforService {
 
+    @Resource
+    private ISysClientService clientService;
+
     @Override
     public QueryWrapper query() {
         return super.query().from(SYS_LOGININFOR);
@@ -61,6 +69,12 @@ public class SysLogininforServiceImpl extends BaseServiceImpl<SysLogininforMappe
         HttpServletRequest request = logininforEvent.getRequest();
         final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
         final String ip = ServletUtils.getClientIP(request);
+        // 客户端信息
+        String clientid = request.getHeader(LoginHelper.CLIENT_KEY);
+        SysClient client = null;
+        if (StringUtils.isNotBlank(clientid)) {
+            client = clientService.selectByClientId(clientid);
+        }
 
         String address = AddressUtils.getRealAddressByIP(ip);
         StringBuilder s = new StringBuilder();
@@ -79,6 +93,10 @@ public class SysLogininforServiceImpl extends BaseServiceImpl<SysLogininforMappe
         SysLogininforBo logininfor = new SysLogininforBo();
         logininfor.setTenantId(logininforEvent.getTenantId());
         logininfor.setUserName(logininforEvent.getUsername());
+        if (ObjectUtil.isNotNull(client)) {
+            logininfor.setClientKey(client.getClientKey());
+            logininfor.setDeviceType(client.getDeviceType());
+        }
         logininfor.setIpaddr(ip);
         logininfor.setLoginLocation(address);
         logininfor.setBrowser(browser);
@@ -120,9 +138,7 @@ public class SysLogininforServiceImpl extends BaseServiceImpl<SysLogininforMappe
      * @return 查询条件
      */
     private QueryWrapper buildQueryWrapper(SysLogininforBo logininforBo) {
-        QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(SYS_LOGININFOR.INFO_ID, SYS_LOGININFOR.USER_NAME, SYS_LOGININFOR.IPADDR, SYS_LOGININFOR.LOGIN_LOCATION, SYS_LOGININFOR.BROWSER, SYS_LOGININFOR.OS, SYS_LOGININFOR.STATUS, SYS_LOGININFOR.MSG, SYS_LOGININFOR.LOGIN_TIME)
-            .from(SYS_LOGININFOR)
+        QueryWrapper queryWrapper = query()
             .and(SYS_LOGININFOR.IPADDR.like(logininforBo.getIpaddr()))
             .and(SYS_LOGININFOR.STATUS.eq(logininforBo.getStatus()))
             .and(SYS_LOGININFOR.USER_NAME.like(logininforBo.getUserName()))
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
index 5cc672a..ea28e06 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
@@ -1,14 +1,10 @@
 package com.ruoyi.system.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
 import cn.hutool.core.lang.tree.Tree;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import com.mybatisflex.core.query.QueryMethods;
 import com.mybatisflex.core.query.QueryWrapper;
@@ -21,6 +17,7 @@ import com.ruoyi.system.domain.*;
 import com.ruoyi.system.domain.bo.SysMenuBo;
 import com.ruoyi.system.domain.vo.SysMenuVo;
 import com.ruoyi.system.domain.vo.SysRoleVo;
+import com.ruoyi.system.mapper.SysTenantPackageMapper;
 import com.ruoyi.system.service.ISysRoleMenuService;
 import com.ruoyi.system.service.ISysRoleService;
 import jakarta.annotation.Resource;
@@ -57,6 +54,8 @@ public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu>
 
     @Resource
     private ISysRoleMenuService roleMenuService;
+    @Resource
+    private SysTenantPackageMapper tenantPackageMapper;
 
     @Override
     public QueryWrapper query() {
@@ -274,6 +273,26 @@ public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu>
         return this.listAs(queryWrapper, Long.class);
     }
 
+    /**
+     * 根据租户套餐ID查询菜单树信息
+     *
+     * @param packageId 租户套餐ID
+     * @return 选中菜单列表
+     */
+    @Override
+    public List<Long> selectMenuListByPackageId(Long packageId) {
+        SysTenantPackage tenantPackage = tenantPackageMapper.selectOneById(packageId);
+        List<Long> menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong);
+        if (CollUtil.isEmpty(menuIds)) {
+            return List.of();
+        }
+        List<Long> parentIds = null;
+        if (tenantPackage.getMenuCheckStrictly()) {
+            parentIds = menuMapper.selectObjectListByQueryAs(QueryWrapper.create().select(SYS_MENU.PARENT_ID).from(SYS_MENU).where(SYS_MENU.MENU_ID.in(menuIds)), Long.class);
+        }
+        return menuMapper.selectObjectListByQueryAs(QueryWrapper.create().select(SYS_MENU.MENU_ID).from(SYS_MENU).where(SYS_MENU.MENU_ID.in(menuIds)).and(SYS_MENU.MENU_ID.notIn(parentIds)), Long.class);
+    }
+
     /**
      * 构建前端路由所需要的菜单
      *
@@ -386,6 +405,14 @@ public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu>
     @Override
     public int insertMenu(SysMenuBo menuBo) {
         SysMenu menu = MapstructUtils.convert(menuBo, SysMenu.class);
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        menu.setCreateBy(loginUserId);
+        menu.setCreateTime(createTime);
+        menu.setUpdateBy(loginUserId);
+        menu.setUpdateTime(createTime);
+
         return menuMapper.insert(menu, false);
     }
 
@@ -398,6 +425,12 @@ public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu>
     @Override
     public boolean updateMenu(SysMenuBo menuBo) {
         SysMenu menu = MapstructUtils.convert(menuBo, SysMenu.class);
+
+        Long loginUserId = LoginHelper.getUserId();
+        Date createTime = new Date();
+        menu.setUpdateBy(loginUserId);
+        menu.setUpdateTime(createTime);
+
         return this.updateById(menu);
     }
 
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
index 5322edc..8409bf2 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.mybatisflex.core.paginate.Page;
 import com.mybatisflex.core.query.QueryWrapper;
 import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
+import jakarta.annotation.Resource;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import com.ruoyi.common.core.constant.CacheNames;
@@ -43,8 +44,6 @@ import static com.ruoyi.system.domain.table.SysOssConfigTableDef.SYS_OSS_CONFIG;
 @Service
 public class SysOssConfigServiceImpl extends BaseServiceImpl<SysOssConfigMapper, SysOssConfig> implements ISysOssConfigService {
 
-    private final SysOssConfigMapper baseMapper;
-
     @Override
     public QueryWrapper query() {
         return super.query().from(SYS_OSS_CONFIG);
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
index 203227f..faa3d7c 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -210,28 +210,27 @@ public class SysRoleServiceImpl extends BaseServiceImpl<SysRoleMapper, SysRole>
         return SpringUtils.getAopProxy(this).selectRoleList(new SysRoleBo());
     }
 
-    /**
-     * 根据用户ID获取角色选择框列表
-     *
-     * @param userId 用户ID
-     * @return 选中角色ID列表
-     */
-    @Override
-    public List<Long> selectRoleListByUserId(Long userId) {
-        //return roleMapper.selectRoleListByUserId(userId);
-        /*select r.role_id
-        from sys_role r
-        left join sys_user_role ur on ur.role_id = r.role_id
-        left join sys_user u on u.user_id = ur.user_id
-        where u.user_id = #{userId}*/
-        QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(SYS_ROLE.ROLE_ID)
-            .from(SYS_ROLE.as("r"))
-            .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE.ROLE_ID))
-            .leftJoin(SYS_USER).as("u").on(SYS_USER.USER_ID.eq(SYS_USER_ROLE.USER_ID))
-            .where(SYS_USER.USER_ID.eq(userId));
-        return roleMapper.selectObjectListByQueryAs(queryWrapper, Long.class);
-    }
+//    /**
+//     * 根据用户ID获取角色选择框列表
+//     *
+//     * @param userId 用户ID
+//     * @return 选中角色ID列表
+//     */
+//    public List<Long> selectRoleListByUserId(Long userId) {
+//        //return roleMapper.selectRoleListByUserId(userId);
+//        /*select r.role_id
+//        from sys_role r
+//        left join sys_user_role ur on ur.role_id = r.role_id
+//        left join sys_user u on u.user_id = ur.user_id
+//        where u.user_id = #{userId}*/
+//        QueryWrapper queryWrapper = QueryWrapper.create()
+//            .select(SYS_ROLE.ROLE_ID)
+//            .from(SYS_ROLE.as("r"))
+//            .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE.ROLE_ID))
+//            .leftJoin(SYS_USER).as("u").on(SYS_USER.USER_ID.eq(SYS_USER_ROLE.USER_ID))
+//            .where(SYS_USER.USER_ID.eq(userId));
+//        return roleMapper.selectObjectListByQueryAs(queryWrapper, Long.class);
+//    }
 
     /**
      * 通过角色ID查询角色
@@ -417,6 +416,7 @@ public class SysRoleServiceImpl extends BaseServiceImpl<SysRoleMapper, SysRole>
      * @param role 角色对象
      * @return true 保存成功,false 保存失败
      */
+    @Override
     @Transactional
     public boolean insertRoleMenu(SysRole role) {
         boolean inserted = true;
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 1e74945..fee6a45 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -19,6 +19,7 @@ import com.ruoyi.common.orm.core.page.PageQuery;
 import com.ruoyi.common.orm.core.page.TableDataInfo;
 import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
 import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.tenant.helper.TenantHelper;
 import com.ruoyi.system.domain.*;
 import com.ruoyi.system.domain.bo.SysUserBo;
 import com.ruoyi.system.domain.vo.SysPostVo;
@@ -85,13 +86,13 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         return super.query().from(SYS_USER);
     }
 
-    private QueryWrapper buildListQueryWrapper(SysUserBo userBo){
+    private QueryWrapper buildListQueryWrapper(SysUserBo userBo) {
         /*select u.user_id, u.tenant_id, u.dept_id, u.nick_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.gender, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader
         from sys_user u
         left join sys_dept d on u.dept_id = d.dept_id
         where u.del_flag = '0'*/
         QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(SYS_USER.USER_ID,SYS_USER.TENANT_ID,SYS_USER.DEPT_ID,SYS_USER.NICK_NAME,SYS_USER.USER_NAME,SYS_USER.USER_TYPE,SYS_USER.EMAIL,SYS_USER.AVATAR,SYS_USER.PHONENUMBER,SYS_USER.GENDER,SYS_USER.STATUS,SYS_USER.DEL_FLAG,SYS_USER.LOGIN_IP,SYS_USER.LOGIN_DATE,SYS_USER.CREATE_BY,SYS_USER.CREATE_TIME,SYS_USER.REMARK,SYS_DEPT.DEPT_NAME,SYS_DEPT.LEADER)
+            .select(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.NICK_NAME, SYS_USER.USER_NAME, SYS_USER.USER_TYPE, SYS_USER.EMAIL, SYS_USER.AVATAR, SYS_USER.PHONENUMBER, SYS_USER.GENDER, SYS_USER.STATUS, SYS_USER.DEL_FLAG, SYS_USER.LOGIN_IP, SYS_USER.LOGIN_DATE, SYS_USER.CREATE_BY, SYS_USER.CREATE_TIME, SYS_USER.REMARK, SYS_DEPT.DEPT_NAME, SYS_DEPT.LEADER)
             .from(SYS_USER.as("u"))
             .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
             .where(SYS_USER.DEL_FLAG.eq(0));
@@ -112,13 +113,13 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
             queryWrapper.and(SYS_USER.CREATE_TIME.between(params.get("beginTime"), params.get("endTime")));
         }
         if (ObjectUtil.isNotNull(userBo.getDeptId())) {
-            queryWrapper.and(SYS_USER.DEPT_ID.eq(userBo.getDeptId()).or(SYS_USER.DEPT_ID.in(select(SYS_DEPT.DEPT_ID).from(SYS_DEPT.as("t")).where(findInSet(number(userBo.getDeptId()),SYS_DEPT.ANCESTORS).gt(0)))));
+            queryWrapper.and(SYS_USER.DEPT_ID.eq(userBo.getDeptId()).or(SYS_USER.DEPT_ID.in(select(SYS_DEPT.DEPT_ID).from(SYS_DEPT.as("t")).where(findInSet(number(userBo.getDeptId()), SYS_DEPT.ANCESTORS).gt(0)))));
         }
-
+        queryWrapper.orderBy(SYS_USER.USER_ID.desc());
         return queryWrapper;
     }
 
-    private QueryWrapper buildOneQueryWrapper(){
+    private QueryWrapper buildOneQueryWrapper() {
         /*  select u.user_id, u.tenant_id,u.dept_id, u.user_name, u.nick_name, u.user_type, u.email, u.avatar, u.phonenumber, u.password, u.gender, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
@@ -135,14 +136,14 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
             .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
             .leftJoin(SYS_ROLE).as("r").on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID));*/
         return QueryWrapper.create()
-            .select(QueryMethods.distinct(SYS_USER.USER_ID,SYS_USER.TENANT_ID,SYS_USER.DEPT_ID,SYS_USER.NICK_NAME,SYS_USER.USER_NAME,SYS_USER.USER_TYPE,SYS_USER.EMAIL,SYS_USER.AVATAR,SYS_USER.PHONENUMBER,SYS_USER.PASSWORD,SYS_USER.GENDER,SYS_USER.STATUS,SYS_USER.DEL_FLAG,SYS_USER.LOGIN_IP,SYS_USER.LOGIN_DATE,SYS_USER.CREATE_BY,SYS_USER.CREATE_TIME,SYS_USER.REMARK,
-                SYS_DEPT.DEPT_ID,SYS_DEPT.PARENT_ID,SYS_DEPT.ANCESTORS,SYS_DEPT.DEPT_NAME,SYS_DEPT.ORDER_NUM,SYS_DEPT.LEADER,SYS_DEPT.STATUS.as("dept_status")
-                ))
+            .select(QueryMethods.distinct(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.NICK_NAME, SYS_USER.USER_NAME, SYS_USER.USER_TYPE, SYS_USER.EMAIL, SYS_USER.AVATAR, SYS_USER.PHONENUMBER, SYS_USER.PASSWORD, SYS_USER.GENDER, SYS_USER.STATUS, SYS_USER.DEL_FLAG, SYS_USER.LOGIN_IP, SYS_USER.LOGIN_DATE, SYS_USER.CREATE_BY, SYS_USER.CREATE_TIME, SYS_USER.REMARK,
+                SYS_DEPT.DEPT_ID, SYS_DEPT.PARENT_ID, SYS_DEPT.ANCESTORS, SYS_DEPT.DEPT_NAME, SYS_DEPT.ORDER_NUM, SYS_DEPT.LEADER, SYS_DEPT.STATUS.as("dept_status")
+            ))
             .from(SYS_USER.as("u"))
             .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
             .where(SYS_USER.DEL_FLAG.eq(0));
-            //.leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
-            //.leftJoin(SYS_ROLE).as("r").on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID));
+        //.leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
+        //.leftJoin(SYS_ROLE).as("r").on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID));
     }
 
 
@@ -194,7 +195,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
 		<!-- 数据范围过滤 -->
             ${params.dataScope}*/
         QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(QueryMethods.distinct(SYS_USER.USER_ID,SYS_USER.TENANT_ID,SYS_USER.DEPT_ID,SYS_USER.USER_NAME,SYS_USER.NICK_NAME,SYS_USER.USER_TYPE,SYS_USER.EMAIL,SYS_USER.PHONENUMBER,SYS_USER.STATUS,SYS_USER.CREATE_TIME))
+            .select(QueryMethods.distinct(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.USER_NAME, SYS_USER.NICK_NAME, SYS_USER.USER_TYPE, SYS_USER.EMAIL, SYS_USER.PHONENUMBER, SYS_USER.STATUS, SYS_USER.CREATE_TIME))
             .from(SYS_USER.as("u"))
             .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
             .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
@@ -236,7 +237,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
 		<!-- 数据范围过滤 -->
             ${params.dataScope}*/
         QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(QueryMethods.distinct(SYS_USER.USER_ID,SYS_USER.TENANT_ID,SYS_USER.DEPT_ID,SYS_USER.USER_NAME,SYS_USER.NICK_NAME,SYS_USER.USER_TYPE,SYS_USER.EMAIL,SYS_USER.PHONENUMBER,SYS_USER.STATUS,SYS_USER.CREATE_TIME))
+            .select(QueryMethods.distinct(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.USER_NAME, SYS_USER.NICK_NAME, SYS_USER.USER_TYPE, SYS_USER.EMAIL, SYS_USER.PHONENUMBER, SYS_USER.STATUS, SYS_USER.CREATE_TIME))
             .from(SYS_USER.as("u"))
             .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
             .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
@@ -269,7 +270,24 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         if (StringUtils.isNotEmpty(userName)) {
             queryWrapper.and(SYS_USER.USER_NAME.eq(userName));
         }
-        return this.getOneAs(queryWrapper,SysUserVo.class);
+        return this.getOneAs(queryWrapper, SysUserVo.class);
+    }
+
+    /**
+     * 登录时通过用户名、租户编号查询用户(不走Mybatis-Flex租户插件)
+     *
+     * @param userName 用户名
+     * @param tenantId 租户编号
+     * @return 用户对象信息
+     */
+    @Override
+    public SysUserVo selectTenantUserByUserName(String userName, Long tenantId) {
+        return TenantHelper.ignore(() -> {
+            QueryWrapper queryWrapper = buildOneQueryWrapper()
+                .where(SYS_USER.TENANT_ID.eq(tenantId))
+                .and(SYS_USER.USER_NAME.eq(userName));
+            return this.getOneAs(queryWrapper, SysUserVo.class);
+        });
     }
 
     /**
@@ -285,7 +303,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         if (StringUtils.isNotEmpty(email)) {
             queryWrapper.and(SYS_USER.EMAIL.eq(email));
         }
-        return this.getOneAs(queryWrapper,SysUserVo.class);
+        return this.getOneAs(queryWrapper, SysUserVo.class);
     }
 
     /**
@@ -301,7 +319,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         if (ObjectUtil.isNotNull(userId)) {
             queryWrapper.where(SYS_USER.USER_ID.eq(userId));
         }
-        return userMapper.selectOneWithRelationsByQueryAs(queryWrapper,SysUserVo.class);//使用Relation注解从sys_oss中查询头像地址URL
+        return userMapper.selectOneWithRelationsByQueryAs(queryWrapper, SysUserVo.class);//使用Relation注解从sys_oss中查询头像地址URL
     }
 
     /**
@@ -314,8 +332,8 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     public SysUserVo selectProfileUserById(Long userId) {
         //使用leftjoin取得部门名称
         QueryWrapper queryWrapper = QueryWrapper.create()
-            .select(QueryMethods.distinct(SYS_USER.USER_ID,SYS_USER.TENANT_ID,SYS_USER.DEPT_ID,SYS_USER.NICK_NAME,SYS_USER.USER_NAME,SYS_USER.USER_TYPE,SYS_USER.EMAIL,SYS_USER.AVATAR,SYS_USER.PHONENUMBER,SYS_USER.PASSWORD,SYS_USER.GENDER,SYS_USER.STATUS,SYS_USER.DEL_FLAG,SYS_USER.LOGIN_IP,SYS_USER.LOGIN_DATE,SYS_USER.CREATE_BY,SYS_USER.CREATE_TIME,SYS_USER.REMARK,
-                SYS_DEPT.DEPT_ID,SYS_DEPT.PARENT_ID,SYS_DEPT.ANCESTORS,SYS_DEPT.DEPT_NAME,SYS_DEPT.ORDER_NUM,SYS_DEPT.LEADER,SYS_DEPT.STATUS.as("dept_status")
+            .select(QueryMethods.distinct(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.NICK_NAME, SYS_USER.USER_NAME, SYS_USER.USER_TYPE, SYS_USER.EMAIL, SYS_USER.AVATAR, SYS_USER.PHONENUMBER, SYS_USER.PASSWORD, SYS_USER.GENDER, SYS_USER.STATUS, SYS_USER.DEL_FLAG, SYS_USER.LOGIN_IP, SYS_USER.LOGIN_DATE, SYS_USER.CREATE_BY, SYS_USER.CREATE_TIME, SYS_USER.REMARK,
+                SYS_DEPT.DEPT_ID, SYS_DEPT.PARENT_ID, SYS_DEPT.ANCESTORS, SYS_DEPT.DEPT_NAME, SYS_DEPT.ORDER_NUM, SYS_DEPT.LEADER, SYS_DEPT.STATUS.as("dept_status")
             ))
             .from(SYS_USER.as("u"))
             .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
@@ -323,7 +341,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         if (ObjectUtil.isNotNull(userId)) {
             queryWrapper.and(SYS_USER.USER_ID.eq(userId));
         }
-        return this.getOneAs(queryWrapper,SysUserVo.class);
+        return this.getOneAs(queryWrapper, SysUserVo.class);
     }
 
     /**
@@ -458,7 +476,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
             .where(SYS_USER.DEPT_ID.eq(deptId))
             .and(SYS_USER.DEL_FLAG.eq(0));
 
-        int result = userMapper.selectObjectByQueryAs(queryWrapper,Integer.class);
+        int result = userMapper.selectObjectByQueryAs(queryWrapper, Integer.class);
         return result > 0;
     }
 
@@ -474,7 +492,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         SysUser user = MapstructUtils.convert(userBo, SysUser.class);
         // 新增用户信息
         boolean saved = this.save(user);
-        if(saved){
+        if (saved) {
             // 新增用户岗位关联
             insertUserPost(user);
             // 新增用户与角色管理
@@ -534,12 +552,13 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     @Transactional
     public void insertUserAuth(Long userId, Long[] roleIds) {
         userRoleService.deleteUserRoleByUserId(userId);
-        userRoleService.insertUserRoles(userId,roleIds);
+        userRoleService.insertUserRoles(userId, roleIds);
     }
 
     /**
      * 修改用户状态
      * update sys_user set status = #{status} where user_id = #{userId}
+     *
      * @param user 用户信息
      * @return 结果:true 操作成功,false 操作失败。
      */
@@ -566,6 +585,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     /**
      * 修改用户头像
      * update sys_user set avatar = #{avatar} where user_id = #{userId}
+     *
      * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果:true 更新成功,false 更新失败
@@ -576,7 +596,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         SysUser sysUser = new SysUser();
         sysUser.setUserId(userId);
         sysUser.setAvatar(avatar);
-        return this.update(sysUser,queryWrapper);
+        return this.update(sysUser, queryWrapper);
     }
 
     /**
@@ -587,7 +607,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
      */
     @Override
     public boolean resetPwd(SysUserBo user) {
-        return  UpdateChain.of(SysUser.class)
+        return UpdateChain.of(SysUser.class)
             .set(SysUser::getPassword, user.getPassword())
             .where(SysUser::getUserId).eq(user.getUserId())
             .update();
@@ -596,6 +616,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     /**
      * 重置用户密码
      * update sys_user set password = #{password} where user_name = #{userName}
+     *
      * @param userName 用户名
      * @param password 密码
      * @return 结果:true 更新成功,false 更新失败
@@ -605,7 +626,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         QueryWrapper queryWrapper = query().where(SYS_USER.USER_NAME.eq(userName));
         SysUser sysUser = new SysUser();
         sysUser.setPassword(password);
-        return this.update(sysUser,queryWrapper);
+        return this.update(sysUser, queryWrapper);
     }
 
     /**
@@ -615,7 +636,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
      */
     public void insertUserRole(SysUser user) {
         if (ObjectUtil.isNotEmpty(user.getUserId()) && ObjectUtil.isNotEmpty(user.getRoleIds())) {
-            userRoleService.insertUserRoles(user.getUserId(),user.getRoleIds());
+            userRoleService.insertUserRoles(user.getUserId(), user.getRoleIds());
         }
     }
 
@@ -637,7 +658,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
                 list.add(up);
             }
             if (list.size() > 0) {
-                return userPostService.saveBatchWithPk(list,100);//批量保存
+                return userPostService.saveBatchWithPk(list, 100);//批量保存
             }
         }
         return inserted;
@@ -686,7 +707,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
         QueryWrapper queryWrapper = query().where(SYS_USER.USER_ID.in(Arrays.asList(userIds)));
         SysUser sysUser = new SysUser();
         sysUser.setDelFlag(1);
-        return this.update(sysUser,queryWrapper);
+        return this.update(sysUser, queryWrapper);
         //return UpdateChain.of(SysUser.class)
 //            .set(SysUser::getDelFlag, "1")
 //            .where(SysUser::getUserId).in(Arrays.asList(userIds))
@@ -754,7 +775,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     @Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId")
     @Override
     public String selectUserNameById(Long userId) {
-        SysUserVo sysUser=selectUserById(userId);
+        SysUserVo sysUser = selectUserById(userId);
         return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName();
     }
 
@@ -767,6 +788,6 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
     @Override
     public List<SysUserVo> selectUserListByDept(Long deptId) {
         QueryWrapper queryWrapper = query().where(SYS_USER.DEPT_ID.eq(deptId)).and(SYS_USER.DEL_FLAG.eq(0));
-        return this.listAs(queryWrapper,SysUserVo.class);
+        return this.listAs(queryWrapper, SysUserVo.class);
     }
 }