mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-24 07:19:46 +08:00
发布 v2.5.0
This commit is contained in:
@ -2,7 +2,7 @@ package com.ruoyi.common.constant;
|
||||
|
||||
/**
|
||||
* 用户常量信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserConstants
|
||||
@ -57,6 +57,9 @@ public class UserConstants
|
||||
/** ParentView组件标识 */
|
||||
public final static String PARENT_VIEW = "ParentView";
|
||||
|
||||
/** InnerLink组件标识 */
|
||||
public final static String INNER_LINK = "InnerLink";
|
||||
|
||||
/** 校验返回结果码 */
|
||||
public final static String UNIQUE = "0";
|
||||
public final static String NOT_UNIQUE = "1";
|
||||
|
@ -148,6 +148,10 @@ public class SysUser implements Serializable
|
||||
@TableField(exist = false)
|
||||
private Long[] postIds;
|
||||
|
||||
/** 角色ID */
|
||||
@TableField(exist = false)
|
||||
private Long roleId;
|
||||
|
||||
public SysUser(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
|
@ -15,6 +15,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
/**
|
||||
* mybatis-redis 二级缓存
|
||||
*
|
||||
* 使用方法 配置文件开启 mybatis-plus 二级缓存
|
||||
* 在 XxxMapper.java 类上添加注解 @CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -1,13 +1,17 @@
|
||||
package com.ruoyi.common.core.mybatisplus.methods;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.KeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
|
||||
/**
|
||||
* 单sql批量插入
|
||||
*
|
||||
@ -20,9 +24,28 @@ public class InsertAll extends AbstractMethod {
|
||||
final String sql = "<script>insert into %s %s values %s</script>";
|
||||
final String fieldSql = prepareFieldSql(tableInfo);
|
||||
final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
|
||||
KeyGenerator keyGenerator = new NoKeyGenerator();
|
||||
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
|
||||
String keyProperty = null;
|
||||
String keyColumn = null;
|
||||
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
|
||||
if (StrUtil.isNotBlank(tableInfo.getKeyProperty())) {
|
||||
if (tableInfo.getIdType() == IdType.AUTO) {
|
||||
/** 自增主键 */
|
||||
keyGenerator = new Jdbc3KeyGenerator();
|
||||
keyProperty = tableInfo.getKeyProperty();
|
||||
keyColumn = tableInfo.getKeyColumn();
|
||||
} else {
|
||||
if (null != tableInfo.getKeySequence()) {
|
||||
keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
|
||||
keyProperty = tableInfo.getKeyProperty();
|
||||
keyColumn = tableInfo.getKeyColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
|
||||
return this.addInsertMappedStatement(mapperClass, modelClass, "insertAll", sqlSource, new NoKeyGenerator(), null, null);
|
||||
return this.addInsertMappedStatement(mapperClass, modelClass, "insertAll", sqlSource, keyGenerator, keyProperty, keyColumn);
|
||||
}
|
||||
|
||||
private String prepareFieldSql(TableInfo tableInfo) {
|
||||
|
@ -205,9 +205,9 @@ public class RedisCache {
|
||||
* @param hKeys Hash键集合
|
||||
* @return Hash对象集合
|
||||
*/
|
||||
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
|
||||
RListMultimap rListMultimap = redissonClient.getListMultimap(key);
|
||||
return rListMultimap.getAll(hKeys);
|
||||
public <K,V> Map<K,V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
|
||||
RMap<K,V> rMap = redissonClient.getMap(key);
|
||||
return rMap.getAll(hKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +88,7 @@ public class DictUtils
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StrUtil.containsAny(separator, dictValue) && CollUtil.isNotEmpty(datas))
|
||||
if (StrUtil.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
@ -128,7 +128,7 @@ public class DictUtils
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StrUtil.containsAny(separator, dictLabel) && CollUtil.isNotEmpty(datas))
|
||||
if (StrUtil.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
|
28
ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
Normal file
28
ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
|
||||
/**
|
||||
* 字符串工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/** 空字符串 */
|
||||
private static final String NULLSTR = "";
|
||||
|
||||
/** 下划线 */
|
||||
private static final char SEPARATOR = '_';
|
||||
|
||||
/**
|
||||
* 是否为http(s)://开头
|
||||
*
|
||||
* @param link 链接
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean ishttp(String link) {
|
||||
return StrUtil.startWithAny(link, Constants.HTTP, Constants.HTTPS);
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Excel相关处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ExcelUtil<T>
|
||||
@ -88,12 +88,12 @@ public class ExcelUtil<T>
|
||||
* 统计列表
|
||||
*/
|
||||
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
|
||||
|
||||
|
||||
/**
|
||||
* 数字格式
|
||||
*/
|
||||
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
|
||||
|
||||
|
||||
/**
|
||||
* 实体对象
|
||||
*/
|
||||
@ -119,7 +119,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 对excel表单默认第一个索引名转换成list
|
||||
*
|
||||
*
|
||||
* @param is 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
@ -130,7 +130,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 对excel表单指定表格索引名转换成list
|
||||
*
|
||||
*
|
||||
* @param sheetName 表格索引名
|
||||
* @param is 输入流
|
||||
* @return 转换后集合
|
||||
@ -298,7 +298,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
*
|
||||
* @param list 导出数据集合
|
||||
* @param sheetName 工作表的名称
|
||||
* @return 结果
|
||||
@ -311,7 +311,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
*
|
||||
* @param sheetName 工作表的名称
|
||||
* @return 结果
|
||||
*/
|
||||
@ -323,7 +323,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult exportExcel()
|
||||
@ -391,7 +391,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 填充excel数据
|
||||
*
|
||||
*
|
||||
* @param index 序号
|
||||
* @param row 单元格行
|
||||
*/
|
||||
@ -418,7 +418,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 创建表格样式
|
||||
*
|
||||
*
|
||||
* @param wb 工作薄对象
|
||||
* @return 样式列表
|
||||
*/
|
||||
@ -456,7 +456,7 @@ public class ExcelUtil<T>
|
||||
headerFont.setColor(IndexedColors.WHITE.getIndex());
|
||||
style.setFont(headerFont);
|
||||
styles.put("header", style);
|
||||
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
@ -500,7 +500,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 设置单元格信息
|
||||
*
|
||||
*
|
||||
* @param value 单元格值
|
||||
* @param attr 注解相关
|
||||
* @param cell 单元格信息
|
||||
@ -531,7 +531,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取画布
|
||||
*/
|
||||
@ -646,7 +646,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 设置 POI XSSFSheet 单元格提示
|
||||
*
|
||||
*
|
||||
* @param sheet 表单
|
||||
* @param promptTitle 提示标题
|
||||
* @param promptContent 提示内容
|
||||
@ -669,7 +669,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 设置某些列的值只能输入预制的数据,显示下拉框.
|
||||
*
|
||||
*
|
||||
* @param sheet 要设置的sheet.
|
||||
* @param textlist 下拉框显示的内容
|
||||
* @param firstRow 开始行
|
||||
@ -703,7 +703,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 解析导出值 0=男,1=女,2=未知
|
||||
*
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
@ -716,7 +716,7 @@ public class ExcelUtil<T>
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (StrUtil.containsAny(separator, propertyValue))
|
||||
if (StrUtil.containsAny(propertyValue, separator))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
@ -740,7 +740,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 反向解析值 男=0,女=1,未知=2
|
||||
*
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
@ -753,7 +753,7 @@ public class ExcelUtil<T>
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (StrUtil.containsAny(separator, propertyValue))
|
||||
if (StrUtil.containsAny(propertyValue, separator))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
@ -774,10 +774,10 @@ public class ExcelUtil<T>
|
||||
}
|
||||
return StrUtil.strip(propertyString.toString(), null,separator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析字典值
|
||||
*
|
||||
*
|
||||
* @param dictValue 字典值
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
@ -790,7 +790,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 反向解析值字典值
|
||||
*
|
||||
*
|
||||
* @param dictLabel 字典标签
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
@ -800,7 +800,7 @@ public class ExcelUtil<T>
|
||||
{
|
||||
return DictUtils.getDictValue(dictType, dictLabel, separator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 合计统计信息
|
||||
*/
|
||||
@ -837,7 +837,7 @@ public class ExcelUtil<T>
|
||||
cell = row.createCell(0);
|
||||
cell.setCellStyle(styles.get("total"));
|
||||
cell.setCellValue("合计");
|
||||
|
||||
|
||||
for (Integer key : keys)
|
||||
{
|
||||
cell = row.createCell(key);
|
||||
@ -859,7 +859,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*
|
||||
*
|
||||
* @param filename 文件名称
|
||||
*/
|
||||
public String getAbsoluteFile(String filename)
|
||||
@ -875,7 +875,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 获取bean中的属性值
|
||||
*
|
||||
*
|
||||
* @param vo 实体对象
|
||||
* @param field 字段
|
||||
* @param excel 注解
|
||||
@ -906,7 +906,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 以类的属性的get方法方法形式获取值
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @param name
|
||||
* @return value
|
||||
@ -955,7 +955,7 @@ public class ExcelUtil<T>
|
||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||
this.maxHeight = getRowHeight();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据注解获取最大行高
|
||||
*/
|
||||
@ -991,7 +991,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 创建工作表
|
||||
*
|
||||
*
|
||||
* @param sheetNo sheet数量
|
||||
* @param index 序号
|
||||
*/
|
||||
@ -1012,7 +1012,7 @@ public class ExcelUtil<T>
|
||||
|
||||
/**
|
||||
* 获取单元格值
|
||||
*
|
||||
*
|
||||
* @param row 获取的行
|
||||
* @param column 获取单元格列号
|
||||
* @return 单元格值
|
||||
@ -1069,4 +1069,4 @@ public class ExcelUtil<T>
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
package com.ruoyi.demo.controller;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* spring-cache 演示案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
// 类级别 缓存统一配置
|
||||
//@CacheConfig(cacheNames = "redissonCacheMap")
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@RestController
|
||||
@RequestMapping("/demo/cache")
|
||||
public class RedisCacheController {
|
||||
|
||||
/**
|
||||
* 测试 @Cacheable
|
||||
*
|
||||
* 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
|
||||
* 下一次调用该方法前,会去检查是否缓存中已经有值
|
||||
* 如果有就直接返回,不调用方法
|
||||
* 如果没有,就调用方法,然后把结果缓存起来
|
||||
* 这个注解「一般用在查询方法上」
|
||||
*
|
||||
* cacheNames 为配置文件内 groupId
|
||||
*/
|
||||
@Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
|
||||
@GetMapping("/test1")
|
||||
public AjaxResult<String> test1(String key, String value){
|
||||
return AjaxResult.success("操作成功", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 @CachePut
|
||||
*
|
||||
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
|
||||
* 它「通常用在新增方法上」
|
||||
*
|
||||
* cacheNames 为 配置文件内 groupId
|
||||
*/
|
||||
@CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
|
||||
@GetMapping("/test2")
|
||||
public AjaxResult<String> test2(String key, String value){
|
||||
return AjaxResult.success("操作成功", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 @CacheEvict
|
||||
*
|
||||
* 使用了CacheEvict注解的方法,会清空指定缓存
|
||||
* 「一般用在更新或者删除的方法上」
|
||||
*
|
||||
* cacheNames 为 配置文件内 groupId
|
||||
*/
|
||||
@CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
|
||||
@GetMapping("/test3")
|
||||
public AjaxResult<String> test3(String key, String value){
|
||||
return AjaxResult.success("操作成功", value);
|
||||
}
|
||||
|
||||
}
|
@ -7,7 +7,10 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* feign测试fallback
|
||||
* 自定义封装结构体熔断
|
||||
* 需重写解码器 根据自定义实体 自行解析熔断
|
||||
*
|
||||
* @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()}
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
|
@ -1,63 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import de.codecentric.boot.admin.server.config.EnableAdminServer;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties;
|
||||
import org.springframework.boot.task.TaskExecutorBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.thymeleaf.dialect.IDialect;
|
||||
import org.thymeleaf.spring5.ISpringTemplateEngine;
|
||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* springboot-admin server配置类
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAdminServer
|
||||
public class AdminServerConfig {
|
||||
|
||||
@Lazy
|
||||
@Bean(name = TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
|
||||
@ConditionalOnMissingBean(Executor.class)
|
||||
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决 admin 与 项目 页面的交叉引用 将 admin 的路由放到最后
|
||||
* @param properties
|
||||
* @param templateResolvers
|
||||
* @param dialects
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ISpringTemplateEngine.class)
|
||||
SpringTemplateEngine templateEngine(ThymeleafProperties properties,
|
||||
ObjectProvider<ITemplateResolver> templateResolvers, ObjectProvider<IDialect> dialects) {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
engine.setEnableSpringELCompiler(properties.isEnableSpringElCompiler());
|
||||
engine.setRenderHiddenMarkersBeforeCheckboxes(properties.isRenderHiddenMarkersBeforeCheckboxes());
|
||||
templateResolvers.orderedStream().forEach(engine::addTemplateResolver);
|
||||
dialects.orderedStream().forEach(engine::addDialect);
|
||||
Set<ITemplateResolver> templateResolvers1 = engine.getTemplateResolvers();
|
||||
templateResolvers1 = templateResolvers1.stream()
|
||||
.sorted(Comparator.comparing(ITemplateResolver::getOrder))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
engine.setTemplateResolvers(templateResolvers1);
|
||||
return engine;
|
||||
}
|
||||
}
|
@ -54,4 +54,40 @@ public class FeignConfig {
|
||||
return new Retryer.Default();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 自定义异常解码器
|
||||
// * 用于自定义返回体异常熔断
|
||||
// */
|
||||
// @Bean
|
||||
// public ErrorDecoder errorDecoder() {
|
||||
// return new CustomErrorDecoder();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 自定义返回体解码器
|
||||
// */
|
||||
// @Slf4j
|
||||
// public static class CustomErrorDecoder implements ErrorDecoder {
|
||||
//
|
||||
// @Override
|
||||
// public Exception decode(String methodKey, Response response) {
|
||||
// Exception exception = null;
|
||||
// try {
|
||||
// // 获取原始的返回内容
|
||||
// String json = JsonUtils.toJsonString(response.body().asReader(StandardCharsets.UTF_8));
|
||||
// exception = new RuntimeException(json);
|
||||
// // 将返回内容反序列化为Result,这里应根据自身项目作修改
|
||||
// AjaxResult result = JsonUtils.parseObject(json, AjaxResult.class);
|
||||
// // 业务异常抛出简单的 RuntimeException,保留原来错误信息
|
||||
// if (result.getCode() != 200) {
|
||||
// exception = new RuntimeException(result.getMsg());
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// log.error(e.getMessage(), e);
|
||||
// }
|
||||
// return exception;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -78,8 +79,13 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||
*/
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedissonClient redissonClient) {
|
||||
List<RedissonProperties.CacheGroup> cacheGroup = redissonProperties.getCacheGroup();
|
||||
Map<String, CacheConfig> config = new HashMap<>();
|
||||
config.put("redissonCacheMap", new CacheConfig(30*60*1000, 10*60*1000));
|
||||
for (RedissonProperties.CacheGroup group : cacheGroup) {
|
||||
CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
|
||||
cacheConfig.setMaxSize(group.getMaxSize());
|
||||
config.put(group.getGroupId(), cacheConfig);
|
||||
}
|
||||
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package com.ruoyi.framework.config;
|
||||
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
import de.codecentric.boot.admin.server.config.AdminServerProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@ -57,9 +56,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
@Autowired
|
||||
private CorsFilter corsFilter;
|
||||
|
||||
@Autowired
|
||||
private AdminServerProperties adminServerProperties;
|
||||
|
||||
/**
|
||||
* 解决 无法直接注入 AuthenticationManager
|
||||
*
|
||||
@ -104,12 +100,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
.antMatchers("/login", "/captchaImage").anonymous()
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/",
|
||||
"/*.html",
|
||||
"/**/*.html",
|
||||
"/**/*.css",
|
||||
"/**/*.js"
|
||||
"/**/*.js",
|
||||
"/profile/**"
|
||||
).permitAll()
|
||||
.antMatchers("/profile/**").anonymous()
|
||||
.antMatchers("/common/download**").anonymous()
|
||||
.antMatchers("/common/download/resource**").anonymous()
|
||||
.antMatchers("/doc.html").anonymous()
|
||||
@ -117,9 +114,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
.antMatchers("/webjars/**").anonymous()
|
||||
.antMatchers("/*/api-docs").anonymous()
|
||||
.antMatchers("/druid/**").anonymous()
|
||||
// Spring Boot Admin Server 的安全配置
|
||||
.antMatchers(adminServerProperties.getContextPath()).anonymous()
|
||||
.antMatchers(adminServerProperties.getContextPath() + "/**").anonymous()
|
||||
// Spring Boot Actuator 的安全配置
|
||||
.antMatchers("/actuator").anonymous()
|
||||
.antMatchers("/actuator/**").anonymous()
|
||||
|
@ -2,11 +2,12 @@ package com.ruoyi.framework.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.redisson.client.codec.Codec;
|
||||
import org.redisson.config.TransportMode;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Redisson 配置属性
|
||||
*
|
||||
@ -37,6 +38,11 @@ public class RedissonProperties {
|
||||
*/
|
||||
private SingleServerConfig singleServerConfig;
|
||||
|
||||
/**
|
||||
* 缓存组
|
||||
*/
|
||||
private List<CacheGroup> cacheGroup;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class SingleServerConfig {
|
||||
@ -98,4 +104,30 @@ public class RedissonProperties {
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class CacheGroup {
|
||||
|
||||
/**
|
||||
* 组id
|
||||
*/
|
||||
private String groupId;
|
||||
|
||||
/**
|
||||
* 组过期时间
|
||||
*/
|
||||
private long ttl;
|
||||
|
||||
/**
|
||||
* 组最大空闲时间
|
||||
*/
|
||||
private long maxIdleTime;
|
||||
|
||||
/**
|
||||
* 组最大长度
|
||||
*/
|
||||
private int maxSize;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.ruoyi.framework.mybatisplus;
|
||||
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.ruoyi.common.exception.CustomException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
|
||||
@ -8,6 +10,7 @@ import java.util.Date;
|
||||
|
||||
/**
|
||||
* MP注入处理器
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2021/4/25
|
||||
*/
|
||||
@ -15,30 +18,38 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
//根据属性名字设置要填充的值
|
||||
if (metaObject.hasGetter("createTime")) {
|
||||
if (metaObject.getValue("createTime") == null) {
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
try {
|
||||
//根据属性名字设置要填充的值
|
||||
if (metaObject.hasGetter("createTime")) {
|
||||
if (metaObject.getValue("createTime") == null) {
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (metaObject.hasGetter("createBy")) {
|
||||
if (metaObject.getValue("createBy") == null) {
|
||||
this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject);
|
||||
if (metaObject.hasGetter("createBy")) {
|
||||
if (metaObject.getValue("createBy") == null) {
|
||||
this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
if (metaObject.hasGetter("updateBy")) {
|
||||
if (metaObject.getValue("updateBy") == null) {
|
||||
this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject);
|
||||
try {
|
||||
if (metaObject.hasGetter("updateBy")) {
|
||||
if (metaObject.getValue("updateBy") == null) {
|
||||
this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (metaObject.hasGetter("updateTime")) {
|
||||
if (metaObject.getValue("updateTime") == null) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
if (metaObject.hasGetter("updateTime")) {
|
||||
if (metaObject.getValue("updateTime") == null) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,9 +182,9 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
|
||||
List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
|
||||
for (GenTableColumn column : genTableColumns) {
|
||||
GenUtils.initColumnField(column, table);
|
||||
genTableColumnMapper.insert(column);
|
||||
}
|
||||
}
|
||||
genTableColumnMapper.insertAll(genTableColumns);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CustomException("导入失败:" + e.getMessage());
|
||||
@ -258,7 +258,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
|
||||
// 获取模板列表
|
||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
||||
for (String template : templates) {
|
||||
if (!StrUtil.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) {
|
||||
if (!StrUtil.containsAny("sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm", template)) {
|
||||
// 渲染模板
|
||||
StringWriter sw = new StringWriter();
|
||||
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
|
||||
@ -290,9 +290,9 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
|
||||
dbTableColumns.forEach(column -> {
|
||||
if (!tableColumnNames.contains(column.getColumnName())) {
|
||||
GenUtils.initColumnField(column, table);
|
||||
genTableColumnMapper.insert(column);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
genTableColumnMapper.insertAll(tableColumns);
|
||||
|
||||
List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(delColumns)) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.ruoyi.system.domain.vo;
|
||||
|
||||
import lombok.*;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
@ -28,6 +30,11 @@ public class MetaVo {
|
||||
*/
|
||||
private boolean noCache;
|
||||
|
||||
/**
|
||||
* 内链地址(http(s)://开头)
|
||||
*/
|
||||
private String link;
|
||||
|
||||
public MetaVo(String title, String icon) {
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
@ -39,4 +46,19 @@ public class MetaVo {
|
||||
this.noCache = noCache;
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon, String link) {
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon, boolean noCache, String link) {
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.noCache = noCache;
|
||||
if (StringUtils.ishttp(link)) {
|
||||
this.link = link;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,22 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser> {
|
||||
*/
|
||||
public List<SysUser> selectUserList(SysUser sysUser);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询未已配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public Page<SysUser> selectAllocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询未分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public Page<SysUser> selectUnallocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user);
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户
|
||||
*
|
||||
|
@ -3,6 +3,8 @@ package com.ruoyi.system.service;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.system.domain.SysUserRole;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -26,7 +28,15 @@ public interface ISysRoleService extends IServicePlus<SysRole> {
|
||||
public List<SysRole> selectRoleList(SysRole role);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色
|
||||
* 根据用户ID查询角色列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 角色列表
|
||||
*/
|
||||
public List<SysRole> selectRolesByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色权限
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 权限列表
|
||||
@ -134,4 +144,30 @@ public interface ISysRoleService extends IServicePlus<SysRole> {
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleByIds(Long[] roleIds);
|
||||
|
||||
/**
|
||||
* 取消授权用户角色
|
||||
*
|
||||
* @param userRole 用户和角色关联信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAuthUser(SysUserRole userRole);
|
||||
|
||||
/**
|
||||
* 批量取消授权用户角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param userIds 需要取消授权的用户数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAuthUsers(Long roleId, Long[] userIds);
|
||||
|
||||
/**
|
||||
* 批量选择授权用户角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param userIds 需要删除的用户数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertAuthUsers(Long roleId, Long[] userIds);
|
||||
}
|
||||
|
@ -24,6 +24,22 @@ public interface ISysUserService extends IServicePlus<SysUser> {
|
||||
*/
|
||||
public List<SysUser> selectUserList(SysUser user);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询已分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public TableDataInfo<SysUser> selectAllocatedList(SysUser user);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询未分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public TableDataInfo<SysUser> selectUnallocatedList(SysUser user);
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户
|
||||
*
|
||||
@ -103,6 +119,14 @@ public interface ISysUserService extends IServicePlus<SysUser> {
|
||||
*/
|
||||
public int updateUser(SysUser user);
|
||||
|
||||
/**
|
||||
* 用户授权角色
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param roleIds 角色组
|
||||
*/
|
||||
public void insertUserAuth(Long userId, Long[] roleIds);
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
*
|
||||
@ -123,7 +147,7 @@ public interface ISysUserService extends IServicePlus<SysUser> {
|
||||
* 修改用户头像
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @param avatar 头像地址
|
||||
* @param avatar 头像地址
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean updateUserAvatar(String userName, String avatar);
|
||||
@ -164,9 +188,9 @@ public interface ISysUserService extends IServicePlus<SysUser> {
|
||||
/**
|
||||
* 导入用户数据
|
||||
*
|
||||
* @param userList 用户数据列表
|
||||
* @param userList 用户数据列表
|
||||
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
|
||||
* @param operName 操作用户
|
||||
* @param operName 操作用户
|
||||
* @return 结果
|
||||
*/
|
||||
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
|
||||
|
@ -3,6 +3,7 @@ package com.ruoyi.system.service.impl;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.domain.TreeSelect;
|
||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||
@ -10,6 +11,7 @@ import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.domain.SysRoleMenu;
|
||||
import com.ruoyi.system.domain.vo.MetaVo;
|
||||
import com.ruoyi.system.domain.vo.RouterVo;
|
||||
@ -135,7 +137,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
router.setName(getRouteName(menu));
|
||||
router.setPath(getRouterPath(menu));
|
||||
router.setComponent(getComponent(menu));
|
||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache())));
|
||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache()), menu.getPath()));
|
||||
List<SysMenu> cMenus = menu.getChildren();
|
||||
if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
|
||||
router.setAlwaysShow(true);
|
||||
@ -148,7 +150,19 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
children.setPath(menu.getPath());
|
||||
children.setComponent(menu.getComponent());
|
||||
children.setName(StrUtil.upperFirst(menu.getPath()));
|
||||
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache())));
|
||||
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache()), menu.getPath()));
|
||||
childrenList.add(children);
|
||||
router.setChildren(childrenList);
|
||||
} else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
|
||||
router.setMeta(null);
|
||||
router.setPath("/inner");
|
||||
List<RouterVo> childrenList = new ArrayList<RouterVo>();
|
||||
RouterVo children = new RouterVo();
|
||||
String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
|
||||
children.setPath(routerPath);
|
||||
children.setComponent(UserConstants.INNER_LINK);
|
||||
children.setName(StringUtils.capitalize(routerPath));
|
||||
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
|
||||
childrenList.add(children);
|
||||
router.setChildren(childrenList);
|
||||
}
|
||||
@ -305,6 +319,10 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
*/
|
||||
public String getRouterPath(SysMenu menu) {
|
||||
String routerPath = menu.getPath();
|
||||
// 内链打开外网方式
|
||||
if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
|
||||
routerPath = StringUtils.replaceEach(routerPath, new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
|
||||
}
|
||||
// 非外链并且是一级目录(类型为目录)
|
||||
if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
|
||||
&& UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
|
||||
@ -327,7 +345,9 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
String component = UserConstants.LAYOUT;
|
||||
if (StrUtil.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
|
||||
component = menu.getComponent();
|
||||
} else if (StrUtil.isEmpty(menu.getComponent()) && isParentView(menu)) {
|
||||
} else if (StrUtil.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
|
||||
component = UserConstants.INNER_LINK;
|
||||
} else if (StrUtil.isEmpty(menu.getComponent()) && isParentView(menu)) {
|
||||
component = UserConstants.PARENT_VIEW;
|
||||
}
|
||||
return component;
|
||||
@ -344,6 +364,16 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为内链组件
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isInnerLink(SysMenu menu) {
|
||||
return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为parent_view组件
|
||||
*
|
||||
@ -357,7 +387,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu>
|
||||
/**
|
||||
* 根据父节点的ID获取所有子节点
|
||||
*
|
||||
* @param list 分类表
|
||||
* @param list 分类表
|
||||
* @param parentId 传入的父节点ID
|
||||
* @return String
|
||||
*/
|
||||
|
@ -59,6 +59,27 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole>
|
||||
return baseMapper.selectRoleList(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 角色列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysRole> selectRolesByUserId(Long userId) {
|
||||
List<SysRole> userRoles = baseMapper.selectRolePermissionByUserId(userId);
|
||||
List<SysRole> roles = selectRoleAll();
|
||||
for (SysRole role : roles) {
|
||||
for (SysRole userRole : userRoles) {
|
||||
if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
|
||||
role.setFlag(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询权限
|
||||
*
|
||||
@ -305,4 +326,51 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole>
|
||||
roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, ids));
|
||||
return baseMapper.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消授权用户角色
|
||||
*
|
||||
* @param userRole 用户和角色关联信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAuthUser(SysUserRole userRole) {
|
||||
return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
|
||||
.eq(SysUserRole::getRoleId, userRole.getRoleId())
|
||||
.eq(SysUserRole::getUserId, userRole.getUserId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量取消授权用户角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param userIds 需要取消授权的用户数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAuthUsers(Long roleId, Long[] userIds) {
|
||||
return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
|
||||
.eq(SysUserRole::getRoleId, roleId)
|
||||
.in(SysUserRole::getUserId, Arrays.asList(userIds)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量选择授权用户角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param userIds 需要删除的用户数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertAuthUsers(Long roleId, Long[] userIds) {
|
||||
// 新增用户与角色管理
|
||||
List<SysUserRole> list = new ArrayList<SysUserRole>();
|
||||
for (Long userId : userIds) {
|
||||
SysUserRole ur = new SysUserRole();
|
||||
ur.setUserId(userId);
|
||||
ur.setRoleId(roleId);
|
||||
list.add(ur);
|
||||
}
|
||||
return userRoleMapper.insertAll(list);
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,30 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser>
|
||||
return baseMapper.selectUserList(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件分页查询已分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
|
||||
public TableDataInfo<SysUser> selectAllocatedList(SysUser user) {
|
||||
return PageUtils.buildDataInfo(baseMapper.selectAllocatedList(PageUtils.buildPage(), user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件分页查询未分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
|
||||
public TableDataInfo<SysUser> selectUnallocatedList(SysUser user) {
|
||||
return PageUtils.buildDataInfo(baseMapper.selectUnallocatedList(PageUtils.buildPage(), user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户
|
||||
*
|
||||
@ -231,6 +255,21 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser>
|
||||
return baseMapper.updateById(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户授权角色
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param roleIds 角色组
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void insertUserAuth(Long userId, Long[] roleIds)
|
||||
{
|
||||
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
|
||||
.eq(SysUserRole::getUserId, userId));
|
||||
insertUserRole(userId, roleIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
*
|
||||
@ -257,7 +296,7 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser>
|
||||
* 修改用户头像
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @param avatar 头像地址
|
||||
* @param avatar 头像地址
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@ -338,6 +377,28 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户角色信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param roleIds 角色组
|
||||
*/
|
||||
public void insertUserRole(Long userId, Long[] roleIds) {
|
||||
if (Validator.isNotNull(roleIds)) {
|
||||
// 新增用户与角色管理
|
||||
List<SysUserRole> list = new ArrayList<SysUserRole>();
|
||||
for (Long roleId : roleIds) {
|
||||
SysUserRole ur = new SysUserRole();
|
||||
ur.setUserId(userId);
|
||||
ur.setRoleId(roleId);
|
||||
list.add(ur);
|
||||
}
|
||||
if (list.size() > 0) {
|
||||
userRoleMapper.insertAll(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户ID删除用户
|
||||
*
|
||||
@ -377,9 +438,9 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser>
|
||||
/**
|
||||
* 导入用户数据
|
||||
*
|
||||
* @param userList 用户数据列表
|
||||
* @param userList 用户数据列表
|
||||
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
|
||||
* @param operName 操作用户
|
||||
* @param operName 操作用户
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
|
@ -0,0 +1,29 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
public class SysIndexController
|
||||
{
|
||||
/** 系统基础配置 */
|
||||
@Autowired
|
||||
private RuoYiConfig ruoyiConfig;
|
||||
|
||||
/**
|
||||
* 访问首页,提示语
|
||||
*/
|
||||
@RequestMapping("/")
|
||||
public String index()
|
||||
{
|
||||
return StrUtil.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
@ -11,6 +9,7 @@ import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -98,8 +97,7 @@ public class SysMenuController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
|
||||
&& !StrUtil.startWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
|
||||
{
|
||||
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
}
|
||||
@ -119,8 +117,7 @@ public class SysMenuController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
|
||||
&& !StrUtil.startWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
|
||||
{
|
||||
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
@ -14,6 +15,7 @@ import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.system.domain.SysUserRole;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -25,7 +27,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
@ -171,4 +173,57 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
return AjaxResult.success(roleService.selectRoleAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询已分配用户角色列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:list')")
|
||||
@GetMapping("/authUser/allocatedList")
|
||||
public TableDataInfo allocatedList(SysUser user)
|
||||
{
|
||||
return userService.selectAllocatedList(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询未分配用户角色列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:list')")
|
||||
@GetMapping("/authUser/unallocatedList")
|
||||
public TableDataInfo unallocatedList(SysUser user)
|
||||
{
|
||||
return userService.selectUnallocatedList(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消授权用户
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/cancel")
|
||||
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
|
||||
{
|
||||
return toAjax(roleService.deleteAuthUser(userRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量取消授权用户
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/cancelAll")
|
||||
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
|
||||
{
|
||||
return toAjax(roleService.deleteAuthUsers(roleId, userIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量选择用户授权
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/selectAll")
|
||||
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
|
||||
{
|
||||
return toAjax(roleService.insertAuthUsers(roleId, userIds));
|
||||
}
|
||||
}
|
||||
|
@ -196,4 +196,31 @@ public class SysUserController extends BaseController
|
||||
user.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(userService.updateUserStatus(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户编号获取授权角色
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:query')")
|
||||
@GetMapping("/authRole/{userId}")
|
||||
public AjaxResult authRole(@PathVariable("userId") Long userId)
|
||||
{
|
||||
SysUser user = userService.selectUserById(userId);
|
||||
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||
Map<String, Object> ajax = new HashMap<>();
|
||||
ajax.put("user", user);
|
||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
return AjaxResult.success(ajax);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户授权角色
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authRole")
|
||||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||
{
|
||||
userService.insertUserAuth(userId, roleIds);
|
||||
return success();
|
||||
}
|
||||
}
|
||||
|
@ -110,3 +110,30 @@ redisson:
|
||||
subscriptionsPerConnection: 5
|
||||
# DNS监测时间间隔,单位:毫秒
|
||||
dnsMonitoringInterval: 5000
|
||||
|
||||
--- # 监控配置
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
username: ruoyi
|
||||
password: 123456
|
||||
|
||||
# Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
base-path: /actuator
|
||||
exposure:
|
||||
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||
include: '*'
|
||||
endpoint:
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
|
@ -12,7 +12,7 @@ spring:
|
||||
# 主库数据源
|
||||
master:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||
url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||
username: root
|
||||
password: root
|
||||
# 从库数据源
|
||||
@ -66,7 +66,7 @@ spring:
|
||||
# redis 配置
|
||||
redis:
|
||||
# 地址
|
||||
host: localhost
|
||||
host: 172.30.0.48
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
@ -110,3 +110,30 @@ redisson:
|
||||
subscriptionsPerConnection: 5
|
||||
# DNS监测时间间隔,单位:毫秒
|
||||
dnsMonitoringInterval: 5000
|
||||
|
||||
--- # 监控配置
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://172.30.0.90:9090/admin
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
username: ruoyi
|
||||
password: 123456
|
||||
|
||||
# Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
base-path: /actuator
|
||||
exposure:
|
||||
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||
include: health,info
|
||||
endpoint:
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
|
@ -64,6 +64,8 @@ logging:
|
||||
|
||||
# Spring配置
|
||||
spring:
|
||||
application:
|
||||
name: ${ruoyi.name}
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
@ -110,6 +112,8 @@ token:
|
||||
# MyBatisPlus配置
|
||||
# https://baomidou.com/config/
|
||||
mybatis-plus:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.mapper
|
||||
mapperPackage: com.ruoyi.**.mapper
|
||||
# 对应的 XML 文件位置
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
@ -156,7 +160,9 @@ mybatis-plus:
|
||||
# STATEMENT 关闭一级缓存
|
||||
localCacheScope: SESSION
|
||||
# 开启Mybatis二级缓存,默认为 true
|
||||
cacheEnabled: true
|
||||
cacheEnabled: false
|
||||
# 更详细的日志输出 会有性能损耗
|
||||
# logImpl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
# 是否打印 Logo banner
|
||||
banner: true
|
||||
@ -203,7 +209,7 @@ swagger:
|
||||
# 请求前缀
|
||||
pathMapping: /dev-api
|
||||
# 标题
|
||||
title: '标题:RuoYi-Vue-Plus后台管理系统_接口文档'
|
||||
title: '标题:${ruoyi.name}后台管理系统_接口文档'
|
||||
# 描述
|
||||
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
|
||||
# 版本
|
||||
@ -244,6 +250,8 @@ thread-pool:
|
||||
|
||||
# feign 相关配置
|
||||
feign:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.feign
|
||||
package: com.ruoyi.**.feign
|
||||
# 开启压缩
|
||||
compression:
|
||||
@ -256,6 +264,21 @@ feign:
|
||||
circuitbreaker:
|
||||
enabled: true
|
||||
|
||||
--- # redisson 缓存配置
|
||||
redisson:
|
||||
cacheGroup:
|
||||
# 用例: @Cacheable(cacheNames="groupId", key="#XXX") 方可使用缓存组配置
|
||||
- groupId: redissonCacheMap
|
||||
# 组过期时间(脚本监控)
|
||||
ttl: 60000
|
||||
# 组最大空闲时间(脚本监控)
|
||||
maxIdleTime: 60000
|
||||
# 组最大长度
|
||||
maxSize: 0
|
||||
- groupId: testCache
|
||||
ttl: 1000
|
||||
maxIdleTime: 500
|
||||
|
||||
--- # 分布式锁 lock4j 全局配置
|
||||
lock4j:
|
||||
# 获取分布式锁超时时间,默认为 3000 毫秒
|
||||
@ -293,31 +316,3 @@ spring:
|
||||
tablePrefix: QRTZ_
|
||||
# sqlserver 启用
|
||||
# selectWithLockSQL: SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?
|
||||
|
||||
--- # 监控配置
|
||||
spring:
|
||||
application:
|
||||
name: ruoyi-vue-plus
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://localhost:${server.port}${spring.boot.admin.context-path}
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
# Spring Boot Admin Server 服务端的相关配置
|
||||
context-path: /admin # 配置 Spring
|
||||
|
||||
# Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
base-path: /actuator
|
||||
exposure:
|
||||
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
include: '*'
|
||||
endpoint:
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
|
33
ruoyi/src/main/resources/i18n/messages_en_US.properties
Normal file
33
ruoyi/src/main/resources/i18n/messages_en_US.properties
Normal file
@ -0,0 +1,33 @@
|
||||
#错误消息
|
||||
not.null=
|
||||
user.jcaptcha.error=
|
||||
user.jcaptcha.expire=
|
||||
user.not.exists=
|
||||
user.password.not.match=
|
||||
user.password.retry.limit.count=
|
||||
user.password.retry.limit.exceed=
|
||||
user.password.delete=
|
||||
user.blocked=
|
||||
role.blocked=
|
||||
user.logout.success=
|
||||
length.not.valid=
|
||||
user.username.not.valid=
|
||||
user.password.not.valid=
|
||||
user.email.not.valid=
|
||||
user.mobile.phone.number.not.valid=
|
||||
user.login.success=
|
||||
user.notfound=
|
||||
user.forcelogout=
|
||||
user.unknown.error=
|
||||
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=
|
||||
upload.filename.exceed.length=
|
||||
|
||||
##权限
|
||||
no.permission=
|
||||
no.create.permission=
|
||||
no.update.permission=
|
||||
no.delete.permission=
|
||||
no.export.permission=
|
||||
no.view.permission=
|
36
ruoyi/src/main/resources/i18n/messages_zh_CN.properties
Normal file
36
ruoyi/src/main/resources/i18n/messages_zh_CN.properties
Normal file
@ -0,0 +1,36 @@
|
||||
#错误消息
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.jcaptcha.expire=验证码已失效
|
||||
user.not.exists=用户不存在/密码错误
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
user.blocked=用户已封禁,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
|
||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
|
||||
user.password.not.valid=* 5-50个字符
|
||||
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.mobile.phone.number.not.valid=手机号格式错误
|
||||
user.login.success=登录成功
|
||||
user.notfound=请重新登录
|
||||
user.forcelogout=管理员强制退出,请重新登录
|
||||
user.unknown.error=未知错误,请重新登录
|
||||
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
|
||||
upload.filename.exceed.length=上传的文件名最长{0}个字符
|
||||
|
||||
##权限
|
||||
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
|
@ -75,9 +75,9 @@
|
||||
r.data_scope,
|
||||
r.status as role_status
|
||||
from sys_user u
|
||||
left join sys_dept d on u.dept_id = d.dept_id
|
||||
left join sys_user_role ur on u.user_id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id
|
||||
left join sys_dept d on u.dept_id = d.dept_id
|
||||
left join sys_user_role ur on u.user_id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id
|
||||
</sql>
|
||||
|
||||
<select id="selectPageUserList" parameterType="SysUser" resultMap="SysUserResult">
|
||||
@ -142,6 +142,45 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
|
||||
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
|
||||
from sys_user u
|
||||
left join sys_dept d on u.dept_id = d.dept_id
|
||||
left join sys_user_role ur on u.user_id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id
|
||||
where u.del_flag = '0' and r.role_id = #{user.roleId}
|
||||
<if test="user.userName != null and user.userName != ''">
|
||||
AND u.user_name like concat('%', #{user.userName}, '%')
|
||||
</if>
|
||||
<if test="user.phonenumber != null and user.phonenumber != ''">
|
||||
AND u.phonenumber like concat('%', #{user.phonenumber}, '%')
|
||||
</if>
|
||||
<!-- 数据范围过滤 -->
|
||||
<if test="user.params.dataScope != null and user.params.dataScope != ''">
|
||||
AND ( ${user.params.dataScope} )
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
|
||||
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
|
||||
from sys_user u
|
||||
left join sys_dept d on u.dept_id = d.dept_id
|
||||
left join sys_user_role ur on u.user_id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id
|
||||
where u.del_flag = '0' and (r.role_id != #{user.roleId} or r.role_id IS NULL)
|
||||
and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{user.roleId})
|
||||
<if test="user.userName != null and user.userName != ''">
|
||||
AND u.user_name like concat('%', #{user.userName}, '%')
|
||||
</if>
|
||||
<if test="user.phonenumber != null and user.phonenumber != ''">
|
||||
AND u.phonenumber like concat('%', #{user.phonenumber}, '%')
|
||||
</if>
|
||||
<!-- 数据范围过滤 -->
|
||||
<if test="user.params.dataScope != null and user.params.dataScope != ''">
|
||||
AND ( ${user.params.dataScope} )
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
|
||||
<include refid="selectUserVo"/>
|
||||
where u.user_name = #{userName}
|
||||
|
@ -11,8 +11,6 @@ import org.apache.ibatis.annotations.CacheNamespace;
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
|
||||
@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
|
||||
public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}> {
|
||||
|
||||
}
|
||||
|
@ -256,52 +256,16 @@
|
||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "imageUpload")
|
||||
import ImageUpload from '@/components/ImageUpload';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "fileUpload")
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "editor")
|
||||
import Editor from '@/components/Editor';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
|
||||
export default {
|
||||
name: "${BusinessName}",
|
||||
components: {
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "imageUpload")
|
||||
ImageUpload,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "fileUpload")
|
||||
FileUpload,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "editor")
|
||||
Editor,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
Treeselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//按钮loading
|
||||
buttonLoading: false,
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
@ -510,17 +474,19 @@ export default {
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
this.buttonLoading = false;
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
this.buttonLoading = false;
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -308,51 +308,13 @@
|
||||
|
||||
<script>
|
||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "imageUpload")
|
||||
import ImageUpload from '@/components/ImageUpload';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "fileUpload")
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "editor")
|
||||
import Editor from '@/components/Editor';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
|
||||
export default {
|
||||
name: "${BusinessName}",
|
||||
components: {
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "imageUpload")
|
||||
ImageUpload,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "fileUpload")
|
||||
FileUpload,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.pk && $column.htmlType == "editor")
|
||||
Editor,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//按钮loading
|
||||
buttonLoading: false,
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
@ -567,17 +529,19 @@ export default {
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
this.buttonLoading = false;
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
this.buttonLoading = false;
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user