整理架构,初次提交

This commit is contained in:
马宝龙
2026-06-24 19:24:47 +08:00
parent a4c719f9a5
commit ac7e4e9088
338 changed files with 147 additions and 29066 deletions

View File

@@ -1,241 +0,0 @@
package com.ruoyi.cms.util;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.cms.domain.BussinessDictData;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import java.util.Collection;
import java.util.List;
/**
* 字典工具类
*
* @author ruoyi
*/
public class DictUtils
{
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/**
* 设置字典缓存
*
* @param key 参数键
* @param dictDatas 字典数据列表
*/
public static void setDictCache(String key, List<BussinessDictData> dictDatas)
{
SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
}
/**
* 获取字典缓存
*
* @param key 参数键
* @return dictDatas 字典数据列表
*/
public static List<BussinessDictData> getDictCache(String key)
{
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(arrayCache))
{
return arrayCache.toList(BussinessDictData.class);
}
return null;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue)
{
if (StringUtils.isEmpty(dictValue))
{
return StringUtils.EMPTY;
}
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel)
{
if (StringUtils.isEmpty(dictLabel))
{
return StringUtils.EMPTY;
}
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<BussinessDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
if (StringUtils.containsAny(separator, dictValue))
{
for (BussinessDictData dict : datas)
{
for (String value : dictValue.split(separator))
{
if (value.equals(dict.getDictValue()))
{
propertyString.append(dict.getDictLabel()).append(separator);
break;
}
}
}
}
else
{
for (BussinessDictData dict : datas)
{
if (dictValue.equals(dict.getDictValue()))
{
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<BussinessDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
if (StringUtils.containsAny(separator, dictLabel))
{
for (BussinessDictData dict : datas)
{
for (String label : dictLabel.split(separator))
{
if (label.equals(dict.getDictLabel()))
{
propertyString.append(dict.getDictValue()).append(separator);
break;
}
}
}
}
else
{
for (BussinessDictData dict : datas)
{
if (dictLabel.equals(dict.getDictLabel()))
{
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型获取字典所有值
*
* @param dictType 字典类型
* @return 字典值
*/
public static String getDictValues(String dictType)
{
StringBuilder propertyString = new StringBuilder();
List<BussinessDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
for (BussinessDictData dict : datas)
{
propertyString.append(dict.getDictValue()).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
/**
* 根据字典类型获取字典所有标签
*
* @param dictType 字典类型
* @return 字典值
*/
public static String getDictLabels(String dictType)
{
StringBuilder propertyString = new StringBuilder();
List<BussinessDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
for (BussinessDictData dict : datas)
{
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
/**
* 删除指定字典缓存
*
* @param key 字典键
*/
public static void removeDictCache(String key)
{
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
}
/**
* 清空字典缓存
*/
public static void clearDictCache()
{
Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.BUSSINESS_DICT_KEY + "*");
SpringUtils.getBean(RedisCache.class).deleteObject(keys);
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
public static String getCacheKey(String configKey)
{
return CacheConstants.BUSSINESS_DICT_KEY + configKey;
}
}

View File

@@ -1,107 +0,0 @@
package com.ruoyi.cms.util.notice;
import com.ruoyi.cms.domain.EmployeeConfirm;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.Notice;
import com.ruoyi.common.core.domain.entity.AppUser;
import java.util.ArrayList;
import java.util.List;
public class NoticeUtils {
/**
* 消息已读
*/
public static final String NOTICE_YD="1";
/**
* 消息未读
*/
public static final String NOTICE_WD="0";
public static final String NOTICE_REMARK="notice_bar";
public static final String NOTICE_COMENT_ZH="衷心祝贺您通过";
public static final String NOTICE_COMENT_LY="全流程招聘考核,正式被录用,岗位为【";
public static final String NOTICE_COMENT_FF="";
public static final String NOTICE_TYPE_LY="录用通知";
public static final String NOTICE_TYPE_GWSX="您收藏的公司有新的职位发布";
public static final String NOTICE_TYPE_XTLX="1";
public static final String NOTICE_TYPE_SXLX="2";
public static final String NOTICE_TYPE_MSLX="4";
/**
* 拼装岗位
*/
public static final String JOB_NEW="刚刚发布职位";
public static final String JOB_XZ="薪资";
public static final String JOB_KKB="快去看看吧";
public static final String JOB_QFH="";
public static final String JOB_HFH="";
public static final String JOB_ZJG="-";
public static final String JOB_DH=",";
/**
* 录用通知
* @param companyName
* @param jobName
* @return
*/
public static String appUserLytz(String companyName,String jobName){
return NoticeUtils.NOTICE_COMENT_ZH+companyName+NoticeUtils.NOTICE_COMENT_LY+jobName+NoticeUtils.NOTICE_COMENT_FF;
}
/**
* “海尔集团”刚刚发布职位“产品性能分析工程师”薪资“1.5-2.5k,快去看看吧
* @param job
* @return
*/
public static String appUserGwsx(Job job){
return JOB_QFH+job.getCompanyName()+JOB_HFH+JOB_NEW+JOB_QFH+job.getJobTitle()+JOB_HFH+JOB_XZ+job.getMinSalary()+JOB_ZJG+job.getMaxSalary()+JOB_DH+JOB_KKB;
}
/**
* 审核确认界面拼装消息
*/
public static Notice createLytzNotice(EmployeeConfirm employeeConfirm, Job job) {
Notice notice = new Notice();
notice.setUserId(employeeConfirm.getUserId());
notice.setBussinessId(job.getJobId());
notice.setIsRead(NoticeUtils.NOTICE_WD);
notice.setTitle(NoticeUtils.NOTICE_TYPE_LY);
notice.setSubTitle(NoticeUtils.NOTICE_TYPE_LY);
notice.setNoticeType(NoticeUtils.NOTICE_TYPE_XTLX);
notice.setRemark(NoticeUtils.NOTICE_REMARK);
String content = appUserLytz(job.getCompanyName(), job.getJobTitle());
notice.setNoticeContent(content);
return notice;
}
/**
* 岗位上新
*/
public static List<Notice> createGwsxNotice(List<AppUser> appUserList, Job job) {
List<Notice> add=new ArrayList<>();
appUserList.forEach(appUser -> {
String content = appUserGwsx(job);
Notice notice = new Notice();
notice.setUserId(appUser.getUserId());
notice.setBussinessId(job.getJobId());
notice.setIsRead(NoticeUtils.NOTICE_WD);
notice.setTitle(NoticeUtils.NOTICE_TYPE_GWSX);
notice.setSubTitle(content);
notice.setNoticeType(NoticeUtils.NOTICE_TYPE_SXLX);
notice.setRemark(NoticeUtils.NOTICE_REMARK);
notice.setNoticeContent(content);
add.add(notice);
});
return add;
}
}

View File

@@ -1,105 +0,0 @@
package com.ruoyi.cms.util.sensitiveWord;
import com.ruoyi.cms.domain.SensitiveWordData;
import com.ruoyi.cms.mapper.SensitiveWordDataMapper;
import com.ruoyi.common.core.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component
public class SensitiveWordChecker {
@Autowired
private SensitiveWordDataMapper sensitiveWordDataMapper;
@Autowired
private SensitiveWordTrie trie; // 注入前缀树
// 缓存键常量
private static final String SENSITIVE_WORD_CACHE_KEY = "sensitive:words";
@Autowired
private RedisCache redisCache;
/**
* 项目启动时初始化敏感词库到前缀树
*/
@PostConstruct
public void init() {
List<String> sensitiveWords = getSensitiveWordsFromCache();
if (sensitiveWords.isEmpty()) {
// 缓存未命中,从数据库加载
sensitiveWords = loadSensitiveWordsFromDbAndCache();
}
// 初始化前缀树
trie.batchAddWords(sensitiveWords);
}
/**
* 检测文本中的敏感词
* @param text 待检测文本如job.getDescription()
* @return 敏感词列表(空列表表示无敏感词)
*/
public List<String> checkSensitiveWords(String text) {
return trie.findAllSensitiveWords(text);
}
/**
* 从缓存获取敏感词列表
*/
@Cacheable(value = SENSITIVE_WORD_CACHE_KEY)
public List<String> getSensitiveWordsFromCache() {
// 从Redis获取
Object cachedWords = redisCache.getCacheObject(SENSITIVE_WORD_CACHE_KEY);
if (cachedWords instanceof List<?>) {
return ((List<?>) cachedWords).stream()
.filter(obj -> obj instanceof String)
.map(obj -> (String) obj)
.collect(Collectors.toList());
}
return Collections.emptyList();
}
/**
* 从数据库加载敏感词并更新缓存
*/
public List<String> loadSensitiveWordsFromDbAndCache() {
List<SensitiveWordData> wordList = sensitiveWordDataMapper.selectSensitiveworddataList(new SensitiveWordData());
List<String> sensitiveWords = wordList.stream()
.map(SensitiveWordData::getSensitiveWord)
.collect(Collectors.toList());
// 缓存有效期设置为24小时可根据实际需求调整
redisCache.setCacheObject(SENSITIVE_WORD_CACHE_KEY, sensitiveWords, 24, TimeUnit.HOURS);
return sensitiveWords;
}
/**
* 敏感词更新时清除缓存(需在敏感词管理服务中调用)
*/
@CacheEvict(value = SENSITIVE_WORD_CACHE_KEY, allEntries = true)
public void clearSensitiveWordCache() {
// 清除缓存后可重新加载
loadSensitiveWordsFromDbAndCache();
// 重新初始化前缀树
trie.clear();
init();
}
/**
* 新增/修改敏感词后更新缓存和前缀树
*/
public void updateCacheAfterModify() {
// 1. 清除旧缓存
redisCache.deleteObject(SENSITIVE_WORD_CACHE_KEY);
// 2. 从数据库重新加载最新数据并更新缓存
List<String> latestWords = loadSensitiveWordsFromDbAndCache();
// 3. 重建前缀树
trie.clear();
trie.batchAddWords(latestWords);
}
}

View File

@@ -1,97 +0,0 @@
package com.ruoyi.cms.util.sensitiveWord;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* 前缀树Trie树节点
*/
/**
* 前缀树Trie树工具类
*/
@Component
public class SensitiveWordTrie {
// 根节点(无实际字符)
private final TrieNode root = new TrieNode();
/**
* 向前缀树中添加敏感词
*/
public void addWord(String word) {
if (word == null || word.isEmpty()) {
return;
}
TrieNode current = root;
for (char c : word.toCharArray()) {
// 若子节点中不存在该字符,则创建新节点
current.getChildren().putIfAbsent(c, new TrieNode());
// 移动到子节点
current = current.getChildren().get(c);
}
// 标记当前节点为敏感词结尾
current.setEnd(true);
}
/**
* 检测文本中所有敏感词(去重)
* @param text 待检测文本
* @return 敏感词列表
*/
public List<String> findAllSensitiveWords(String text) {
if (text == null || text.isEmpty()) {
return new ArrayList<>();
}
Set<String> sensitiveWords = new HashSet<>();
TrieNode current = root;
StringBuilder currentWord = new StringBuilder(); // 记录当前匹配的字符
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
// 若当前字符不在子节点中,重置匹配状态
if (!current.getChildren().containsKey(c)) {
current = root; // 回到根节点
currentWord.setLength(0); // 清空当前匹配的字符
continue;
}
// 匹配到字符,移动到子节点
current = current.getChildren().get(c);
currentWord.append(c);
// 若当前节点是敏感词结尾,记录该敏感词
if (current.isEnd()) {
sensitiveWords.add(currentWord.toString());
}
}
return new ArrayList<>(sensitiveWords);
}
/**
* 批量添加敏感词到前缀树
* @param words 敏感词列表
*/
public void batchAddWords(List<String> words) {
if (words == null || words.isEmpty()) {
return;
}
// 批量处理比循环单次添加更高效,减少重复判断
for (String word : words) {
addWord(word);
}
}
/**
* 清空前缀树所有节点
*/
public void clear() {
// 清空根节点的子节点映射,达到清空整个前缀树的效果
root.getChildren().clear();
}
}

View File

@@ -1,23 +0,0 @@
package com.ruoyi.cms.util.sensitiveWord;
import java.util.HashMap;
import java.util.Map;
class TrieNode {
// 子节点key=字符value=子节点
private final Map<Character, TrieNode> children = new HashMap<>();
// 标记当前节点是否为敏感词的结尾
private boolean isEnd = false;
public Map<Character, TrieNode> getChildren() {
return children;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean end) {
isEnd = end;
}
}