mirror of
https://gitee.com/y_project/RuoYi-Cloud.git
synced 2026-01-26 11:51:55 +08:00
Compare commits
25 Commits
0d44bd6b8d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d54693b27 | ||
|
|
cfd619fa4f | ||
|
|
e942847b89 | ||
|
|
0b09d7c1da | ||
|
|
1c0562ba18 | ||
|
|
da65996e69 | ||
|
|
873444dd0b | ||
|
|
2301280c4d | ||
|
|
4eebb27956 | ||
|
|
c2ff461ff0 | ||
|
|
eb489bda83 | ||
|
|
1db2086163 | ||
|
|
839e4f35f5 | ||
|
|
f53b783049 | ||
|
|
97f30a5415 | ||
|
|
ad1d009165 | ||
|
|
90cbabb7a7 | ||
|
|
1c4dbb1e46 | ||
|
|
a3eefb6bad | ||
|
|
09e8e9995a | ||
|
|
381151bc50 | ||
|
|
66e502727a | ||
|
|
4265f8ecb7 | ||
|
|
2c82079d04 | ||
|
|
6aecd35a4f |
@@ -1,11 +1,11 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
|
||||||
</p>
|
</p>
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.6</h1>
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.7</h1>
|
||||||
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
|
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.6-brightgreen.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.7-brightgreen.svg"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ usage() {
|
|||||||
# copy sql
|
# copy sql
|
||||||
echo "begin copy sql "
|
echo "begin copy sql "
|
||||||
cp ../sql/ry_20250523.sql ./mysql/db
|
cp ../sql/ry_20250523.sql ./mysql/db
|
||||||
cp ../sql/ry_config_20250224.sql ./mysql/db
|
cp ../sql/ry_config_20250902.sql ./mysql/db
|
||||||
|
|
||||||
# copy html
|
# copy html
|
||||||
echo "begin copy html "
|
echo "begin copy html "
|
||||||
|
|||||||
12
pom.xml
12
pom.xml
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
|
|
||||||
<name>ruoyi</name>
|
<name>ruoyi</name>
|
||||||
<url>http://www.ruoyi.vip</url>
|
<url>http://www.ruoyi.vip</url>
|
||||||
<description>若依微服务系统</description>
|
<description>若依微服务系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi.version>3.6.6</ruoyi.version>
|
<ruoyi.version>3.6.7</ruoyi.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
@@ -24,18 +24,18 @@
|
|||||||
<tobato.version>1.27.2</tobato.version>
|
<tobato.version>1.27.2</tobato.version>
|
||||||
<kaptcha.version>2.3.3</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<pagehelper.boot.version>2.0.0</pagehelper.boot.version>
|
<pagehelper.boot.version>2.0.0</pagehelper.boot.version>
|
||||||
<druid.version>1.2.23</druid.version>
|
<druid.version>1.2.27</druid.version>
|
||||||
<dynamic-ds.version>4.3.1</dynamic-ds.version>
|
<dynamic-ds.version>4.3.1</dynamic-ds.version>
|
||||||
<commons.io.version>2.19.0</commons.io.version>
|
<commons.io.version>2.21.0</commons.io.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<fastjson.version>2.0.57</fastjson.version>
|
<fastjson.version>2.0.60</fastjson.version>
|
||||||
<jjwt.version>0.9.1</jjwt.version>
|
<jjwt.version>0.9.1</jjwt.version>
|
||||||
<minio.version>8.2.2</minio.version>
|
<minio.version>8.2.2</minio.version>
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<springdoc.version>1.6.9</springdoc.version>
|
<springdoc.version>1.6.9</springdoc.version>
|
||||||
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
|
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
|
||||||
<!-- override dependency version -->
|
<!-- override dependency version -->
|
||||||
<tomcat.version>9.0.108</tomcat.version>
|
<tomcat.version>9.0.112</tomcat.version>
|
||||||
<logback.version>1.2.13</logback.version>
|
<logback.version>1.2.13</logback.version>
|
||||||
<spring-framework.version>5.3.39</spring-framework.version>
|
<spring-framework.version>5.3.39</spring-framework.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-api</artifactId>
|
<artifactId>ruoyi-api</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -114,11 +114,6 @@ public class SysUser extends BaseEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAdmin()
|
public boolean isAdmin()
|
||||||
{
|
|
||||||
return isAdmin(this.userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAdmin(Long userId)
|
|
||||||
{
|
{
|
||||||
return UserConstants.isAdmin(userId);
|
return UserConstants.isAdmin(userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,16 @@ public class Constants
|
|||||||
*/
|
*/
|
||||||
public static final String LOGIN_FAIL = "Error";
|
public static final String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有权限标识
|
||||||
|
*/
|
||||||
|
public static final String ALL_PERMISSION = "*:*:*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员角色权限标识
|
||||||
|
*/
|
||||||
|
public static final String SUPER_ADMIN = "admin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前记录起始索引
|
* 当前记录起始索引
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.ruoyi.common.core.exception.file;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件上传 误异常类
|
* 文件上传无效扩展名异常类
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -147,12 +147,12 @@ public class ExcelUtil<T>
|
|||||||
/**
|
/**
|
||||||
* 对象的子列表方法
|
* 对象的子列表方法
|
||||||
*/
|
*/
|
||||||
private Method subMethod;
|
private Map<String, Method> subMethods;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象的子列表属性
|
* 对象的子列表属性
|
||||||
*/
|
*/
|
||||||
private List<Field> subFields;
|
private Map<String, List<Field>> subFieldsMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计列表
|
* 统计列表
|
||||||
@@ -225,7 +225,10 @@ public class ExcelUtil<T>
|
|||||||
int titleLastCol = this.fields.size() - 1;
|
int titleLastCol = this.fields.size() - 1;
|
||||||
if (isSubList())
|
if (isSubList())
|
||||||
{
|
{
|
||||||
titleLastCol = titleLastCol + subFields.size() - 1;
|
for (List<Field> currentSubFields : subFieldsMap.values())
|
||||||
|
{
|
||||||
|
titleLastCol = titleLastCol + currentSubFields.size() - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
|
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
|
||||||
titleRow.setHeightInPoints(30);
|
titleRow.setHeightInPoints(30);
|
||||||
@@ -245,16 +248,17 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
Row subRow = sheet.createRow(rownum);
|
Row subRow = sheet.createRow(rownum);
|
||||||
int column = 0;
|
int column = 0;
|
||||||
int subFieldSize = subFields != null ? subFields.size() : 0;
|
|
||||||
for (Object[] objects : fields)
|
for (Object[] objects : fields)
|
||||||
{
|
{
|
||||||
Field field = (Field) objects[0];
|
Field field = (Field) objects[0];
|
||||||
Excel attr = (Excel) objects[1];
|
Excel attr = (Excel) objects[1];
|
||||||
|
CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
|
||||||
if (Collection.class.isAssignableFrom(field.getType()))
|
if (Collection.class.isAssignableFrom(field.getType()))
|
||||||
{
|
{
|
||||||
Cell cell = subRow.createCell(column);
|
Cell cell = subRow.createCell(column);
|
||||||
cell.setCellValue(attr.name());
|
cell.setCellValue(attr.name());
|
||||||
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
|
cell.setCellStyle(cellStyle);
|
||||||
|
int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
|
||||||
if (subFieldSize > 1)
|
if (subFieldSize > 1)
|
||||||
{
|
{
|
||||||
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
|
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
|
||||||
@@ -266,7 +270,7 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
Cell cell = subRow.createCell(column++);
|
Cell cell = subRow.createCell(column++);
|
||||||
cell.setCellValue(attr.name());
|
cell.setCellValue(attr.name());
|
||||||
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
|
cell.setCellStyle(cellStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rownum++;
|
rownum++;
|
||||||
@@ -338,7 +342,11 @@ public class ExcelUtil<T>
|
|||||||
Map<String, Integer> cellMap = new HashMap<String, Integer>();
|
Map<String, Integer> cellMap = new HashMap<String, Integer>();
|
||||||
// 获取表头
|
// 获取表头
|
||||||
Row heard = sheet.getRow(titleNum);
|
Row heard = sheet.getRow(titleNum);
|
||||||
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
|
if (heard == null)
|
||||||
|
{
|
||||||
|
throw new UtilException("文件标题行为空,请检查Excel文件格式");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < heard.getLastCellNum(); i++)
|
||||||
{
|
{
|
||||||
Cell cell = heard.getCell(i);
|
Cell cell = heard.getCell(i);
|
||||||
if (StringUtils.isNotNull(cell))
|
if (StringUtils.isNotNull(cell))
|
||||||
@@ -346,10 +354,6 @@ public class ExcelUtil<T>
|
|||||||
String value = this.getCellValue(heard, i).toString();
|
String value = this.getCellValue(heard, i).toString();
|
||||||
cellMap.put(value, i);
|
cellMap.put(value, i);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
cellMap.put(null, i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 有数据时才处理 得到类的所有field.
|
// 有数据时才处理 得到类的所有field.
|
||||||
List<Object[]> fields = this.getFields();
|
List<Object[]> fields = this.getFields();
|
||||||
@@ -562,7 +566,8 @@ public class ExcelUtil<T>
|
|||||||
Excel excel = (Excel) os[1];
|
Excel excel = (Excel) os[1];
|
||||||
if (Collection.class.isAssignableFrom(field.getType()))
|
if (Collection.class.isAssignableFrom(field.getType()))
|
||||||
{
|
{
|
||||||
for (Field subField : subFields)
|
List<Field> currentSubFields = subFieldsMap.get(field.getName());
|
||||||
|
for (Field subField : currentSubFields)
|
||||||
{
|
{
|
||||||
Excel subExcel = subField.getAnnotation(Excel.class);
|
Excel subExcel = subField.getAnnotation(Excel.class);
|
||||||
this.createHeadCell(subExcel, row, column++);
|
this.createHeadCell(subExcel, row, column++);
|
||||||
@@ -575,7 +580,7 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
if (Type.EXPORT.equals(type))
|
if (Type.EXPORT.equals(type))
|
||||||
{
|
{
|
||||||
fillExcelData(index, row);
|
fillExcelData(index);
|
||||||
addStatisticsRow();
|
addStatisticsRow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,10 +590,9 @@ public class ExcelUtil<T>
|
|||||||
* 填充excel数据
|
* 填充excel数据
|
||||||
*
|
*
|
||||||
* @param index 序号
|
* @param index 序号
|
||||||
* @param row 单元格行
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void fillExcelData(int index, Row row)
|
public void fillExcelData(int index)
|
||||||
{
|
{
|
||||||
int startNo = index * sheetSize;
|
int startNo = index * sheetSize;
|
||||||
int endNo = Math.min(startNo + sheetSize, list.size());
|
int endNo = Math.min(startNo + sheetSize, list.size());
|
||||||
@@ -596,7 +600,7 @@ public class ExcelUtil<T>
|
|||||||
|
|
||||||
for (int i = startNo; i < endNo; i++)
|
for (int i = startNo; i < endNo; i++)
|
||||||
{
|
{
|
||||||
row = sheet.createRow(currentRowNum);
|
Row row = sheet.createRow(currentRowNum);
|
||||||
T vo = (T) list.get(i);
|
T vo = (T) list.get(i);
|
||||||
int column = 0;
|
int column = 0;
|
||||||
int maxSubListSize = getCurrentMaxSubListSize(vo);
|
int maxSubListSize = getCurrentMaxSubListSize(vo);
|
||||||
@@ -609,6 +613,7 @@ public class ExcelUtil<T>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
|
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
|
||||||
|
List<Field> currentSubFields = subFieldsMap.get(field.getName());
|
||||||
if (subList != null && !subList.isEmpty())
|
if (subList != null && !subList.isEmpty())
|
||||||
{
|
{
|
||||||
int subIndex = 0;
|
int subIndex = 0;
|
||||||
@@ -621,15 +626,15 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
int subColumn = column;
|
int subColumn = column;
|
||||||
for (Field subField : subFields)
|
for (Field subField : currentSubFields)
|
||||||
{
|
{
|
||||||
Excel subExcel = subField.getAnnotation(Excel.class);
|
Excel subExcel = subField.getAnnotation(Excel.class);
|
||||||
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
|
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
|
||||||
}
|
}
|
||||||
subIndex++;
|
subIndex++;
|
||||||
}
|
}
|
||||||
column += subFields.size();
|
|
||||||
}
|
}
|
||||||
|
column += currentSubFields.size();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -982,7 +987,7 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
// 创建cell
|
// 创建cell
|
||||||
cell = row.createCell(column);
|
cell = row.createCell(column);
|
||||||
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
|
if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge())
|
||||||
{
|
{
|
||||||
if (subMergedLastRowNum >= subMergedFirstRowNum)
|
if (subMergedLastRowNum >= subMergedFirstRowNum)
|
||||||
{
|
{
|
||||||
@@ -998,7 +1003,7 @@ public class ExcelUtil<T>
|
|||||||
String separator = attr.separator();
|
String separator = attr.separator();
|
||||||
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
|
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
|
||||||
{
|
{
|
||||||
cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
|
cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat));
|
||||||
cell.setCellValue(parseDateToStr(dateFormat, value));
|
cell.setCellValue(parseDateToStr(dateFormat, value));
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
|
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
|
||||||
@@ -1028,6 +1033,21 @@ public class ExcelUtil<T>
|
|||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用自定义格式,同时避免样式污染
|
||||||
|
*
|
||||||
|
* @param cellStyle 从此样式复制
|
||||||
|
* @param format 格式匹配的字符串
|
||||||
|
* @return 格式化后CellStyle对象
|
||||||
|
*/
|
||||||
|
private CellStyle createCellStyle(CellStyle cellStyle, String format)
|
||||||
|
{
|
||||||
|
CellStyle style = wb.createCellStyle();
|
||||||
|
style.cloneStyleFrom(cellStyle);
|
||||||
|
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 POI XSSFSheet 单元格提示或选择框
|
* 设置 POI XSSFSheet 单元格提示或选择框
|
||||||
*
|
*
|
||||||
@@ -1079,18 +1099,36 @@ public class ExcelUtil<T>
|
|||||||
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
|
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
|
||||||
{
|
{
|
||||||
String hideSheetName = "combo_" + firstCol + "_" + endCol;
|
String hideSheetName = "combo_" + firstCol + "_" + endCol;
|
||||||
Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
|
Sheet hideSheet = null;
|
||||||
for (int i = 0; i < textlist.length; i++)
|
String hideSheetDataName = hideSheetName + "_data";
|
||||||
|
Name name = wb.getName(hideSheetDataName);
|
||||||
|
if (name != null)
|
||||||
{
|
{
|
||||||
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
|
// 名称已存在,尝试从名称的引用中找到sheet名称
|
||||||
|
String refersToFormula = name.getRefersToFormula();
|
||||||
|
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
|
||||||
|
{
|
||||||
|
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
|
||||||
|
hideSheet = wb.getSheet(sheetNameFromFormula);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 创建名称,可被其他单元格引用
|
|
||||||
Name name = wb.createName();
|
if (hideSheet == null)
|
||||||
name.setNameName(hideSheetName + "_data");
|
{
|
||||||
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
|
hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
|
||||||
|
for (int i = 0; i < textlist.length; i++)
|
||||||
|
{
|
||||||
|
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
|
||||||
|
}
|
||||||
|
// 创建名称,可被其他单元格引用
|
||||||
|
name = wb.createName();
|
||||||
|
name.setNameName(hideSheetDataName);
|
||||||
|
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
|
||||||
|
}
|
||||||
|
|
||||||
DataValidationHelper helper = sheet.getDataValidationHelper();
|
DataValidationHelper helper = sheet.getDataValidationHelper();
|
||||||
// 加载下拉列表内容
|
// 加载下拉列表内容
|
||||||
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
|
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName);
|
||||||
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
|
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
|
||||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
||||||
// 数据有效性对象
|
// 数据有效性对象
|
||||||
@@ -1328,6 +1366,8 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
List<Object[]> fields = new ArrayList<Object[]>();
|
List<Object[]> fields = new ArrayList<Object[]>();
|
||||||
List<Field> tempFields = new ArrayList<>();
|
List<Field> tempFields = new ArrayList<>();
|
||||||
|
subFieldsMap = new HashMap<>();
|
||||||
|
subMethods = new HashMap<>();
|
||||||
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
|
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
|
||||||
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||||
if (StringUtils.isNotEmpty(includeFields))
|
if (StringUtils.isNotEmpty(includeFields))
|
||||||
@@ -1375,10 +1415,11 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
if (Collection.class.isAssignableFrom(field.getType()))
|
if (Collection.class.isAssignableFrom(field.getType()))
|
||||||
{
|
{
|
||||||
subMethod = getSubMethod(field.getName(), clazz);
|
String fieldName = field.getName();
|
||||||
|
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
|
||||||
ParameterizedType pt = (ParameterizedType) field.getGenericType();
|
ParameterizedType pt = (ParameterizedType) field.getGenericType();
|
||||||
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
|
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
|
||||||
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
|
subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1447,7 +1488,8 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
this.sheet = wb.createSheet();
|
this.sheet = wb.createSheet();
|
||||||
this.createTitle();
|
this.createTitle();
|
||||||
wb.setSheetName(index, sheetName + index);
|
int actualIndex = wb.getSheetIndex(this.sheet);
|
||||||
|
wb.setSheetName(actualIndex, sheetName + index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1572,7 +1614,7 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
public boolean isSubList()
|
public boolean isSubList()
|
||||||
{
|
{
|
||||||
return StringUtils.isNotNull(subFields) && subFields.size() > 0;
|
return !StringUtils.isEmpty(subFieldsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1580,24 +1622,32 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
public boolean isSubListValue(T vo)
|
public boolean isSubListValue(T vo)
|
||||||
{
|
{
|
||||||
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
|
return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取集合的值
|
* 获取集合的值
|
||||||
*/
|
*/
|
||||||
public Collection<?> getListCellValue(Object obj)
|
public int getListCellValue(Object obj)
|
||||||
{
|
{
|
||||||
Object value;
|
Collection<?> value;
|
||||||
|
int max = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
value = subMethod.invoke(obj, new Object[] {});
|
for (String s : subMethods.keySet())
|
||||||
|
{
|
||||||
|
value = (Collection<?>) subMethods.get(s).invoke(obj);
|
||||||
|
if (value.size() > max)
|
||||||
|
{
|
||||||
|
max = value.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
return new ArrayList<Object>();
|
return 0;
|
||||||
}
|
}
|
||||||
return (Collection<?>) value;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class DataScopeAspect
|
|||||||
List<String> conditions = new ArrayList<String>();
|
List<String> conditions = new ArrayList<String>();
|
||||||
List<String> scopeCustomIds = new ArrayList<String>();
|
List<String> scopeCustomIds = new ArrayList<String>();
|
||||||
user.getRoles().forEach(role -> {
|
user.getRoles().forEach(role -> {
|
||||||
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))))
|
||||||
{
|
{
|
||||||
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
|
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ public class DataScopeAspect
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public class LogAspect
|
|||||||
/** 计算操作消耗时间 */
|
/** 计算操作消耗时间 */
|
||||||
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
||||||
|
|
||||||
|
/** 参数最大长度限制 */
|
||||||
|
private static final int PARAM_MAX_LENGTH = 2000;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsyncLogService asyncLogService;
|
private AsyncLogService asyncLogService;
|
||||||
|
|
||||||
@@ -166,16 +169,16 @@ public class LogAspect
|
|||||||
*/
|
*/
|
||||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
||||||
{
|
{
|
||||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
|
||||||
String requestMethod = operLog.getRequestMethod();
|
String requestMethod = operLog.getRequestMethod();
|
||||||
|
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||||
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
|
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
|
||||||
{
|
{
|
||||||
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
||||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
operLog.setOperParam(params);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
|
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +187,7 @@ public class LogAspect
|
|||||||
*/
|
*/
|
||||||
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
||||||
{
|
{
|
||||||
String params = "";
|
StringBuilder params = new StringBuilder();
|
||||||
if (paramsArray != null && paramsArray.length > 0)
|
if (paramsArray != null && paramsArray.length > 0)
|
||||||
{
|
{
|
||||||
for (Object o : paramsArray)
|
for (Object o : paramsArray)
|
||||||
@@ -194,15 +197,20 @@ public class LogAspect
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
||||||
params += jsonObj.toString() + " ";
|
params.append(jsonObj).append(" ");
|
||||||
|
if (params.length() >= PARAM_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return params.trim();
|
return params.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import com.ruoyi.common.core.constant.SecurityConstants;
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
import com.ruoyi.common.core.constant.TokenConstants;
|
import com.ruoyi.common.core.constant.TokenConstants;
|
||||||
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.context.SecurityContextHolder;
|
import com.ruoyi.common.core.context.SecurityContextHolder;
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
@@ -79,6 +80,16 @@ public class SecurityUtils
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为管理员
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean isAdmin()
|
||||||
|
{
|
||||||
|
return isAdmin(getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为管理员
|
* 是否为管理员
|
||||||
*
|
*
|
||||||
@@ -87,7 +98,7 @@ public class SecurityUtils
|
|||||||
*/
|
*/
|
||||||
public static boolean isAdmin(Long userId)
|
public static boolean isAdmin(Long userId)
|
||||||
{
|
{
|
||||||
return userId != null && 1L == userId;
|
return UserConstants.isAdmin(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-modules</artifactId>
|
<artifactId>ruoyi-modules</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-modules</artifactId>
|
<artifactId>ruoyi-modules</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ function getList() {
|
|||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
|
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ function getList() {
|
|||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
|
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-modules</artifactId>
|
<artifactId>ruoyi-modules</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-modules</artifactId>
|
<artifactId>ruoyi-modules</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ public class SysMenuController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||||
}
|
}
|
||||||
|
else if (!menuService.checkRouteConfigUnique(menu))
|
||||||
|
{
|
||||||
|
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
|
||||||
|
}
|
||||||
menu.setCreateBy(SecurityUtils.getUsername());
|
menu.setCreateBy(SecurityUtils.getUsername());
|
||||||
return toAjax(menuService.insertMenu(menu));
|
return toAjax(menuService.insertMenu(menu));
|
||||||
}
|
}
|
||||||
@@ -121,6 +125,10 @@ public class SysMenuController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
|
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
|
||||||
}
|
}
|
||||||
|
else if (!menuService.checkRouteConfigUnique(menu))
|
||||||
|
{
|
||||||
|
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
|
||||||
|
}
|
||||||
menu.setUpdateBy(SecurityUtils.getUsername());
|
menu.setUpdateBy(SecurityUtils.getUsername());
|
||||||
return toAjax(menuService.updateMenu(menu));
|
return toAjax(menuService.updateMenu(menu));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public class SysUserController extends BaseController
|
|||||||
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
|
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
List<SysRole> roles = roleService.selectRoleAll();
|
List<SysRole> roles = roleService.selectRoleAll();
|
||||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
ajax.put("posts", postService.selectPostAll());
|
ajax.put("posts", postService.selectPostAll());
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ public class SysUserController extends BaseController
|
|||||||
SysUser user = userService.selectUserById(userId);
|
SysUser user = userService.selectUserById(userId);
|
||||||
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||||
ajax.put("user", user);
|
ajax.put("user", user);
|
||||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,4 +122,13 @@ public interface SysMenuMapper
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
|
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据路由路径或名称查询菜单信息(用于唯一性校验)
|
||||||
|
*
|
||||||
|
* @param path 路由地址
|
||||||
|
* @param routeName 路由名称
|
||||||
|
* @return 匹配的菜单列表
|
||||||
|
*/
|
||||||
|
public List<SysMenu> selectMenusByPathOrRouteName(@Param("path") String path, @Param("routeName") String routeName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,4 +141,12 @@ public interface ISysMenuService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public boolean checkMenuNameUnique(SysMenu menu);
|
public boolean checkMenuNameUnique(SysMenu menu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验路由组合是否唯一
|
||||||
|
*
|
||||||
|
* @param menu 菜单信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean checkRouteConfigUnique(SysMenu menu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import com.ruoyi.common.datascope.annotation.DataScope;
|
|||||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.system.api.domain.SysDept;
|
import com.ruoyi.system.api.domain.SysDept;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
|
||||||
import com.ruoyi.system.domain.vo.TreeSelect;
|
import com.ruoyi.system.domain.vo.TreeSelect;
|
||||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||||
import com.ruoyi.system.mapper.SysRoleMapper;
|
import com.ruoyi.system.mapper.SysRoleMapper;
|
||||||
@@ -190,7 +189,7 @@ public class SysDeptServiceImpl implements ISysDeptService
|
|||||||
@Override
|
@Override
|
||||||
public void checkDeptDataScope(Long deptId)
|
public void checkDeptDataScope(Long deptId)
|
||||||
{
|
{
|
||||||
if (!SysUser.isAdmin(SecurityUtils.getUserId()) && StringUtils.isNotNull(deptId))
|
if (!SecurityUtils.isAdmin() && StringUtils.isNotNull(deptId))
|
||||||
{
|
{
|
||||||
SysDept dept = new SysDept();
|
SysDept dept = new SysDept();
|
||||||
dept.setDeptId(deptId);
|
dept.setDeptId(deptId);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.ruoyi.common.core.constant.Constants;
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
@@ -15,7 +17,6 @@ import com.ruoyi.common.core.constant.UserConstants;
|
|||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
|
||||||
import com.ruoyi.system.domain.SysMenu;
|
import com.ruoyi.system.domain.SysMenu;
|
||||||
import com.ruoyi.system.domain.vo.MetaVo;
|
import com.ruoyi.system.domain.vo.MetaVo;
|
||||||
import com.ruoyi.system.domain.vo.RouterVo;
|
import com.ruoyi.system.domain.vo.RouterVo;
|
||||||
@@ -33,8 +34,12 @@ import com.ruoyi.system.service.ISysMenuService;
|
|||||||
@Service
|
@Service
|
||||||
public class SysMenuServiceImpl implements ISysMenuService
|
public class SysMenuServiceImpl implements ISysMenuService
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SysMenuServiceImpl.class);
|
||||||
|
|
||||||
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
|
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
|
||||||
|
|
||||||
|
public static final Long MENU_ROOT_ID = 0L;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysMenuMapper menuMapper;
|
private SysMenuMapper menuMapper;
|
||||||
|
|
||||||
@@ -67,7 +72,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
{
|
{
|
||||||
List<SysMenu> menuList = null;
|
List<SysMenu> menuList = null;
|
||||||
// 管理员显示所有菜单信息
|
// 管理员显示所有菜单信息
|
||||||
if (SysUser.isAdmin(userId))
|
if (SecurityUtils.isAdmin(userId))
|
||||||
{
|
{
|
||||||
menuList = menuMapper.selectMenuList(menu);
|
menuList = menuMapper.selectMenuList(menu);
|
||||||
}
|
}
|
||||||
@@ -139,7 +144,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
{
|
{
|
||||||
menus = menuMapper.selectMenuTreeByUserId(userId);
|
menus = menuMapper.selectMenuTreeByUserId(userId);
|
||||||
}
|
}
|
||||||
return getChildPerms(menus, 0);
|
return getChildPerms(menus, MENU_ROOT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,7 +199,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
childrenList.add(children);
|
childrenList.add(children);
|
||||||
router.setChildren(childrenList);
|
router.setChildren(childrenList);
|
||||||
}
|
}
|
||||||
else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
|
else if (menu.getParentId().intValue() == MENU_ROOT_ID && isInnerLink(menu))
|
||||||
{
|
{
|
||||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
|
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
|
||||||
router.setPath("/");
|
router.setPath("/");
|
||||||
@@ -346,6 +351,47 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
return UserConstants.UNIQUE;
|
return UserConstants.UNIQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验路由名称是否唯一
|
||||||
|
*
|
||||||
|
* @param menu 菜单信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean checkRouteConfigUnique(SysMenu menu)
|
||||||
|
{
|
||||||
|
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
|
||||||
|
Long parentId = menu.getParentId();
|
||||||
|
String path = menu.getPath();
|
||||||
|
String routeName = StringUtils.isEmpty(menu.getRouteName()) ? path : menu.getRouteName();
|
||||||
|
List<SysMenu> sysMenuList = menuMapper.selectMenusByPathOrRouteName(path, routeName);
|
||||||
|
for (SysMenu sysMenu : sysMenuList)
|
||||||
|
{
|
||||||
|
if (sysMenu.getMenuId().longValue() != menuId.longValue())
|
||||||
|
{
|
||||||
|
Long dbParentId = sysMenu.getParentId();
|
||||||
|
String dbPath = sysMenu.getPath();
|
||||||
|
String dbRouteName = StringUtils.isEmpty(sysMenu.getRouteName()) ? dbPath : sysMenu.getRouteName();
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == dbParentId.longValue())
|
||||||
|
{
|
||||||
|
log.warn("[同级路由冲突] 同级下已存在相同路由路径 '{}',冲突菜单:{}", dbPath, sysMenu.getMenuName());
|
||||||
|
return UserConstants.NOT_UNIQUE;
|
||||||
|
}
|
||||||
|
else if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == MENU_ROOT_ID)
|
||||||
|
{
|
||||||
|
log.warn("[根目录路由冲突] 根目录下路由 '{}' 必须唯一,已被菜单 '{}' 占用", path, sysMenu.getMenuName());
|
||||||
|
return UserConstants.NOT_UNIQUE;
|
||||||
|
}
|
||||||
|
else if (StringUtils.equalsAnyIgnoreCase(routeName, dbRouteName))
|
||||||
|
{
|
||||||
|
log.warn("[路由名称冲突] 路由名称 '{}' 需全局唯一,已被菜单 '{}' 使用", routeName, sysMenu.getMenuName());
|
||||||
|
return UserConstants.NOT_UNIQUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UserConstants.UNIQUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取路由名称
|
* 获取路由名称
|
||||||
*
|
*
|
||||||
@@ -385,12 +431,12 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
{
|
{
|
||||||
String routerPath = menu.getPath();
|
String routerPath = menu.getPath();
|
||||||
// 内链打开外网方式
|
// 内链打开外网方式
|
||||||
if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
|
if (menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu))
|
||||||
{
|
{
|
||||||
routerPath = innerLinkReplaceEach(routerPath);
|
routerPath = innerLinkReplaceEach(routerPath);
|
||||||
}
|
}
|
||||||
// 非外链并且是一级目录(类型为目录)
|
// 非外链并且是一级目录(类型为目录)
|
||||||
if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
|
if (MENU_ROOT_ID == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
|
||||||
&& UserConstants.NO_FRAME.equals(menu.getIsFrame()))
|
&& UserConstants.NO_FRAME.equals(menu.getIsFrame()))
|
||||||
{
|
{
|
||||||
routerPath = "/" + menu.getPath();
|
routerPath = "/" + menu.getPath();
|
||||||
@@ -416,7 +462,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
{
|
{
|
||||||
component = menu.getComponent();
|
component = menu.getComponent();
|
||||||
}
|
}
|
||||||
else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
|
else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu))
|
||||||
{
|
{
|
||||||
component = UserConstants.INNER_LINK;
|
component = UserConstants.INNER_LINK;
|
||||||
}
|
}
|
||||||
@@ -435,10 +481,21 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
*/
|
*/
|
||||||
public boolean isMenuFrame(SysMenu menu)
|
public boolean isMenuFrame(SysMenu menu)
|
||||||
{
|
{
|
||||||
return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
|
return menu.getParentId().intValue() == MENU_ROOT_ID && UserConstants.TYPE_MENU.equals(menu.getMenuType())
|
||||||
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
|
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为parent_view组件
|
||||||
|
*
|
||||||
|
* @param menu 菜单信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean isParentView(SysMenu menu)
|
||||||
|
{
|
||||||
|
return menu.getParentId().intValue() != MENU_ROOT_ID && UserConstants.TYPE_DIR.equals(menu.getMenuType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为内链组件
|
* 是否为内链组件
|
||||||
*
|
*
|
||||||
@@ -450,17 +507,6 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
|
return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为parent_view组件
|
|
||||||
*
|
|
||||||
* @param menu 菜单信息
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
public boolean isParentView(SysMenu menu)
|
|
||||||
{
|
|
||||||
return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据父节点的ID获取所有子节点
|
* 根据父节点的ID获取所有子节点
|
||||||
*
|
*
|
||||||
@@ -468,7 +514,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
* @param parentId 传入的父节点ID
|
* @param parentId 传入的父节点ID
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
|
public List<SysMenu> getChildPerms(List<SysMenu> list, long parentId)
|
||||||
{
|
{
|
||||||
List<SysMenu> returnList = new ArrayList<SysMenu>();
|
List<SysMenu> returnList = new ArrayList<SysMenu>();
|
||||||
for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
|
for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.Set;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
@@ -41,7 +42,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
|
|||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin())
|
||||||
{
|
{
|
||||||
roles.add("admin");
|
roles.add(Constants.SUPER_ADMIN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -63,7 +64,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
|
|||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin())
|
||||||
{
|
{
|
||||||
perms.add("*:*:*");
|
perms.add(Constants.ALL_PERMISSION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import com.ruoyi.common.core.utils.StringUtils;
|
|||||||
import com.ruoyi.common.datascope.annotation.DataScope;
|
import com.ruoyi.common.datascope.annotation.DataScope;
|
||||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
|
||||||
import com.ruoyi.system.domain.SysRoleDept;
|
import com.ruoyi.system.domain.SysRoleDept;
|
||||||
import com.ruoyi.system.domain.SysRoleMenu;
|
import com.ruoyi.system.domain.SysRoleMenu;
|
||||||
import com.ruoyi.system.domain.SysUserRole;
|
import com.ruoyi.system.domain.SysUserRole;
|
||||||
@@ -197,7 +196,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
|||||||
@Override
|
@Override
|
||||||
public void checkRoleDataScope(Long... roleIds)
|
public void checkRoleDataScope(Long... roleIds)
|
||||||
{
|
{
|
||||||
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
|
if (!SecurityUtils.isAdmin())
|
||||||
{
|
{
|
||||||
for (Long roleId : roleIds)
|
for (Long roleId : roleIds)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ public class SysUserServiceImpl implements ISysUserService
|
|||||||
@Override
|
@Override
|
||||||
public void checkUserDataScope(Long userId)
|
public void checkUserDataScope(Long userId)
|
||||||
{
|
{
|
||||||
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
|
if (!SecurityUtils.isAdmin())
|
||||||
{
|
{
|
||||||
SysUser user = new SysUser();
|
SysUser user = new SysUser();
|
||||||
user.setUserId(userId);
|
user.setUserId(userId);
|
||||||
|
|||||||
@@ -130,7 +130,12 @@
|
|||||||
|
|
||||||
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
|
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
|
||||||
<include refid="selectMenuVo"/>
|
<include refid="selectMenuVo"/>
|
||||||
where menu_name=#{menuName} and parent_id = #{parentId} limit 1
|
where menu_name= #{menuName} and parent_id = #{parentId} limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectMenusByPathOrRouteName" parameterType="SysMenu" resultMap="SysMenuResult">
|
||||||
|
<include refid="selectMenuVo"/>
|
||||||
|
where menu_type in ('M', 'C') and (path = #{path} or path = #{routeName} or route_name = #{path} or route_name = #{routeName})
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<update id="updateMenu" parameterType="SysMenu">
|
<update id="updateMenu" parameterType="SysMenu">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ruoyi",
|
"name": "ruoyi",
|
||||||
"version": "3.6.6",
|
"version": "3.6.7",
|
||||||
"description": "若依管理系统",
|
"description": "若依管理系统",
|
||||||
"author": "若依",
|
"author": "若依",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -130,6 +130,16 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* horizontal el menu */
|
||||||
|
.el-menu--horizontal .el-menu-item .svg-icon + span,
|
||||||
|
.el-menu--horizontal .el-submenu__title .svg-icon + span {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--horizontal .el-menu--popup {
|
||||||
|
min-width: 120px !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.pagination-container .el-pagination > .el-pagination__jump {
|
.pagination-container .el-pagination > .el-pagination__jump {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
margin-right: 16px;
|
margin-right: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu {
|
.el-menu {
|
||||||
@@ -116,15 +116,17 @@
|
|||||||
margin-left: 54px;
|
margin-left: 54px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu-title-noDropdown {
|
.el-menu:not(.el-menu--horizontal) {
|
||||||
padding: 0 !important;
|
.submenu-title-noDropdown {
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.el-tooltip {
|
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.svg-icon {
|
.el-tooltip {
|
||||||
margin-left: 20px;
|
padding: 0 !important;
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ export default {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
margin-left: 8px;
|
|
||||||
.no-redirect {
|
.no-redirect {
|
||||||
color: #97a8be;
|
color: #97a8be;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<template v-for="(item, index) in options">
|
<template v-for="(item, index) in options">
|
||||||
<template v-if="values.includes(item.value)">
|
<template v-if="isValueMatch(item.value)">
|
||||||
<span
|
<span
|
||||||
v-if="(item.raw.listClass == 'default' || item.raw.listClass == '') && (item.raw.cssClass == '' || item.raw.cssClass == null)"
|
v-if="(item.raw.listClass == 'default' || item.raw.listClass == '') && (item.raw.cssClass == '' || item.raw.cssClass == null)"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
@@ -36,7 +36,6 @@ export default {
|
|||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
value: [Number, String, Array],
|
value: [Number, String, Array],
|
||||||
// 当未找到匹配的数据时,显示value
|
|
||||||
showValue: {
|
showValue: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@@ -54,6 +53,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
values() {
|
values() {
|
||||||
if (this.value === null || typeof this.value === 'undefined' || this.value === '') return []
|
if (this.value === null || typeof this.value === 'undefined' || this.value === '') return []
|
||||||
|
if (typeof this.value === 'number' || typeof this.value === 'boolean') return [this.value]
|
||||||
return Array.isArray(this.value) ? this.value.map(item => '' + item) : String(this.value).split(this.separator)
|
return Array.isArray(this.value) ? this.value.map(item => '' + item) : String(this.value).split(this.separator)
|
||||||
},
|
},
|
||||||
unmatch() {
|
unmatch() {
|
||||||
@@ -63,14 +63,18 @@ export default {
|
|||||||
// 传入值为数组
|
// 传入值为数组
|
||||||
let unmatch = false // 添加一个标志来判断是否有未匹配项
|
let unmatch = false // 添加一个标志来判断是否有未匹配项
|
||||||
this.values.forEach(item => {
|
this.values.forEach(item => {
|
||||||
if (!this.options.some(v => v.value === item)) {
|
if (!this.options.some(v => v.value == item)) {
|
||||||
this.unmatchArray.push(item)
|
this.unmatchArray.push(item)
|
||||||
unmatch = true // 如果有未匹配项,将标志设置为true
|
unmatch = true // 如果有未匹配项,将标志设置为true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return unmatch // 返回标志的值
|
return unmatch // 返回标志的值
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isValueMatch(itemValue) {
|
||||||
|
return this.values.some(val => val == itemValue)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
handleArray(array) {
|
handleArray(array) {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export default {
|
|||||||
this.$store.dispatch('app/toggleSideBarHide', true)
|
this.$store.dispatch('app/toggleSideBarHide', true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ export default {
|
|||||||
float: left;
|
float: left;
|
||||||
height: 50px !important;
|
height: 50px !important;
|
||||||
line-height: 50px !important;
|
line-height: 50px !important;
|
||||||
color: #999093 !important;
|
color: #303133 !important;
|
||||||
padding: 0 5px !important;
|
padding: 0 5px !important;
|
||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ export default {
|
|||||||
float: left;
|
float: left;
|
||||||
height: 50px !important;
|
height: 50px !important;
|
||||||
line-height: 50px !important;
|
line-height: 50px !important;
|
||||||
color: #999093 !important;
|
color: #303133 !important;
|
||||||
padding: 0 5px !important;
|
padding: 0 5px !important;
|
||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,39 @@ export default {
|
|||||||
min-height: 0px;
|
min-height: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端fixed-header优化 */
|
||||||
|
@media screen and (max-width: 991px) {
|
||||||
|
.fixed-header + .app-main {
|
||||||
|
padding-bottom: max(60px, calc(constant(safe-area-inset-bottom) + 40px));
|
||||||
|
padding-bottom: max(60px, calc(env(safe-area-inset-bottom) + 40px));
|
||||||
|
overscroll-behavior-y: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasTagsView .fixed-header + .app-main {
|
||||||
|
padding-bottom: max(60px, calc(constant(safe-area-inset-bottom) + 40px));
|
||||||
|
padding-bottom: max(60px, calc(env(safe-area-inset-bottom) + 40px));
|
||||||
|
overscroll-behavior-y: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (-webkit-touch-callout: none) {
|
||||||
|
@media screen and (max-width: 991px) {
|
||||||
|
.fixed-header + .app-main {
|
||||||
|
padding-bottom: max(17px, calc(constant(safe-area-inset-bottom) + 10px));
|
||||||
|
padding-bottom: max(17px, calc(env(safe-area-inset-bottom) + 10px));
|
||||||
|
height: calc(100svh - 50px);
|
||||||
|
height: calc(100dvh - 50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasTagsView .fixed-header + .app-main {
|
||||||
|
padding-bottom: max(17px, calc(constant(safe-area-inset-bottom) + 10px));
|
||||||
|
padding-bottom: max(17px, calc(env(safe-area-inset-bottom) + 10px));
|
||||||
|
height: calc(100svh - 84px);
|
||||||
|
height: calc(100dvh - 84px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="navbar">
|
<div class="navbar" :class="'nav' + navType">
|
||||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||||
|
|
||||||
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container" />
|
<breadcrumb v-if="navType == 1" id="breadcrumb-container" class="breadcrumb-container" />
|
||||||
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container" />
|
<top-nav v-if="navType == 2" id="topmenu-container" class="topmenu-container" />
|
||||||
|
<template v-if="navType == 3">
|
||||||
|
<logo v-show="showLogo" :collapse="false"></logo>
|
||||||
|
<top-bar id="topbar-container" class="topbar-container" />
|
||||||
|
</template>
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
<template v-if="device!=='mobile'">
|
<template v-if="device!=='mobile'">
|
||||||
<search id="header-search" class="right-menu-item" />
|
<search id="header-search" class="right-menu-item" />
|
||||||
@@ -50,6 +53,8 @@
|
|||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import Breadcrumb from '@/components/Breadcrumb'
|
import Breadcrumb from '@/components/Breadcrumb'
|
||||||
import TopNav from '@/components/TopNav'
|
import TopNav from '@/components/TopNav'
|
||||||
|
import TopBar from './TopBar'
|
||||||
|
import Logo from './Sidebar/Logo'
|
||||||
import Hamburger from '@/components/Hamburger'
|
import Hamburger from '@/components/Hamburger'
|
||||||
import Screenfull from '@/components/Screenfull'
|
import Screenfull from '@/components/Screenfull'
|
||||||
import SizeSelect from '@/components/SizeSelect'
|
import SizeSelect from '@/components/SizeSelect'
|
||||||
@@ -61,7 +66,9 @@ export default {
|
|||||||
emits: ['setLayout'],
|
emits: ['setLayout'],
|
||||||
components: {
|
components: {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
|
Logo,
|
||||||
TopNav,
|
TopNav,
|
||||||
|
TopBar,
|
||||||
Hamburger,
|
Hamburger,
|
||||||
Screenfull,
|
Screenfull,
|
||||||
SizeSelect,
|
SizeSelect,
|
||||||
@@ -81,9 +88,14 @@ export default {
|
|||||||
return this.$store.state.settings.showSettings
|
return this.$store.state.settings.showSettings
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
topNav: {
|
navType: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.topNav
|
return this.$store.state.settings.navType
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showLogo: {
|
||||||
|
get() {
|
||||||
|
return this.$store.state.settings.sidebarLogo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -110,20 +122,33 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.navbar.nav3 {
|
||||||
|
.hamburger-container {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
// padding: 0 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
.hamburger-container {
|
.hamburger-container {
|
||||||
line-height: 46px;
|
line-height: 46px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
float: left;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .3s;
|
transition: background .3s;
|
||||||
-webkit-tap-highlight-color:transparent;
|
-webkit-tap-highlight-color:transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, .025)
|
background: rgba(0, 0, 0, .025)
|
||||||
@@ -131,7 +156,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-container {
|
.breadcrumb-container {
|
||||||
float: left;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenu-container {
|
.topmenu-container {
|
||||||
@@ -139,15 +164,26 @@ export default {
|
|||||||
left: 50px;
|
left: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topbar-container {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.errLog-container {
|
.errLog-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-menu {
|
.right-menu {
|
||||||
float: right;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: auto;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|||||||
@@ -3,6 +3,27 @@
|
|||||||
<div class="drawer-container">
|
<div class="drawer-container">
|
||||||
<div>
|
<div>
|
||||||
<div class="setting-drawer-content">
|
<div class="setting-drawer-content">
|
||||||
|
<div class="setting-drawer-title">
|
||||||
|
<h3 class="drawer-title">菜单导航设置</h3>
|
||||||
|
</div>
|
||||||
|
<div class="nav-wrap">
|
||||||
|
<el-tooltip content="左侧菜单" placement="bottom">
|
||||||
|
<div class="item left" @click="handleNavType(1)" :style="{'--theme': theme}" :class="{ activeItem: navType == 1 }">
|
||||||
|
<b></b><b></b>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
<el-tooltip content="混合菜单" placement="bottom">
|
||||||
|
<div class="item mix" @click="handleNavType(2)" :style="{'--theme': theme}" :class="{ activeItem: navType == 2 }">
|
||||||
|
<b></b><b></b>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="顶部菜单" placement="bottom">
|
||||||
|
<div class="item top" @click="handleNavType(3)" :style="{'--theme': theme}" :class="{ activeItem: navType == 3 }">
|
||||||
|
<b></b><b></b>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
<div class="setting-drawer-title">
|
<div class="setting-drawer-title">
|
||||||
<h3 class="drawer-title">主题风格设置</h3>
|
<h3 class="drawer-title">主题风格设置</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,11 +60,6 @@
|
|||||||
|
|
||||||
<h3 class="drawer-title">系统布局配置</h3>
|
<h3 class="drawer-title">系统布局配置</h3>
|
||||||
|
|
||||||
<div class="drawer-item">
|
|
||||||
<span>开启 TopNav</span>
|
|
||||||
<el-switch v-model="topNav" class="drawer-switch" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
<span>开启 Tags-Views</span>
|
<span>开启 Tags-Views</span>
|
||||||
<el-switch v-model="tagsView" class="drawer-switch" />
|
<el-switch v-model="tagsView" class="drawer-switch" />
|
||||||
@@ -93,6 +109,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
theme: this.$store.state.settings.theme,
|
theme: this.$store.state.settings.theme,
|
||||||
sideTheme: this.$store.state.settings.sideTheme,
|
sideTheme: this.$store.state.settings.sideTheme,
|
||||||
|
navType: this.$store.state.settings.navType,
|
||||||
showSettings: false
|
showSettings: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -108,21 +125,6 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
topNav: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.settings.topNav
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
|
||||||
key: 'topNav',
|
|
||||||
value: val
|
|
||||||
})
|
|
||||||
if (!val) {
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', false)
|
|
||||||
this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tagsView: {
|
tagsView: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.tagsView
|
return this.$store.state.settings.tagsView
|
||||||
@@ -180,6 +182,25 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
navType: {
|
||||||
|
handler(val) {
|
||||||
|
if (val == 1) {
|
||||||
|
this.$store.dispatch("app/toggleSideBarHide", false)
|
||||||
|
}
|
||||||
|
if (val == 2) {
|
||||||
|
}
|
||||||
|
if (val == 3) {
|
||||||
|
this.$store.dispatch("app/toggleSideBarHide", true)
|
||||||
|
}
|
||||||
|
if ([1, 3].includes(val)) {
|
||||||
|
this.$store.commit("SET_SIDEBAR_ROUTERS",this.$store.state.permission.defaultRoutes)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
themeChange(val) {
|
themeChange(val) {
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
this.$store.dispatch('settings/changeSetting', {
|
||||||
@@ -195,6 +216,13 @@ export default {
|
|||||||
})
|
})
|
||||||
this.sideTheme = val
|
this.sideTheme = val
|
||||||
},
|
},
|
||||||
|
handleNavType(val) {
|
||||||
|
this.$store.dispatch('settings/changeSetting', {
|
||||||
|
key: 'navType',
|
||||||
|
value: val
|
||||||
|
})
|
||||||
|
this.navType = val
|
||||||
|
},
|
||||||
openSetting() {
|
openSetting() {
|
||||||
this.showSettings = true
|
this.showSettings = true
|
||||||
},
|
},
|
||||||
@@ -206,7 +234,7 @@ export default {
|
|||||||
this.$cache.local.set(
|
this.$cache.local.set(
|
||||||
"layout-setting",
|
"layout-setting",
|
||||||
`{
|
`{
|
||||||
"topNav":${this.topNav},
|
"navType":${this.navType},
|
||||||
"tagsView":${this.tagsView},
|
"tagsView":${this.tagsView},
|
||||||
"tagsIcon":${this.tagsIcon},
|
"tagsIcon":${this.tagsIcon},
|
||||||
"fixedHeader":${this.fixedHeader},
|
"fixedHeader":${this.fixedHeader},
|
||||||
@@ -229,70 +257,133 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.setting-drawer-content {
|
.setting-drawer-content {
|
||||||
.setting-drawer-title {
|
.setting-drawer-title {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
color: rgba(0, 0, 0, .85);
|
color: rgba(0, 0, 0, .85);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-drawer-block-checbox {
|
.setting-drawer-block-checbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
.setting-drawer-block-checbox-item {
|
.setting-drawer-block-checbox-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-drawer-block-checbox-selectIcon {
|
.setting-drawer-block-checbox-selectIcon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.drawer-container {
|
.drawer-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
.drawer-title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: rgba(0, 0, 0, .85);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5;
|
line-height: 22px;
|
||||||
word-wrap: break-word;
|
}
|
||||||
|
|
||||||
.drawer-title {
|
.drawer-item {
|
||||||
margin-bottom: 12px;
|
color: rgba(0, 0, 0, .65);
|
||||||
color: rgba(0, 0, 0, .85);
|
font-size: 14px;
|
||||||
font-size: 14px;
|
padding: 12px 0;
|
||||||
line-height: 22px;
|
}
|
||||||
|
|
||||||
|
.drawer-switch {
|
||||||
|
float: right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导航模式
|
||||||
|
.nav-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.activeItem {
|
||||||
|
border: 2px solid #{'var(--theme)'} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 56px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
b:first-child {
|
||||||
|
display: block;
|
||||||
|
height: 30%;
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
b:last-child {
|
||||||
.drawer-item {
|
width: 30%;
|
||||||
color: rgba(0, 0, 0, .65);
|
background: #1b2a47;
|
||||||
font-size: 14px;
|
position: absolute;
|
||||||
padding: 12px 0;
|
height: 100%;
|
||||||
}
|
top: 0;
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
.drawer-switch {
|
|
||||||
float: right
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.mix {
|
||||||
|
b:first-child {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
display: block;
|
||||||
|
height: 30%;
|
||||||
|
background: #1b2a47;
|
||||||
|
}
|
||||||
|
b:last-child {
|
||||||
|
width: 30%;
|
||||||
|
background: #1b2a47;
|
||||||
|
position: absolute;
|
||||||
|
height: 70%;
|
||||||
|
border-radius: 0 0 0 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top {
|
||||||
|
b:first-child {
|
||||||
|
display: block;
|
||||||
|
height: 30%;
|
||||||
|
background: #1b2a47;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
|
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' && navType !== 3 ? variables.menuBackground : variables.menuLightBackground }">
|
||||||
<transition name="sidebarLogoFade">
|
<transition name="sidebarLogoFade">
|
||||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||||
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' && navType !== 3 ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||||
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' && navType !== 3 ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
||||||
</router-link>
|
</router-link>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,6 +31,9 @@ export default {
|
|||||||
},
|
},
|
||||||
sideTheme() {
|
sideTheme() {
|
||||||
return this.$store.state.settings.sideTheme
|
return this.$store.state.settings.sideTheme
|
||||||
|
},
|
||||||
|
navType() {
|
||||||
|
return this.$store.state.settings.navType
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -54,7 +57,6 @@ export default {
|
|||||||
|
|
||||||
.sidebar-logo-container {
|
.sidebar-logo-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
background: #2b2f3a;
|
background: #2b2f3a;
|
||||||
|
|||||||
98
ruoyi-ui/src/layout/components/TopBar/index.vue
Normal file
98
ruoyi-ui/src/layout/components/TopBar/index.vue
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<el-menu class="topbar-menu" :default-active="activeMenu" :active-text-color="theme" mode="horizontal">
|
||||||
|
<sidebar-item :key="route.path + index" v-for="(route, index) in topMenus" :item="route" :base-path="route.path" />
|
||||||
|
|
||||||
|
<el-submenu index="more" class="el-submenu__hide-arrow" v-if="moreRoutes.length > 0">
|
||||||
|
<template slot="title">更多菜单</template>
|
||||||
|
<sidebar-item :key="route.path + index" v-for="(route, index) in moreRoutes" :item="route" :base-path="route.path" />
|
||||||
|
</el-submenu>
|
||||||
|
</el-menu>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SidebarItem from '../Sidebar/SidebarItem'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { SidebarItem },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 顶部栏初始数
|
||||||
|
visibleNumber: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
theme() {
|
||||||
|
return this.$store.state.settings.theme
|
||||||
|
},
|
||||||
|
topMenus() {
|
||||||
|
return this.$store.state.permission.sidebarRouters.filter((f) => !f.hidden).slice(0, this.visibleNumber)
|
||||||
|
},
|
||||||
|
moreRoutes() {
|
||||||
|
const sidebarRouters = this.$store.state.permission.sidebarRouters;
|
||||||
|
return sidebarRouters.filter((f) => !f.hidden).slice(this.visibleNumber, sidebarRouters.length - this.visibleNumber)
|
||||||
|
},
|
||||||
|
// 默认激活的菜单
|
||||||
|
activeMenu() {
|
||||||
|
const { meta, path } = this.$route
|
||||||
|
if (meta.activeMenu) {
|
||||||
|
return meta.activeMenu
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeMount() {
|
||||||
|
window.addEventListener('resize', this.setVisibleNumber)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.setVisibleNumber)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setVisibleNumber()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 根据宽度计算设置显示栏数
|
||||||
|
setVisibleNumber() {
|
||||||
|
const width = document.body.getBoundingClientRect().width / 3
|
||||||
|
this.visibleNumber = parseInt(width / 85)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
/* menu item */
|
||||||
|
.topbar-menu.el-menu--horizontal .el-submenu__title, .topbar-menu.el-menu--horizontal .el-menu-item {
|
||||||
|
padding: 0 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--horizontal .el-menu--popup .el-menu-item:hover {
|
||||||
|
background-color: #f5f7fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* submenu item */
|
||||||
|
.topbar-menu.el-menu--horizontal > .el-submenu .el-submenu__title {
|
||||||
|
float: left;
|
||||||
|
height: 47px !important;
|
||||||
|
line-height: 50px !important;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0 15px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* topbar more arrow */
|
||||||
|
.topbar-menu .el-submenu .el-submenu__icon-arrow {
|
||||||
|
position: static;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* menu__title el-menu-item */
|
||||||
|
.topbar-menu.el-menu--horizontal .el-submenu__title, .topbar-menu.el-menu--horizontal .el-menu-item {
|
||||||
|
height: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--horizontal .el-menu .el-menu-item, .el-menu--horizontal .el-menu .el-submenu__title{
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -15,9 +15,9 @@ module.exports = {
|
|||||||
showSettings: true,
|
showSettings: true,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示顶部导航
|
* 菜单导航模式 1、纯左侧 2、混合(左侧+顶部) 3、纯顶部
|
||||||
*/
|
*/
|
||||||
topNav: false,
|
navType: 1,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示 tagsView
|
* 是否显示 tagsView
|
||||||
@@ -32,7 +32,7 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* 是否固定头部
|
* 是否固定头部
|
||||||
*/
|
*/
|
||||||
fixedHeader: false,
|
fixedHeader: true,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示logo
|
* 是否显示logo
|
||||||
@@ -52,5 +52,5 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* 底部版权文本内容
|
* 底部版权文本内容
|
||||||
*/
|
*/
|
||||||
footerContent: 'Copyright © 2018-2025 RuoYi. All Rights Reserved.'
|
footerContent: 'Copyright © 2018-2026 RuoYi. All Rights Reserved.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import defaultSettings from '@/settings'
|
import defaultSettings from '@/settings'
|
||||||
import { useDynamicTitle } from '@/utils/dynamicTitle'
|
import { useDynamicTitle } from '@/utils/dynamicTitle'
|
||||||
|
|
||||||
const { sideTheme, showSettings, topNav, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings
|
const { sideTheme, showSettings, navType, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings
|
||||||
|
|
||||||
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
|
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
|
||||||
const state = {
|
const state = {
|
||||||
@@ -9,7 +9,7 @@ const state = {
|
|||||||
theme: storageSetting.theme || '#409EFF',
|
theme: storageSetting.theme || '#409EFF',
|
||||||
sideTheme: storageSetting.sideTheme || sideTheme,
|
sideTheme: storageSetting.sideTheme || sideTheme,
|
||||||
showSettings: showSettings,
|
showSettings: showSettings,
|
||||||
topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
|
navType: storageSetting.navType === undefined ? navType : storageSetting.navType,
|
||||||
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
|
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
|
||||||
tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
|
tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
|
||||||
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
|
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
|
||||||
@@ -23,6 +23,9 @@ const mutations = {
|
|||||||
if (state.hasOwnProperty(key)) {
|
if (state.hasOwnProperty(key)) {
|
||||||
state[key] = value
|
state[key] = value
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
SET_TITLE: (state, title) => {
|
||||||
|
state.title = title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +36,7 @@ const actions = {
|
|||||||
},
|
},
|
||||||
// 设置网页标题
|
// 设置网页标题
|
||||||
setTitle({ commit }, title) {
|
setTitle({ commit }, title) {
|
||||||
state.title = title
|
commit('SET_TITLE', title)
|
||||||
useDynamicTitle()
|
useDynamicTitle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,37 @@
|
|||||||
export default [
|
export const drawingDefaultValue = []
|
||||||
{
|
|
||||||
layout: 'colFormItem',
|
export function initDrawingDefaultValue() {
|
||||||
tagIcon: 'input',
|
if (drawingDefaultValue.length === 0) {
|
||||||
label: '手机号',
|
drawingDefaultValue.push({
|
||||||
vModel: 'mobile',
|
layout: 'colFormItem',
|
||||||
formId: 6,
|
tagIcon: 'input',
|
||||||
tag: 'el-input',
|
label: '手机号',
|
||||||
placeholder: '请输入手机号',
|
vModel: 'mobile',
|
||||||
defaultValue: '',
|
formId: 6,
|
||||||
span: 24,
|
tag: 'el-input',
|
||||||
style: { width: '100%' },
|
placeholder: '请输入手机号',
|
||||||
clearable: true,
|
defaultValue: '',
|
||||||
prepend: '',
|
span: 24,
|
||||||
append: '',
|
style: {width: '100%'},
|
||||||
'prefix-icon': 'el-icon-mobile',
|
clearable: true,
|
||||||
'suffix-icon': '',
|
prepend: '',
|
||||||
maxlength: 11,
|
append: '',
|
||||||
'show-word-limit': true,
|
'prefix-icon': 'el-icon-mobile',
|
||||||
readonly: false,
|
'suffix-icon': '',
|
||||||
disabled: false,
|
maxlength: 11,
|
||||||
required: true,
|
'show-word-limit': true,
|
||||||
changeTag: true,
|
readonly: false,
|
||||||
regList: [{
|
disabled: false,
|
||||||
pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
|
required: true,
|
||||||
message: '手机号格式错误'
|
changeTag: true,
|
||||||
}]
|
regList: [{
|
||||||
|
pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
|
||||||
|
message: '手机号格式错误'
|
||||||
|
}]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
|
|
||||||
|
export function cleanDrawingDefaultValue() {
|
||||||
|
drawingDefaultValue.splice(0, drawingDefaultValue.length)
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ service.interceptors.request.use(config => {
|
|||||||
const isToken = (config.headers || {}).isToken === false
|
const isToken = (config.headers || {}).isToken === false
|
||||||
// 是否需要防止数据重复提交
|
// 是否需要防止数据重复提交
|
||||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
|
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
|
||||||
|
// 间隔时间(ms),小于此时间视为重复提交
|
||||||
|
const interval = (config.headers || {}).interval || 1000
|
||||||
if (getToken() && !isToken) {
|
if (getToken() && !isToken) {
|
||||||
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
}
|
}
|
||||||
@@ -55,7 +57,6 @@ service.interceptors.request.use(config => {
|
|||||||
const s_url = sessionObj.url // 请求地址
|
const s_url = sessionObj.url // 请求地址
|
||||||
const s_data = sessionObj.data // 请求数据
|
const s_data = sessionObj.data // 请求数据
|
||||||
const s_time = sessionObj.time // 请求时间
|
const s_time = sessionObj.time // 请求时间
|
||||||
const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交
|
|
||||||
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
|
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
|
||||||
const message = '数据正在处理,请勿重复提交'
|
const message = '数据正在处理,请勿重复提交'
|
||||||
console.warn(`[${s_url}]: ` + message)
|
console.warn(`[${s_url}]: ` + message)
|
||||||
@@ -115,7 +116,7 @@ service.interceptors.response.use(res => {
|
|||||||
} else if (message.includes("timeout")) {
|
} else if (message.includes("timeout")) {
|
||||||
message = "系统接口请求超时"
|
message = "系统接口请求超时"
|
||||||
} else if (message.includes("Request failed with status code")) {
|
} else if (message.includes("Request failed with status code")) {
|
||||||
message = "系统接口" + message.substr(message.length - 3) + "异常"
|
message = "系统接口" + message.slice(-3) + "异常"
|
||||||
}
|
}
|
||||||
Message({ message: message, type: 'error', duration: 5 * 1000 })
|
Message({ message: message, type: 'error', duration: 5 * 1000 })
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
|
|||||||
@@ -108,6 +108,37 @@
|
|||||||
<span>更新日志</span>
|
<span>更新日志</span>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse accordion>
|
<el-collapse accordion>
|
||||||
|
<el-collapse-item title="v3.6.7 - 2025-12-22">
|
||||||
|
<ol>
|
||||||
|
<li>支持防盗链功能</li>
|
||||||
|
<li>菜单导航设置支持纯顶部</li>
|
||||||
|
<li>用户头像更换后移除旧头像文件</li>
|
||||||
|
<li>支持Excel导出对象的多个子列表</li>
|
||||||
|
<li>升级druid到最新版本1.2.27</li>
|
||||||
|
<li>升级fastjson到最新版2.0.60</li>
|
||||||
|
<li>升级tomcat到最新版本9.0.112</li>
|
||||||
|
<li>升级commons.io到最新版本2.21.0</li>
|
||||||
|
<li>用户导入添加验证提示</li>
|
||||||
|
<li>显示列信息支持对象格式</li>
|
||||||
|
<li>网页标题设置新增SET_TITLE方法</li>
|
||||||
|
<li>自动识别json对象白名单配置范围缩小</li>
|
||||||
|
<li>登录/注册页面底部版权信息修改为读取配置</li>
|
||||||
|
<li>修复用户归属部门无法修改为空问题</li>
|
||||||
|
<li>修复固定头部时出现的导航栏偏移问题</li>
|
||||||
|
<li>修复v3时间控件between选择后清空报错问题</li>
|
||||||
|
<li>修复comboReadDict属性下多个sheet出现的报错</li>
|
||||||
|
<li>修复表单构建移除所有控件后切换路由回来空白问题</li>
|
||||||
|
<li>优化布局设置显示</li>
|
||||||
|
<li>优化字典组件值宽松匹配</li>
|
||||||
|
<li>优化生成代码下载的zip文件名</li>
|
||||||
|
<li>优化日志记录参数拼装提升效率</li>
|
||||||
|
<li>优化导入文件检查标题行不能为空</li>
|
||||||
|
<li>优化表单构建关闭页签销毁复制插件</li>
|
||||||
|
<li>优化Excel统计行数值的单元格样式显示</li>
|
||||||
|
<li>优化数据权限控制逻辑,放开permission限制</li>
|
||||||
|
<li>其他细节优化</li>
|
||||||
|
</ol>
|
||||||
|
</el-collapse-item>
|
||||||
<el-collapse-item title="v3.6.6 - 2025-05-30">
|
<el-collapse-item title="v3.6.6 - 2025-05-30">
|
||||||
<ol>
|
<ol>
|
||||||
<li>优化菜单搜索查询页</li>
|
<li>优化菜单搜索查询页</li>
|
||||||
@@ -956,7 +987,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 版本号
|
// 版本号
|
||||||
version: "3.6.6"
|
version: "3.6.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-login-footer">
|
<div class="el-login-footer">
|
||||||
<span>Copyright © 2018-2025 ruoyi.vip All Rights Reserved.</span>
|
<span>{{ footerContent }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -65,12 +65,14 @@
|
|||||||
import { getCodeImg } from "@/api/login"
|
import { getCodeImg } from "@/api/login"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
||||||
|
import defaultSettings from '@/settings'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Login",
|
name: "Login",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: process.env.VUE_APP_TITLE,
|
title: process.env.VUE_APP_TITLE,
|
||||||
|
footerContent: defaultSettings.footerContent,
|
||||||
codeUrl: "",
|
codeUrl: "",
|
||||||
loginForm: {
|
loginForm: {
|
||||||
username: "admin",
|
username: "admin",
|
||||||
@@ -156,7 +158,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style rel="stylesheet/scss" lang="scss">
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
.login {
|
.login {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -61,13 +61,14 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-register-footer">
|
<div class="el-register-footer">
|
||||||
<span>Copyright © 2018-2025 ruoyi.vip All Rights Reserved.</span>
|
<span>{{ footerContent }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCodeImg, register } from "@/api/login"
|
import { getCodeImg, register } from "@/api/login"
|
||||||
|
import defaultSettings from '@/settings'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Register",
|
name: "Register",
|
||||||
@@ -81,6 +82,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
title: process.env.VUE_APP_TITLE,
|
title: process.env.VUE_APP_TITLE,
|
||||||
|
footerContent: defaultSettings.footerContent,
|
||||||
codeUrl: "",
|
codeUrl: "",
|
||||||
registerForm: {
|
registerForm: {
|
||||||
username: "",
|
username: "",
|
||||||
@@ -147,7 +149,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style rel="stylesheet/scss" lang="scss">
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
.register {
|
.register {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -146,13 +146,14 @@ import { beautifierConf, titleCase } from '@/utils/index'
|
|||||||
import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
|
import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
|
||||||
import { makeUpJs } from '@/utils/generator/js'
|
import { makeUpJs } from '@/utils/generator/js'
|
||||||
import { makeUpCss } from '@/utils/generator/css'
|
import { makeUpCss } from '@/utils/generator/css'
|
||||||
import drawingDefault from '@/utils/generator/drawingDefault'
|
import { drawingDefaultValue, initDrawingDefaultValue, cleanDrawingDefaultValue } from '@/utils/generator/drawingDefault'
|
||||||
import logo from '@/assets/logo/logo.png'
|
import logo from '@/assets/logo/logo.png'
|
||||||
import CodeTypeDialog from './CodeTypeDialog'
|
import CodeTypeDialog from './CodeTypeDialog'
|
||||||
import DraggableItem from './DraggableItem'
|
import DraggableItem from './DraggableItem'
|
||||||
|
|
||||||
let oldActiveId
|
let oldActiveId
|
||||||
let tempActiveData
|
let tempActiveData
|
||||||
|
let clipboard = null
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -171,17 +172,20 @@ export default {
|
|||||||
selectComponents,
|
selectComponents,
|
||||||
layoutComponents,
|
layoutComponents,
|
||||||
labelWidth: 100,
|
labelWidth: 100,
|
||||||
drawingList: drawingDefault,
|
drawingList: drawingDefaultValue,
|
||||||
drawingData: {},
|
drawingData: {},
|
||||||
activeId: drawingDefault[0].formId,
|
activeId: drawingDefaultValue[0].formId,
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
formData: {},
|
formData: {},
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
generateConf: null,
|
generateConf: null,
|
||||||
showFileName: false,
|
showFileName: false,
|
||||||
activeData: drawingDefault[0]
|
activeData: drawingDefaultValue[0]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeCreate() {
|
||||||
|
initDrawingDefaultValue()
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
// 防止 firefox 下 拖拽 会新打卡一个选项卡
|
// 防止 firefox 下 拖拽 会新打卡一个选项卡
|
||||||
document.body.ondrop = event => {
|
document.body.ondrop = event => {
|
||||||
@@ -208,7 +212,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const clipboard = new ClipboardJS('#copyNode', {
|
clipboard = new ClipboardJS('#copyNode', {
|
||||||
text: trigger => {
|
text: trigger => {
|
||||||
const codeStr = this.generateCode()
|
const codeStr = this.generateCode()
|
||||||
this.$notify({
|
this.$notify({
|
||||||
@@ -223,6 +227,9 @@ export default {
|
|||||||
this.$message.error('代码复制失败')
|
this.$message.error('代码复制失败')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clipboard.destroy()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
activeFormItem(element) {
|
activeFormItem(element) {
|
||||||
this.activeData = element
|
this.activeData = element
|
||||||
@@ -284,6 +291,7 @@ export default {
|
|||||||
this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
|
this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
|
||||||
() => {
|
() => {
|
||||||
this.drawingList = []
|
this.drawingList = []
|
||||||
|
cleanDrawingDefaultValue()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -253,7 +253,8 @@ export default {
|
|||||||
this.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath)
|
this.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$download.zip("/code/gen/batchGenCode?tables=" + tableNames, "ruoyi.zip")
|
const zipName = Array.isArray(tableNames) ? "ruoyi.zip" : tableNames + ".zip"
|
||||||
|
this.$download.zip("/code/gen/batchGenCode?tables=" + tableNames, zipName)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 同步数据库操作 */
|
/** 同步数据库操作 */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-visual</artifactId>
|
<artifactId>ruoyi-visual</artifactId>
|
||||||
<version>3.6.6</version>
|
<version>3.6.7</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user