diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml index 0eb44eec6..35b6b07f8 100644 --- a/.run/ruoyi-monitor-admin.run.xml +++ b/.run/ruoyi-monitor-admin.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-server.run.xml b/.run/ruoyi-server.run.xml index c75e92af0..c0c575bee 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-xxl-job-admin.run.xml b/.run/ruoyi-xxl-job-admin.run.xml index 2a30437f1..ae25907a8 100644 --- a/.run/ruoyi-xxl-job-admin.run.xml +++ b/.run/ruoyi-xxl-job-admin.run.xml @@ -2,7 +2,7 @@ - diff --git a/README.md b/README.md index 1fd86c0c4..728871149 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.4.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.5.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.7-blue.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() diff --git a/pom.xml b/pom.xml index 3de969cfd..d17587a0f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,49 +6,77 @@ com.ruoyi ruoyi-vue-plus - 4.4.0 + 4.5.0 RuoYi-Vue-Plus https://gitee.com/JavaLionLi/RuoYi-Vue-Plus RuoYi-Vue-Plus后台管理系统 - 4.4.0 - 2.7.6 + 4.5.0 + 2.7.7 UTF-8 UTF-8 1.8 3.2.2 2.2.2 - 1.6.13 + 1.6.14 5.2.3 - 3.1.3 + 3.1.5 2.3 - 1.33.0 - 3.5.2 + 1.34.0 + 3.5.3.1 3.9.1 - 5.8.10 + 5.8.11 4.10.0 - 2.7.7 - 3.18.0 + 2.7.10 + 3.19.1 2.2.3 3.5.2 2.14.2 2.3.1 1.18.24 - - 31.1-jre - 1.32 + 1.33 - 1.12.349 + 1.12.373 - 2.0.22 - 3.1.635 + 2.0.23 + 3.1.660 + + + local + + + local + debug + + + + dev + + + dev + debug + + + + true + + + + prod + + prod + warn + + + + @@ -149,11 +177,7 @@ mybatis-plus-boot-starter ${mybatis-plus.version} - - com.baomidou - mybatis-plus-extension - ${mybatis-plus.version} - + p6spy @@ -221,13 +245,6 @@ ${alibaba-ttl.version} - - - com.google.guava - guava - ${guava.version} - - org.yaml @@ -374,8 +391,8 @@ public - huawei nexus - https://mirrors.huaweicloud.com/repository/maven/ + aliyun nexus + https://maven.aliyun.com/repository/public/ true @@ -385,8 +402,8 @@ public - huawei nexus - https://mirrors.huaweicloud.com/repository/maven/ + aliyun nexus + https://maven.aliyun.com/repository/public/ true @@ -396,36 +413,6 @@ - - - local - - - local - debug - - - - dev - - - dev - debug - - - - true - - - - prod - - prod - warn - - - - diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index a588f62da..91baa5cfa 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 jar diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java index 94630e2e9..795359c5b 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -3,7 +3,6 @@ package com.ruoyi.web.controller.common; import cn.dev33.satoken.annotation.SaIgnore; import cn.hutool.captcha.AbstractCaptcha; import cn.hutool.captcha.generator.CodeGenerator; -import cn.hutool.core.convert.Convert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.RandomUtil; import com.ruoyi.common.constant.CacheConstants; @@ -21,6 +20,9 @@ import com.ruoyi.sms.entity.SmsResult; import com.ruoyi.system.service.ISysConfigService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -95,28 +97,16 @@ public class CaptchaController { AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz()); captcha.setGenerator(codeGenerator); captcha.createCode(); - String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode(); + String code = captcha.getCode(); + if (isMath) { + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression(StringUtils.remove(code, "=")); + code = exp.getValue(String.class); + } RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); ajax.put("uuid", uuid); ajax.put("img", captcha.getImageBase64()); return R.ok(ajax); } - private String getCodeResult(String capStr) { - int numberLength = captchaProperties.getNumberLength(); - int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim()); - char operator = capStr.charAt(numberLength); - int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim()); - switch (operator) { - case '*': - return Convert.toStr(a * b); - case '+': - return Convert.toStr(a + b); - case '-': - return Convert.toStr(a - b); - default: - return StringUtils.EMPTY; - } - } - } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index a65cb6252..78c44e305 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -13,7 +13,6 @@ import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.SysLoginService; -import com.ruoyi.system.service.SysPermissionService; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -39,7 +38,6 @@ public class SysLoginController { private final SysLoginService loginService; private final ISysMenuService menuService; private final ISysUserService userService; - private final SysPermissionService permissionService; /** * 登录方法 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 80f3bf35e..0468a33ac 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -83,6 +83,9 @@ spring: restart: # 热部署开关 enabled: true + mvc: + format: + date-time: yyyy-MM-dd HH:mm:ss jackson: # 日期格式化 date-format: yyyy-MM-dd HH:mm:ss @@ -202,6 +205,9 @@ swagger: name: ${sa-token.token-name} springdoc: + swagger-ui: + # 持久化认证数据 + persistAuthorization: true #这里定义了两个分组,可定义多个,也可以不定义 group-configs: - group: 1.演示模块 diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties index e1423a8fd..4ff55f41a 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试 rate.limiter.message=访问过于频繁,请稍候再试 sms.code.not.blank=短信验证码不能为空 sms.code.retry.limit.count=短信验证码输入错误{0}次 -sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟 +sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟 xcx.code.not.blank=小程序code不能为空 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 04a4aa372..c0faca93a 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties @@ -41,5 +41,5 @@ repeat.submit.message=Repeat submit is not allowed, please try again later rate.limiter.message=Visit too frequently, please try again later sms.code.not.blank=Sms code cannot be blank sms.code.retry.limit.count=Sms code input error {0} times -sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {0} minutes +sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes xcx.code.not.blank=Mini program code cannot be blank 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 e1423a8fd..4ff55f41a 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties @@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试 rate.limiter.message=访问过于频繁,请稍候再试 sms.code.not.blank=短信验证码不能为空 sms.code.retry.limit.count=短信验证码输入错误{0}次 -sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟 +sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟 xcx.code.not.blank=小程序code不能为空 diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 90d29940b..94896ecaa 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 @@ -79,10 +79,6 @@ com.baomidou mybatis-plus-boot-starter - - com.baomidou - mybatis-plus-extension - diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java index 29ce1d1e7..cdd3905a3 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java @@ -1,6 +1,5 @@ package com.ruoyi.common.core.domain.dto; -import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java new file mode 100644 index 000000000..733f97f91 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java @@ -0,0 +1,44 @@ +package com.ruoyi.common.core.domain.event; + +import lombok.Data; + +import javax.servlet.http.HttpServletRequest; +import java.io.Serializable; + +/** + * 登录事件 + * + * @author Lion Li + */ + +@Data +public class LogininforEvent implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户账号 + */ + private String username; + + /** + * 登录状态 0成功 1失败 + */ + private String status; + + /** + * 提示消息 + */ + private String message; + + /** + * 请求体 + */ + private HttpServletRequest request; + + /** + * 其他参数 + */ + private Object[] args; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/OperLogDTO.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java similarity index 92% rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/OperLogDTO.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java index 26bf67440..3a2997810 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/OperLogDTO.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java @@ -1,4 +1,4 @@ -package com.ruoyi.common.core.domain.dto; +package com.ruoyi.common.core.domain.event; import lombok.Data; @@ -6,13 +6,13 @@ import java.io.Serializable; import java.util.Date; /** - * 通用操作日志实体 + * 操作日志事件 * * @author Lion Li */ @Data -public class OperLogDTO implements Serializable { +public class OperLogEvent implements Serializable { private static final long serialVersionUID = 1L; diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java index 862887d16..0a8539ad6 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java @@ -4,16 +4,12 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.core.metadata.TableInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.*; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.baomidou.mybatisplus.extension.toolkit.Db; import com.ruoyi.common.utils.BeanCopyUtils; -import org.apache.ibatis.binding.MapperMethod; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; @@ -21,7 +17,6 @@ import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Objects; /** * 自定义 Mapper 接口, 实现 自定义扩展 @@ -37,8 +32,6 @@ public interface BaseMapperPlus extends BaseMapper { Log log = LogFactory.getLog(BaseMapperPlus.class); - int DEFAULT_BATCH_SIZE = 1000; - default Class currentVoClass() { return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2); } @@ -59,79 +52,49 @@ public interface BaseMapperPlus extends BaseMapper { * 批量插入 */ default boolean insertBatch(Collection entityList) { - return insertBatch(entityList, DEFAULT_BATCH_SIZE); + return Db.saveBatch(entityList); } /** * 批量更新 */ default boolean updateBatchById(Collection entityList) { - return updateBatchById(entityList, DEFAULT_BATCH_SIZE); + return Db.updateBatchById(entityList); } /** * 批量插入或更新 */ default boolean insertOrUpdateBatch(Collection entityList) { - return insertOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); + return Db.saveOrUpdateBatch(entityList); } /** * 批量插入(包含限制条数) */ default boolean insertBatch(Collection entityList, int batchSize) { - String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.INSERT_ONE); - return SqlHelper.executeBatch(this.currentModelClass(), log, entityList, batchSize, - (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); + return Db.saveBatch(entityList, batchSize); } /** * 批量更新(包含限制条数) */ default boolean updateBatchById(Collection entityList, int batchSize) { - String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.UPDATE_BY_ID); - return SqlHelper.executeBatch(this.currentModelClass(), log, entityList, batchSize, - (sqlSession, entity) -> { - MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); - param.put(Constants.ENTITY, entity); - sqlSession.update(sqlStatement, param); - }); + return Db.updateBatchById(entityList, batchSize); } /** * 批量插入或更新(包含限制条数) */ default boolean insertOrUpdateBatch(Collection entityList, int batchSize) { - TableInfo tableInfo = TableInfoHelper.getTableInfo(this.currentModelClass()); - Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); - String keyProperty = tableInfo.getKeyProperty(); - Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); - return SqlHelper.saveOrUpdateBatch(this.currentModelClass(), this.currentMapperClass(), log, entityList, batchSize, (sqlSession, entity) -> { - Object idVal = tableInfo.getPropertyValue(entity, keyProperty); - String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.SELECT_BY_ID); - return StringUtils.checkValNull(idVal) - || CollectionUtils.isEmpty(sqlSession.selectList(sqlStatement, entity)); - }, (sqlSession, entity) -> { - MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); - param.put(Constants.ENTITY, entity); - String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.UPDATE_BY_ID); - sqlSession.update(sqlStatement, param); - }); + return Db.saveOrUpdateBatch(entityList, batchSize); } /** * 插入或更新(包含限制条数) */ default boolean insertOrUpdate(T entity) { - if (null != entity) { - TableInfo tableInfo = TableInfoHelper.getTableInfo(this.currentModelClass()); - Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); - String keyProperty = tableInfo.getKeyProperty(); - Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); - Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty()); - return StringUtils.checkValNull(idVal) || Objects.isNull(selectById((Serializable) idVal)) ? insert(entity) > 0 : updateById(entity) > 0; - } - return false; + return Db.saveOrUpdate(entity); } default V selectVoById(Serializable id) { diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/LogininforService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/LogininforService.java deleted file mode 100644 index 91aee4369..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/LogininforService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.common.core.service; - -import javax.servlet.http.HttpServletRequest; - -/** - * 通用 系统访问日志 - * - * @author Lion Li - */ -public interface LogininforService { - - void recordLogininfor(String username, String status, String message, - HttpServletRequest request, Object... args); -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OperLogService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OperLogService.java deleted file mode 100644 index a3b27e6a7..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OperLogService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ruoyi.common.core.service; - -import com.ruoyi.common.core.domain.dto.OperLogDTO; -import org.springframework.scheduling.annotation.Async; - -/** - * 通用 操作日志 - * - * @author Lion Li - */ -public interface OperLogService { - - @Async - void recordOper(OperLogDTO operLogDTO); -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java index 04a1bbb8a..6102eec50 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java @@ -86,7 +86,7 @@ public class CellMergeStrategy extends AbstractMergeStrategy { // 空值跳过不合并 continue; } - if (cellValue != val) { + if (!cellValue.equals(val)) { if (i - repeatCell.getCurrent() > 1) { cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java index 3646f1fee..a7fbd4ca9 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java @@ -33,12 +33,12 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { String[] values = super.getParameterValues(name); if (values != null) { int length = values.length; - String[] escapseValues = new String[length]; + String[] escapesValues = new String[length]; for (int i = 0; i < length; i++) { // 防xss攻击和过滤前后空格 - escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); + escapesValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); } - return escapseValues; + return escapesValues; } return super.getParameterValues(name); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java index 1cef0278b..05e370b5d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java @@ -81,12 +81,18 @@ public class LoginHelper { LoginUser loginUser = getLoginUser(); if (ObjectUtil.isNull(loginUser)) { String loginId = StpUtil.getLoginIdAsString(); - String[] strs = StringUtils.split(loginId, JOIN_CODE); - if (!ArrayUtil.containsAny(strs, UserType.values())) { + String userId = null; + for (UserType value : UserType.values()) { + if (StringUtils.contains(loginId, value.getUserType())) { + String[] strs = StringUtils.split(loginId, JOIN_CODE); + // 用户id在总是在最后 + userId = strs[strs.length - 1]; + } + } + if (StringUtils.isBlank(userId)) { throw new UtilException("登录用户: LoginId异常 => " + loginId); } - // 用户id在总是在最后 - return Long.parseLong(strs[strs.length - 1]); + return Long.parseLong(userId); } return loginUser.getUserId(); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index 3ff8fec40..211c6214c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -24,6 +24,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.List; @@ -84,7 +85,13 @@ public class ExcelUtil { * @param response 响应体 */ public static void exportExcel(List list, String sheetName, Class clazz, HttpServletResponse response) { - exportExcel(list, sheetName, clazz, false, response); + try { + resetResponse(sheetName, response); + ServletOutputStream os = response.getOutputStream(); + exportExcel(list, sheetName, clazz, false, os); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } } /** @@ -100,23 +107,48 @@ public class ExcelUtil { try { resetResponse(sheetName, response); ServletOutputStream os = response.getOutputStream(); - ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) - .autoCloseStream(false) - // 自动适配 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) - // 大数值自动转换 防止失真 - .registerConverter(new ExcelBigNumberConvert()) - .sheet(sheetName); - if (merge) { - // 合并处理器 - builder.registerWriteHandler(new CellMergeStrategy(list, true)); - } - builder.doWrite(list); + exportExcel(list, sheetName, clazz, merge, os); } catch (IOException e) { throw new RuntimeException("导出Excel异常"); } } + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param os 输出流 + */ + public static void exportExcel(List list, String sheetName, Class clazz, OutputStream os) { + exportExcel(list, sheetName, clazz, false, os); + } + + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param merge 是否合并单元格 + * @param os 输出流 + */ + public static void exportExcel(List list, String sheetName, Class clazz, boolean merge, OutputStream os) { + ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) + .autoCloseStream(false) + // 自动适配 + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .sheet(sheetName); + if (merge) { + // 合并处理器 + builder.registerWriteHandler(new CellMergeStrategy(list, true)); + } + builder.doWrite(list); + } + /** * 单表多数据模板导出 模板格式为 {.属性} * @@ -125,31 +157,46 @@ public class ExcelUtil { * 例如: excel/temp.xlsx * 重点: 模板文件必须放置到启动类对应的 resource 目录下 * @param data 模板需要的数据 + * @param response 响应体 */ public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { try { resetResponse(filename, response); - ClassPathResource templateResource = new ClassPathResource(templatePath); - ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()) - .withTemplate(templateResource.getStream()) - .autoCloseStream(false) - // 大数值自动转换 防止失真 - .registerConverter(new ExcelBigNumberConvert()) - .build(); - WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } - // 单表多数据导出 模板格式为 {.属性} - for (Object d : data) { - excelWriter.fill(d, writeSheet); - } - excelWriter.finish(); + ServletOutputStream os = response.getOutputStream(); + exportTemplate(data, templatePath, os); } catch (IOException e) { throw new RuntimeException("导出Excel异常"); } } + /** + * 单表多数据模板导出 模板格式为 {.属性} + * + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param os 输出流 + */ + public static void exportTemplate(List data, String templatePath, OutputStream os) { + ClassPathResource templateResource = new ClassPathResource(templatePath); + ExcelWriter excelWriter = EasyExcel.write(os) + .withTemplate(templateResource.getStream()) + .autoCloseStream(false) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } + // 单表多数据导出 模板格式为 {.属性} + for (Object d : data) { + excelWriter.fill(d, writeSheet); + } + excelWriter.finish(); + } + /** * 多表多数据模板导出 模板格式为 {key.属性} * @@ -158,37 +205,52 @@ public class ExcelUtil { * 例如: excel/temp.xlsx * 重点: 模板文件必须放置到启动类对应的 resource 目录下 * @param data 模板需要的数据 + * @param response 响应体 */ public static void exportTemplateMultiList(Map data, String filename, String templatePath, HttpServletResponse response) { try { resetResponse(filename, response); - ClassPathResource templateResource = new ClassPathResource(templatePath); - ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()) - .withTemplate(templateResource.getStream()) - .autoCloseStream(false) - // 大数值自动转换 防止失真 - .registerConverter(new ExcelBigNumberConvert()) - .build(); - WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } - for (Map.Entry map : data.entrySet()) { - // 设置列表后续还有数据 - FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); - if (map.getValue() instanceof Collection) { - // 多表导出必须使用 FillWrapper - excelWriter.fill(new FillWrapper(map.getKey(), (Collection) map.getValue()), fillConfig, writeSheet); - } else { - excelWriter.fill(map.getValue(), writeSheet); - } - } - excelWriter.finish(); + ServletOutputStream os = response.getOutputStream(); + exportTemplateMultiList(data, templatePath, os); } catch (IOException e) { throw new RuntimeException("导出Excel异常"); } } + /** + * 多表多数据模板导出 模板格式为 {key.属性} + * + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param os 输出流 + */ + public static void exportTemplateMultiList(Map data, String templatePath, OutputStream os) { + ClassPathResource templateResource = new ClassPathResource(templatePath); + ExcelWriter excelWriter = EasyExcel.write(os) + .withTemplate(templateResource.getStream()) + .autoCloseStream(false) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } + for (Map.Entry map : data.entrySet()) { + // 设置列表后续还有数据 + FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); + if (map.getValue() instanceof Collection) { + // 多表导出必须使用 FillWrapper + excelWriter.fill(new FillWrapper(map.getKey(), (Collection) map.getValue()), fillConfig, writeSheet); + } else { + excelWriter.fill(map.getValue(), writeSheet); + } + } + excelWriter.finish(); + } + /** * 重置响应体 */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java index 80f5f5281..162380890 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java @@ -4,7 +4,6 @@ import com.ruoyi.common.utils.spring.SpringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.redisson.api.*; -import org.redisson.config.Config; import java.time.Duration; import java.util.Collection; @@ -27,14 +26,6 @@ public class RedisUtils { private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class); - public static NameMapper getNameMapper() { - Config config = CLIENT.getConfig(); - if (config.isClusterConfig()) { - return config.useClusterServers().getNameMapper(); - } - return config.useSingleServer().getNameMapper(); - } - /** * 限流 * @@ -218,6 +209,15 @@ public class RedisUtils { batch.execute(); } + /** + * 检查缓存对象是否存在 + * + * @param key 缓存的键值 + */ + public static boolean isExistsObject(final String key) { + return CLIENT.getBucket(key).isExists(); + } + /** * 缓存List数据 * @@ -437,8 +437,8 @@ public class RedisUtils { * @return 对象列表 */ public static Collection keys(final String pattern) { - Stream stream = CLIENT.getKeys().getKeysStreamByPattern(getNameMapper().map(pattern)); - return stream.map(key -> getNameMapper().unmap(key)).collect(Collectors.toList()); + Stream stream = CLIENT.getKeys().getKeysStreamByPattern(pattern); + return stream.collect(Collectors.toList()); } /** @@ -447,7 +447,7 @@ public class RedisUtils { * @param pattern 字符串前缀 */ public static void deleteKeys(final String pattern) { - CLIENT.getKeys().deleteByPattern(getNameMapper().map(pattern)); + CLIENT.getKeys().deleteByPattern(pattern); } /** @@ -457,6 +457,6 @@ public class RedisUtils { */ public static Boolean hasKey(String key) { RKeys rKeys = CLIENT.getKeys(); - return rKeys.countExists(getNameMapper().map(key)) > 0; + return rKeys.countExists(key) > 0; } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java index ebc6d27f4..8b37e416d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java @@ -3,6 +3,7 @@ package com.ruoyi.common.utils.spring; import cn.hutool.extra.spring.SpringUtil; import org.springframework.aop.framework.AopContext; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; /** @@ -62,4 +63,12 @@ public final class SpringUtils extends SpringUtil { return (T) AopContext.currentProxy(); } + + /** + * 获取spring上下文 + */ + public static ApplicationContext context() { + return getApplicationContext(); + } + } diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index 46b45981d..31f712cbc 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java index 320a640da..c86c92aa6 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java @@ -2,7 +2,6 @@ package com.ruoyi.demo.controller.queue; import lombok.Data; import lombok.NoArgsConstructor; -import org.jetbrains.annotations.NotNull; /** * 实体类 注意不允许使用内部类 否则会找不到类 @@ -17,7 +16,7 @@ public class PriorityDemo implements Comparable { private Integer orderNum; @Override - public int compareTo(@NotNull PriorityDemo other) { + public int compareTo(PriorityDemo other) { return Integer.compare(getOrderNum(), other.getOrderNum()); } } diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml index 8b0e2fb67..a55645806 100644 --- a/ruoyi-extend/pom.xml +++ b/ruoyi-extend/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 ruoyi-extend diff --git a/ruoyi-extend/ruoyi-monitor-admin/pom.xml b/ruoyi-extend/ruoyi-monitor-admin/pom.xml index 687d95853..19fc04e20 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/pom.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-extend com.ruoyi - 4.4.0 + 4.5.0 4.0.0 jar diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml index 9305051d9..7e65df583 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml @@ -4,7 +4,7 @@ ruoyi-extend com.ruoyi - 4.4.0 + 4.5.0 ruoyi-xxl-job-admin jar diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 52e1b0651..072b5b2f2 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java index 3b6a858a4..64ab736a6 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -4,8 +4,7 @@ import cn.hutool.core.lang.Dict; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.domain.dto.OperLogDTO; -import com.ruoyi.common.core.service.OperLogService; +import com.ruoyi.common.core.domain.event.OperLogEvent; import com.ruoyi.common.enums.BusinessStatus; import com.ruoyi.common.enums.HttpMethod; import com.ruoyi.common.helper.LoginHelper; @@ -67,7 +66,7 @@ public class LogAspect { try { // *========数据库日志=========*// - OperLogDTO operLog = new OperLogDTO(); + OperLogEvent operLog = new OperLogEvent(); operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); // 请求的地址 String ip = ServletUtils.getClientIP(); @@ -87,8 +86,8 @@ public class LogAspect { operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); - // 保存数据库 - SpringUtils.getBean(OperLogService.class).recordOper(operLog); + // 发布事件保存数据库 + SpringUtils.context().publishEvent(operLog); } catch (Exception exp) { // 记录本地异常日志 log.error("异常信息:{}", exp.getMessage()); @@ -103,7 +102,7 @@ public class LogAspect { * @param operLog 操作日志 * @throws Exception */ - public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogDTO operLog, Object jsonResult) throws Exception { + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception { // 设置action动作 operLog.setBusinessType(log.businessType().ordinal()); // 设置标题 @@ -127,7 +126,7 @@ public class LogAspect { * @param operLog 操作日志 * @throws Exception 异常 */ - private void setRequestValue(JoinPoint joinPoint, OperLogDTO operLog) throws Exception { + private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception { String requestMethod = operLog.getRequestMethod(); if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { String params = argsArrayToString(joinPoint.getArgs()); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java index 47898e3fa..d011b583d 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java @@ -18,7 +18,7 @@ import java.util.concurrent.ScheduledExecutorService; * * @author Lion Li */ -@EnableAsync +@EnableAsync(proxyTargetClass = true) @Configuration public class AsyncConfig extends AsyncConfigurerSupport { diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java index 9a7938a4b..8016ab869 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -11,7 +11,6 @@ import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,7 +24,7 @@ import org.springframework.context.annotation.Configuration; @Configuration @EnableCaching @EnableConfigurationProperties(RedissonProperties.class) -public class RedisConfig extends CachingConfigurerSupport { +public class RedisConfig { @Autowired private RedissonProperties redissonProperties; diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java index 7107661cb..ab92cf591 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java @@ -23,6 +23,7 @@ import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Set; /** * Swagger 文档配置 @@ -51,8 +52,11 @@ public class SwaggerConfig { openApi.tags(swaggerProperties.getTags()); openApi.paths(swaggerProperties.getPaths()); openApi.components(swaggerProperties.getComponents()); + Set keySet = swaggerProperties.getComponents().getSecuritySchemes().keySet(); List list = new ArrayList<>(); - list.add(new SecurityRequirement().addList("apikey")); + SecurityRequirement securityRequirement = new SecurityRequirement(); + keySet.forEach(securityRequirement::addList); + list.add(securityRequirement); openApi.security(list); return openApi; diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java index 63e777dee..3825a0ba7 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java @@ -54,7 +54,7 @@ public class PlusDataPermissionHandler { /** * 无效注解方法缓存用于快速返回 */ - private final Set inavlidCacheSet = new ConcurrentHashSet<>(); + private final Set invalidCacheSet = new ConcurrentHashSet<>(); /** * spel 解析器 @@ -70,7 +70,7 @@ public class PlusDataPermissionHandler { public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) { DataColumn[] dataColumns = findAnnotation(mappedStatementId); if (ArrayUtil.isEmpty(dataColumns)) { - inavlidCacheSet.add(mappedStatementId); + invalidCacheSet.add(mappedStatementId); return where; } LoginUser currentUser = DataPermissionHelper.getVariable("user"); @@ -194,6 +194,6 @@ public class PlusDataPermissionHandler { * 是否为无效方法 无数据权限 */ public boolean isInvalid(String mappedStatementId) { - return inavlidCacheSet.contains(mappedStatementId); + return invalidCacheSet.contains(mappedStatementId); } } diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml index 3e55d4424..529048eed 100644 --- a/ruoyi-generator/pom.xml +++ b/ruoyi-generator/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java index 92c522f0b..187426f7e 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Component; */ @Component @ConfigurationProperties(prefix = "gen") -@PropertySource(value = {"classpath:generator.yml"}) +@PropertySource(value = {"classpath:generator.yml"}, encoding = "UTF-8") public class GenConfig { /** diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index 7a80229b1..085589fb2 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -3,12 +3,11 @@ package com.ruoyi.generator.service; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Dict; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.Constants; @@ -58,6 +57,7 @@ public class GenTableServiceImpl implements IGenTableService { private final GenTableMapper baseMapper; private final GenTableColumnMapper genTableColumnMapper; + private final IdentifierGenerator identifierGenerator; /** * 查询业务字段列表 @@ -205,10 +205,9 @@ public class GenTableServiceImpl implements IGenTableService { Map dataMap = new LinkedHashMap<>(); // 查询表信息 GenTable table = baseMapper.selectGenTableById(tableId); - Snowflake snowflake = IdUtil.getSnowflake(); List menuIds = new ArrayList<>(); for (int i = 0; i < 6; i++) { - menuIds.add(snowflake.nextId()); + menuIds.add(identifierGenerator.nextId(null).longValue()); } table.setMenuIds(menuIds); // 设置主子表信息 @@ -356,10 +355,9 @@ public class GenTableServiceImpl implements IGenTableService { private void generatorCode(String tableName, ZipOutputStream zip) { // 查询表信息 GenTable table = baseMapper.selectGenTableByName(tableName); - Snowflake snowflake = IdUtil.getSnowflake(); List menuIds = new ArrayList<>(); for (int i = 0; i < 6; i++) { - menuIds.add(snowflake.nextId()); + menuIds.add(identifierGenerator.nextId(null).longValue()); } table.setMenuIds(menuIds); // 设置主子表信息 diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index 4ad96df33..2bc699a20 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -186,11 +186,11 @@ #elseif($column.htmlType == "imageUpload") - + #elseif($column.htmlType == "fileUpload") - + #elseif($column.htmlType == "editor") @@ -204,8 +204,11 @@ v-for="dict in dict.type.${dictType}" :key="dict.value" :label="dict.label" - #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end - +#if($column.javaType == "Integer" || $column.javaType == "Long") + :value="parseInt(dict.value)" +#else + :value="dict.value" +#end > @@ -216,7 +219,7 @@ #elseif($column.htmlType == "checkbox" && "" != $dictType) - + #elseif($column.htmlType == "checkbox" && $dictType) - + 请选择字典生成 #elseif($column.htmlType == "radio" && "" != $dictType) - + {{dict.label}} #elseif($column.htmlType == "radio" && $dictType) - + 请选择字典生成 @@ -335,7 +341,7 @@ export default { #set($comment=$column.columnComment) #end $column.javaField: [ - { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end } + { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end } ]#if($foreach.count != $columns.size()),#end #end #end @@ -398,10 +404,7 @@ export default { reset() { this.form = { #foreach ($column in $columns) -#if($column.htmlType == "radio") - $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end - -#elseif($column.htmlType == "checkbox") +#if($column.htmlType == "checkbox") $column.javaField: []#if($foreach.count != $columns.size()),#end #else $column.javaField: null#if($foreach.count != $columns.size()),#end diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index 7a57c7fde..e645b6bb8 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -133,9 +133,9 @@ #elseif($column.list && $column.htmlType == "imageUpload") - + #elseif($column.list && $column.dictType && "" != $column.dictType) @@ -197,11 +197,11 @@ #elseif($column.htmlType == "imageUpload") - + #elseif($column.htmlType == "fileUpload") - + #elseif($column.htmlType == "editor") @@ -215,8 +215,11 @@ v-for="dict in dict.type.${dictType}" :key="dict.value" :label="dict.label" - #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end - +#if($column.javaType == "Integer" || $column.javaType == "Long") + :value="parseInt(dict.value)" +#else + :value="dict.value" +#end > @@ -227,7 +230,7 @@ #elseif($column.htmlType == "checkbox" && "" != $dictType) - + #elseif($column.htmlType == "checkbox" && $dictType) - + 请选择字典生成 #elseif($column.htmlType == "radio" && "" != $dictType) - + {{dict.label}} #elseif($column.htmlType == "radio" && $dictType) - + 请选择字典生成 @@ -412,7 +418,7 @@ export default { #set($comment=$column.columnComment) #end $column.javaField: [ - { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end } + { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end } ]#if($foreach.count != $columns.size()),#end #end #end @@ -456,9 +462,7 @@ export default { reset() { this.form = { #foreach ($column in $columns) -#if($column.htmlType == "radio") - $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end -#elseif($column.htmlType == "checkbox") +#if($column.htmlType == "checkbox") $column.javaField: []#if($foreach.count != $columns.size()),#end #else $column.javaField: undefined#if($foreach.count != $columns.size()),#end diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm index 01a7367f8..663893a2c 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -135,11 +135,11 @@ #end #end - + @@ -172,11 +172,11 @@ #elseif($column.htmlType == "imageUpload") - + #elseif($column.htmlType == "fileUpload") - + #elseif($column.htmlType == "editor") @@ -190,8 +190,11 @@ v-for="dict in ${dictType}" :key="dict.value" :label="dict.label" - #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end - +#if($column.javaType == "Integer" || $column.javaType == "Long") + :value="parseInt(dict.value)" +#else + :value="dict.value" +#end > @@ -202,7 +205,7 @@ #elseif($column.htmlType == "checkbox" && "" != $dictType) - + #elseif($column.htmlType == "checkbox" && $dictType) - + 请选择字典生成 #elseif($column.htmlType == "radio" && "" != $dictType) - + {{dict.label}} #elseif($column.htmlType == "radio" && $dictType) - + 请选择字典生成 @@ -306,7 +312,7 @@ const data = reactive({ #set($comment=$column.columnComment) #end $column.javaField: [ - { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end } + { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end } ]#if($foreach.count != $columns.size()),#end #end #end @@ -359,10 +365,7 @@ function cancel() { function reset() { form.value = { #foreach ($column in $columns) -#if($column.htmlType == "radio") - $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end - -#elseif($column.htmlType == "checkbox") +#if($column.htmlType == "checkbox") $column.javaField: []#if($foreach.count != $columns.size()),#end #else $column.javaField: null#if($foreach.count != $columns.size()),#end diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm index d0f4f8bc8..a93922ef5 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm @@ -147,10 +147,10 @@ #end #end - + @@ -180,11 +180,11 @@ #elseif($column.htmlType == "imageUpload") - + #elseif($column.htmlType == "fileUpload") - + #elseif($column.htmlType == "editor") @@ -198,8 +198,11 @@ v-for="dict in ${dictType}" :key="dict.value" :label="dict.label" - #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end - +#if($column.javaType == "Integer" || $column.javaType == "Long") + :value="parseInt(dict.value)" +#else + :value="dict.value" +#end > @@ -210,7 +213,7 @@ #elseif($column.htmlType == "checkbox" && "" != $dictType) - + #elseif($column.htmlType == "checkbox" && $dictType) - + 请选择字典生成 #elseif($column.htmlType == "radio" && "" != $dictType) - + {{dict.label}} #elseif($column.htmlType == "radio" && $dictType) - + 请选择字典生成 @@ -387,7 +393,7 @@ const data = reactive({ #set($comment=$column.columnComment) #end $column.javaField: [ - { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end } + { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end } ]#if($foreach.count != $columns.size()),#end #end #end @@ -431,9 +437,7 @@ function cancel() { function reset() { form.value = { #foreach ($column in $columns) -#if($column.htmlType == "radio") - $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end -#elseif($column.htmlType == "checkbox") +#if($column.htmlType == "checkbox") $column.javaField: []#if($foreach.count != $columns.size()),#end #else $column.javaField: null#if($foreach.count != $columns.size()),#end diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml index 4162183f4..1146c9254 100644 --- a/ruoyi-job/pom.xml +++ b/ruoyi-job/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 jar diff --git a/ruoyi-oss/pom.xml b/ruoyi-oss/pom.xml index 78e618e95..d25f2b8df 100644 --- a/ruoyi-oss/pom.xml +++ b/ruoyi-oss/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml index 0ebabbb25..7180b058a 100644 --- a/ruoyi-sms/pom.xml +++ b/ruoyi-sms/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index daa5aba7b..c1c28d9f8 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.4.0 + 4.5.0 4.0.0 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java index a257fd988..3c29b85cf 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java @@ -5,23 +5,28 @@ import cn.dev33.satoken.secure.BCrypt; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.event.LogininforEvent; import com.ruoyi.common.core.domain.dto.RoleDTO; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.XcxLoginUser; -import com.ruoyi.common.core.service.LogininforService; import com.ruoyi.common.enums.DeviceType; import com.ruoyi.common.enums.LoginType; import com.ruoyi.common.enums.UserStatus; -import com.ruoyi.common.exception.user.*; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.exception.user.UserException; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -42,9 +47,8 @@ import java.util.function.Supplier; @Service public class SysLoginService { - private final ISysUserService userService; + private final SysUserMapper userMapper; private final ISysConfigService configService; - private final LogininforService asyncService; private final SysPermissionService permissionService; @Value("${user.password.maxRetryCount}") @@ -76,7 +80,7 @@ public class SysLoginService { // 生成token LoginHelper.loginByDevice(loginUser, DeviceType.PC); - asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request); + recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); recordLoginInfo(user.getUserId(), username); return StpUtil.getTokenValue(); } @@ -85,21 +89,19 @@ public class SysLoginService { // 通过手机号查找用户 SysUser user = loadUserByPhonenumber(phonenumber); - HttpServletRequest request = ServletUtils.getRequest(); - checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode, request)); + checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode)); // 此处可根据登录用户的数据不同 自行创建 loginUser LoginUser loginUser = buildLoginUser(user); // 生成token LoginHelper.loginByDevice(loginUser, DeviceType.APP); - asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request); + recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); recordLoginInfo(user.getUserId(), user.getUserName()); return StpUtil.getTokenValue(); } public String xcxLogin(String xcxCode) { - HttpServletRequest request = ServletUtils.getRequest(); // xcxCode 为 小程序调用 wx.login 授权后获取 // todo 以下自行实现 // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid @@ -115,7 +117,7 @@ public class SysLoginService { // 生成token LoginHelper.loginByDevice(loginUser, DeviceType.XCX); - asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request); + recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); recordLoginInfo(user.getUserId(), user.getUserName()); return StpUtil.getTokenValue(); } @@ -127,18 +129,35 @@ public class SysLoginService { try { LoginUser loginUser = LoginHelper.getLoginUser(); StpUtil.logout(); - asyncService.recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest()); + recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success")); } catch (NotLoginException ignored) { } } + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息内容 + * @return + */ + private void recordLogininfor(String username, String status, String message) { + LogininforEvent logininforEvent = new LogininforEvent(); + logininforEvent.setUsername(username); + logininforEvent.setStatus(status); + logininforEvent.setMessage(message); + logininforEvent.setRequest(ServletUtils.getRequest()); + SpringUtils.context().publishEvent(logininforEvent); + } + /** * 校验短信验证码 */ - private boolean validateSmsCode(String phonenumber, String smsCode, HttpServletRequest request) { + private boolean validateSmsCode(String phonenumber, String smsCode) { String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber); if (StringUtils.isBlank(code)) { - asyncService.recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request); + recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); throw new CaptchaExpireException(); } return code.equals(smsCode); @@ -156,43 +175,41 @@ public class SysLoginService { String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { - asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request); + recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); throw new CaptchaExpireException(); } if (!code.equalsIgnoreCase(captcha)) { - asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request); + recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); throw new CaptchaException(); } } private SysUser loadUserByUsername(String username) { - SysUser user = userService.selectUserByUserName(username); + SysUser user = userMapper.selectOne(new LambdaQueryWrapper() + .select(SysUser::getUserName, SysUser::getStatus) + .eq(SysUser::getUserName, username)); if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", username); throw new UserException("user.not.exists", username); - } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { - log.info("登录用户:{} 已被删除.", username); - throw new UserException("user.password.delete", username); } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", username); throw new UserException("user.blocked", username); } - return user; + return userMapper.selectUserByUserName(username); } private SysUser loadUserByPhonenumber(String phonenumber) { - SysUser user = userService.selectUserByPhonenumber(phonenumber); + SysUser user = userMapper.selectOne(new LambdaQueryWrapper() + .select(SysUser::getPhonenumber, SysUser::getStatus) + .eq(SysUser::getPhonenumber, phonenumber)); if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", phonenumber); throw new UserException("user.not.exists", phonenumber); - } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { - log.info("登录用户:{} 已被删除.", phonenumber); - throw new UserException("user.password.delete", phonenumber); } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", phonenumber); throw new UserException("user.blocked", phonenumber); } - return user; + return userMapper.selectUserByPhonenumber(phonenumber); } private SysUser loadUserByOpenid(String openid) { @@ -202,9 +219,6 @@ public class SysLoginService { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", openid); // todo 用户不存在 业务逻辑自行实现 - } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { - log.info("登录用户:{} 已被删除.", openid); - // todo 用户已被删除 业务逻辑自行实现 } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", openid); // todo 用户已被停用 业务逻辑自行实现 @@ -240,14 +254,13 @@ public class SysLoginService { sysUser.setLoginIp(ServletUtils.getClientIP()); sysUser.setLoginDate(DateUtils.getNowDate()); sysUser.setUpdateBy(username); - userService.updateUserProfile(sysUser); + userMapper.updateById(sysUser); } /** * 登录校验 */ private void checkLogin(LoginType loginType, String username, Supplier supplier) { - HttpServletRequest request = ServletUtils.getRequest(); String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username; String loginFail = Constants.LOGIN_FAIL; @@ -255,7 +268,7 @@ public class SysLoginService { Integer errorNumber = RedisUtils.getCacheObject(errorKey); // 锁定时间内登录 则踢出 if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) { - asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request); + recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); } @@ -265,12 +278,12 @@ public class SysLoginService { // 达到规定错误次数 则锁定登录 if (errorNumber.equals(maxRetryCount)) { RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime)); - asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request); + recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); } else { // 未达到规定错误次数 则递增 RedisUtils.setCacheObject(errorKey, errorNumber); - asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber), request); + recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber)); throw new UserException(loginType.getRetryLimitCount(), errorNumber); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java index 983173d11..bf9d00d4d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java @@ -4,9 +4,9 @@ import cn.dev33.satoken.secure.BCrypt; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.event.LogininforEvent; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.RegisterBody; -import com.ruoyi.common.core.service.LogininforService; import com.ruoyi.common.enums.UserType; import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaExpireException; @@ -15,6 +15,7 @@ import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.spring.SpringUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -31,7 +32,6 @@ public class SysRegisterService { private final ISysUserService userService; private final ISysConfigService configService; - private final LogininforService asyncService; /** * 注册 @@ -61,7 +61,7 @@ public class SysRegisterService { if (!regFlag) { throw new UserException("user.register.error"); } - asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"), request); + recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")); } /** @@ -77,12 +77,30 @@ public class SysRegisterService { String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { - asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"), request); + recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire")); throw new CaptchaExpireException(); } if (!code.equalsIgnoreCase(captcha)) { - asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"), request); + recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error")); throw new CaptchaException(); } } + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息内容 + * @return + */ + private void recordLogininfor(String username, String status, String message) { + LogininforEvent logininforEvent = new LogininforEvent(); + logininforEvent.setUsername(username); + logininforEvent.setStatus(status); + logininforEvent.setMessage(message); + logininforEvent.setRequest(ServletUtils.getRequest()); + SpringUtils.context().publishEvent(logininforEvent); + } + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index 72dc42bb4..c39ec74df 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -138,6 +138,10 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { public String updateConfig(SysConfig config) { int row = 0; if (config.getConfigId() != null) { + SysConfig temp = baseMapper.selectById(config.getConfigId()); + if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) { + CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey()); + } row = baseMapper.updateById(config); } else { row = baseMapper.update(config, new LambdaQueryWrapper() diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java index 159db624e..1cd176f79 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java @@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.event.LogininforEvent; import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.service.LogininforService; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.AddressUtils; @@ -16,6 +16,7 @@ import com.ruoyi.system.mapper.SysLogininforMapper; import com.ruoyi.system.service.ISysLogininforService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -33,22 +34,19 @@ import java.util.Map; @RequiredArgsConstructor @Slf4j @Service -public class SysLogininforServiceImpl implements ISysLogininforService, LogininforService { +public class SysLogininforServiceImpl implements ISysLogininforService { private final SysLogininforMapper baseMapper; /** * 记录登录信息 * - * @param username 用户名 - * @param status 状态 - * @param message 消息 - * @param args 列表 + * @param logininforEvent 登录事件 */ @Async - @Override - public void recordLogininfor(final String username, final String status, final String message, - HttpServletRequest request, final Object... args) { + @EventListener + public void recordLogininfor(LogininforEvent logininforEvent) { + HttpServletRequest request = logininforEvent.getRequest(); final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); final String ip = ServletUtils.getClientIP(request); @@ -56,27 +54,27 @@ public class SysLogininforServiceImpl implements ISysLogininforService, Logininf StringBuilder s = new StringBuilder(); s.append(getBlock(ip)); s.append(address); - s.append(getBlock(username)); - s.append(getBlock(status)); - s.append(getBlock(message)); + s.append(getBlock(logininforEvent.getUsername())); + s.append(getBlock(logininforEvent.getStatus())); + s.append(getBlock(logininforEvent.getMessage())); // 打印信息到日志 - log.info(s.toString(), args); + log.info(s.toString(), logininforEvent.getArgs()); // 获取客户端操作系统 String os = userAgent.getOs().getName(); // 获取客户端浏览器 String browser = userAgent.getBrowser().getName(); // 封装对象 SysLogininfor logininfor = new SysLogininfor(); - logininfor.setUserName(username); + logininfor.setUserName(logininforEvent.getUsername()); logininfor.setIpaddr(ip); logininfor.setLoginLocation(address); logininfor.setBrowser(browser); logininfor.setOs(os); - logininfor.setMsg(message); + logininfor.setMsg(logininforEvent.getMessage()); // 日志状态 - if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) { + if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) { logininfor.setStatus(Constants.SUCCESS); - } else if (Constants.LOGIN_FAIL.equals(status)) { + } else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) { logininfor.setStatus(Constants.FAIL); } // 插入数据 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java index 8610d974f..28ac34cba 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java @@ -5,15 +5,15 @@ import cn.hutool.core.util.ArrayUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.PageQuery; -import com.ruoyi.common.core.domain.dto.OperLogDTO; +import com.ruoyi.common.core.domain.event.OperLogEvent; import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.service.OperLogService; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.system.mapper.SysOperLogMapper; import com.ruoyi.system.service.ISysOperLogService; import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -29,19 +29,19 @@ import java.util.Map; */ @RequiredArgsConstructor @Service -public class SysOperLogServiceImpl implements ISysOperLogService, OperLogService { +public class SysOperLogServiceImpl implements ISysOperLogService { private final SysOperLogMapper baseMapper; /** * 操作日志记录 * - * @param operLogDTO 操作日志信息 + * @param operLogEvent 操作日志事件 */ @Async - @Override - public void recordOper(final OperLogDTO operLogDTO) { - SysOperLog operLog = BeanUtil.toBean(operLogDTO, SysOperLog.class); + @EventListener + public void recordOper(OperLogEvent operLogEvent) { + SysOperLog operLog = BeanUtil.toBean(operLogEvent, SysOperLog.class); // 远程查询操作地点 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); insertOperlog(operLog); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java index 8ceff7cb5..d6269242c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java @@ -16,6 +16,7 @@ import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOssConfig; @@ -25,6 +26,7 @@ import com.ruoyi.system.mapper.SysOssConfigMapper; import com.ruoyi.system.service.ISysOssConfigService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -57,7 +59,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { if ("0".equals(config.getStatus())) { RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey); } - setConfigCache(true, config); + SpringUtils.context().publishEvent(config); } // 初始化OSS工厂 OssFactory.init(); @@ -88,7 +90,11 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { public Boolean insertByBo(SysOssConfigBo bo) { SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class); validEntityBeforeSave(config); - return setConfigCache(baseMapper.insert(config) > 0, config); + boolean flag = baseMapper.insert(config) > 0; + if (flag) { + SpringUtils.context().publishEvent(config); + } + return flag; } @Override @@ -101,7 +107,11 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { luw.set(ObjectUtil.isNull(config.getExt1()), SysOssConfig::getExt1, ""); luw.set(ObjectUtil.isNull(config.getRemark()), SysOssConfig::getRemark, ""); luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId()); - return setConfigCache(baseMapper.update(config, luw) > 0, config); + boolean flag = baseMapper.update(config, luw) > 0; + if (flag) { + SpringUtils.context().publishEvent(config); + } + return flag; } /** @@ -165,19 +175,15 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { } /** - * 如果操作成功 则更新缓存 + * 更新配置缓存 * - * @param flag 操作状态 * @param config 配置 - * @return 返回操作状态 */ - private boolean setConfigCache(boolean flag, SysOssConfig config) { - if (flag) { - CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); - RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> { - log.info("发布刷新OSS配置 => " + msg); - }); - } - return flag; + @EventListener + public void updateConfigCache(SysOssConfig config) { + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); + RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> { + log.info("发布刷新OSS配置 => " + msg); + }); } } diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 48ba1f9a4..c1975834f 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi-vue-plus", - "version": "4.4.0", + "version": "4.5.0", "description": "RuoYi-Vue-Plus后台管理系统", "author": "LionLi", "license": "MIT", @@ -39,7 +39,7 @@ "axios": "0.24.0", "clipboard": "2.0.8", "core-js": "3.25.3", - "echarts": "4.9.0", + "echarts": "5.4.0", "element-ui": "2.15.10", "file-saver": "2.0.5", "fuse.js": "6.4.3", diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index 16a4740f4..4e298744c 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -73,6 +73,10 @@ color: inherit; } +.el-message-box__status + .el-message-box__message{ + word-break: break-word; +} + .el-dialog:not(.is-fullscreen) { margin-top: 6vh !important; } diff --git a/ruoyi-ui/src/components/HeaderSearch/index.vue b/ruoyi-ui/src/components/HeaderSearch/index.vue index c44eff56e..c4d76bbb9 100644 --- a/ruoyi-ui/src/components/HeaderSearch/index.vue +++ b/ruoyi-ui/src/components/HeaderSearch/index.vue @@ -90,7 +90,6 @@ export default { threshold: 0.4, location: 0, distance: 100, - maxPatternLength: 32, minMatchCharLength: 1, keys: [{ name: 'title', diff --git a/ruoyi-ui/src/components/RightPanel/index.vue b/ruoyi-ui/src/components/RightPanel/index.vue index 2d6122bc0..5abeecb00 100644 --- a/ruoyi-ui/src/components/RightPanel/index.vue +++ b/ruoyi-ui/src/components/RightPanel/index.vue @@ -39,7 +39,6 @@ export default { } }, mounted() { - this.insertToBody() this.addEventClick() }, beforeDestroy() { @@ -56,11 +55,6 @@ export default { this.show = false window.removeEventListener('click', this.closeSidebar) } - }, - insertToBody() { - const elx = this.$refs.rightPanel - const body = document.querySelector('body') - body.insertBefore(elx, body.firstChild) } } } diff --git a/ruoyi-ui/src/plugins/download.js b/ruoyi-ui/src/plugins/download.js index 85138bb17..a1b21dad9 100644 --- a/ruoyi-ui/src/plugins/download.js +++ b/ruoyi-ui/src/plugins/download.js @@ -21,7 +21,7 @@ export default { const isLogin = await blobValidate(res.data); if (isLogin) { const blob = new Blob([res.data], { type: 'application/octet-stream' }) - this.saveAs(blob, decodeURI(res.headers['download-filename'])) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) } else { this.printErrMsg(res.data); } diff --git a/ruoyi-ui/src/views/dashboard/BarChart.vue b/ruoyi-ui/src/views/dashboard/BarChart.vue index be0af34f8..88e7ef64c 100644 --- a/ruoyi-ui/src/views/dashboard/BarChart.vue +++ b/ruoyi-ui/src/views/dashboard/BarChart.vue @@ -3,7 +3,7 @@ + + + diff --git a/ruoyi-ui/src/views/register.vue b/ruoyi-ui/src/views/register.vue index 1797599c9..649c4d8d1 100644 --- a/ruoyi-ui/src/views/register.vue +++ b/ruoyi-ui/src/views/register.vue @@ -87,7 +87,7 @@ export default { confirmPassword: "", code: "", uuid: "", - user_type: "sys_user" + userType: "sys_user" }, registerRules: { username: [ diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index 496aaafa8..f0a489875 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -78,9 +78,9 @@ services: # 时区上海 TZ: Asia/Shanghai # 管理后台用户名 - MINIO_ACCESS_KEY: ruoyi + MINIO_ROOT_USER: ruoyi # 管理后台密码,最小8个字符 - MINIO_SECRET_KEY: ruoyi123 + MINIO_ROOT_PASSWORD: ruoyi123 # https需要指定域名 #MINIO_SERVER_URL: "https://xxx.com:9000" #MINIO_BROWSER_REDIRECT_URL: "https://xxx.com:9001" @@ -100,7 +100,7 @@ services: network_mode: "host" ruoyi-server1: - image: ruoyi/ruoyi-server:4.4.0 + image: ruoyi/ruoyi-server:4.5.0 container_name: ruoyi-server1 environment: # 时区上海 @@ -115,7 +115,7 @@ services: network_mode: "host" ruoyi-server2: - image: "ruoyi/ruoyi-server:4.4.0" + image: "ruoyi/ruoyi-server:4.5.0" container_name: ruoyi-server2 environment: # 时区上海 @@ -130,7 +130,7 @@ services: network_mode: "host" ruoyi-monitor-admin: - image: ruoyi/ruoyi-monitor-admin:4.4.0 + image: ruoyi/ruoyi-monitor-admin:4.5.0 container_name: ruoyi-monitor-admin environment: # 时区上海 @@ -142,7 +142,7 @@ services: network_mode: "host" ruoyi-xxl-job-admin: - image: ruoyi/ruoyi-xxl-job-admin:4.4.0 + image: ruoyi/ruoyi-xxl-job-admin:4.5.0 container_name: ruoyi-xxl-job-admin environment: # 时区上海