diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index 89b9ab63c..e4be72c36 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -99,7 +99,7 @@ public class AuthController { return R.fail(MessageUtils.message("auth.grant.type.blocked")); } // 校验租户 - loginService.checkTenant(loginBody.getTenantId()); + loginService.checkTenant(loginBody.getUsername()); // 登录 LoginVo loginVo = IAuthStrategy.login(body, client, grantType); diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java index dcd04c5e1..326402822 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java @@ -63,10 +63,11 @@ public class CaptchaController { String code = RandomUtil.randomNumbers(4); RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); // 验证码模板id 自行处理 (查数据库或写死均可) - String templateId = ""; + String templateId = "SMS_249510287"; LinkedHashMap map = new LinkedHashMap<>(1); map.put("code", code); SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); + System.out.println("SmsBlend = " + smsBlend); SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map); if (!smsResponse.isSuccess()) { log.error("验证码短信发送异常 => {}", smsResponse); diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 41a802b44..e54e1d46f 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -222,28 +222,28 @@ public class SysLoginService { /** * 校验租户 * - * @param tenantId 租户ID + * @param username 手机号 或 登录账号 */ - public void checkTenant(String tenantId) { + public void checkTenant(String username) { if (!TenantHelper.isEnable()) { return; } - if (StringUtils.isBlank(tenantId)) { - throw new TenantException("tenant.number.not.blank"); + if (StringUtils.isBlank(username)) { + throw new TenantException("user.username.not.blank"); } - if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + if (TenantConstants.DEFAULT_USERNAME.equals(username) || TenantConstants.DEFAULT_PHONENUMBER.equals(username)) { return; } - SysTenantVo tenant = tenantService.queryByTenantId(tenantId); + SysTenantVo tenant = tenantService.queryByUsername(username); if (ObjectUtil.isNull(tenant)) { - log.info("登录租户:{} 不存在.", tenantId); + log.info("登录公司:{} 不存在.", username); throw new TenantException("tenant.not.exists"); } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) { - log.info("登录租户:{} 已被停用.", tenantId); + log.info("登录公司:{} 已被停用.", username); throw new TenantException("tenant.blocked"); } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) && new Date().after(tenant.getExpireTime())) { - log.info("登录租户:{} 已超过有效期.", tenantId); + log.info("登录公司:{} 已超过有效期.", username); throw new TenantException("tenant.expired"); } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java index abf590b36..6e58da11a 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java @@ -51,19 +51,21 @@ public class PasswordAuthStrategy implements IAuthStrategy { public LoginVo login(String body, SysClientVo client) { PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class); ValidatorUtils.validate(loginBody); - String tenantId = loginBody.getTenantId(); String username = loginBody.getUsername(); String password = loginBody.getPassword(); String code = loginBody.getCode(); String uuid = loginBody.getUuid(); + // 先查询用户信息获取租户ID + SysUserVo user = loadUserByUsername(username); + String tenantId = user.getTenantId(); + boolean captchaEnabled = captchaProperties.getEnable(); // 验证码开关 if (captchaEnabled) { validateCaptcha(tenantId, username, code, uuid); } LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { - SysUserVo user = loadUserByUsername(username); loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); // 此处可根据登录用户的数据不同 自行创建 loginUser return loginService.buildLoginUser(user); @@ -109,7 +111,15 @@ public class PasswordAuthStrategy implements IAuthStrategy { } private SysUserVo loadUserByUsername(String username) { - SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, username)); + // 不指定租户上下文,允许查询所有租户的用户 + SysUserVo user = TenantHelper.ignore(() -> + userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, username)) + ); + if (ObjectUtil.isNull(user)) { + user = TenantHelper.ignore(() -> + userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getPhonenumber, username)) + ); + } if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", username); throw new UserException("user.not.exists", username); diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java index 597a6013b..e6dd6dd79 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java @@ -47,11 +47,14 @@ public class SmsAuthStrategy implements IAuthStrategy { public LoginVo login(String body, SysClientVo client) { SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class); ValidatorUtils.validate(loginBody); - String tenantId = loginBody.getTenantId(); String phonenumber = loginBody.getPhonenumber(); String smsCode = loginBody.getSmsCode(); + + // 先查询用户信息获取租户ID + SysUserVo user = loadUserByUsername(phonenumber); + String tenantId = user.getTenantId(); + LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { - SysUserVo user = loadUserByPhonenumber(phonenumber); loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode)); // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 return loginService.buildLoginUser(user); @@ -87,14 +90,22 @@ public class SmsAuthStrategy implements IAuthStrategy { return code.equals(smsCode); } - private SysUserVo loadUserByPhonenumber(String phonenumber) { - SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getPhonenumber, phonenumber)); + private SysUserVo loadUserByUsername(String username) { + // 不指定租户上下文,允许查询所有租户的用户 + SysUserVo user = TenantHelper.ignore(() -> + userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, username)) + ); + if (ObjectUtil.isNull(user)) { + user = TenantHelper.ignore(() -> + userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getPhonenumber, username)) + ); + } if (ObjectUtil.isNull(user)) { - log.info("登录用户:{} 不存在.", phonenumber); - throw new UserException("user.not.exists", phonenumber); + log.info("登录用户:{} 不存在.", username); + throw new UserException("user.not.exists", username); } else if (SystemConstants.DISABLE.equals(user.getStatus())) { - log.info("登录用户:{} 已被停用.", phonenumber); - throw new UserException("user.blocked", phonenumber); + 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 6eac3f9dc..b2002fc3e 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -172,11 +172,13 @@ sms: # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 supplier: alibaba # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。 - access-key-id: 您的accessKey + access-key-id: LTAI5t8EFke56vn9YPQSgtMP # 称为accessSecret有些称之为apiSecret - access-key-secret: 您的accessKeySecret - signature: 您的短信签名 - sdk-app-id: 您的sdkAppId + access-key-secret: 1QudSASPkiXrLJON6KQr4Vrojt1rO6 + # 短信签名 - 在阿里云短信控制台「签名管理」中申请,填写时不要加【】符号 + # 例如: 若羽物联 (不要写成 【若羽物联】) + signature: 速通互联验证码 + # 注意: 阿里云不需要 sdk-app-id 参数,已删除 config2: # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 supplier: tencent diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java index 33ce0cf6c..aa986759c 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java @@ -32,4 +32,14 @@ public interface TenantConstants { */ String DEFAULT_TENANT_ID = "000000"; + /** + * 默认手机号 + */ + String DEFAULT_PHONENUMBER = "13888888888"; + + /** + * 默认登录账号 + */ + String DEFAULT_USERNAME = "administrator"; + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java index 63bee0ddc..2ccb46982 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java @@ -35,6 +35,11 @@ public class LoginBody implements Serializable { */ private String tenantId; + /** + * 用户手机号码 或 登录账号 + */ + private String username; + /** * 验证码 */ diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ClientConnection.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ClientConnection.java new file mode 100644 index 000000000..92fde0cba --- /dev/null +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ClientConnection.java @@ -0,0 +1,12 @@ +package org.dromara.demo.domain; +import lombok.Data; + +import java.net.Socket; + +@Data +public class ClientConnection { + private String clientId; // 你的设备唯一ID + private Socket socket; // 保存socket + private long lastActiveTime; // 最近一次心跳/数据时间 + private long connectTime; // 建连时间 +} diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/server/IotTcpServer.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/server/IotTcpServer.java new file mode 100644 index 000000000..776494693 --- /dev/null +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/server/IotTcpServer.java @@ -0,0 +1,313 @@ +package org.dromara.demo.server; + +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.dromara.demo.domain.ClientConnection; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import jakarta.annotation.PreDestroy; + +/** + * TCP服务器,用于接收单片机4G模块发送的传感器数据 + * 协议:每帧以 "hellohello" 开始,以 "byebye" 结束,帧内为 JSON 文本 + * 说明:使用起止分隔符解析,解决无换行、粘包、半包问题 + */ +@Slf4j +@Component +public class IotTcpServer implements CommandLineRunner { + + @Value("${tcp.server.port:8888}") + private int tcpPort; + + private final ObjectMapper objectMapper = new ObjectMapper(); + private final ExecutorService executorService = Executors.newCachedThreadPool(); + private final ScheduledExecutorService heartbeatService = Executors.newScheduledThreadPool(2); + private final AtomicBoolean started = new AtomicBoolean(false); + private ServerSocket serverSocket; + + // 用于存储客户端连接和起信息 + @Getter + private final ConcurrentHashMap clientMaps = new ConcurrentHashMap<>(); + + @Override + public void run(String... args) throws Exception { + executorService.submit(this::startTcpServer); + // 启动心跳检测任务,每10秒检查一次 + heartbeatService.scheduleAtFixedRate(this::checkHeartbeats, 10, 30, TimeUnit.SECONDS); + } + + /** + * 启动TCP服务器 + */ + public void startTcpServer() { + if (!started.compareAndSet(false, true)) { + log.warn("TCP服务器已启动,忽略重复启动"); + return; + } + try { + serverSocket = new ServerSocket(tcpPort); + log.info("TCP服务器启动成功,监听端口: {}", tcpPort); + + // 持续监听客户端连接 + while (!serverSocket.isClosed()) { + try { + Socket clientSocket = serverSocket.accept(); + configureClientSocket(clientSocket); + // 为每个客户端连接创建独立的处理线程 + executorService.submit(() -> handleClient(clientSocket)); + } catch (IOException e) { + if (!serverSocket.isClosed()) { + log.error("接受客户端连接时发生错误", e); + } + } + } + } catch (IOException e) { + log.error("启动TCP服务器失败", e); + } + } + + /** + * 处理客户端连接 + * 协议:以 "hellohello" 开始,以 "byebye" 结束;帧内为 JSON + * 处理粘包/半包:累积缓冲区,查找起止分隔符,可一次解析多帧。 + */ + private void handleClient(Socket clientSocket) { + //TODO 应该处理为 首个hellohello 和最后一个bygbye + //并且 如果开头和结尾不为这样的数据,则丢弃 + final String START = "hellohello"; + final String END = "byebye"; + final String HEARTBEAT = "heartbeat"; + final Charset charset = StandardCharsets.UTF_8; + String clientId = null; + try (InputStream in = clientSocket.getInputStream()) { + StringBuilder sb = new StringBuilder(4096); + byte[] buf = new byte[4096]; + int n; + + // 第一个完整的帧包含设备唯一标识符 + boolean identifierReceived = false; + + + while ((n = in.read(buf)) != -1) { + if (n <= 0) continue; + String chunk = new String(buf, 0, n, charset); + sb.append(chunk); + + while (true) { + int s = sb.indexOf(START); + if (s < 0) { + // 可选:避免缓冲区无限增长(很少触达) + if (sb.length() > 65536) { + sb.delete(0, sb.length() - 65536); + } + break; + } + int e = sb.indexOf(END, s + START.length()); + if (e < 0) { + // 起始存在但尚无结束,保留从起始开始的内容,丢弃起始前的噪声 + if (s > 0) sb.delete(0, s); + break; + } + // 帧内容为 [s+START.length, e) + int payloadStart = s + START.length(); + String json = sb.substring(payloadStart, e).trim(); + + if (!identifierReceived) { + // 解析首个帧作为设备标识符 + clientId = json; + ClientConnection clientConnection = clientMaps.get(clientId); + if (ObjectUtil.isNotNull(clientConnection) && ObjectUtil.isNotNull(clientConnection.getSocket())) { + log.info("客户端连接重复: {},断开旧连接。", clientId); + clientConnection.getSocket().close(); //有重复连接,断开旧连接 + + }else { + clientConnection = new ClientConnection(); + } + clientConnection.setSocket(clientSocket); + clientConnection.setConnectTime(System.currentTimeMillis()); + clientConnection.setLastActiveTime(System.currentTimeMillis()); + clientMaps.put(clientId, clientConnection); // 关联标识符与Socket + log.info("新客户端连接: {}", clientId); + identifierReceived = true; + continue; + } + + // 若尾部含其他字符,兜底裁到最后一个 '}' + int lastBrace = json.lastIndexOf('}'); + if (lastBrace >= 0) { + json = json.substring(0, lastBrace + 1); + } + + // 检查是否是心跳包 + if (HEARTBEAT.equals(json.trim())) { + log.info("收到客户端 {} 的心跳包", clientId); + // 更新客户端最后活动时间 + ClientConnection clientConnection = clientMaps.get(clientId); + clientConnection.setLastActiveTime(System.currentTimeMillis()); + // 发送心跳响应 + String finalClientId = clientId; + heartbeatService.schedule(() -> writeFrame(finalClientId, "heartbeat_ack", charset), 100, TimeUnit.MILLISECONDS); + sb.delete(0, e + END.length()); + continue; + }else { + log.info("接收到帧: {}", json); + try { + // 解析成功后,封装并发送温湿度响应 + try { + JsonNode root = objectMapper.readTree(json); + log.info("解析数据成功:{}",root); + } catch (Exception sendEx) { + log.warn("构造/发送温湿度响应失败: {}", sendEx.getMessage()); + } + } catch (Exception ex) { + log.error("解析传感器数据失败: {}", json, ex); + } + + } + + // 删除到结束标记之后,继续解析后续帧 + sb.delete(0, e + END.length()); + } + } + + // 连接关闭时的尾帧兜底 + int s = sb.indexOf(START); + int e = (s >= 0) ? sb.indexOf(END, s + START.length()) : -1; + if (s >= 0 && e > s) { + String json = sb.substring(s + START.length(), e).trim(); + int lastBrace = json.lastIndexOf('}'); + if (lastBrace >= 0) json = json.substring(0, lastBrace + 1); + if (!json.isEmpty()) { + log.info("接收到尾帧: {}", json); + try { + } catch (Exception ex) { + log.error("解析传感器数据失败(尾帧): {}", json, ex); + } + } + } + } catch (IOException e) { + log.error("处理客户端连接时发生错误", e); + } finally { + if (clientId != null) { + clientMaps.remove(clientId); + } + try { + // 客户端断开连接时执行的代码 + clientSocket.close(); + log.info("客户端连接已关闭: {}", clientId); + } catch (IOException e) { + log.error("关闭客户端连接时发生错误", e); + } + } + } + + /** + * 检查客户端心跳,断开超时的连接 + */ + private void checkHeartbeats() { + long currentTime = System.currentTimeMillis(); + long timeout = 90 * 1000; // 90秒超时 + + clientMaps.entrySet().removeIf(entry -> { + String clientId = entry.getKey(); + ClientConnection clientConnection = entry.getValue(); + if (ObjectUtil.isNotNull(clientConnection) && ObjectUtil.isNotNull(clientConnection.getLastActiveTime())) { + // 检查是否超时 + if (currentTime - clientConnection.getLastActiveTime() > timeout) { + log.warn("客户端 {} 心跳超时,断开连接", clientId); + try { + clientConnection.getSocket().close(); + } catch (IOException e) { + log.error("关闭超时客户端连接时发生错误", e); + } + return true; // 移除该客户端 + } + return false; // 保留该客户端 + }else{ + return true; + } + }); + } + + /** + * 封装:按协议发送一帧数据(hellohello + json + byebye) + */ + private void writeFrame(String clientId, String json, Charset charset) { + String frame = "hellohello" + json + "byebye"; + try { + ClientConnection clientConnection = clientMaps.get(clientId); + if (ObjectUtil.isNotNull(clientConnection)) { + clientConnection.getSocket().getOutputStream().write(frame.getBytes(charset)); + clientConnection.getSocket().getOutputStream().flush(); + } + log.info("向客户端 {} 发送帧:{}", clientId, frame); + } catch (IOException e) { + log.warn("向客户端 {} 发送帧失败: {}", clientId, e.getMessage()); + } + } + + /** + * 向特定单片机发送数据 + * @param clientId 单片机的唯一标识符 + * @param message 要发送的消息 + * @throws IOException 如果发送过程中遇到IO错误 + */ + public void sendDataToClient(String clientId, String message) throws IOException { + ClientConnection clientConnection = clientMaps.get(clientId); + if (ObjectUtil.isNotNull(clientConnection) && clientConnection.getSocket() != null && !clientConnection.getSocket().isClosed()) { + writeFrame(clientId, message, StandardCharsets.UTF_8); + } else { + log.warn("无法向客户端 {} 发送数据,因为找不到对应的Socket或已关闭", clientId); + } + } + + /** + * 配置客户端Socket参数,增强长连接稳定性与实时性 + */ + private void configureClientSocket(Socket socket) { + try { + socket.setKeepAlive(true); + socket.setTcpNoDelay(true); + // 设置读超时,避免永久阻塞 + // socket.setSoTimeout(60000); // 60秒超时 + } catch (Exception e) { + log.warn("配置客户端Socket参数失败: {}", e.getMessage()); + } + } + + /** + * 停止TCP服务器 + */ + @PreDestroy + public void stopTcpServer() { + try { + if (serverSocket != null && !serverSocket.isClosed()) { + serverSocket.close(); + log.info("TCP服务器已停止"); + } + executorService.shutdown(); + heartbeatService.shutdown(); + started.set(false); + } catch (IOException e) { + log.error("停止TCP服务器时发生错误", e); + } + } + +} diff --git a/ruoyi-modules/ruoyi-generator/pom.xml b/ruoyi-modules/ruoyi-generator/pom.xml index b93b8371e..1cb7897c2 100644 --- a/ruoyi-modules/ruoyi-generator/pom.xml +++ b/ruoyi-modules/ruoyi-generator/pom.xml @@ -59,25 +59,25 @@ ${anyline.version} - - org.anyline - anyline-data-jdbc-mysql - ${anyline.version} - - - - + + - + + + org.anyline + anyline-data-jdbc-postgresql + ${anyline.version} + + diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index c4c79b0ba..77ce00b79 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -321,7 +321,7 @@ public class GenTableServiceImpl implements IGenTableService { // 查询表信息 GenTable table = baseMapper.selectGenTableById(tableId); List menuIds = new ArrayList<>(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 7; i++) { menuIds.add(identifierGenerator.nextId(null).longValue()); } table.setMenuIds(menuIds); @@ -467,7 +467,7 @@ public class GenTableServiceImpl implements IGenTableService { // 查询表信息 GenTable table = baseMapper.selectGenTableById(tableId); List menuIds = new ArrayList<>(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 7; i++) { menuIds.add(identifierGenerator.nextId(null).longValue()); } table.setMenuIds(menuIds); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm index f6638be58..6bb3708bb 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm @@ -1,8 +1,11 @@ -- 菜单 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 103, 1, sysdate, null, null, '${functionName}菜单'); +values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '', '#', 103, 1, sysdate, null, null, '${functionName}菜单'); -- 按钮 SQL +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) +values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:list', '#', 103, 1, sysdate, null, null, ''); + insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, sysdate, null, null, ''); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm index 09233923e..668417dcf 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm @@ -1,20 +1,23 @@ -- 菜单 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 103, 1, now(), null, null, '${functionName}菜单'); +values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '', '#', 103, 1, now(), null, null, '${functionName}菜单'); -- 按钮 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, now(), null, null, ''); +values(${table.menuIds[1]}, '${functionName}列表', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:list', '#', 103, 1, now(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, now(), null, null, ''); +values(${table.menuIds[2]}, '${functionName}查询', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, now(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, now(), null, null, ''); +values(${table.menuIds[3]}, '${functionName}新增', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, now(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, now(), null, null, ''); +values(${table.menuIds[4]}, '${functionName}修改', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, now(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, now(), null, null, ''); +values(${table.menuIds[5]}, '${functionName}删除', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, now(), null, null, ''); + +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) +values(${table.menuIds[6]}, '${functionName}导出', ${table.menuIds[0]}, '6', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, now(), null, null, ''); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm index 01824c277..da533230d 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm @@ -1,19 +1,22 @@ -- 菜单 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 103, 1, sysdate(), null, null, '${functionName}菜单'); +values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '', '#', 103, 1, sysdate(), null, null, '${functionName}菜单'); -- 按钮 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, sysdate(), null, null, ''); +values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:list', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, sysdate(), null, null, ''); +values(${table.menuIds[2]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, sysdate(), null, null, ''); +values(${table.menuIds[3]}, '${functionName}新增', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, sysdate(), null, null, ''); +values(${table.menuIds[4]}, '${functionName}修改', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, sysdate(), null, null, ''); +values(${table.menuIds[5]}, '${functionName}删除', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, sysdate(), null, null, ''); + +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) +values(${table.menuIds[6]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, sysdate(), null, null, ''); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm index bdf166e5f..29b0b8282 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm @@ -1,19 +1,22 @@ -- 菜单 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 103, 1, getdate(), null, null, '${functionName}菜单'); +values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '', '#', 103, 1, getdate(), null, null, '${functionName}菜单'); -- 按钮 SQL insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, getdate(), null, null, ''); +values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:list', '#', 103, 1, getdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, getdate(), null, null, ''); +values(${table.menuIds[2]}, '${functionName}查询', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 103, 1, getdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, getdate(), null, null, ''); +values(${table.menuIds[3]}, '${functionName}新增', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 103, 1, getdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, getdate(), null, null, ''); +values(${table.menuIds[4]}, '${functionName}修改', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 103, 1, getdate(), null, null, ''); insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, getdate(), null, null, ''); +values(${table.menuIds[5]}, '${functionName}删除', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 103, 1, getdate(), null, null, ''); + +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) +values(${table.menuIds[6]}, '${functionName}导出', ${table.menuIds[0]}, '6', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 103, 1, getdate(), null, null, ''); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java index 9621cb239..5cae89764 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java @@ -67,7 +67,7 @@ public class SysProfileController extends BaseController { SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class); user.setUserId(LoginHelper.getUserId()); String username = LoginHelper.getUsername(); - if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user.getPhonenumber())) { return R.fail("修改用户'" + username + "'失败,手机号码已存在"); } if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java index b29e68110..4e83f03c7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java @@ -24,6 +24,7 @@ import org.dromara.common.web.core.BaseController; import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.service.ISysTenantService; +import org.dromara.system.service.ISysUserService; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -43,6 +44,7 @@ import java.util.List; public class SysTenantController extends BaseController { private final ISysTenantService tenantService; + private final ISysUserService userService; /** * 查询租户列表 @@ -93,6 +95,13 @@ public class SysTenantController extends BaseController { if (!tenantService.checkCompanyNameUnique(bo)) { return R.fail("新增租户'" + bo.getCompanyName() + "'失败,企业名称已存在"); } + // 校验用户名和手机号是否全局唯一(方法内部已使用TenantHelper.ignore) + if (!userService.checkUserNameUnique(bo.getUsername())) { + return R.fail("新增租户失败,管理员账号'" + bo.getUsername() + "'已存在"); + } + if (!userService.checkPhoneUnique(bo.getContactPhone())) { + return R.fail("新增租户失败,联系电话'" + bo.getContactPhone() + "'已存在"); + } return toAjax(TenantHelper.ignore(() -> tenantService.insertByBo(bo))); } @@ -109,6 +118,9 @@ public class SysTenantController extends BaseController { if (!tenantService.checkCompanyNameUnique(bo)) { return R.fail("修改租户'" + bo.getCompanyName() + "'失败,公司名称已存在"); } + if (!userService.checkPhoneUnique(bo.getContactPhone())) { + return R.fail("新增租户失败,联系电话'" + bo.getContactPhone() + "'已存在"); + } return toAjax(tenantService.updateByBo(bo)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index 2847fc299..9383f28a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -161,9 +161,9 @@ public class SysUserController extends BaseController { @PostMapping public R add(@Validated @RequestBody SysUserBo user) { deptService.checkDeptDataScope(user.getDeptId()); - if (!userService.checkUserNameUnique(user)) { + if (!userService.checkUserNameUnique(user.getUserName())) { return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); - } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user.getPhonenumber())) { return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); @@ -188,9 +188,9 @@ public class SysUserController extends BaseController { userService.checkUserAllowed(user.getUserId()); userService.checkUserDataScope(user.getUserId()); deptService.checkDeptDataScope(user.getDeptId()); - if (!userService.checkUserNameUnique(user)) { + if (!userService.checkUserNameUnique(user.getUserName())) { return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); - } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user.getPhonenumber())) { return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantService.java index 1c763e0ec..c51b04c4f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantService.java @@ -25,6 +25,11 @@ public interface ISysTenantService { */ SysTenantVo queryByTenantId(String tenantId); + /** + * 基于用户手机号查询租户 + */ + SysTenantVo queryByUsername(String username); + /** * 查询租户列表 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java index 1fe554547..ce4c0be73 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java @@ -103,18 +103,18 @@ public interface ISysUserService { /** * 校验用户名称是否唯一 * - * @param user 用户信息 + * @param username 用户信息 * @return 结果 */ - boolean checkUserNameUnique(SysUserBo user); + boolean checkUserNameUnique(String username); /** * 校验手机号码是否唯一 * - * @param user 用户信息 + * @param phone 用户信息 * @return 结果 */ - boolean checkPhoneUnique(SysUserBo user); + boolean checkPhoneUnique(String phone); /** * 校验email是否唯一 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index efbb040d5..7aa29acc8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -28,8 +28,10 @@ import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.*; import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.vo.SysTenantVo; +import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.mapper.*; import org.dromara.system.service.ISysTenantService; +import org.dromara.system.service.ISysUserService; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -49,6 +51,7 @@ public class SysTenantServiceImpl implements ISysTenantService { private final SysTenantMapper baseMapper; private final SysTenantPackageMapper tenantPackageMapper; private final SysUserMapper userMapper; + private final ISysUserService userService; private final SysDeptMapper deptMapper; private final SysRoleMapper roleMapper; private final SysRoleMenuMapper roleMenuMapper; @@ -75,6 +78,22 @@ public class SysTenantServiceImpl implements ISysTenantService { return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(SysTenant::getTenantId, tenantId)); } + /** + * 基于用户手机号或账号查询租户 + */ + @Cacheable(cacheNames = CacheNames.SYS_TENANT, key = "#username") + @Override + public SysTenantVo queryByUsername(String username) { + SysUserVo sysUserVo = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, username)); + if (ObjectUtil.isNull(sysUserVo)) { + sysUserVo = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getPhonenumber, username)); + } + if (ObjectUtil.isNotNull(sysUserVo)) { + return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(SysTenant::getTenantId, sysUserVo.getTenantId())); + } + return null; + } + /** * 查询租户列表 */ @@ -158,6 +177,7 @@ public class SysTenantServiceImpl implements ISysTenantService { user.setNickName(bo.getUsername()); user.setPassword(BCrypt.hashpw(bo.getPassword())); user.setDeptId(deptId); + user.setPhonenumber(bo.getContactPhone()); userMapper.insert(user); //新增系统用户后,默认当前用户为部门的负责人 SysDept sd = new SysDept(); @@ -325,6 +345,19 @@ public class SysTenantServiceImpl implements ISysTenantService { throw new ServiceException("超管租户不能删除"); } } + // 删除租户前,先查询出租户编号(String类型),再删除对应用户 + List tenantIds = baseMapper.selectList( + new LambdaQueryWrapper() + .select(SysTenant::getTenantId) + .in(SysTenant::getId, ids) + ).stream().map(SysTenant::getTenantId).toList(); + + if (CollUtil.isNotEmpty(tenantIds)) { + TenantHelper.ignore(() -> { + userMapper.delete(new LambdaQueryWrapper().in(SysUser::getTenantId, tenantIds)); + }); + } + return baseMapper.deleteByIds(ids) > 0; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index aafc73e29..c1e2ecdc6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -22,6 +22,7 @@ import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.SysUser; import org.dromara.system.domain.SysUserPost; import org.dromara.system.domain.SysUserRole; @@ -38,6 +39,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; /** * 用户 业务层处理 @@ -234,28 +236,33 @@ public class SysUserServiceImpl implements ISysUserService, UserService { /** * 校验用户名称是否唯一 * - * @param user 用户信息 + * @param username 用户信息 * @return 结果 */ @Override - public boolean checkUserNameUnique(SysUserBo user) { - boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysUser::getUserName, user.getUserName()) - .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); - return !exist; + public boolean checkUserNameUnique(String username) { + AtomicBoolean exist = new AtomicBoolean(false); + TenantHelper.ignore(() -> { + exist.set(baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getUserName, username))); + }); + + return !exist.get(); } /** * 校验手机号码是否唯一 * - * @param user 用户信息 + * @param phonenumber 用户信息 */ @Override - public boolean checkPhoneUnique(SysUserBo user) { - boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysUser::getPhonenumber, user.getPhonenumber()) - .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); - return !exist; + public boolean checkPhoneUnique(String phonenumber) { + AtomicBoolean exist = new AtomicBoolean(false); + TenantHelper.ignore(() -> { + exist.set(baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getPhonenumber, phonenumber))); + }); + return !exist.get(); } /**