Merge remote-tracking branch 'origin/master' into master
This commit is contained in:
commit
873bf7203a
@ -9,6 +9,10 @@
|
||||
* 查看ruoyi-framework模块的pom.xml文件,根据注释更改依赖
|
||||
* 查看ruoyi-admin模块中的application.yml文件,根据注释更改配置
|
||||
|
||||
关于如何创建新模块
|
||||
* 参考ruoyi-demo模块
|
||||
* 需要改动: 父pom 与 admin模块pom
|
||||
|
||||
## 修改RuoYi功能
|
||||
|
||||
* ORM框架 使用 Mybatis-Plus 简化CRUD
|
||||
@ -17,16 +21,19 @@
|
||||
* 代码生成模板 改为适配 Mybatis-Plus 的代码
|
||||
* 项目修改为 maven多环境配置
|
||||
* 重磅更新 升级MybatisPlus 3.4.1 重写配置文件详细注释 更新所有插件
|
||||
* 增加demo模块示例(给不会增加模块的小伙伴做参考)
|
||||
* 同步升级 3.3
|
||||
|
||||
## 平台简介
|
||||
|
||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||
|
||||
* 前端采用Vue、Element UI。
|
||||
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
||||
* 权限认证使用Jwt,支持多终端认证系统。
|
||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
||||
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
||||
* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||
* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
||||
|
||||
## 内置功能
|
||||
|
10
pom.xml
10
pom.xml
@ -43,7 +43,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<version>2.2.12.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@ -224,6 +224,13 @@
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- demo模块 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-demo</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@ -234,6 +241,7 @@
|
||||
<module>ruoyi-quartz</module>
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ruoyi-demo</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
@ -66,6 +66,12 @@
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- demo模块 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-demo</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -61,6 +61,8 @@ spring:
|
||||
host: 127.0.0.1
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password:
|
||||
# 连接超时时间
|
||||
|
@ -61,6 +61,8 @@ spring:
|
||||
host: 127.0.0.1
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password:
|
||||
# 连接超时时间
|
||||
|
@ -149,7 +149,7 @@ public @interface Excel
|
||||
|
||||
public enum ColumnType
|
||||
{
|
||||
NUMERIC(0), STRING(1);
|
||||
NUMERIC(0), STRING(1), IMAGE(2);
|
||||
private final int value;
|
||||
|
||||
ColumnType(int value)
|
||||
|
@ -29,8 +29,10 @@ public class GenConstants
|
||||
public static final String PARENT_MENU_NAME = "parentMenuName";
|
||||
|
||||
/** 数据库字符串类型 */
|
||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2", "tinytext", "text",
|
||||
"mediumtext", "longtext" };
|
||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
||||
|
||||
/** 数据库文本类型 */
|
||||
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
|
||||
|
||||
/** 数据库时间类型 */
|
||||
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
|
||||
|
@ -29,8 +29,8 @@ public class RepeatableFilter implements Filter
|
||||
throws IOException, ServletException
|
||||
{
|
||||
ServletRequest requestWrapper = null;
|
||||
if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(),
|
||||
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
if (request instanceof HttpServletRequest
|
||||
&& StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
|
||||
{
|
||||
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
|
||||
public boolean isJsonRequest()
|
||||
{
|
||||
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
|
||||
return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header)
|
||||
|| MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(header);
|
||||
return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header);
|
||||
}
|
||||
}
|
@ -44,4 +44,33 @@ public class FileTypeUtils
|
||||
}
|
||||
return fileName.substring(separatorIndex + 1).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
*
|
||||
* @param photoByte 文件字节码
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileExtendName(byte[] photoByte)
|
||||
{
|
||||
String strFileExtendName = "JPG";
|
||||
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
|
||||
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
|
||||
{
|
||||
strFileExtendName = "GIF";
|
||||
}
|
||||
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
|
||||
{
|
||||
strFileExtendName = "JPG";
|
||||
}
|
||||
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
|
||||
{
|
||||
strFileExtendName = "BMP";
|
||||
}
|
||||
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
|
||||
{
|
||||
strFileExtendName = "PNG";
|
||||
}
|
||||
return strFileExtendName;
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.ruoyi.common.utils.file;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Arrays;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 图片处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ImageUtils
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
|
||||
|
||||
public static byte[] getImage(String imagePath)
|
||||
{
|
||||
InputStream is = getFile(imagePath);
|
||||
try
|
||||
{
|
||||
return IOUtils.toByteArray(is);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("图片加载异常 {}", e);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getFile(String imagePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] result = readFile(imagePath);
|
||||
result = Arrays.copyOf(result, result.length);
|
||||
return new ByteArrayInputStream(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("获取图片异常 {}", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件为字节数据
|
||||
*
|
||||
* @param key 地址
|
||||
* @return 字节数据
|
||||
*/
|
||||
public static byte[] readFile(String url)
|
||||
{
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
try
|
||||
{
|
||||
if (url.startsWith("http"))
|
||||
{
|
||||
// 网络地址
|
||||
URL urlObj = new URL(url);
|
||||
URLConnection urlConnection = urlObj.openConnection();
|
||||
urlConnection.setConnectTimeout(30 * 1000);
|
||||
urlConnection.setReadTimeout(60 * 1000);
|
||||
urlConnection.setDoInput(true);
|
||||
in = urlConnection.getInputStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 本机地址
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
|
||||
in = new FileInputStream(downloadPath);
|
||||
}
|
||||
return IOUtils.toByteArray(in);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("获取文件路径异常 {}", e);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(baos);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,10 +22,12 @@ import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.DataValidation;
|
||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
@ -37,6 +39,7 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -51,6 +54,8 @@ import com.ruoyi.common.exception.CustomException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileTypeUtils;
|
||||
import com.ruoyi.common.utils.file.ImageUtils;
|
||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||
|
||||
/**
|
||||
@ -102,16 +107,21 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
private List<Object[]> fields;
|
||||
|
||||
/**
|
||||
* 最大高度
|
||||
*/
|
||||
private short maxHeight;
|
||||
|
||||
/**
|
||||
* 统计列表
|
||||
*/
|
||||
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
|
||||
|
||||
|
||||
/**
|
||||
* 数字格式
|
||||
*/
|
||||
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
|
||||
|
||||
|
||||
/**
|
||||
* 实体对象
|
||||
*/
|
||||
@ -239,7 +249,15 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Convert.toStr(val);
|
||||
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
|
||||
if (StringUtils.isNotEmpty(dateFormat))
|
||||
{
|
||||
val = DateUtils.parseDateToStr(dateFormat, (Date) val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Convert.toStr(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
|
||||
@ -521,6 +539,47 @@ public class ExcelUtil<T>
|
||||
{
|
||||
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
|
||||
}
|
||||
else if (ColumnType.IMAGE == attr.cellType())
|
||||
{
|
||||
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
|
||||
cell.getRow().getRowNum() + 1);
|
||||
String imagePath = Convert.toStr(value);
|
||||
if (StringUtils.isNotEmpty(imagePath))
|
||||
{
|
||||
byte[] data = ImageUtils.getImage(imagePath);
|
||||
getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
|
||||
cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取画布
|
||||
*/
|
||||
public static Drawing<?> getDrawingPatriarch(Sheet sheet)
|
||||
{
|
||||
if (sheet.getDrawingPatriarch() == null)
|
||||
{
|
||||
sheet.createDrawingPatriarch();
|
||||
}
|
||||
return sheet.getDrawingPatriarch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片类型,设置图片插入类型
|
||||
*/
|
||||
public int getImageType(byte[] value)
|
||||
{
|
||||
String type = FileTypeUtils.getFileExtendName(value);
|
||||
if ("JPG".equalsIgnoreCase(type))
|
||||
{
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
}
|
||||
else if ("PNG".equalsIgnoreCase(type))
|
||||
{
|
||||
return Workbook.PICTURE_TYPE_PNG;
|
||||
}
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -536,7 +595,6 @@ public class ExcelUtil<T>
|
||||
{
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
}
|
||||
// 如果设置了提示信息则鼠标放上去提示.
|
||||
if (StringUtils.isNotEmpty(attr.prompt()))
|
||||
@ -561,7 +619,7 @@ public class ExcelUtil<T>
|
||||
try
|
||||
{
|
||||
// 设置行高
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
row.setHeight(maxHeight);
|
||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||
if (attr.isExport())
|
||||
{
|
||||
@ -737,7 +795,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析字典值
|
||||
*
|
||||
@ -763,7 +821,7 @@ public class ExcelUtil<T>
|
||||
{
|
||||
return DictUtils.getDictValue(dictType, dictLabel, separator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 合计统计信息
|
||||
*/
|
||||
@ -800,7 +858,7 @@ public class ExcelUtil<T>
|
||||
cell = row.createCell(0);
|
||||
cell.setCellStyle(styles.get("total"));
|
||||
cell.setCellValue("合计");
|
||||
|
||||
|
||||
for (Integer key : keys)
|
||||
{
|
||||
cell = row.createCell(key);
|
||||
@ -916,6 +974,21 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||
this.maxHeight = getRowHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解获取最大行高
|
||||
*/
|
||||
public short getRowHeight()
|
||||
{
|
||||
double maxHeight = 0;
|
||||
for (Object[] os : this.fields)
|
||||
{
|
||||
Excel excel = (Excel) os[1];
|
||||
maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
|
||||
}
|
||||
return (short) (maxHeight * 20);
|
||||
}
|
||||
|
||||
/**
|
||||
|
28
ruoyi-demo/pom.xml
Normal file
28
ruoyi-demo/pom.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-demo</artifactId>
|
||||
|
||||
<description>
|
||||
demo模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.demo.controller;
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.demo.domain;
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.demo.mapper;
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.demo.service.impl;
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.demo.service;
|
@ -8,8 +8,10 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
@ -31,7 +33,7 @@ public class RedisConfig extends CachingConfigurerSupport
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
serializer.setObjectMapper(mapper);
|
||||
|
||||
template.setValueSerializer(serializer);
|
||||
|
@ -40,13 +40,14 @@ public class GenUtils
|
||||
column.setCreateBy(table.getCreateBy());
|
||||
// 设置java字段名
|
||||
column.setJavaField(StringUtils.toCamelCase(columnName));
|
||||
// 设置默认类型
|
||||
column.setJavaType(GenConstants.TYPE_STRING);
|
||||
|
||||
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType))
|
||||
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
|
||||
{
|
||||
column.setJavaType(GenConstants.TYPE_STRING);
|
||||
// 字符串长度超过500设置为文本域
|
||||
Integer columnLength = getColumnLength(column.getColumnType());
|
||||
String htmlType = columnLength >= 500 ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
||||
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
||||
column.setHtmlType(htmlType);
|
||||
}
|
||||
else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
|
||||
|
@ -1,12 +1,8 @@
|
||||
package ${packageName}.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -49,98 +45,14 @@ public class ${ClassName}Controller extends BaseController {
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
|
||||
@GetMapping("/list")
|
||||
#if($table.crud)
|
||||
public TableDataInfo list(${ClassName} ${className})
|
||||
{
|
||||
public TableDataInfo list(${ClassName} ${className}) {
|
||||
startPage();
|
||||
LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery(${className});
|
||||
#foreach($column in $columns)
|
||||
#set($queryType=$column.queryType)
|
||||
#set($javaField=$column.javaField)
|
||||
#set($javaType=$column.javaType)
|
||||
#set($columnName=$column.columnName)
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#if($column.query)
|
||||
#if($column.queryType == "EQ")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.eq(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.eq(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "NE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.ne(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.ne(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "GT")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.gt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.gt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "GTE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.ge(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.ge(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LT")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.lt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.lt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LTE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.le(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.le(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LIKE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.like(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.like(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "BETWEEN")
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
List<${ClassName}> list = i${ClassName}Service.list(lqw);
|
||||
List<${ClassName}> list = i${ClassName}Service.queryList(${className});
|
||||
return getDataTable(list);
|
||||
}
|
||||
#elseif($table.tree)
|
||||
public AjaxResult list(${ClassName} ${className}) {
|
||||
LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery(${className});
|
||||
List<${ClassName}> list = i${ClassName}Service.list(lqw);
|
||||
List<${ClassName}> list = i${ClassName}Service.queryList(${className});
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
#end
|
||||
@ -152,9 +64,8 @@ public class ${ClassName}Controller extends BaseController {
|
||||
@Log(title = "${functionName}" , businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export" )
|
||||
public AjaxResult export(${ClassName} ${className}) {
|
||||
LambdaQueryWrapper<${ClassName}> lqw = new LambdaQueryWrapper<${ClassName}>(${className});
|
||||
List<${ClassName}> list = i${ClassName}Service.list(lqw);
|
||||
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}. class);
|
||||
List<${ClassName}> list = i${ClassName}Service.queryList(${className});
|
||||
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
|
||||
return util.exportExcel(list, "${businessName}" );
|
||||
}
|
||||
|
||||
|
@ -10,14 +10,12 @@ import com.ruoyi.common.annotation.Excel;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.math.BigDecimal;
|
||||
#if($table.crud)
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
#elseif($table.tree)
|
||||
import com.ruoyi.common.core.domain.TreeEntity;
|
||||
#end
|
||||
|
||||
/**
|
||||
* ${functionName}对象 ${tableName}
|
||||
@ -25,11 +23,6 @@ import com.ruoyi.common.core.domain.TreeEntity;
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
#if($table.crud)
|
||||
#set($Entity="BaseEntity")
|
||||
#elseif($table.tree)
|
||||
#set($Entity="TreeEntity")
|
||||
#end
|
||||
@Data
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@ -66,4 +59,7 @@ private static final long serialVersionUID=1L;
|
||||
private $column.javaType $column.javaField;
|
||||
#end
|
||||
#end
|
||||
|
||||
@TableField(exist = false)
|
||||
private Map<String, Object> params = new HashMap<>();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package ${packageName}.service;
|
||||
|
||||
import ${packageName}.domain.${ClassName};
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ${functionName}Service接口
|
||||
@ -11,4 +12,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface I${ClassName}Service extends IService<${ClassName}> {
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
List<${ClassName}> queryList(${ClassName} ${className});
|
||||
}
|
||||
|
@ -2,10 +2,16 @@ package ${packageName}.service.impl;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import ${packageName}.mapper.${ClassName}Mapper;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
import ${packageName}.service.I${ClassName}Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ${functionName}Service业务层处理
|
||||
*
|
||||
@ -15,4 +21,94 @@ import ${packageName}.service.I${ClassName}Service;
|
||||
@Service
|
||||
public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}> implements I${ClassName}Service {
|
||||
|
||||
@Override
|
||||
public List<${ClassName}> queryList(${ClassName} ${className}) {
|
||||
LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery();
|
||||
#foreach($column in $columns)
|
||||
#set($queryType=$column.queryType)
|
||||
#set($javaField=$column.javaField)
|
||||
#set($javaType=$column.javaType)
|
||||
#set($columnName=$column.columnName)
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#if($column.query)
|
||||
#if($column.queryType == "EQ")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.eq(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.eq(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "NE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.ne(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.ne(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "GT")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.gt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.gt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "GTE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.ge(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.ge(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LT")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.lt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.lt(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LTE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.le(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.le(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "LIKE")
|
||||
#if($javaType == 'String')
|
||||
if (StringUtils.isNotBlank(${className}.get$AttrName())){
|
||||
lqw.like(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#else
|
||||
if (${className}.get$AttrName() != null){
|
||||
lqw.like(${ClassName}::get$AttrName ,${className}.get$AttrName());
|
||||
}
|
||||
#end
|
||||
#elseif($queryType == "BETWEEN")
|
||||
Map<String, Object> params = ${className}.getParams();
|
||||
if (params.get("begin$AttrName") != null && params.get("end$AttrName") != null) {
|
||||
lqw.between(${ClassName}::get$AttrName ,params.get("begin$AttrName"),params.get("end$AttrName"));
|
||||
}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
return this.list(lqw);
|
||||
}
|
||||
}
|
||||
|
@ -38,15 +38,28 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择${comment}">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
<el-form-item label="${comment}">
|
||||
<el-date-picker
|
||||
v-model="daterange${AttrName}"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
@ -201,7 +214,7 @@
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="form.${field}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
@ -283,6 +296,10 @@ export default {
|
||||
#if(${column.dictType} != '')
|
||||
// $comment字典
|
||||
${column.javaField}Options: [],
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
// $comment时间范围
|
||||
daterange${AttrName}: [],
|
||||
#end
|
||||
#end
|
||||
// 查询参数
|
||||
@ -329,6 +346,21 @@ export default {
|
||||
/** 查询${functionName}列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
this.queryParams.params = {};
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
||||
}
|
||||
#end
|
||||
#end
|
||||
list${BusinessName}(this.queryParams).then(response => {
|
||||
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
||||
this.loading = false;
|
||||
@ -397,6 +429,12 @@ export default {
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
this.daterange${AttrName} = [];
|
||||
#end
|
||||
#end
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
|
@ -38,15 +38,28 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择${comment}">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
<el-form-item label="${comment}">
|
||||
<el-date-picker
|
||||
v-model="daterange${AttrName}"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
@ -95,7 +108,7 @@
|
||||
v-hasPermi="['${moduleName}:${businessName}:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
|
||||
@ -230,7 +243,7 @@
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="form.${field}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
@ -315,6 +328,10 @@ export default {
|
||||
#if(${column.dictType} != '')
|
||||
// $comment字典
|
||||
${column.javaField}Options: [],
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
// $comment时间范围
|
||||
daterange${AttrName}: [],
|
||||
#end
|
||||
#end
|
||||
// 查询参数
|
||||
@ -363,6 +380,21 @@ export default {
|
||||
/** 查询${functionName}列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
this.queryParams.params = {};
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
||||
}
|
||||
#end
|
||||
#end
|
||||
list${BusinessName}(this.queryParams).then(response => {
|
||||
this.${businessName}List = response.rows;
|
||||
this.total = response.total;
|
||||
@ -413,6 +445,12 @@ export default {
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
this.daterange${AttrName} = [];
|
||||
#end
|
||||
#end
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
|
@ -131,7 +131,7 @@
|
||||
<if test="parentId != null">parent_id = #{parentId},</if>
|
||||
<if test="orderNum != null and orderNum != ''">order_num = #{orderNum},</if>
|
||||
<if test="path != null and path != ''">path = #{path},</if>
|
||||
<if test="component != null and component != ''">component = #{component},</if>
|
||||
<if test="component != null">component = #{component},</if>
|
||||
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
|
||||
<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
|
||||
<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
|
||||
|
@ -141,8 +141,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
|
||||
<if test="userName != null and userName != ''">user_name = #{userName},</if>
|
||||
<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
|
||||
<if test="email != null and email != ''">email = #{email},</if>
|
||||
<if test="phonenumber != null and phonenumber != ''">phonenumber = #{phonenumber},</if>
|
||||
<if test="email != null ">email = #{email},</if>
|
||||
<if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
|
||||
<if test="sex != null and sex != ''">sex = #{sex},</if>
|
||||
<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
|
||||
<if test="password != null and password != ''">password = #{password},</if>
|
||||
|
@ -49,7 +49,6 @@
|
||||
"js-cookie": "2.2.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "6.2.0",
|
||||
"quill": "1.3.7",
|
||||
"screenfull": "5.0.2",
|
||||
"sortablejs": "1.10.2",
|
||||
|
@ -10,8 +10,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -49,18 +47,13 @@ export default {
|
||||
}
|
||||
return name.trim() === '首页'
|
||||
},
|
||||
pathCompile(path) {
|
||||
const { params } = this.$route
|
||||
var toPath = pathToRegexp.compile(path)
|
||||
return toPath(params)
|
||||
},
|
||||
handleLink(item) {
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
this.$router.push(redirect)
|
||||
return
|
||||
}
|
||||
this.$router.push(this.pathCompile(path))
|
||||
this.$router.push(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
<!-- @author ruoyi 20201128 支持三级以上菜单缓存 -->
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<keep-alive :max="20" :exclude="notCacheName">
|
||||
<keep-alive :include="cachedViews">
|
||||
<router-view :key="key" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
@ -10,119 +9,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
name: 'AppMain',
|
||||
computed: {
|
||||
notCacheName() {
|
||||
var visitedViews = this.$store.state.tagsView.visitedViews;
|
||||
var noCacheViews = [];
|
||||
Object.keys(visitedViews).some((index) => {
|
||||
if (visitedViews[index].meta.noCache) {
|
||||
noCacheViews.push(visitedViews[index].name);
|
||||
}
|
||||
});
|
||||
return noCacheViews;
|
||||
cachedViews() {
|
||||
return this.$store.state.tagsView.cachedViews
|
||||
},
|
||||
key() {
|
||||
return this.$route.path;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// 关闭标签触发
|
||||
Global.$on("removeCache", (name, view) => {
|
||||
this.removeCache(name, view);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
// 获取有keep-alive子节点的Vnode
|
||||
getVnode() {
|
||||
// 判断子集非空
|
||||
if (this.$children.length == 0) return false;
|
||||
let vnode;
|
||||
for (let item of this.$children) {
|
||||
// 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key
|
||||
if (item.$vnode.data.key) {
|
||||
vnode = item.$vnode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return vnode ? vnode : false;
|
||||
},
|
||||
// 移除keep-alive缓存
|
||||
removeCache(name, view = {}) {
|
||||
let vnode = this.getVnode();
|
||||
if (!vnode) return false;
|
||||
let componentInstance = vnode.parent.componentInstance;
|
||||
// 这个key是用来获取前缀用来后面正则匹配用的
|
||||
let keyStart = vnode.key.split("/")[0];
|
||||
let thisKey = `${keyStart}${view.fullPath}`;
|
||||
let regKey = `${keyStart}${view.path}`;
|
||||
|
||||
this[name]({ componentInstance, thisKey, regKey });
|
||||
},
|
||||
// 移除其他
|
||||
closeOthersTags({ componentInstance, thisKey }) {
|
||||
Object.keys(componentInstance.cache).forEach((key, index) => {
|
||||
if (key != thisKey) {
|
||||
// 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 移除所有缓存
|
||||
closeAllTags({ componentInstance }) {
|
||||
// 销毁实例
|
||||
Object.keys(componentInstance.cache).forEach((key) => {
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
});
|
||||
// 删除缓存
|
||||
componentInstance.cache = {};
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys = [];
|
||||
},
|
||||
// 移除单个缓存
|
||||
closeSelectedTag({ componentInstance, regKey }) {
|
||||
let reg = new RegExp(`^${regKey}`);
|
||||
Object.keys(componentInstance.cache).forEach((key, i) => {
|
||||
if (reg.test(key)) {
|
||||
// 销毁实例
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys.splice(i, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 刷新单个缓存
|
||||
refreshSelectedTag({ componentInstance, thisKey }) {
|
||||
Object.keys(componentInstance.cache).forEach((key, index) => {
|
||||
if (null != thisKey && key.replace("/redirect", "") == thisKey) {
|
||||
// 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 2 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 3 移除key中对应的key
|
||||
componentInstance.keys.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -134,7 +31,7 @@ export default {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fixed-header + .app-main {
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
@ -144,7 +41,7 @@ export default {
|
||||
min-height: calc(100vh - 84px);
|
||||
}
|
||||
|
||||
.fixed-header + .app-main {
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 84px;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
mode="vertical"
|
||||
>
|
||||
<sidebar-item
|
||||
v-for="(route, index) in permission_routes"
|
||||
v-for="(route, index) in sidebarRouters"
|
||||
:key="route.path + index"
|
||||
:item="route"
|
||||
:base-path="route.path"
|
||||
@ -33,7 +33,7 @@ export default {
|
||||
components: { SidebarItem, Logo },
|
||||
computed: {
|
||||
...mapState(["settings"]),
|
||||
...mapGetters(["permission_routes", "sidebar"]),
|
||||
...mapGetters(["sidebarRouters", "sidebar"]),
|
||||
activeMenu() {
|
||||
const route = this.$route;
|
||||
const { meta, path } = route;
|
||||
|
@ -29,7 +29,6 @@
|
||||
<script>
|
||||
import ScrollPane from './ScrollPane'
|
||||
import path from 'path'
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
components: { ScrollPane },
|
||||
@ -145,7 +144,6 @@ export default {
|
||||
})
|
||||
})
|
||||
})
|
||||
Global.$emit("removeCache", "refreshSelectedTag", this.selectedTag);
|
||||
},
|
||||
closeSelectedTag(view) {
|
||||
this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
|
||||
@ -153,14 +151,12 @@ export default {
|
||||
this.toLastView(visitedViews, view)
|
||||
}
|
||||
})
|
||||
Global.$emit("removeCache", "closeSelectedTag", view);
|
||||
},
|
||||
closeOthersTags() {
|
||||
this.$router.push(this.selectedTag)
|
||||
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
|
||||
this.moveToCurrentTag()
|
||||
})
|
||||
Global.$emit("removeCache", "closeOthersTags", this.selectedTag);
|
||||
},
|
||||
closeAllTags(view) {
|
||||
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
|
||||
@ -169,7 +165,6 @@ export default {
|
||||
}
|
||||
this.toLastView(visitedViews, view)
|
||||
})
|
||||
Global.$emit("removeCache", "closeAllTags");
|
||||
},
|
||||
toLastView(visitedViews, view) {
|
||||
const latestView = visitedViews.slice(-1)[0]
|
||||
|
@ -23,28 +23,18 @@ router.beforeEach((to, from, next) => {
|
||||
// 拉取user_info
|
||||
const roles = res.roles
|
||||
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
|
||||
// 测试 默认静态页面
|
||||
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
store.dispatch('FedLogOut').then(() => {
|
||||
}).catch(err => {
|
||||
store.dispatch('LogOut').then(() => {
|
||||
Message.error(err)
|
||||
next({ path: '/' })
|
||||
})
|
||||
})
|
||||
} else {
|
||||
next()
|
||||
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
|
||||
// if (hasPermission(store.getters.roles, to.meta.roles)) {
|
||||
// next()
|
||||
// } else {
|
||||
// next({ path: '/401', replace: true, query: { noGoBack: true }})
|
||||
// }
|
||||
// 可删 ↑
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -10,6 +10,7 @@ const getters = {
|
||||
introduction: state => state.user.introduction,
|
||||
roles: state => state.user.roles,
|
||||
permissions: state => state.user.permissions,
|
||||
permission_routes: state => state.permission.routes
|
||||
permission_routes: state => state.permission.routes,
|
||||
sidebarRouters:state => state.permission.sidebarRouters,
|
||||
}
|
||||
export default getters
|
||||
|
@ -6,13 +6,17 @@ import ParentView from '@/components/ParentView';
|
||||
const permission = {
|
||||
state: {
|
||||
routes: [],
|
||||
addRoutes: []
|
||||
addRoutes: [],
|
||||
sidebarRouters: []
|
||||
},
|
||||
mutations: {
|
||||
SET_ROUTES: (state, routes) => {
|
||||
state.addRoutes = routes
|
||||
state.routes = constantRoutes.concat(routes)
|
||||
}
|
||||
},
|
||||
SET_SIDEBAR_ROUTERS: (state, routers) => {
|
||||
state.sidebarRouters = constantRoutes.concat(routers)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
// 生成路由
|
||||
@ -20,10 +24,14 @@ const permission = {
|
||||
return new Promise(resolve => {
|
||||
// 向后端请求路由数据
|
||||
getRouters().then(res => {
|
||||
const accessedRoutes = filterAsyncRouter(res.data)
|
||||
accessedRoutes.push({ path: '*', redirect: '/404', hidden: true })
|
||||
commit('SET_ROUTES', accessedRoutes)
|
||||
resolve(accessedRoutes)
|
||||
const sdata = JSON.parse(JSON.stringify(res.data))
|
||||
const rdata = JSON.parse(JSON.stringify(res.data))
|
||||
const sidebarRoutes = filterAsyncRouter(sdata)
|
||||
const rewriteRoutes = filterAsyncRouter(rdata, true)
|
||||
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
|
||||
commit('SET_ROUTES', rewriteRoutes)
|
||||
commit('SET_SIDEBAR_ROUTERS', sidebarRoutes)
|
||||
resolve(rewriteRoutes)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -31,8 +39,11 @@ const permission = {
|
||||
}
|
||||
|
||||
// 遍历后台传来的路由字符串,转换为组件对象
|
||||
function filterAsyncRouter(asyncRouterMap) {
|
||||
function filterAsyncRouter(asyncRouterMap, isRewrite = false) {
|
||||
return asyncRouterMap.filter(route => {
|
||||
if (isRewrite && route.children) {
|
||||
route.children = filterChildren(route.children)
|
||||
}
|
||||
if (route.component) {
|
||||
// Layout ParentView 组件特殊处理
|
||||
if (route.component === 'Layout') {
|
||||
@ -44,14 +55,35 @@ function filterAsyncRouter(asyncRouterMap) {
|
||||
}
|
||||
}
|
||||
if (route.children != null && route.children && route.children.length) {
|
||||
route.children = filterAsyncRouter(route.children)
|
||||
route.children = filterAsyncRouter(route.children, route, isRewrite)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
function filterChildren(childrenMap) {
|
||||
var children = []
|
||||
childrenMap.forEach((el, index) => {
|
||||
if (el.children && el.children.length) {
|
||||
if (el.component === 'ParentView') {
|
||||
el.children.forEach(c => {
|
||||
c.path = el.path + '/' + c.path
|
||||
if (c.children && c.children.length) {
|
||||
children = children.concat(filterChildren(c.children, c))
|
||||
return
|
||||
}
|
||||
children.push(c)
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
children = children.concat(el)
|
||||
})
|
||||
return children
|
||||
}
|
||||
|
||||
export const loadView = (view) => { // 路由懒加载
|
||||
return (resolve) => require([`@/views/${view}`], resolve)
|
||||
return (resolve) => require([`@/views/${view}`], resolve)
|
||||
}
|
||||
|
||||
export default permission
|
||||
|
@ -9,9 +9,10 @@ export function checkPermi(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const permissions = store.getters && store.getters.permissions
|
||||
const permissionDatas = value
|
||||
const all_permission = "*:*:*";
|
||||
|
||||
const hasPermission = permissions.some(permission => {
|
||||
return permissionDatas.includes(permission)
|
||||
return all_permission === permission || permissionDatas.includes(permission)
|
||||
})
|
||||
|
||||
if (!hasPermission) {
|
||||
@ -33,9 +34,10 @@ export function checkRole(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const roles = store.getters && store.getters.roles
|
||||
const permissionRoles = value
|
||||
const super_admin = "admin";
|
||||
|
||||
const hasRole = roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
return super_admin === role || permissionRoles.includes(role)
|
||||
})
|
||||
|
||||
if (!hasRole) {
|
||||
@ -46,4 +48,4 @@ export function checkRole(value) {
|
||||
console.error(`need roles! Like checkRole="['admin','editor']"`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ service.interceptors.request.use(config => {
|
||||
for (const propName of Object.keys(config.params)) {
|
||||
const value = config.params[propName];
|
||||
var part = encodeURIComponent(propName) + "=";
|
||||
if (value && typeof(value) !== "undefined") {
|
||||
if (value !== null && typeof(value) !== "undefined") {
|
||||
if (typeof value === 'object') {
|
||||
for (const key of Object.keys(value)) {
|
||||
let params = propName + '[' + key + ']';
|
||||
|
@ -62,8 +62,8 @@ export function addDateRange(params, dateRange, propName) {
|
||||
search.params["beginTime"] = dateRange[0];
|
||||
search.params["endTime"] = dateRange[1];
|
||||
} else {
|
||||
search.params[propName + "BeginTime"] = dateRange[0];
|
||||
search.params[propName + "EndTime"] = dateRange[1];
|
||||
search.params["begin" + propName] = dateRange[0];
|
||||
search.params["end" + propName] = dateRange[1];
|
||||
}
|
||||
}
|
||||
return search;
|
||||
|
@ -126,15 +126,12 @@ export default {
|
||||
Cookies.remove("password");
|
||||
Cookies.remove('rememberMe');
|
||||
}
|
||||
this.$store
|
||||
.dispatch("Login", this.loginForm)
|
||||
.then(() => {
|
||||
this.$router.push({ path: this.redirect || "/" });
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
this.getCode();
|
||||
});
|
||||
this.$store.dispatch("Login", this.loginForm).then(() => {
|
||||
this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
this.getCode();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
<script>
|
||||
import { updateUserPwd } from "@/api/system/user";
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -65,7 +64,6 @@ export default {
|
||||
});
|
||||
},
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/index" });
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
<script>
|
||||
import { updateUserProfile } from "@/api/system/user";
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -69,7 +68,6 @@ export default {
|
||||
});
|
||||
},
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/index" });
|
||||
}
|
||||
|
@ -127,7 +127,6 @@
|
||||
import { getGenTable, updateGenTable } from "@/api/tool/gen";
|
||||
import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
|
||||
import { listMenu as getMenuTreeselect } from "@/api/system/menu";
|
||||
import Global from "@/layout/components/global.js";
|
||||
import basicInfoForm from "./basicInfoForm";
|
||||
import genInfoForm from "./genInfoForm";
|
||||
import Sortable from 'sortablejs'
|
||||
@ -208,7 +207,6 @@ export default {
|
||||
},
|
||||
/** 关闭按钮 */
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/tool/gen", query: { t: Date.now()}})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user