From a583c1bfa73f822cf73995fc8d9ac6be4da495df Mon Sep 17 00:00:00 2001 From: yixiaco Date: Wed, 21 Aug 2024 00:15:18 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=95=8F?= =?UTF-8?q?=E6=84=9F=E8=AF=8D=E5=8A=9F=E8=83=BD=E3=80=81=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=94=9F=E6=88=90=E6=96=B0=E5=A2=9E=E5=AF=BC=E5=85=A5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=81RedisUtils=E5=B7=A5=E5=85=B7=E6=96=B0?= =?UTF-8?q?=E5=A2=9EZSet=20fix:=20=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E6=9C=AA=E9=80=89=E6=97=B6=E4=B8=8D=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=B1=9E=E6=80=A7=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 1 + ruoyi-common/ruoyi-common-core/pom.xml | 5 + .../common/core/constant/CacheConstants.java | 5 + .../common/core/utils/ValidatorUtils.java | 2 +- .../sensitive/SensitiveWordReplacer.java | 131 ++++ .../common/redis/utils/RedisUtils.java | 97 +++ .../constant/WebSocketConstants.java | 4 +- .../generator/domain/vo/GenTableOptions.java | 4 + .../service/impl/GenTableServiceImpl.java | 4 +- .../dromara/generator/util/VelocityUtils.java | 14 +- .../main/resources/vm/java/controller.java.vm | 34 + .../src/main/resources/vm/java/import.java.vm | 57 ++ .../main/resources/vm/java/listener.java.vm | 100 +++ .../src/main/resources/vm/sql/oracle/sql.vm | 5 + .../src/main/resources/vm/sql/postgres/sql.vm | 5 + .../src/main/resources/vm/sql/sql.vm | 5 + .../main/resources/vm/sql/sqlserver/sql.vm | 5 + .../main/resources/vm/vue/index-tree.vue.vm | 50 +- .../src/main/resources/vm/vue/index.vue.vm | 51 +- .../system/SysSensitiveWordController.java | 161 +++++ .../system/domain/SysSensitiveWord.java | 80 +++ .../system/domain/bo/SysSensitiveWordBo.java | 57 ++ .../domain/bo/SysSensitiveWordTestBo.java | 27 + .../domain/query/SysSensitiveWordQuery.java | 35 ++ .../SysSensitiveWordImportTemplate.java | 55 ++ .../domain/vo/SysSensitiveWordTestVo.java | 23 + .../system/domain/vo/SysSensitiveWordVo.java | 72 +++ .../SensitiveWordRedisMQListener.java | 39 ++ .../SysSensitiveWordImportListener.java | 92 +++ .../system/mapper/SysSensitiveWordMapper.java | 26 + .../service/ISysSensitiveWordService.java | 106 ++++ .../impl/SysSensitiveWordServiceImpl.java | 265 ++++++++ .../mapper/system/SysSensitiveWordMapper.xml | 27 + ruoyi-ui/components.d.ts | 1 + .../api/system/model/sensitiveWordModel.ts | 65 ++ ruoyi-ui/src/api/system/sensitiveWord.ts | 64 ++ ruoyi-ui/src/api/tool/model/genModel.ts | 2 + .../src/components/upload-excel/index.vue | 127 ++++ .../src/pages/system/sensitiveWord/index.vue | 589 ++++++++++++++++++ ruoyi-ui/src/pages/system/user/index.vue | 40 +- ruoyi-ui/src/pages/tool/gen/genInfoForm.vue | 1 + script/sql/oracle/oracle_ry_vue_1.X.sql | 38 ++ script/sql/postgres/postgres_ry_vue_1.X.sql | 39 ++ script/sql/ry_vue_1.X.sql | 29 +- .../sql/update/oracle/update_1.3.0_1.3.1.sql | 43 ++ .../update/postgres/update_1.3.0_1.3.1.sql | 44 ++ script/sql/update/update_1.3.0_1.3.1.sql | 32 + 47 files changed, 2711 insertions(+), 47 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sensitive/SensitiveWordReplacer.java create mode 100644 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/import.java.vm create mode 100644 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysSensitiveWordController.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSensitiveWord.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordBo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordTestBo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/query/SysSensitiveWordQuery.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/template/SysSensitiveWordImportTemplate.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordTestVo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordVo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SensitiveWordRedisMQListener.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysSensitiveWordMapper.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSensitiveWordMapper.xml create mode 100644 ruoyi-ui/src/api/system/model/sensitiveWordModel.ts create mode 100644 ruoyi-ui/src/api/system/sensitiveWord.ts create mode 100644 ruoyi-ui/src/components/upload-excel/index.vue create mode 100644 ruoyi-ui/src/pages/system/sensitiveWord/index.vue diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index aad44273..56716d45 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -188,6 +188,7 @@ tenant: - sys_oss_rule - sys_dict_data - sys_dict_type + - sys_sensitive_word # MyBatisPlus配置 # https://baomidou.com/config/ diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index b4417f08..2c012798 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -116,6 +116,11 @@ compile + + cn.hutool + hutool-dfa + + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java index de66c0c7..192f6143 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java @@ -22,6 +22,11 @@ public interface CacheConstants { */ String SYS_DICT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sys_dict:"; + /** + * 敏感词管理 cache key + */ + String SYS_SENSITIVE_WORD = GlobalConstants.GLOBAL_REDIS_KEY + "sys_sensitive_word:"; + /** * 字典类型管理 cache key */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ValidatorUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ValidatorUtils.java index 153decb4..f8b8426a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ValidatorUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ValidatorUtils.java @@ -22,7 +22,7 @@ public class ValidatorUtils { public static void validate(T object, Class... groups) { Set> validate = VALID.validate(object, groups); if (!validate.isEmpty()) { - throw new ConstraintViolationException("参数校验异常", validate); + throw new ConstraintViolationException("参数校验异常: " + validate.iterator().next().getMessage(), validate); } } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sensitive/SensitiveWordReplacer.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sensitive/SensitiveWordReplacer.java new file mode 100644 index 00000000..6b1f7287 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sensitive/SensitiveWordReplacer.java @@ -0,0 +1,131 @@ +package org.dromara.common.core.utils.sensitive; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.dfa.FoundWord; +import cn.hutool.dfa.SensitiveProcessor; +import cn.hutool.dfa.WordTree; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 敏感词替换器 + * + * @author hexm + */ +public class SensitiveWordReplacer { + private final WordTree sensitiveTree = new WordTree(); + + public SensitiveWordReplacer() { + } + + public SensitiveWordReplacer(Collection sensitiveWords) { + sensitiveTree.addWords(sensitiveWords); + } + + public void addWord(String word) { + sensitiveTree.addWord(word); + } + + public void addWords(Collection sensitiveWords) { + sensitiveTree.addWords(sensitiveWords); + } + + public void clear() { + sensitiveTree.clear(); + } + + /** + * 判断是否包含敏感词 + * + * @param text 文本 + * @return + */ + public boolean containsSensitiveWord(String text) { + return sensitiveTree.isMatch(text); + } + + /** + * 查找敏感词,返回找到的第一个敏感词 + * + * @param text 文本 + * @return 敏感词 + */ + public FoundWord getFoundFirstSensitive(String text) { + return sensitiveTree.matchWord(text); + } + + /** + * 查找敏感词,返回找到的所有敏感词 + * + * @param text 文本 + * @return 敏感词 + */ + public List getFoundAllSensitive(String text) { + return sensitiveTree.matchAllWords(text); + } + + /** + * 查找敏感词,返回找到的所有敏感词
+ * 密集匹配原则:假如关键词有 ab,b,文本是abab,将匹配 [ab,b,ab]
+ * 贪婪匹配(最长匹配)原则:假如关键字a,ab,最长匹配将匹配[a, ab] + * + * @param text 文本 + * @param isDensityMatch 是否使用密集匹配原则 + * @param isGreedMatch 是否使用贪婪匹配(最长匹配)原则 + * @return 敏感词 + */ + public List getFoundAllSensitive(String text, boolean isDensityMatch, boolean isGreedMatch) { + return sensitiveTree.matchAllWords(text, -1, isDensityMatch, isGreedMatch); + } + + /** + * 处理过滤文本中的敏感词,默认替换成* + * + * @param text 文本 + * @return 敏感词过滤处理后的文本 + */ + public String sensitiveWordReplace(String text) { + return sensitiveWordReplace(text, true, null); + } + + /** + * 处理过滤文本中的敏感词,默认替换成* + * + * @param text 文本 + * @param isGreedMatch 贪婪匹配(最长匹配)原则:假如关键字a,ab,最长匹配将匹配[a, ab] + * @param sensitiveProcessor 敏感词处理器,默认按匹配内容的字符数替换成* + * @return 敏感词过滤处理后的文本 + */ + public String sensitiveWordReplace(String text, boolean isGreedMatch, SensitiveProcessor sensitiveProcessor) { + if (StrUtil.isEmpty(text)) { + return text; + } + + //敏感词过滤场景下,不需要密集匹配 + final List foundWordList = getFoundAllSensitive(text, true, isGreedMatch); + if (CollUtil.isEmpty(foundWordList)) { + return text; + } + sensitiveProcessor = sensitiveProcessor == null ? new SensitiveProcessor() { + } : sensitiveProcessor; + + final Map foundWordMap = new HashMap<>(foundWordList.size(), 1); + foundWordList.forEach(foundWord -> foundWordMap.put(foundWord.getStartIndex(), foundWord)); + final int length = text.length(); + final StringBuilder textStringBuilder = new StringBuilder(); + for (int i = 0; i < length; i++) { + final FoundWord fw = foundWordMap.get(i); + if (fw != null) { + textStringBuilder.append(sensitiveProcessor.process(fw)); + i = fw.getEndIndex(); + } else { + textStringBuilder.append(text.charAt(i)); + } + } + return textStringBuilder.toString(); + } +} diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java index fc111368..02665baa 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java @@ -4,9 +4,11 @@ import lombok.NoArgsConstructor; import org.dromara.common.core.utils.spring.SpringUtils; import org.redisson.api.*; +import org.redisson.api.listener.MessageListener; import java.time.Duration; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -87,6 +89,29 @@ public static void subscribe(String channelKey, Class clazz, Consumer topic.addListener(clazz, (channel, msg) -> consumer.accept(msg)); } + /** + * 订阅通道接收消息 + * + * @param channelKey 通道key + * @param clazz 消息类型 + * @param listener 自定义处理 + */ + public static void subscribe(String channelKey, Class clazz, MessageListener listener) { + RTopic topic = CLIENT.getTopic(channelKey); + topic.addListener(clazz, listener); + } + + /** + * 取消订阅 + * + * @param channelKey 通道key + * @param listener 自定义处理 + */ + public static void unsubscribe(String channelKey, MessageListener listener) { + RTopic topic = CLIENT.getTopic(channelKey); + topic.removeListener(listener); + } + /** * 缓存基本的对象,Integer、String、实体类等 * @@ -395,6 +420,78 @@ public static Set getSet(final String key) { return rSet.readAll(); } + /** + * 缓存ZSet + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public static int addZSet(final String key, final Map dataSet) { + RScoredSortedSet scoredSortedSet = CLIENT.getScoredSortedSet(key); + return scoredSortedSet.addAll(dataSet); + } + + /** + * 缓存ZSet + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public static void setZSet(final String key, final Map dataSet) { + RBatch batch = CLIENT.createBatch(); + RScoredSortedSetAsync scoredSortedSet = batch.getScoredSortedSet(key); + scoredSortedSet.deleteAsync(); + scoredSortedSet.addAllAsync(dataSet); + batch.execute(); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @param expire 过期时间 + * @return 缓存数据的对象 + */ + public static void setZSet(final String key, final Map dataSet, final Duration expire) { + RBatch batch = CLIENT.createBatch(); + RScoredSortedSetAsync scoredSortedSet = batch.getScoredSortedSet(key); + scoredSortedSet.deleteAsync(); + scoredSortedSet.expireAsync(expire); + scoredSortedSet.addAllAsync(dataSet); + batch.execute(); + } + + /** + * 注册ZSet监听器 + *

+ * key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置 + * + * @param key 缓存的键值 + * @param listener 监听器配置 + */ + public static void addZSetListener(final String key, final ObjectListener listener) { + RScoredSortedSet scoredSortedSet = CLIENT.getScoredSortedSet(key); + scoredSortedSet.addListener(listener); + } + + /** + * 获得缓存的set + * + * @param key 缓存的key + * @return set对象 + */ + public static Set getZSet(final String key) { + RScoredSortedSet scoredSortedSet = CLIENT.getScoredSortedSet(key); + Collection all = scoredSortedSet.readAll(); + if (all instanceof Set) { + return (Set) all; + } + return new LinkedHashSet<>(all); + } + /** * put缓存Map * diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java index 54eb4470..608c2f2e 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java @@ -1,5 +1,7 @@ package org.dromara.common.websocket.constant; +import org.dromara.common.core.constant.GlobalConstants; + /** * websocket的常量配置 * @@ -14,7 +16,7 @@ public interface WebSocketConstants { /** * 订阅的频道 */ - String WEB_SOCKET_TOPIC = "global:websocket"; + String WEB_SOCKET_TOPIC = GlobalConstants.GLOBAL_REDIS_KEY + "websocket"; /** * 前端心跳检查的命令 diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/vo/GenTableOptions.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/vo/GenTableOptions.java index 046dbae4..0f93472b 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/vo/GenTableOptions.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/vo/GenTableOptions.java @@ -68,6 +68,10 @@ public class GenTableOptions implements Serializable { * 是否使用删除方法 */ private Boolean isUseRemoveMethod = true; + /** + * 是否使用导入方法 + */ + private Boolean isUseImportMethod = false; /** * 是否使用导出方法 */ diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/impl/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/impl/GenTableServiceImpl.java index 4020e79d..8ff099bd 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/impl/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/impl/GenTableServiceImpl.java @@ -272,7 +272,7 @@ public Map tempPreviewCode(GenTableBo tableBo) { private Map previewCode(GenTableVo tableVo) { List menuIds = new ArrayList<>(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 7; i++) { menuIds.add(identifierGenerator.nextId(null).longValue()); } tableVo.setMenuIds(menuIds); @@ -430,7 +430,7 @@ private void generatorCode(Long tableId, ZipOutputStream zip) { // 查询表信息 GenTableVo 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/java/org/dromara/generator/util/VelocityUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java index 4492c95b..28486f7c 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java @@ -110,11 +110,15 @@ public static List getTemplateList(GenTableVo table) { if (options.getIsUseQuery()) { templates.add("vm/java/query.java.vm"); } + if (options.getIsUseBO()) { + templates.add("vm/java/bo.java.vm"); + } if (options.getIsUseVO()) { templates.add("vm/java/vo.java.vm"); } - if (options.getIsUseBO()) { - templates.add("vm/java/bo.java.vm"); + if (options.getIsUseImportMethod()) { + templates.add("vm/java/import.java.vm"); + templates.add("vm/java/listener.java.vm"); } if (options.getIsUseController()) { templates.add("vm/java/controller.java.vm"); @@ -177,6 +181,12 @@ public static String getFileName(String template, GenTableVo genTable) { if (template.contains("bo.java.vm")) { fileName = StringUtils.format("{}/domain/bo/{}Bo.java", javaPath, className); } + if (template.contains("import.java.vm")) { + fileName = StringUtils.format("{}/domain/template/{}ImportTemplate.java", javaPath, className); + } + if (template.contains("listener.java.vm")) { + fileName = StringUtils.format("{}/listener/{}ImportListener.java", javaPath, className); + } if (template.contains("mapper.java.vm")) { fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); } else if (template.contains("service.java.vm")) { diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm index bae2c805..b4e9944c 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -3,6 +3,14 @@ package ${packageName}.controller; #if($isUseQueryMethod || $isUseExportMethod || $isUseRemoveMethod) import java.util.List; #end +#if($isUseImportMethod) +import java.util.ArrayList; +import org.dromara.common.excel.core.ExcelResult; +import ${packageName}.domain.template.${ClassName}ImportTemplate; +import ${packageName}.listener.${ClassName}ImportListener; +import org.springframework.http.MediaType; +import org.springframework.web.multipart.MultipartFile; +#end #if($isUseExportMethod) import jakarta.servlet.http.HttpServletResponse; @@ -114,6 +122,32 @@ public class ${ClassName}Controller extends BaseController { ExcelUtil.exportExcel(list, "${functionName}", ${vo}.class, response); } #end +#if($isUseImportMethod) + + /** + * 导入数据 + * + * @param file 导入文件 + * @param updateSupport 是否更新已存在数据 + */ + @Log(title = "${functionName}", businessType = BusinessType.IMPORT) + @SaCheckPermission("${permissionPrefix}:import") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception { + ${ClassName}ImportListener listener = new ${ClassName}ImportListener(${className}Service, updateSupport); + ExcelResult<${ClassName}ImportTemplate> result = ExcelUtil.importExcel(file.getInputStream(), ${ClassName}ImportTemplate.class, listener); + return R.msg(result.getAnalysis()); + } + + /** + * 获取导入模板 + */ + @SaCheckPermission("${permissionPrefix}:import") + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + ExcelUtil.exportExcel(new ArrayList<>(), "${functionName}", ${ClassName}ImportTemplate.class, response); + } +#end #if($isUseEditMethod || $isUseDetailMethod) /** diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/import.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/import.java.vm new file mode 100644 index 00000000..1db90269 --- /dev/null +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/import.java.vm @@ -0,0 +1,57 @@ +package ${packageName}.domain.template; + +#if($isUseBO) +#set($bo="${ClassName}Bo") +import ${packageName}.domain.bo.${ClassName}Bo; +#else +#set($bo=$ClassName) +import ${packageName}.domain.${ClassName}; +#end +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +#foreach ($import in $importList) +import ${import}; +#end + +import java.io.Serial; +import java.io.Serializable; + +/** + * ${functionName}导入对象 + * + * @author ${author} + * @date ${datetime} + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = ${bo}.class, reverseConvertGenerate = false) +public class ${ClassName}ImportTemplate implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + +#foreach ($column in $columns) +#if(($column.isPk() || $column.isInsert() || $column.isEdit())) + /** + * $column.columnComment + */ +#set($parentheseIndex=$column.columnComment.indexOf("(")) +#if($parentheseIndex != -1) +#set($comment=$column.columnComment.substring(0, $parentheseIndex)) +#else +#set($comment=$column.columnComment) +#end +#if(${column.dictType} && ${column.dictType} != '') + @ExcelProperty(value = "${comment}", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "${column.dictType}") +#else + @ExcelProperty(value = "${comment}") +#end + private $column.javaType $column.javaField; +#end +#end +} diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm new file mode 100644 index 00000000..ae02fd3e --- /dev/null +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm @@ -0,0 +1,100 @@ +package ${packageName}.listener; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.core.ExcelListener; +import org.dromara.common.excel.core.ExcelResult; +#if($isUseBO) +#set($bo="${ClassName}Bo") +#set($boObjName="bo") +import ${packageName}.domain.bo.${ClassName}Bo; +#else +#set($bo=$ClassName) +#set($boObjName="${className}") +import ${packageName}.domain.${ClassName}; +#end +import ${packageName}.domain.template.${ClassName}ImportTemplate; +import ${packageName}.service.I${ClassName}Service; + +import java.util.List; + +/** + * ${functionName}自定义导入 + * + * @author ${author} + * @date ${datetime} + */ +public class ${ClassName}ImportListener extends AnalysisEventListener<${ClassName}ImportTemplate> implements ExcelListener<${ClassName}ImportTemplate> { + + private final I${ClassName}Service ${className}Service; + + private final boolean isUpdateSupport; + + private int successNum = 1; + private int failureNum = 0; + private final StringBuilder successMsg = new StringBuilder(); + private final StringBuilder failureMsg = new StringBuilder(); + + public ${ClassName}ImportListener(I${ClassName}Service sysSensitiveWordService, boolean isUpdateSupport) { + this.sysSensitiveWordService = sysSensitiveWordService; + this.isUpdateSupport = isUpdateSupport; + } + + @Override + public void invoke(${ClassName}ImportTemplate importTemplate, AnalysisContext context) { + try { + $bo $boObjName = MapstructUtils.convert(importTemplate, ${bo}.class); + if (!isUpdateSupport) { + ValidatorUtils.validate($boObjName, AddGroup.class); + sysSensitiveWordService.insertByBo($boObjName); + successNum++; + successMsg.append("
第").append(successNum).append("行 导入成功"); + } else { + ValidatorUtils.validate($boObjName, EditGroup.class); + sysSensitiveWordService.updateByBo($boObjName); + successNum++; + successMsg.append("
第").append(successNum).append("行 更新成功"); + } + } catch (Exception e) { + failureNum++; + failureMsg.append("
第").append(failureNum).append("行 导入失败:").append(e.getMessage()); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + @Override + public ExcelResult<${ClassName}ImportTemplate> getExcelResult() { + return new ExcelResult<>() { + + @Override + public String getAnalysis() { + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + @Override + public List<${ClassName}ImportTemplate> getList() { + return null; + } + + @Override + public List getErrorList() { + return null; + } + }; + } +} 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 6f2ca732..8df0507a 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 @@ -28,3 +28,8 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:export', '#', 103, 1, sysdate, null, null, ''); #end +#if($isUseImportMethod) +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, 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', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:import', '#', 103, 1, sysdate, null, null, ''); + +#end 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 cec9ed66..cc6f8690 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 @@ -28,3 +28,8 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:export', '#', 103, 1, now(), null, null, ''); #end +#if($isUseImportMethod) +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, 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', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:import', '#', 103, 1, now(), null, null, ''); + +#end 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 07dacb19..b040de6c 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 @@ -28,3 +28,8 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:export', '#', 103, 1, sysdate(), null, null, ''); #end +#if($isUseImportMethod) +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, 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', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:import', '#', 103, 1, sysdate(), null, null, ''); + +#end 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 e574fda4..17de732a 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 @@ -28,3 +28,8 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:export', '#', 103, 1, getdate(), null, null, ''); #end +#if($isUseImportMethod) +insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, 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', '#', '', '', 0, 1, 'F', '1', '1', '${permissionPrefix}:import', '#', 103, 1, getdate(), null, null, ''); + +#end diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index 727b52ce..91616982 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -20,7 +20,7 @@ -#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && "" != $dictType) +#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && $dictType) #if($column.queryType == "IN") -#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && $dictType) +#elseif($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") @@ -116,6 +116,17 @@ 全部{{ isExpand ? '折叠' : '展开' }} +#if($isUseImportMethod) + + + 导入 + +#end #if($isUseExportMethod) @@ -189,7 +200,7 @@ :header="title" destroy-on-close :close-on-overlay-click="false" - width="500px" + width="min(500px, 100%)" attach="body" :confirm-btn="{ loading: buttonLoading, @@ -248,7 +259,7 @@ -#elseif($column.htmlType == "select" && "" != $dictType) +#elseif($column.htmlType == "select" && $dictType) -#elseif($column.htmlType == "select" && $dictType) +#elseif($column.htmlType == "select") -#elseif($column.htmlType == "checkbox" && "" != $dictType) +#elseif($column.htmlType == "checkbox" && $dictType) -#elseif($column.htmlType == "checkbox" && $dictType) +#elseif($column.htmlType == "checkbox") 请选择字典生成 -#elseif($column.htmlType == "radio" && "" != $dictType) +#elseif($column.htmlType == "radio" && $dictType) {{dict.label}} -#elseif($column.htmlType == "radio" && $dictType) +#elseif($column.htmlType == "radio") 请选择字典生成 @@ -334,7 +345,7 @@ v-model:visible="openView" header="${functionName}详情" placement="center" - width="700px" + width="min(700px, 100%)" attach="body" :footer="false" > @@ -371,6 +382,18 @@ #end +#end +#if($isUseImportMethod) + + + #end @@ -400,6 +423,9 @@ import { SettingIcon, UnfoldLessIcon, UnfoldMoreIcon, +#if($isUseImportMethod) + UploadIcon, +#end } from 'tdesign-icons-vue-next'; #end import type { @@ -421,7 +447,6 @@ import type { #end } from 'tdesign-vue-next'; import { computed, getCurrentInstance, ref } from 'vue'; - ## 导入对象类型 #set($importApiModel = []) #if((!$isUseBO && $addOrUpdate || (!$isUseQuery && !$isUseBO) || !$isUseVO) && $importApiModel.add(${ClassName}))#end @@ -497,6 +522,9 @@ const expandedTreeNodes = ref([]); const dateRange${AttrName} = ref([]); #end #end +#if($isUseImportMethod) +const openImportExcel = ref(false); +#end #if($addOrUpdate) // 校验规则 diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index 55b76ccc..85e549d9 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -21,7 +21,7 @@ -#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && "" != $dictType) +#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && $dictType) #if($column.queryType == "IN") -#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") && $dictType) +#elseif($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") @@ -142,6 +142,17 @@ 删除 #end +#if($isUseImportMethod) + + + 导入 + +#end #if($isUseExportMethod) @@ -213,7 +224,7 @@ :header="title" destroy-on-close :close-on-overlay-click="false" - width="500px" + width="min(500px, 100%)" attach="body" :confirm-btn="{ loading: buttonLoading, @@ -260,7 +271,7 @@ -#elseif($column.htmlType == "select" && "" != $dictType) +#elseif($column.htmlType == "select" && $dictType) -#elseif($column.htmlType == "select" && $dictType) +#elseif($column.htmlType == "select") -#elseif($column.htmlType == "checkbox" && "" != $dictType) +#elseif($column.htmlType == "checkbox" && $dictType) -#elseif($column.htmlType == "checkbox" && $dictType) +#elseif($column.htmlType == "checkbox") 请选择字典生成 -#elseif($column.htmlType == "radio" && "" != $dictType) +#elseif($column.htmlType == "radio" && $dictType) {{dict.label}} -#elseif($column.htmlType == "radio" && $dictType) +#elseif($column.htmlType == "radio") 请选择字典生成 @@ -346,7 +357,7 @@ v-model:visible="openView" header="${functionName}详情" placement="center" - width="700px" + width="min(700px, 100%)" attach="body" :footer="false" > @@ -383,6 +394,18 @@ #end +#end +#if($isUseImportMethod) + + + #end @@ -410,9 +433,12 @@ import { RefreshIcon, SearchIcon, SettingIcon, +#if($isUseImportMethod) + UploadIcon, +#end } from 'tdesign-icons-vue-next'; #end -import type { #if($addOrUpdate)FormInstanceFunctions, FormRule, #end#if($isUseQueryMethod)PageInfo, PrimaryTableCol, #{end}#if($addOrUpdate)SubmitContext, #end#if($hasSorting && $isUseQueryMethod)TableSort#end } from 'tdesign-vue-next'; +import type { #if($addOrUpdate)FormInstanceFunctions, FormRule, #end#if($isUseQueryMethod)PageInfo, PrimaryTableCol, #{end}#if($addOrUpdate)SubmitContext, #end#if($hasSorting && $isUseQueryMethod)TableSort, #end } from 'tdesign-vue-next'; import { #if($isUseQueryMethod)computed, #{end}getCurrentInstance, ref } from 'vue'; #if($isUseRemoveMethod) import { ArrayOps } from '@/utils/array'; @@ -498,6 +524,9 @@ const sort = ref(); const dateRange${AttrName} = ref([]); #end #end +#if($isUseImportMethod) +const openImportExcel = ref(false); +#end #if($addOrUpdate) // 校验规则 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysSensitiveWordController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysSensitiveWordController.java new file mode 100644 index 00000000..cace89e0 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysSensitiveWordController.java @@ -0,0 +1,161 @@ +package org.dromara.system.controller.system; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.core.ExcelResult; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.system.domain.bo.SysSensitiveWordBo; +import org.dromara.system.domain.bo.SysSensitiveWordTestBo; +import org.dromara.system.domain.query.SysSensitiveWordQuery; +import org.dromara.system.domain.template.SysSensitiveWordImportTemplate; +import org.dromara.system.domain.vo.SysSensitiveWordTestVo; +import org.dromara.system.domain.vo.SysSensitiveWordVo; +import org.dromara.system.listener.SysSensitiveWordImportListener; +import org.dromara.system.service.ISysSensitiveWordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * 敏感词 + * + * @author hexm + * @date 2024-08-16 + */ +@Validated +@RestController +@RequestMapping("/system/sensitiveWord") +public class SysSensitiveWordController extends BaseController { + + @Autowired + private ISysSensitiveWordService sysSensitiveWordService; + + /** + * 查询敏感词列表 + */ + @SaCheckPermission("system:sensitiveWord:list") + @GetMapping("/list") + public TableDataInfo list(SysSensitiveWordQuery query) { + return sysSensitiveWordService.queryPageList(query); + } + + /** + * 导出敏感词列表 + */ + @SaCheckPermission("system:sensitiveWord:export") + @Log(title = "敏感词", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysSensitiveWordQuery query, HttpServletResponse response) { + List list = sysSensitiveWordService.queryList(query); + ExcelUtil.exportExcel(list, "敏感词", SysSensitiveWordVo.class, response); + } + + /** + * 导入数据 + * + * @param file 导入文件 + * @param updateSupport 是否更新已存在数据 + */ + @Log(title = "敏感词", businessType = BusinessType.IMPORT) + @SaCheckPermission("system:sensitiveWord:import") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception { + SysSensitiveWordImportListener listener = new SysSensitiveWordImportListener(sysSensitiveWordService, updateSupport); + ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), SysSensitiveWordImportTemplate.class, listener); + return R.msg(result.getAnalysis()); + } + + /** + * 获取导入模板 + */ + @SaCheckPermission("system:sensitiveWord:import") + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + ExcelUtil.exportExcel(new ArrayList<>(), "敏感词", SysSensitiveWordImportTemplate.class, response); + } + + /** + * 获取敏感词详细信息 + * + * @param wordId 主键 + */ + @SaCheckPermission(value = {"system:sensitiveWord:query", "system:sensitiveWord:edit"}, mode = SaMode.OR) + @GetMapping("/{wordId}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long wordId) { + return R.ok(sysSensitiveWordService.queryById(wordId)); + } + + /** + * 新增敏感词 + */ + @SaCheckPermission("system:sensitiveWord:add") + @Log(title = "敏感词", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SysSensitiveWordBo bo) { + return toAjax(sysSensitiveWordService.insertByBo(bo)); + } + + /** + * 修改敏感词 + */ + @SaCheckPermission("system:sensitiveWord:edit") + @Log(title = "敏感词", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SysSensitiveWordBo bo) { + return toAjax(sysSensitiveWordService.updateByBo(bo)); + } + + /** + * 删除敏感词 + * + * @param wordIds 主键串 + */ + @SaCheckPermission("system:sensitiveWord:remove") + @Log(title = "敏感词", businessType = BusinessType.DELETE) + @DeleteMapping("/{wordIds}") + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] wordIds) { + return toAjax(sysSensitiveWordService.deleteWithValidByIds(List.of(wordIds))); + } + + /** + * 刷新敏感词缓存 + */ + @SaCheckPermission("system:sensitiveWord:remove") + @Log(title = "敏感词", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public R refreshCache() { + sysSensitiveWordService.refreshCache(); + return R.ok(); + } + + /** + * 测试敏感词 + */ + @SaCheckPermission("system:sensitiveWord:list") + @GetMapping("/test") + public R sensitiveWordTest(@Validated SysSensitiveWordTestBo bo) { + SysSensitiveWordTestVo testVo = new SysSensitiveWordTestVo(); + testVo.setContainsSensitiveWord(sysSensitiveWordService.containsSensitiveWord(bo.getText(), bo.getCategory())); + testVo.setSensitiveWordReplace(sysSensitiveWordService.sensitiveWordReplace(bo.getText(), bo.getCategory())); + testVo.setSensitiveWords(sysSensitiveWordService.getFoundAllSensitive(bo.getText(), bo.getCategory())); + return R.ok(testVo); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSensitiveWord.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSensitiveWord.java new file mode 100644 index 00000000..6904a1be --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSensitiveWord.java @@ -0,0 +1,80 @@ +package org.dromara.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.math.BigDecimal; + +/** + * 敏感词对象 sys_sensitive_word + * + * @author hexm + * @date 2024-08-16 + */ +@Data +@TableName("sys_sensitive_word") +public class SysSensitiveWord implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 敏感词id + */ + @TableId(value = "word_id") + private Long wordId; + + /** + * 敏感词 + */ + private String word; + + /** + * 敏感词类别 + */ + private String category; + + /** + * 描述 + */ + private String description; + + /** + * 启用状态 + */ + private Integer status; + + /** + * 创建部门 + */ + @TableField(fill = FieldFill.INSERT) + private Long createDept; + + /** + * 创建者 + */ + @TableField(fill = FieldFill.INSERT) + private Long createBy; + + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updateBy; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateTime; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordBo.java new file mode 100644 index 00000000..4066bb0f --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordBo.java @@ -0,0 +1,57 @@ +package org.dromara.system.domain.bo; + +import org.dromara.system.domain.SysSensitiveWord; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.hibernate.validator.constraints.Length; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +/** + * 敏感词业务对象 sys_sensitive_word + * + * @author hexm + * @date 2024-08-16 + */ +@Data +@AutoMapper(target = SysSensitiveWord.class, reverseConvertGenerate = false) +public class SysSensitiveWordBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 敏感词id + */ + @NotNull(message = "敏感词id不能为空", groups = {EditGroup.class}) + private Long wordId; + /** + * 敏感词 + */ + @NotBlank(message = "敏感词不能为空", groups = {AddGroup.class, EditGroup.class}) + @Length(max = 255, message = "敏感词不能大于{max}个字符", groups = {AddGroup.class, EditGroup.class}) + private String word; + /** + * 敏感词类别 + */ + @NotBlank(message = "敏感词类别不能为空", groups = {AddGroup.class, EditGroup.class}) + @Length(max = 20, message = "敏感词类别不能大于{max}个字符", groups = {AddGroup.class, EditGroup.class}) + private String category; + /** + * 描述 + */ + @Length(max = 500, message = "描述不能大于{max}个字符", groups = {AddGroup.class, EditGroup.class}) + private String description; + /** + * 启用状态 + */ + @NotNull(message = "启用状态不能为空", groups = {AddGroup.class, EditGroup.class}) + private Integer status; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordTestBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordTestBo.java new file mode 100644 index 00000000..2b3aac06 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSensitiveWordTestBo.java @@ -0,0 +1,27 @@ +package org.dromara.system.domain.bo; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 敏感词测试 + * + * @author hexm + * @date 2024/8/20 + */ +@Data +public class SysSensitiveWordTestBo implements Serializable { + + /** + * 测试文本 + */ + @NotBlank(message = "测试文本不能为空") + private String text; + + /** + * 敏感词分类 + */ + private String[] category; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/query/SysSensitiveWordQuery.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/query/SysSensitiveWordQuery.java new file mode 100644 index 00000000..d43024d0 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/query/SysSensitiveWordQuery.java @@ -0,0 +1,35 @@ +package org.dromara.system.domain.query; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +import org.dromara.common.mybatis.core.domain.BasePageQuery; + +/** + * 敏感词查询对象 sys_sensitive_word + * + * @author hexm + * @date 2024-08-16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class SysSensitiveWordQuery extends BasePageQuery { + + /** + * 敏感词 + */ + private String word; + + /** + * 敏感词类别 + */ + private String category; + + /** + * 启用状态 + */ + private Integer status; + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/template/SysSensitiveWordImportTemplate.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/template/SysSensitiveWordImportTemplate.java new file mode 100644 index 00000000..a5d53f0a --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/template/SysSensitiveWordImportTemplate.java @@ -0,0 +1,55 @@ +package org.dromara.system.domain.template; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.system.domain.bo.SysSensitiveWordBo; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 敏感词导入对象 + * + * @author hexm + * @date 2024-08-16 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysSensitiveWordBo.class, reverseConvertGenerate = false) +public class SysSensitiveWordImportTemplate implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 敏感词id + */ + @ExcelProperty(value = "敏感词id") + private Long wordId; + /** + * 敏感词 + */ + @ExcelProperty(value = "敏感词") + private String word; + /** + * 敏感词类别 + */ + @ExcelProperty(value = "敏感词类别", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sensitive_words_category") + private String category; + /** + * 描述 + */ + @ExcelProperty(value = "描述") + private String description; + /** + * 启用状态 + */ + @ExcelProperty(value = "启用状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private Integer status; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordTestVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordTestVo.java new file mode 100644 index 00000000..66ab1666 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordTestVo.java @@ -0,0 +1,23 @@ +package org.dromara.system.domain.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Collection; + +/** + * 敏感词测试结果vo + * + * @author hexm + * @date 2024/8/20 + */ +@Data +public class SysSensitiveWordTestVo implements Serializable { + + /** 是否包含敏感词 */ + private boolean containsSensitiveWord; + /** 敏感词替换后的内容 */ + private String sensitiveWordReplace; + /** 包含的敏感词 */ + private Collection sensitiveWords; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordVo.java new file mode 100644 index 00000000..b8b8c071 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSensitiveWordVo.java @@ -0,0 +1,72 @@ +package org.dromara.system.domain.vo; + +import org.dromara.system.domain.SysSensitiveWord; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import java.util.Date; +import java.io.Serial; +import java.io.Serializable; + +/** + * 敏感词视图对象 sys_sensitive_word + * + * @author hexm + * @date 2024-08-16 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysSensitiveWord.class) +public class SysSensitiveWordVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 敏感词id + */ + @ExcelProperty(value = "敏感词id") + private Long wordId; + + /** + * 敏感词 + */ + @ExcelProperty(value = "敏感词") + private String word; + + /** + * 敏感词类别 + */ + @ExcelProperty(value = "敏感词类别", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sensitive_words_category") + private String category; + + /** + * 描述 + */ + @ExcelProperty(value = "描述") + private String description; + + /** + * 启用状态 + */ + @ExcelProperty(value = "启用状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private Integer status; + + /** + * 更新时间 + */ + @ExcelProperty(value = "更新时间") + private Date updateTime; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SensitiveWordRedisMQListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SensitiveWordRedisMQListener.java new file mode 100644 index 00000000..e8042c74 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SensitiveWordRedisMQListener.java @@ -0,0 +1,39 @@ +package org.dromara.system.listener; + +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.system.service.ISysSensitiveWordService; +import org.redisson.api.listener.MessageListener; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +/** + * 敏感词监听器 + * + * @author hexm + * @date 2024/8/19 + */ +@Component +@RequiredArgsConstructor +public class SensitiveWordRedisMQListener implements InitializingBean, DisposableBean, MessageListener { + + public static final String CHANNEL_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sensitiveWord_channelKey"; + private final ISysSensitiveWordService sensitiveWordService; + + @Override + public void afterPropertiesSet() throws Exception { + RedisUtils.subscribe(CHANNEL_KEY, String.class, this); + } + + @Override + public void destroy() throws Exception { + RedisUtils.unsubscribe(CHANNEL_KEY, this); + } + + @Override + public void onMessage(CharSequence channel, String msg) { + sensitiveWordService.initSensitiveWordReplacers(); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java new file mode 100644 index 00000000..4716fc23 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java @@ -0,0 +1,92 @@ +package org.dromara.system.listener; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.core.ExcelListener; +import org.dromara.common.excel.core.ExcelResult; +import org.dromara.system.domain.bo.SysSensitiveWordBo; +import org.dromara.system.domain.template.SysSensitiveWordImportTemplate; +import org.dromara.system.service.ISysSensitiveWordService; + +import java.util.List; + +/** + * 敏感词自定义导入 + * + * @author hexm + * @date 2024-08-16 + */ +public class SysSensitiveWordImportListener extends AnalysisEventListener implements ExcelListener { + + private final ISysSensitiveWordService sysSensitiveWordService; + + private final boolean isUpdateSupport; + + private int successNum = 1; + private int failureNum = 0; + private final StringBuilder successMsg = new StringBuilder(); + private final StringBuilder failureMsg = new StringBuilder(); + + public SysSensitiveWordImportListener(ISysSensitiveWordService sysSensitiveWordService, boolean isUpdateSupport) { + this.sysSensitiveWordService = sysSensitiveWordService; + this.isUpdateSupport = isUpdateSupport; + } + + @Override + public void invoke(SysSensitiveWordImportTemplate importTemplate, AnalysisContext context) { + try { + SysSensitiveWordBo bo = MapstructUtils.convert(importTemplate, SysSensitiveWordBo.class); + if (!isUpdateSupport) { + ValidatorUtils.validate(bo, AddGroup.class); + sysSensitiveWordService.insertByBo(bo); + successNum++; + successMsg.append("
第").append(successNum).append("行 导入成功"); + } else { + ValidatorUtils.validate(bo, EditGroup.class); + sysSensitiveWordService.updateByBo(bo); + successNum++; + successMsg.append("
第").append(successNum).append("行 更新成功"); + } + } catch (Exception e) { + failureNum++; + failureMsg.append("
第").append(failureNum).append("行 导入失败:").append(e.getMessage()); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + @Override + public ExcelResult getExcelResult() { + return new ExcelResult<>() { + + @Override + public String getAnalysis() { + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + @Override + public List getList() { + return null; + } + + @Override + public List getErrorList() { + return null; + } + }; + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysSensitiveWordMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysSensitiveWordMapper.java new file mode 100644 index 00000000..3539e763 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysSensitiveWordMapper.java @@ -0,0 +1,26 @@ +package org.dromara.system.mapper; + +import org.dromara.system.domain.SysSensitiveWord; +import org.dromara.system.domain.bo.SysSensitiveWordBo; +import org.dromara.system.domain.query.SysSensitiveWordQuery; +import org.dromara.system.domain.vo.SysSensitiveWordVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +import java.util.List; + +/** + * 敏感词Mapper接口 + * + * @author hexm + * @date 2024-08-16 + */ +public interface SysSensitiveWordMapper extends BaseMapperPlus { + + /** + * 查询敏感词列表 + * + * @param query 查询对象 + * @return {@link SysSensitiveWordVo} + */ + List queryList(SysSensitiveWordQuery query); +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java new file mode 100644 index 00000000..e6fa8dab --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java @@ -0,0 +1,106 @@ +package org.dromara.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.system.domain.SysSensitiveWord; +import org.dromara.system.domain.bo.SysSensitiveWordBo; +import org.dromara.system.domain.query.SysSensitiveWordQuery; +import org.dromara.system.domain.vo.SysSensitiveWordVo; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * 敏感词Service接口 + * + * @author hexm + * @date 2024-08-16 + */ +public interface ISysSensitiveWordService extends IService { + + /** + * 查询敏感词 + * + * @param wordId 主键 + * @return SysSensitiveWordVo + */ + SysSensitiveWordVo queryById(Long wordId); + + /** + * 查询敏感词列表 + * + * @param query 查询对象 + * @return SysSensitiveWordVo + */ + TableDataInfo queryPageList(SysSensitiveWordQuery query); + + /** + * 查询敏感词列表 + * + * @param query 查询对象 + * @return SysSensitiveWordVo + */ + List queryList(SysSensitiveWordQuery query); + + /** + * 新增敏感词 + * + * @param bo 敏感词新增业务对象 + * @return Boolean + */ + Boolean insertByBo(SysSensitiveWordBo bo); + + /** + * 修改敏感词 + * + * @param bo 敏感词编辑业务对象 + * @return Boolean + */ + Boolean updateByBo(SysSensitiveWordBo bo); + + /** + * 校验并批量删除敏感词信息 + * + * @param ids 主键集合 + * @return Boolean + */ + Boolean deleteWithValidByIds(Collection ids); + + /** + * 刷新敏感词缓存数据 + */ + void refreshCache(); + + /** + * 初始化敏感词替换器 + */ + void initSensitiveWordReplacers(); + + /** + * 判断是否包含敏感词 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 是否包含敏感词 + */ + boolean containsSensitiveWord(String text, String... category); + + /** + * 敏感词替换 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 替换后的文本 + */ + String sensitiveWordReplace(String text, String... category); + + /** + * 查找敏感词,返回找到的所有敏感词 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 敏感词 + */ + Set getFoundAllSensitive(String text, String... category); +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java new file mode 100644 index 00000000..12f6e26d --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java @@ -0,0 +1,265 @@ +package org.dromara.system.service.impl; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.dfa.FoundWord; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.PostConstruct; +import lombok.Getter; +import org.dromara.common.core.constant.CacheConstants; +import org.dromara.common.core.enums.NormalDisableEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.sensitive.SensitiveWordReplacer; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.redis.utils.RedisLockUtil; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.system.domain.SysSensitiveWord; +import org.dromara.system.domain.bo.SysSensitiveWordBo; +import org.dromara.system.domain.query.SysSensitiveWordQuery; +import org.dromara.system.domain.vo.SysSensitiveWordVo; +import org.dromara.system.listener.SensitiveWordRedisMQListener; +import org.dromara.system.mapper.SysSensitiveWordMapper; +import org.dromara.system.service.ISysSensitiveWordService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 敏感词Service业务层处理 + * + * @author hexm + * @date 2024-08-16 + */ +@Getter +@Service +public class SysSensitiveWordServiceImpl extends ServiceImpl implements ISysSensitiveWordService { + + private volatile SensitiveWordReplacer allSensitiveWordReplacer = new SensitiveWordReplacer(Collections.emptySet()); + /** + * 标签与敏感词的字段数的映射 + */ + private volatile Map categorySensitiveWordReplacers = Collections.emptyMap(); + + /** + * 查询敏感词 + * + * @param wordId 主键 + * @return SysSensitiveWordVo + */ + @Override + public SysSensitiveWordVo queryById(Long wordId) { + return baseMapper.selectVoById(wordId); + } + + /** + * 查询敏感词列表 + * + * @param query 查询对象 + * @return SysSensitiveWordVo + */ + @Override + public TableDataInfo queryPageList(SysSensitiveWordQuery query) { + return PageQuery.of(() -> baseMapper.queryList(query)); + } + + /** + * 查询敏感词列表 + * + * @param query 查询对象 + * @return SysSensitiveWordVo + */ + @Override + public List queryList(SysSensitiveWordQuery query) { + return baseMapper.queryList(query); + } + + /** + * 根据新增业务对象插入敏感词 + * + * @param bo 敏感词新增业务对象 + * @return Boolean + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(SysSensitiveWordBo bo) { + saveValid(bo); + SysSensitiveWord add = MapstructUtils.convert(bo, SysSensitiveWord.class); + boolean save = save(add); + if (save) { + refreshCache(); + } + return save; + } + + /** + * 根据编辑业务对象修改敏感词 + * + * @param bo 敏感词编辑业务对象 + * @return Boolean + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(SysSensitiveWordBo bo) { + saveValid(bo); + SysSensitiveWord word = getById(bo.getWordId()); + SysSensitiveWord update = MapstructUtils.convert(bo, SysSensitiveWord.class); + boolean b = updateById(update); + if (b) { + // 只有改变以下数据的值才刷新缓存 + if (!Objects.equals(word.getWord(), bo.getWord()) + || !Objects.equals(word.getCategory(), bo.getCategory()) + || !Objects.equals(word.getStatus(), bo.getStatus())) { + refreshCache(); + } + } + return b; + } + + /** + * 保存前校验数据 + * + * @param bo 敏感词编辑业务对象 + */ + private void saveValid(SysSensitiveWordBo bo) { + boolean exists = lambdaQuery() + .ne(bo.getWordId() != null, SysSensitiveWord::getWordId, bo.getWordId()) + .eq(SysSensitiveWord::getWord, bo.getWord()) + .exists(); + if (exists) { + throw new ServiceException("敏感词已存在"); + } + } + + /** + * 校验并批量删除敏感词信息 + * + * @param ids 主键集合 + * @return Boolean + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteWithValidByIds(Collection ids) { + boolean b = removeByIds(ids); + if (b) { + refreshCache(); + } + return b; + } + + /** + * 获取敏感词缓存数据 + */ + private Map> getCacheMap() { + return RedisLockUtil.getOrSaveMap(CacheConstants.SYS_SENSITIVE_WORD, () -> { + List list = lambdaQuery() + .eq(SysSensitiveWord::getStatus, NormalDisableEnum.NORMAL.getCodeNum()) + .select(SysSensitiveWord::getCategory, SysSensitiveWord::getWord) + .list(); + return list + .stream() + .collect(Collectors.groupingBy( + SysSensitiveWord::getCategory, + HashMap::new, + Collectors.mapping(SysSensitiveWord::getWord, Collectors.toSet()))); + }); + } + + /** + * 刷新敏感词缓存数据 + */ + @Override + public void refreshCache() { + RedisUtils.deleteObject(CacheConstants.SYS_SENSITIVE_WORD); + RedisUtils.publish(SensitiveWordRedisMQListener.CHANNEL_KEY, ""); + } + + /** + * 初始化敏感词替换器 + */ + @PostConstruct + @Override + public void initSensitiveWordReplacers() { + Map> cacheMap = getCacheMap(); + // 全部替换器 + allSensitiveWordReplacer = new SensitiveWordReplacer(cacheMap.values().stream() + .flatMap(Collection::stream).collect(Collectors.toSet())); + // 分类替换器 + categorySensitiveWordReplacers = new HashMap<>(); + cacheMap.forEach((category, sensitiveWords) -> { + SensitiveWordReplacer sensitiveWordReplacer = new SensitiveWordReplacer(sensitiveWords); + categorySensitiveWordReplacers.put(category, sensitiveWordReplacer); + }); + } + + /** + * 判断是否包含敏感词 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 是否包含敏感词 + */ + @Override + public boolean containsSensitiveWord(String text, String... category) { + if (ArrayUtil.isNotEmpty(category)) { + for (String c : category) { + SensitiveWordReplacer sensitiveWordReplacer = categorySensitiveWordReplacers.get(c); + if (sensitiveWordReplacer != null && sensitiveWordReplacer.containsSensitiveWord(text)) { + return true; + } + } + return false; + } else { + return allSensitiveWordReplacer.containsSensitiveWord(text); + } + } + + /** + * 敏感词替换 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 替换后的文本 + */ + @Override + public String sensitiveWordReplace(String text, String... category) { + if (ArrayUtil.isNotEmpty(category)) { + for (String c : category) { + SensitiveWordReplacer sensitiveWordReplacer = categorySensitiveWordReplacers.get(c); + if (sensitiveWordReplacer != null) { + text = sensitiveWordReplacer.sensitiveWordReplace(text); + } + } + return text; + } else { + return allSensitiveWordReplacer.sensitiveWordReplace(text); + } + } + + /** + * 查找敏感词,返回找到的所有敏感词 + * + * @param text 文本 + * @param category 敏感词分类 + * @return 敏感词 + */ + @Override + public Set getFoundAllSensitive(String text, String... category) { + List list; + if (ArrayUtil.isNotEmpty(category)) { + list = new ArrayList<>(); + for (String c : category) { + SensitiveWordReplacer sensitiveWordReplacer = categorySensitiveWordReplacers.get(c); + if (sensitiveWordReplacer != null) { + list.addAll(sensitiveWordReplacer.getFoundAllSensitive(text, true, true)); + } + } + } else { + list = allSensitiveWordReplacer.getFoundAllSensitive(text, true, true); + } + return StreamUtils.toSet(list, FoundWord::getWord); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSensitiveWordMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSensitiveWordMapper.xml new file mode 100644 index 00000000..398571b2 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSensitiveWordMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + select ssw.word_id, ssw.word, ssw.category, ssw.description, ssw.status, ssw.create_dept, ssw.create_by, ssw.update_by, ssw.update_time, ssw.create_time from sys_sensitive_word ssw + + + + diff --git a/ruoyi-ui/components.d.ts b/ruoyi-ui/components.d.ts index 4baa3d42..56f14bc5 100644 --- a/ruoyi-ui/components.d.ts +++ b/ruoyi-ui/components.d.ts @@ -98,6 +98,7 @@ declare module 'vue' { TTreeSelect: typeof import('tdesign-vue-next')['TreeSelect'] TUpload: typeof import('tdesign-vue-next')['Upload'] TWatermark: typeof import('tdesign-vue-next')['Watermark'] + UploadExcel: typeof import('./src/components/upload-excel/index.vue')['default'] UploadSelect: typeof import('./src/components/upload-select/index.vue')['default'] } } diff --git a/ruoyi-ui/src/api/system/model/sensitiveWordModel.ts b/ruoyi-ui/src/api/system/model/sensitiveWordModel.ts new file mode 100644 index 00000000..7d2bf240 --- /dev/null +++ b/ruoyi-ui/src/api/system/model/sensitiveWordModel.ts @@ -0,0 +1,65 @@ +import type { BaseEntity } from '@/api/model/resultModel'; + +/** + * 敏感词查询对象 + */ +export interface SysSensitiveWordQuery extends BaseEntity { + /** 敏感词 */ + word?: string; + /** 敏感词类别 */ + category?: string; + /** 启用状态 */ + status?: number; +} +/** + * 敏感词业务对象 + */ +export interface SysSensitiveWordForm { + /** 敏感词id */ + wordId?: number; + /** 敏感词 */ + word?: string; + /** 敏感词类别 */ + category?: string; + /** 描述 */ + description?: string; + /** 启用状态 */ + status?: number; +} +/** + * 敏感词视图对象 + */ +export interface SysSensitiveWordVo { + /** 敏感词id */ + wordId?: number; + /** 敏感词 */ + word?: string; + /** 敏感词类别 */ + category?: string; + /** 描述 */ + description?: string; + /** 启用状态 */ + status?: number; + /** 更新时间 */ + updateTime?: any; + /** 创建时间 */ + createTime?: any; +} + +export interface SysSensitiveWordTest { + /** 测试文本 */ + text: string; + /** 敏感词类别 */ + category?: string[]; +} +/** + * 敏感词测试结果vo + */ +export interface SysSensitiveWordTestVo { + /** 是否包含敏感词 */ + containsSensitiveWord: boolean; + /** 敏感词替换后的内容 */ + sensitiveWordReplace: string; + /** 包含的敏感词 */ + sensitiveWords: string[]; +} diff --git a/ruoyi-ui/src/api/system/sensitiveWord.ts b/ruoyi-ui/src/api/system/sensitiveWord.ts new file mode 100644 index 00000000..edcb397c --- /dev/null +++ b/ruoyi-ui/src/api/system/sensitiveWord.ts @@ -0,0 +1,64 @@ +import type { R, TableDataInfo } from '@/api/model/resultModel'; +import type { + SysSensitiveWordForm, + SysSensitiveWordQuery, + SysSensitiveWordTest, + SysSensitiveWordTestVo, + SysSensitiveWordVo, +} from '@/api/system/model/sensitiveWordModel'; +import { request } from '@/utils/request'; + +// 查询敏感词列表 +export function listSensitiveWord(query?: SysSensitiveWordQuery) { + return request.get>({ + url: '/system/sensitiveWord/list', + params: query, + }); +} + +// 查询敏感词详细 +export function getSensitiveWord(wordId: number) { + return request.get>({ + url: `/system/sensitiveWord/${wordId}`, + }); +} + +// 新增敏感词 +export function addSensitiveWord(data: SysSensitiveWordForm) { + return request.post>({ + url: '/system/sensitiveWord', + data, + }); +} + +// 修改敏感词 +export function updateSensitiveWord(data: SysSensitiveWordForm) { + return request.put>({ + url: '/system/sensitiveWord', + data, + }); +} + +// 删除敏感词 +export function delSensitiveWord(wordIds: number | Array) { + return request.delete>({ + url: `/system/sensitiveWord/${wordIds}`, + }); +} + +// 刷新缓存 +export function refreshSensitiveWordCache() { + return request.delete>({ + url: '/system/sensitiveWord/refreshCache', + }); +} + +/** + * 测试敏感词 + */ +export function sensitiveWordTest(params: SysSensitiveWordTest) { + return request.get>({ + url: '/system/sensitiveWord/test', + params, + }); +} diff --git a/ruoyi-ui/src/api/tool/model/genModel.ts b/ruoyi-ui/src/api/tool/model/genModel.ts index aa5d5c00..2caee597 100644 --- a/ruoyi-ui/src/api/tool/model/genModel.ts +++ b/ruoyi-ui/src/api/tool/model/genModel.ts @@ -198,6 +198,8 @@ export interface GenTableOptions { isUseEditMethod?: boolean; /** 是否使用删除方法 */ isUseRemoveMethod?: boolean; + /** 是否使用导入方法 */ + isUseImportMethod?: boolean; /** 是否使用导出方法 */ isUseExportMethod?: boolean; /** 是否使用详情方法 */ diff --git a/ruoyi-ui/src/components/upload-excel/index.vue b/ruoyi-ui/src/components/upload-excel/index.vue new file mode 100644 index 00000000..d725940d --- /dev/null +++ b/ruoyi-ui/src/components/upload-excel/index.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/ruoyi-ui/src/pages/system/sensitiveWord/index.vue b/ruoyi-ui/src/pages/system/sensitiveWord/index.vue new file mode 100644 index 00000000..f44e1597 --- /dev/null +++ b/ruoyi-ui/src/pages/system/sensitiveWord/index.vue @@ -0,0 +1,589 @@ + + diff --git a/ruoyi-ui/src/pages/system/user/index.vue b/ruoyi-ui/src/pages/system/user/index.vue index e2228c5c..6fb93433 100644 --- a/ruoyi-ui/src/pages/system/user/index.vue +++ b/ruoyi-ui/src/pages/system/user/index.vue @@ -366,23 +366,27 @@ attach="body" :footer="null" > - - -

是否更新已经存在的用户数据
- 下载模板 + + + +
是否更新已经存在的用户数据
+ + 下载模板 + +
@@ -501,7 +505,7 @@ const roleOptions = ref([]); const deptActived = ref([]); const sort = ref(); const { token } = storeToRefs(useUserStore()); -/** * 用户导入参数 */ +/** 用户导入参数 */ const upload = reactive({ // 是否显示弹出层(用户导入) open: false, diff --git a/ruoyi-ui/src/pages/tool/gen/genInfoForm.vue b/ruoyi-ui/src/pages/tool/gen/genInfoForm.vue index aca34172..79628bbf 100644 --- a/ruoyi-ui/src/pages/tool/gen/genInfoForm.vue +++ b/ruoyi-ui/src/pages/tool/gen/genInfoForm.vue @@ -163,6 +163,7 @@ 新增 编辑 删除 + 导入 导出 详情 查询 diff --git a/script/sql/oracle/oracle_ry_vue_1.X.sql b/script/sql/oracle/oracle_ry_vue_1.X.sql index af100a8e..820d467f 100644 --- a/script/sql/oracle/oracle_ry_vue_1.X.sql +++ b/script/sql/oracle/oracle_ry_vue_1.X.sql @@ -457,6 +457,7 @@ insert into sys_menu values('115', '代码生成', '3', '2', 'gen', insert into sys_menu values('121', '租户管理', '6', '1', 'tenant', 'system/tenant/index', 'Tenant', '', 0, 1, 'C', '1', '1', 'system:tenant:list', 'bulletpoint', null, null, 103, 1, sysdate, null, null, '租户管理菜单'); insert into sys_menu values('122', '租户套餐管理', '6', '2', 'tenantPackage', 'system/tenantPackage/index', 'TenantPackage', '', 0, 1, 'C', '1', '1', 'system:tenantPackage:list', 'edit-1', null, null, 103, 1, sysdate, null, null, '租户套餐管理菜单'); insert into sys_menu values('123', '客户端管理', '1', '12', 'client', 'system/client/index', 'Client', '', 0, 1, 'C', '1', '1', 'system:client:list', 'internet', null, null, 103, 1, sysdate, null, null, '客户端管理菜单'); +insert into sys_menu values('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, sysdate, 1, sysdate, '敏感词菜单'); -- springboot-admin监控 insert into sys_menu values('117', 'Admin监控', '2', '5', 'Admin', 'monitor/admin/index', 'Admin', '', 0, 1, 'C', '1', '1', 'monitor:admin:list', 'dashboard', null, '!getProperty(''spring.boot.admin.client.enabled'')', 103, 1, sysdate, null, null, 'Admin监控菜单'); -- oss菜单 @@ -584,6 +585,13 @@ insert into sys_menu values('1703', '租户应用管理新增', '1701', 2, '#', insert into sys_menu values('1704', '租户应用管理修改', '1701', 3, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:edit', '#', null, null, 103, 1, sysdate, null, null, ''); insert into sys_menu values('1705', '租户应用管理删除', '1701', 4, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:remove', '#', null, null, 103, 1, sysdate, null, null, ''); insert into sys_menu values('1706', '租户应用管理导出', '1701', 5, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:export', '#', null, null, 103, 1, sysdate, null, null, ''); +-- 敏感词 +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, sysdate, null, null, ''); -- 消息管理 insert into sys_menu values('1801', '消息管理', '1', 11, 'messageManage', '', '', NULL, 0, 1, 'M', '1', '1', NULL, 'chat', null, null, 103, 1, sysdate, 1, sysdate, ''); -- 消息配置 @@ -876,6 +884,7 @@ insert into sys_dict_type values(13, '000000', '消息支持平台', 'sys_messag insert into sys_dict_type values(14, '000000', '消息模板类型', 'sys_message_template_mode', 103, 1, sysdate, 1, sysdate, NULL); insert into sys_dict_type values(15, '000000', '授权类型', 'sys_grant_type', 103, 1, sysdate, null, null, '认证授权类型'); insert into sys_dict_type values(16, '000000', '设备类型', 'sys_device_type', 103, 1, sysdate, null, null, '客户端设备类型'); +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, sysdate, 1, sysdate, null); -- ---------------------------- @@ -977,6 +986,7 @@ insert into sys_dict_data values(58, '000000', 11, '助通短信', 'ZHUTONG', 's insert into sys_dict_data values(59, '000000', 12, '鼎众短信', 'DING_ZHONG', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, sysdate, 1, sysdate, null); insert into sys_dict_data values(60, '000000', 13, '联麓短信', 'LIAN_LU', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, sysdate, 1, sysdate, null); insert into sys_dict_data values(61, '000000', 14, '七牛云短信', 'QI_NIU', 'sys_message_supplier_type', null, 'primary', null, 'N', 103, 1, sysdate, 1, sysdate, null); +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, sysdate, 1, sysdate, null); -- ---------------------------- @@ -1616,6 +1626,34 @@ comment on column sys_message_template.create_by is '创建者'; comment on column sys_message_template.update_time is '更新时间'; comment on column sys_message_template.create_time is '创建时间'; +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +create table sys_sensitive_word ( + word_id number(20) not null, + word nvarchar2(255) not null, + category nvarchar2(20) not null, + description nvarchar2(500), + status number(4) not null, + create_dept number(20), + create_by number(20), + update_by number(20), + update_time date, + create_time date not null +); +alter table sys_sensitive_word add primary key (word_id); +comment on table sys_sensitive_word is '敏感词表'; +comment on column sys_sensitive_word.word_id is '敏感词id'; +comment on column sys_sensitive_word.word is '敏感词'; +comment on column sys_sensitive_word.category is '敏感词类别'; +comment on column sys_sensitive_word.description is '描述'; +comment on column sys_sensitive_word.status is '启用状态 1启用 0禁用'; +comment on column sys_sensitive_word.create_dept is '创建部门'; +comment on column sys_sensitive_word.create_by is '创建者'; +comment on column sys_sensitive_word.update_by is '更新者'; +comment on column sys_sensitive_word.update_time is '更新时间'; +comment on column sys_sensitive_word.create_time is '创建时间'; + -- ---------------------------- -- 钩子 ,用于session连接之后 自动设置默认的date类型格式化 简化时间查询 -- 如需设置其它配置 可在此钩子内任意增加处理语句 diff --git a/script/sql/postgres/postgres_ry_vue_1.X.sql b/script/sql/postgres/postgres_ry_vue_1.X.sql index 58022be3..a90093a3 100644 --- a/script/sql/postgres/postgres_ry_vue_1.X.sql +++ b/script/sql/postgres/postgres_ry_vue_1.X.sql @@ -467,6 +467,7 @@ insert into sys_menu values('115', '代码生成', '3', '2', 'gen', insert into sys_menu values('121', '租户管理', '6', '1', 'tenant', 'system/tenant/index', 'Tenant', '', 0, 1, 'C', '1', '1', 'system:tenant:list', 'bulletpoint', null, null, 103, 1, now(), null, null, '租户管理菜单'); insert into sys_menu values('122', '租户套餐管理', '6', '2', 'tenantPackage', 'system/tenantPackage/index', 'TenantPackage', '', 0, 1, 'C', '1', '1', 'system:tenantPackage:list', 'edit-1', null, null, 103, 1, now(), null, null, '租户套餐管理菜单'); insert into sys_menu values('123', '客户端管理', '1', '12', 'client', 'system/client/index', 'Client', '', 0, 1, 'C', '1', '1', 'system:client:list', 'internet', null, null, 103, 1, now(), null, null, '客户端管理菜单'); +insert into sys_menu values('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, now(), 1, now(), '敏感词菜单'); -- springboot-admin监控 insert into sys_menu values('117', 'Admin监控', '2', '5', 'Admin', 'monitor/admin/index', 'Admin', '', 0, 1, 'C', '1', '1', 'monitor:admin:list', 'dashboard', null, '!getProperty(''spring.boot.admin.client.enabled'')', 103, 1, now(), null, null, 'Admin监控菜单'); @@ -595,6 +596,13 @@ insert into sys_menu values('1703', '租户应用管理新增', '1701', 2, '#', insert into sys_menu values('1704', '租户应用管理修改', '1701', 3, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:edit', '#', null, null, 103, 1, now(), null, null, ''); insert into sys_menu values('1705', '租户应用管理删除', '1701', 4, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:remove', '#', null, null, 103, 1, now(), null, null, ''); insert into sys_menu values('1706', '租户应用管理导出', '1701', 5, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:export', '#', null, null, 103, 1, now(), null, null, ''); +-- 敏感词 +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, now(), null, null, ''); -- 消息管理 insert into sys_menu values('1801', '消息管理', '1', 11, 'messageManage', NULL, NULL, NULL, 0, 1, 'M', '1', '1', NULL, 'chat', null, null, 103, 1, now(), 1, now(), ''); @@ -896,6 +904,7 @@ insert into sys_dict_type values(13, '000000', '消息支持平台', 'sys_messag insert into sys_dict_type values(14, '000000', '消息模板类型', 'sys_message_template_mode', 103, 1, now(), 1, now(), NULL); insert into sys_dict_type values(15, '000000', '授权类型', 'sys_grant_type', 103, 1, now(), null, null, '认证授权类型'); insert into sys_dict_type values(16, '000000', '设备类型', 'sys_device_type', 103, 1, now(), null, null, '客户端设备类型'); +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, now(), 1, now(), null); -- ---------------------------- @@ -998,6 +1007,7 @@ insert into sys_dict_data values(58, '000000', 11, '助通短信', 'ZHUTONG', 's insert into sys_dict_data values(59, '000000', 12, '鼎众短信', 'DING_ZHONG', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, now(), 1, now(), null); insert into sys_dict_data values(60, '000000', 13, '联麓短信', 'LIAN_LU', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, now(), 1, now(), null); insert into sys_dict_data values(61, '000000', 14, '七牛云短信', 'QI_NIU', 'sys_message_supplier_type', null, 'primary', null, 'N', 103, 1, now(), 1, now(), null); +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, now(), 1, now(), null); @@ -1648,6 +1658,35 @@ comment on column sys_message_template.create_by is '创建者'; comment on column sys_message_template.update_time is '更新时间'; comment on column sys_message_template.create_time is '创建时间'; +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +drop table if exists sys_sensitive_word; +create table sys_sensitive_word ( + word_id int8 not null, + word varchar(255) not null, + category varchar(20) not null, + description varchar(500), + status int2 not null, + create_dept int8, + create_by int8, + update_by int8, + update_time timestamp, + create_time timestamp not null +); +alter table sys_sensitive_word add primary key (word_id); +comment on table sys_sensitive_word is '敏感词表'; +comment on column sys_sensitive_word.word_id is '敏感词id'; +comment on column sys_sensitive_word.word is '敏感词'; +comment on column sys_sensitive_word.category is '敏感词类别'; +comment on column sys_sensitive_word.description is '描述'; +comment on column sys_sensitive_word.status is '启用状态 1启用 0禁用'; +comment on column sys_sensitive_word.create_dept is '创建部门'; +comment on column sys_sensitive_word.create_by is '创建者'; +comment on column sys_sensitive_word.update_by is '更新者'; +comment on column sys_sensitive_word.update_time is '更新时间'; +comment on column sys_sensitive_word.create_time is '创建时间'; + -- 字符串自动转时间 避免框架时间查询报错问题 create or replace function cast_varchar_to_timestamp(varchar) returns timestamptz as $$ select to_timestamp($1, 'yyyy-mm-dd hh24:mi:ss'); diff --git a/script/sql/ry_vue_1.X.sql b/script/sql/ry_vue_1.X.sql index e6839766..20a95561 100644 --- a/script/sql/ry_vue_1.X.sql +++ b/script/sql/ry_vue_1.X.sql @@ -298,6 +298,7 @@ insert into sys_menu values('115', '代码生成', '3', '2', 'gen', insert into sys_menu values('121', '租户管理', '6', '1', 'tenant', 'system/tenant/index','Tenant', '', 0, 1, 'C', '1', '1', 'system:tenant:list', 'bulletpoint', null, null, 103, 1, sysdate(), null, null, '租户管理菜单'); insert into sys_menu values('122', '租户套餐管理', '6', '2', 'tenantPackage', 'system/tenantPackage/index','TenantPackage', '', 0, 1, 'C', '1', '1', 'system:tenantPackage:list', 'edit-1', null, null, 103, 1, sysdate(), null, null, '租户套餐管理菜单'); insert into sys_menu values('123', '客户端管理', '1', '12', 'client', 'system/client/index','Client', '', 0, 1, 'C', '1', '1', 'system:client:list', 'internet', null, null, 103, 1, sysdate(), null, null, '客户端管理菜单'); +insert into sys_menu values('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, sysdate(), 1, sysdate(), '敏感词菜单'); -- springboot-admin监控 insert into sys_menu values('117', 'Admin监控', '2', '5', 'Admin', 'monitor/admin/index','Admin', '', 0, 1, 'C', '1', '1', 'monitor:admin:list', 'dashboard', null, '!getProperty(\'spring.boot.admin.client.enabled\')', 103, 1, sysdate(), null, null, 'Admin监控菜单'); @@ -426,6 +427,13 @@ insert into sys_menu values('1703', '租户应用管理新增', '1701', 2, '#', insert into sys_menu values('1704', '租户应用管理修改', '1701', 3, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:edit', '#', null, null, 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1705', '租户应用管理删除', '1701', 4, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:remove', '#', null, null, 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1706', '租户应用管理导出', '1701', 5, '#', '', '', null, 0, 1, 'F', '1', '1', 'system:tenantApp:export', '#', null, null, 103, 1, sysdate(), null, null, ''); +-- 敏感词 +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, sysdate(), null, null, ''); -- 消息管理 insert into sys_menu values('1801', '消息管理', '1', 11, 'messageManage', null, null, null, 0, 1, 'M', '1', '1', null, 'chat', null, null, 103, 1, sysdate(), 1, sysdate(), ''); @@ -673,6 +681,7 @@ insert into sys_dict_type values(13, '000000', '消息支持平台', 'sys_messag insert into sys_dict_type values(14, '000000', '消息模板类型', 'sys_message_template_mode', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_dict_type values(15, '000000', '授权类型', 'sys_grant_type', 103, 1, sysdate(), null, null, '认证授权类型'); insert into sys_dict_type values(16, '000000', '设备类型', 'sys_device_type', 103, 1, sysdate(), null, null, '客户端设备类型'); +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, sysdate(), 1, sysdate(), null); -- ---------------------------- @@ -757,7 +766,7 @@ insert into sys_dict_data values(58, '000000', 11, '助通短信', 'ZHUTONG', 's insert into sys_dict_data values(59, '000000', 12, '鼎众短信', 'DING_ZHONG', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_dict_data values(60, '000000', 13, '联麓短信', 'LIAN_LU', 'sys_message_supplier_type', null, 'primary', '', 'N', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_dict_data values(61, '000000', 14, '七牛云短信', 'QI_NIU', 'sys_message_supplier_type', null, 'primary', null, 'N', 103, 1, sysdate(), 1, sysdate(), null); - +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, sysdate(), 1, sysdate(), null); @@ -1146,3 +1155,21 @@ create table sys_message_template ( index idx_message_key_id(message_key_id) using btree, index idx_message_key(message_key, message_type, status) using btree ) engine = innodb comment = '消息模板表'; + +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +drop table if exists sys_sensitive_word; +create table sys_sensitive_word ( + word_id bigint not null comment '敏感词id', + word varchar(255) not null comment '敏感词', + category varchar(20) not null comment '敏感词类别', + description varchar(500) null default null comment '描述', + status tinyint not null comment '启用状态 1启用 0禁用', + create_dept bigint null default null comment '创建部门', + create_by bigint null default null comment '创建者', + update_by bigint null default null comment '更新者', + update_time datetime null default null comment '更新时间', + create_time datetime not null comment '创建时间', + primary key (word_id) using btree +) engine = innodb comment = '敏感词表'; diff --git a/script/sql/update/oracle/update_1.3.0_1.3.1.sql b/script/sql/update/oracle/update_1.3.0_1.3.1.sql index d701cce6..91e3c305 100644 --- a/script/sql/update/oracle/update_1.3.0_1.3.1.sql +++ b/script/sql/update/oracle/update_1.3.0_1.3.1.sql @@ -12,3 +12,46 @@ UPDATE sys_menu SET menu_name = '租户应用管理新增', perms = 'system:tena UPDATE sys_menu SET menu_name = '租户应用管理修改', perms = 'system:tenantApp:edit' WHERE menu_id = 1704; UPDATE sys_menu SET menu_name = '租户应用管理删除', perms = 'system:tenantApp:remove' WHERE menu_id = 1705; UPDATE sys_menu SET menu_name = '租户应用管理导出', perms = 'system:tenantApp:export' WHERE menu_id = 1706; + +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +create table sys_sensitive_word ( + word_id number(20) not null, + word nvarchar2(255) not null, + category nvarchar2(20) not null, + description nvarchar2(500), + status number(4) not null, + create_dept number(20), + create_by number(20), + update_by number(20), + update_time date, + create_time date not null +); +alter table sys_sensitive_word add primary key (word_id); +comment on table sys_sensitive_word is '敏感词表'; +comment on column sys_sensitive_word.word_id is '敏感词id'; +comment on column sys_sensitive_word.word is '敏感词'; +comment on column sys_sensitive_word.category is '敏感词类别'; +comment on column sys_sensitive_word.description is '描述'; +comment on column sys_sensitive_word.status is '启用状态 1启用 0禁用'; +comment on column sys_sensitive_word.create_dept is '创建部门'; +comment on column sys_sensitive_word.create_by is '创建者'; +comment on column sys_sensitive_word.update_by is '更新者'; +comment on column sys_sensitive_word.update_time is '更新时间'; +comment on column sys_sensitive_word.create_time is '创建时间'; + +-- 敏感词菜单 +insert into sys_menu values('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, sysdate, 1, sysdate, '敏感词菜单'); +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, sysdate, null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, sysdate, null, null, ''); + +-- 敏感词字典 +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, sysdate, 1, sysdate, null); +-- 敏感词字典数据,需要其他类别自行添加 +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, sysdate, 1, sysdate, null); +-- 管理员权限关联自行添加 diff --git a/script/sql/update/postgres/update_1.3.0_1.3.1.sql b/script/sql/update/postgres/update_1.3.0_1.3.1.sql index d701cce6..4d28e710 100644 --- a/script/sql/update/postgres/update_1.3.0_1.3.1.sql +++ b/script/sql/update/postgres/update_1.3.0_1.3.1.sql @@ -12,3 +12,47 @@ UPDATE sys_menu SET menu_name = '租户应用管理新增', perms = 'system:tena UPDATE sys_menu SET menu_name = '租户应用管理修改', perms = 'system:tenantApp:edit' WHERE menu_id = 1704; UPDATE sys_menu SET menu_name = '租户应用管理删除', perms = 'system:tenantApp:remove' WHERE menu_id = 1705; UPDATE sys_menu SET menu_name = '租户应用管理导出', perms = 'system:tenantApp:export' WHERE menu_id = 1706; + +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +drop table if exists sys_sensitive_word; +create table sys_sensitive_word ( + word_id int8 not null, + word varchar(255) not null, + category varchar(20) not null, + description varchar(500), + status int2 not null, + create_dept int8, + create_by int8, + update_by int8, + update_time timestamp, + create_time timestamp not null +); +alter table sys_sensitive_word add primary key (word_id); +comment on table sys_sensitive_word is '敏感词表'; +comment on column sys_sensitive_word.word_id is '敏感词id'; +comment on column sys_sensitive_word.word is '敏感词'; +comment on column sys_sensitive_word.category is '敏感词类别'; +comment on column sys_sensitive_word.description is '描述'; +comment on column sys_sensitive_word.status is '启用状态 1启用 0禁用'; +comment on column sys_sensitive_word.create_dept is '创建部门'; +comment on column sys_sensitive_word.create_by is '创建者'; +comment on column sys_sensitive_word.update_by is '更新者'; +comment on column sys_sensitive_word.update_time is '更新时间'; +comment on column sys_sensitive_word.create_time is '创建时间'; + +-- 敏感词菜单 +insert into sys_menu values('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, now(), 1, now(), '敏感词菜单'); +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, now(), null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, now(), null, null, ''); + +-- 敏感词字典 +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, now(), 1, now(), null); +-- 敏感词字典数据,需要其他类别自行添加 +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, now(), 1, now(), null); +-- 管理员权限关联自行添加 diff --git a/script/sql/update/update_1.3.0_1.3.1.sql b/script/sql/update/update_1.3.0_1.3.1.sql index 8e774e50..31bb6cce 100644 --- a/script/sql/update/update_1.3.0_1.3.1.sql +++ b/script/sql/update/update_1.3.0_1.3.1.sql @@ -12,3 +12,35 @@ UPDATE sys_menu SET menu_name = '租户应用管理新增', perms = 'system:tena UPDATE sys_menu SET menu_name = '租户应用管理修改', perms = 'system:tenantApp:edit' WHERE menu_id = 1704; UPDATE sys_menu SET menu_name = '租户应用管理删除', perms = 'system:tenantApp:remove' WHERE menu_id = 1705; UPDATE sys_menu SET menu_name = '租户应用管理导出', perms = 'system:tenantApp:export' WHERE menu_id = 1706; + +-- ---------------------------- +-- 敏感词表 +-- ---------------------------- +create table sys_sensitive_word ( + word_id bigint not null comment '敏感词id', + word varchar(255) not null comment '敏感词', + category varchar(20) not null comment '敏感词类别', + description varchar(500) null default null comment '描述', + status tinyint not null comment '启用状态 1启用 0禁用', + create_dept bigint null default null comment '创建部门', + create_by bigint null default null comment '创建者', + update_by bigint null default null comment '更新者', + update_time datetime null default null comment '更新时间', + create_time datetime not null comment '创建时间', + primary key (word_id) using btree +) engine = innodb comment = '敏感词表'; + +-- 敏感词菜单 +insert into sys_menu values ('124', '敏感词', '1', '13', 'sensitiveWord', 'system/sensitiveWord/index', 'SensitiveWord', '', 0, 1, 'C', '1', '1', 'system:sensitiveWord:list', 'book-open', null, null, 103, 1, sysdate(), 1, sysdate(), '敏感词菜单'); +insert into sys_menu values ('1710', '敏感词查询', '124', 1, '#', '', NULL, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:query', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1711', '敏感词新增', '124', 2, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:add', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1712', '敏感词修改', '124', 3, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:edit', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1713', '敏感词删除', '124', 4, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:remove', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1714', '敏感词导出', '124', 5, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:export', '#', null, null, 103, 1, sysdate(), null, null, ''); +insert into sys_menu values ('1715', '敏感词导入', '124', 6, '#', '', null, '', 0, 1, 'F', '1', '1', 'system:sensitiveWord:import', '#', null, null, 103, 1, sysdate(), null, null, ''); + +-- 敏感词字典 +insert into sys_dict_type values(17, '000000', '敏感词类别', 'sensitive_words_category', 103, 1, sysdate(), 1, sysdate(), null); +-- 敏感词字典数据,需要其他类别自行添加 +insert into sys_dict_data values(70, '000000', 99, '其他', 'other', 'sensitive_words_category', null, 'primary', null, 'N', 103, 1, sysdate(), 1, sysdate(), null); +-- 管理员权限关联自行添加 From 9498f09676c7fae2cc31e6ecb63fd1b169e7390d Mon Sep 17 00:00:00 2001 From: yixiaco <627428179@qq.com> Date: Wed, 21 Aug 2024 10:43:36 +0800 Subject: [PATCH 2/2] =?UTF-8?q?pref:=20=E6=95=8F=E6=84=9F=E8=AF=8D?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=AE=8C=E6=88=90=E5=90=8E=E6=8C=89=E9=9C=80?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/vm/java/listener.java.vm | 9 +++-- .../SysSensitiveWordImportListener.java | 15 +++++--- .../service/ISysSensitiveWordService.java | 22 ++++++++++-- .../impl/SysSensitiveWordServiceImpl.java | 34 ++++++++++++++++--- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm index ae02fd3e..d7c4f033 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/listener.java.vm @@ -35,7 +35,7 @@ public class ${ClassName}ImportListener extends AnalysisEventListener<${ClassNam private final boolean isUpdateSupport; - private int successNum = 1; + private int successNum = 0; private int failureNum = 0; private final StringBuilder successMsg = new StringBuilder(); private final StringBuilder failureMsg = new StringBuilder(); @@ -68,7 +68,7 @@ public class ${ClassName}ImportListener extends AnalysisEventListener<${ClassNam @Override public void doAfterAllAnalysed(AnalysisContext context) { - + // 导入完成 } @Override @@ -77,7 +77,10 @@ public class ${ClassName}ImportListener extends AnalysisEventListener<${ClassNam @Override public String getAnalysis() { - if (failureNum > 0) { + if (successNum > 0 && failureNum > 0) { + failureMsg.insert(0, "部分导入失败!共 " + successNum + " 条导入成功," + failureNum + " 条导入失败,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); } else { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java index 4716fc23..b6f6021a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysSensitiveWordImportListener.java @@ -27,7 +27,7 @@ public class SysSensitiveWordImportListener extends AnalysisEventListener第").append(successNum).append("行 导入成功"); } else { ValidatorUtils.validate(bo, EditGroup.class); - sysSensitiveWordService.updateByBo(bo); + sysSensitiveWordService.updateByBo(bo, false); successNum++; successMsg.append("
第").append(successNum).append("行 更新成功"); } @@ -60,7 +60,9 @@ public void invoke(SysSensitiveWordImportTemplate importTemplate, AnalysisContex @Override public void doAfterAllAnalysed(AnalysisContext context) { - + if (successNum > 0) { + sysSensitiveWordService.refreshCache(); + } } @Override @@ -69,7 +71,10 @@ public ExcelResult getExcelResult() { @Override public String getAnalysis() { - if (failureNum > 0) { + if (successNum > 0 && failureNum > 0) { + failureMsg.insert(0, "部分导入失败!共 " + successNum + " 条导入成功," + failureNum + " 条导入失败,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); } else { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java index e6fa8dab..44cf1792 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSensitiveWordService.java @@ -46,19 +46,37 @@ public interface ISysSensitiveWordService extends IService { /** * 新增敏感词 * - * @param bo 敏感词新增业务对象 + * @param bo 敏感词新增业务对象 * @return Boolean */ Boolean insertByBo(SysSensitiveWordBo bo); + /** + * 新增敏感词 + * + * @param bo 敏感词新增业务对象 + * @param refreshCache 刷新缓存 + * @return Boolean + */ + Boolean insertByBo(SysSensitiveWordBo bo, boolean refreshCache); + /** * 修改敏感词 * - * @param bo 敏感词编辑业务对象 + * @param bo 敏感词编辑业务对象 * @return Boolean */ Boolean updateByBo(SysSensitiveWordBo bo); + /** + * 修改敏感词 + * + * @param bo 敏感词编辑业务对象 + * @param refreshCache 刷新缓存 + * @return Boolean + */ + Boolean updateByBo(SysSensitiveWordBo bo, boolean refreshCache); + /** * 校验并批量删除敏感词信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java index 12f6e26d..355af5b0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveWordServiceImpl.java @@ -78,7 +78,7 @@ public List queryList(SysSensitiveWordQuery query) { } /** - * 根据新增业务对象插入敏感词 + * 新增敏感词 * * @param bo 敏感词新增业务对象 * @return Boolean @@ -86,17 +86,30 @@ public List queryList(SysSensitiveWordQuery query) { @Override @Transactional(rollbackFor = Exception.class) public Boolean insertByBo(SysSensitiveWordBo bo) { + return insertByBo(bo, true); + } + + /** + * 根据新增业务对象插入敏感词 + * + * @param bo 敏感词新增业务对象 + * @param refreshCache 刷新缓存 + * @return Boolean + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(SysSensitiveWordBo bo, boolean refreshCache) { saveValid(bo); SysSensitiveWord add = MapstructUtils.convert(bo, SysSensitiveWord.class); boolean save = save(add); - if (save) { + if (save && refreshCache) { refreshCache(); } return save; } /** - * 根据编辑业务对象修改敏感词 + * 修改敏感词 * * @param bo 敏感词编辑业务对象 * @return Boolean @@ -104,11 +117,24 @@ public Boolean insertByBo(SysSensitiveWordBo bo) { @Override @Transactional(rollbackFor = Exception.class) public Boolean updateByBo(SysSensitiveWordBo bo) { + return updateByBo(bo, true); + } + + /** + * 根据编辑业务对象修改敏感词 + * + * @param bo 敏感词编辑业务对象 + * @param refreshCache 刷新缓存 + * @return Boolean + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(SysSensitiveWordBo bo, boolean refreshCache) { saveValid(bo); SysSensitiveWord word = getById(bo.getWordId()); SysSensitiveWord update = MapstructUtils.convert(bo, SysSensitiveWord.class); boolean b = updateById(update); - if (b) { + if (b && refreshCache) { // 只有改变以下数据的值才刷新缓存 if (!Objects.equals(word.getWord(), bo.getWord()) || !Objects.equals(word.getCategory(), bo.getCategory())