diff --git a/README.md b/README.md index 4814ec753..4ffaef9e7 100644 --- a/README.md +++ b/README.md @@ -126,4 +126,4 @@ com.ruoyi ## 若依微服务交流群 -QQ群: [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。 \ No newline at end of file +QQ群: [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。 \ No newline at end of file diff --git a/docker/copy.sh b/docker/copy.sh index e2ba1d24d..5426572f6 100644 --- a/docker/copy.sh +++ b/docker/copy.sh @@ -9,8 +9,8 @@ usage() { # copy sql echo "begin copy sql " -cp ../sql/ry_20240629.sql ./mysql/db -cp ../sql/ry_config_20250224.sql ./mysql/db +cp ../sql/ry_20250523.sql ./mysql/db +cp ../sql/ry_config_20250902.sql ./mysql/db # copy html echo "begin copy html " diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java index ae56a54ad..688bb4684 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java @@ -2,7 +2,9 @@ package com.ruoyi.system.api; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.constant.ServiceNameConstants; @@ -26,4 +28,13 @@ public interface RemoteFileService */ @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R upload(@RequestPart(value = "file") MultipartFile file); + + /** + * 删除文件 + * + * @param fileUrl 文件地址 + * @return 结果 + */ + @DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public R delete(@RequestParam("fileUrl") String fileUrl); } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java index bc3b6fffd..421eb9419 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java @@ -30,6 +30,12 @@ public class RemoteFileFallbackFactory implements FallbackFactory delete(String fileUrl) + { + return R.fail("删除文件失败:" + throwable.getMessage()); + } }; } } diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java index ffd79e13d..9ba6046a3 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java @@ -143,6 +143,7 @@ public class SysLoginService SysUser sysUser = new SysUser(); sysUser.setUserName(username); sysUser.setNickName(username); + sysUser.setPwdUpdateDate(DateUtils.getNowDate()); sysUser.setPassword(SecurityUtils.encryptPassword(password)); R registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java index 265aa4cc3..c5cef8af0 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java @@ -87,6 +87,16 @@ public class Constants */ public static final String LOGIN_FAIL = "Error"; + /** + * 所有权限标识 + */ + public static final String ALL_PERMISSION = "*:*:*"; + + /** + * 管理员角色权限标识 + */ + public static final String SUPER_ADMIN = "admin"; + /** * 当前记录起始索引 */ @@ -120,7 +130,7 @@ public class Constants /** * 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全) */ - public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" }; + public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" }; /** * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java index 2e978da36..7efee9ded 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java @@ -3,7 +3,7 @@ package com.ruoyi.common.core.exception.file; import java.util.Arrays; /** - * 文件上传 误异常类 + * 文件上传无效扩展名异常类 * * @author ruoyi */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java index 0c28db794..aabb4fb73 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java @@ -114,20 +114,20 @@ public class FileUtils } /** - * 检查文件是否可下载 + * 校验文件路径合法性(安全性与扩展名) * - * @param resource 需要下载的文件 + * @param fileUrl 待校验的文件地址 * @return true 正常 false 非法 */ - public static boolean checkAllowDownload(String resource) + public static boolean validateFilePath(String fileUrl) { // 禁止目录上跳级别 - if (StringUtils.contains(resource, "..")) + if (StringUtils.contains(fileUrl, "..")) { return false; } // 判断是否在允许下载的文件规则内 - return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)); + return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl)); } /** diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java index b9284df43..8c2434331 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java @@ -73,6 +73,8 @@ public class ExcelUtil { private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + public static final String SEPARATOR = ","; + public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; @@ -145,23 +147,18 @@ public class ExcelUtil /** * 对象的子列表方法 */ - private Method subMethod; + private Map subMethods; /** * 对象的子列表属性 */ - private List subFields; + private Map> subFieldsMap; /** * 统计列表 */ private Map statistics = new HashMap(); - /** - * 数字格式 - */ - private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); - /** * 实体对象 */ @@ -228,7 +225,10 @@ public class ExcelUtil int titleLastCol = this.fields.size() - 1; if (isSubList()) { - titleLastCol = titleLastCol + subFields.size() - 1; + for (List currentSubFields : subFieldsMap.values()) + { + titleLastCol = titleLastCol + currentSubFields.size() - 1; + } } Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); titleRow.setHeightInPoints(30); @@ -248,16 +248,17 @@ public class ExcelUtil { Row subRow = sheet.createRow(rownum); int column = 0; - int subFieldSize = subFields != null ? subFields.size() : 0; for (Object[] objects : fields) { Field field = (Field) objects[0]; Excel attr = (Excel) objects[1]; + CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())); if (Collection.class.isAssignableFrom(field.getType())) { Cell cell = subRow.createCell(column); 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) { CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); @@ -269,7 +270,7 @@ public class ExcelUtil { Cell cell = subRow.createCell(column++); cell.setCellValue(attr.name()); - cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + cell.setCellStyle(cellStyle); } } rownum++; @@ -341,7 +342,11 @@ public class ExcelUtil Map cellMap = new HashMap(); // 获取表头 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); if (StringUtils.isNotNull(cell)) @@ -349,10 +354,6 @@ public class ExcelUtil String value = this.getCellValue(heard, i).toString(); cellMap.put(value, i); } - else - { - cellMap.put(null, i); - } } // 有数据时才处理 得到类的所有field. List fields = this.getFields(); @@ -565,7 +566,8 @@ public class ExcelUtil Excel excel = (Excel) os[1]; if (Collection.class.isAssignableFrom(field.getType())) { - for (Field subField : subFields) + List currentSubFields = subFieldsMap.get(field.getName()); + for (Field subField : currentSubFields) { Excel subExcel = subField.getAnnotation(Excel.class); this.createHeadCell(subExcel, row, column++); @@ -578,7 +580,7 @@ public class ExcelUtil } if (Type.EXPORT.equals(type)) { - fillExcelData(index, row); + fillExcelData(index); addStatisticsRow(); } } @@ -588,10 +590,9 @@ public class ExcelUtil * 填充excel数据 * * @param index 序号 - * @param row 单元格行 */ @SuppressWarnings("unchecked") - public void fillExcelData(int index, Row row) + public void fillExcelData(int index) { int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize, list.size()); @@ -599,7 +600,7 @@ public class ExcelUtil for (int i = startNo; i < endNo; i++) { - row = sheet.createRow(currentRowNum); + Row row = sheet.createRow(currentRowNum); T vo = (T) list.get(i); int column = 0; int maxSubListSize = getCurrentMaxSubListSize(vo); @@ -612,6 +613,7 @@ public class ExcelUtil try { Collection subList = (Collection) getTargetValue(vo, field, excel); + List currentSubFields = subFieldsMap.get(field.getName()); if (subList != null && !subList.isEmpty()) { int subIndex = 0; @@ -624,15 +626,15 @@ public class ExcelUtil } int subColumn = column; - for (Field subField : subFields) + for (Field subField : currentSubFields) { Excel subExcel = subField.getAnnotation(Excel.class); addCell(subExcel, subRow, (T) subVo, subField, subColumn++); } subIndex++; } - column += subFields.size(); } + column += currentSubFields.size(); } catch (Exception e) { @@ -724,6 +726,7 @@ public class ExcelUtil style = wb.createCellStyle(); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setDataFormat(dataFormat.getFormat("######0.00")); Font totalFont = wb.createFont(); totalFont.setFontName("Arial"); totalFont.setFontHeightInPoints((short) 10); @@ -984,7 +987,7 @@ public class ExcelUtil { // 创建cell cell = row.createCell(column); - if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) + if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge()) { if (subMergedLastRowNum >= subMergedFirstRowNum) { @@ -1081,18 +1084,36 @@ public class ExcelUtil public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) { String hideSheetName = "combo_" + firstCol + "_" + endCol; - Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 - for (int i = 0; i < textlist.length; i++) + Sheet hideSheet = null; + String hideSheetDataName = hideSheetName + "_data"; + Name name = wb.getName(hideSheetDataName); + if (name != null) + { + // 名称已存在,尝试从名称的引用中找到sheet名称 + String refersToFormula = name.getRefersToFormula(); + if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!")) + { + String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!")); + hideSheet = wb.getSheet(sheetNameFromFormula); + } + } + + if (hideSheet == null) { - hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); + 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); } - // 创建名称,可被其他单元格引用 - Name name = wb.createName(); - name.setNameName(hideSheetName + "_data"); - name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); + DataValidationHelper helper = sheet.getDataValidationHelper(); // 加载下拉列表内容 - DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); + DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName); // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); // 数据有效性对象 @@ -1130,7 +1151,7 @@ public class ExcelUtil public static String convertByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); + String[] convertSource = converterExp.split(SEPARATOR); for (String item : convertSource) { String[] itemArray = item.split("="); @@ -1167,7 +1188,7 @@ public class ExcelUtil public static String reverseByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); + String[] convertSource = converterExp.split(SEPARATOR); for (String item : convertSource) { String[] itemArray = item.split("="); @@ -1255,7 +1276,7 @@ public class ExcelUtil { cell = row.createCell(key); cell.setCellStyle(styles.get("total")); - cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + cell.setCellValue(statistics.get(key)); } statistics.clear(); } @@ -1330,6 +1351,8 @@ public class ExcelUtil { List fields = new ArrayList(); List tempFields = new ArrayList<>(); + subFieldsMap = new HashMap<>(); + subMethods = new HashMap<>(); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); if (StringUtils.isNotEmpty(includeFields)) @@ -1377,10 +1400,11 @@ public class ExcelUtil } 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(); Class subClass = (Class) pt.getActualTypeArguments()[0]; - this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class)); } } @@ -1449,7 +1473,8 @@ public class ExcelUtil { this.sheet = wb.createSheet(); this.createTitle(); - wb.setSheetName(index, sheetName + index); + int actualIndex = wb.getSheetIndex(this.sheet); + wb.setSheetName(actualIndex, sheetName + index); } } @@ -1574,7 +1599,7 @@ public class ExcelUtil */ public boolean isSubList() { - return StringUtils.isNotNull(subFields) && subFields.size() > 0; + return !StringUtils.isEmpty(subFieldsMap); } /** @@ -1582,24 +1607,32 @@ public class ExcelUtil */ 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 { - 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) { - return new ArrayList(); + return 0; } - return (Collection) value; + return max; } /** diff --git a/ruoyi-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java b/ruoyi-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java index c56108f42..3a20eeafd 100644 --- a/ruoyi-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java +++ b/ruoyi-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java @@ -94,7 +94,7 @@ public class DataScopeAspect List conditions = new ArrayList(); List scopeCustomIds = new ArrayList(); 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())); } @@ -107,7 +107,7 @@ public class DataScopeAspect { continue; } - if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) + if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) { continue; } diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java index 7f4e7441a..6ca5ddcaa 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java @@ -48,6 +48,9 @@ public class LogAspect /** 计算操作消耗时间 */ private static final ThreadLocal TIME_THREADLOCAL = new NamedThreadLocal("Cost Time"); + /** 参数最大长度限制 */ + private static final int PARAM_MAX_LENGTH = 2000; + @Autowired private AsyncLogService asyncLogService; @@ -166,16 +169,16 @@ public class LogAspect */ private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception { - Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); 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())) { String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); - operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + operLog.setOperParam(params); } 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) { - String params = ""; + StringBuilder params = new StringBuilder(); if (paramsArray != null && paramsArray.length > 0) { for (Object o : paramsArray) @@ -194,15 +197,20 @@ public class LogAspect try { 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) { + log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e); } } } } - return params.trim(); + return params.toString(); } /** diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java new file mode 100644 index 000000000..09136bb27 --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java @@ -0,0 +1,46 @@ +package com.ruoyi.file.config; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.ruoyi.file.filter.RefererFilter; + +/** + * Filter配置 + * + * @author ruoyi + */ +@Configuration +public class FilterConfig +{ + /** + * 资源映射路径 前缀 + */ + @Value("${file.prefix}") + public String localFilePrefix; + + @Value("${referer.allowed-domains}") + private String allowedDomains; + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Bean + @ConditionalOnProperty(value = "referer.enabled", havingValue = "true") + public FilterRegistrationBean refererFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new RefererFilter()); + registration.addUrlPatterns(localFilePrefix + "/*"); + registration.setName("refererFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap(); + initParameters.put("allowedDomains", allowedDomains); + registration.setInitParameters(initParameters); + return registration; + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java index 318db4169..82db19bca 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java @@ -3,10 +3,12 @@ package com.ruoyi.file.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.file.service.ISysFileService; import com.ruoyi.system.api.domain.SysFile; @@ -45,4 +47,26 @@ public class SysFileController return R.fail(e.getMessage()); } } -} \ No newline at end of file + + /** + * 文件删除请求 + */ + @DeleteMapping("delete") + public R delete(String fileUrl) + { + try + { + if (!FileUtils.validateFilePath(fileUrl)) + { + throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl)); + } + sysFileService.deleteFile(fileUrl); + return R.ok(); + } + catch (Exception e) + { + log.error("删除文件失败", e); + return R.fail(e.getMessage()); + } + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java new file mode 100644 index 000000000..0aafbe7e6 --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java @@ -0,0 +1,77 @@ +package com.ruoyi.file.filter; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 防盗链过滤器 + * + * @author ruoyi + */ +public class RefererFilter implements Filter +{ + /** + * 允许的域名列表 + */ + public List allowedDomains; + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + String domains = filterConfig.getInitParameter("allowedDomains"); + this.allowedDomains = Arrays.asList(domains.split(",")); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + + String referer = req.getHeader("Referer"); + + // 如果Referer为空,拒绝访问 + if (referer == null || referer.isEmpty()) + { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required"); + return; + } + + // 检查Referer是否在允许的域名列表中 + boolean allowed = false; + for (String domain : allowedDomains) + { + if (referer.contains(domain)) + { + allowed = true; + break; + } + } + + // 根据检查结果决定是否放行 + if (allowed) + { + chain.doFilter(request, response); + } + else + { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed"); + } + } + + @Override + public void destroy() + { + + } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java index da0dc6003..456c6977d 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java @@ -1,11 +1,11 @@ package com.ruoyi.file.service; import java.io.InputStream; -import com.alibaba.nacos.common.utils.IoUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import com.alibaba.nacos.common.utils.IoUtils; import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.ruoyi.common.core.utils.file.FileTypeUtils; @@ -53,4 +53,24 @@ public class FastDfsSysFileServiceImpl implements ISysFileService IoUtils.closeQuietly(inputStream); } } + + /** + * FastDFS文件删除接口 + * + * @param fileUrl 文件访问URL + * @throws Exception + */ + @Override + public void deleteFile(String fileUrl) throws Exception + { + try + { + StorePath storePath = StorePath.parseFromUrl(fileUrl); + storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); + } + catch (Exception e) + { + throw new RuntimeException("FastDfs Failed to delete file: ", e); + } + } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java index 5a353489d..d6119ef91 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java @@ -17,4 +17,12 @@ public interface ISysFileService * @throws Exception */ public String uploadFile(MultipartFile file) throws Exception; + + /** + * 文件删除接口 + * + * @param fileUrl 文件访问URL + * @throws Exception + */ + public void deleteFile(String fileUrl) throws Exception; } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java index c0e20681e..56c6afd21 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java @@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.file.utils.FileUploadUtils; /** @@ -47,4 +49,17 @@ public class LocalSysFileServiceImpl implements ISysFileService String url = domain + localFilePrefix + name; return url; } + + /** + * 本地文件删除接口 + * + * @param fileUrl 文件访问URL + * @throws Exception + */ + @Override + public void deleteFile(String fileUrl) throws Exception + { + String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix); + FileUtils.deleteFile(localFilePath + localFile); + } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java index eade4c801..9afd29100 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java @@ -5,10 +5,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import com.alibaba.nacos.common.utils.IoUtils; +import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.file.config.MinioConfig; import com.ruoyi.file.utils.FileUploadUtils; import io.minio.MinioClient; import io.minio.PutObjectArgs; +import io.minio.RemoveObjectArgs; /** * Minio 文件存储 @@ -57,4 +59,24 @@ public class MinioSysFileServiceImpl implements ISysFileService IoUtils.closeQuietly(inputStream); } } + + /** + * Minio文件删除接口 + * + * @param fileUrl 文件访问URL + * @throws Exception + */ + @Override + public void deleteFile(String fileUrl) throws Exception + { + try + { + String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName()); + client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build()); + } + catch (Exception e) + { + throw new RuntimeException("Minio Failed to delete file", e); + } + } } diff --git a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm index 765a5e300..fabd92160 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm +++ b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -334,7 +334,7 @@ function getList() { #foreach ($column in $columns) #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) - if (null != daterange${AttrName} && '' != daterange${AttrName}) { + if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] } diff --git a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index.vue.vm index 936b4651f..1a9c51797 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index.vue.vm +++ b/ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/v3/index.vue.vm @@ -415,7 +415,7 @@ function getList() { #foreach ($column in $columns) #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) - if (null != daterange${AttrName} && '' != daterange${AttrName}) { + if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] } diff --git a/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/util/ScheduleUtils.java b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/util/ScheduleUtils.java index 165275a20..175ad7bef 100644 --- a/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/util/ScheduleUtils.java +++ b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/util/ScheduleUtils.java @@ -131,11 +131,11 @@ public class ScheduleUtils int count = StringUtils.countMatches(packageName, "."); if (count > 1) { - return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); + return StringUtils.startsWithAny(invokeTarget, Constants.JOB_WHITELIST_STR); } Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); String beanPackageName = obj.getClass().getPackage().getName(); - return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR) - && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR); + return StringUtils.startsWithAny(beanPackageName, Constants.JOB_WHITELIST_STR) + && !StringUtils.startsWithAny(beanPackageName, Constants.JOB_ERROR_STR); } } \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java index 9c5d148be..83aab06ab 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java @@ -100,7 +100,7 @@ public class SysProfileController extends BaseController String oldPassword = params.get("oldPassword"); String newPassword = params.get("newPassword"); LoginUser loginUser = SecurityUtils.getLoginUser(); - String userName = loginUser.getUsername(); + Long userId = loginUser.getUserid(); String password = loginUser.getSysUser().getPassword(); if (!SecurityUtils.matchesPassword(oldPassword, password)) { @@ -111,7 +111,7 @@ public class SysProfileController extends BaseController return error("新密码不能与旧密码相同"); } newPassword = SecurityUtils.encryptPassword(newPassword); - if (userService.resetUserPwd(userName, newPassword) > 0) + if (userService.resetUserPwd(userId, newPassword) > 0) { // 更新缓存用户密码&密码最后更新时间 loginUser.getSysUser().setPwdUpdateDate(DateUtils.getNowDate()); @@ -143,8 +143,13 @@ public class SysProfileController extends BaseController return error("文件服务异常,请联系管理员"); } String url = fileResult.getData().getUrl(); - if (userService.updateUserAvatar(loginUser.getUsername(), url)) + if (userService.updateUserAvatar(loginUser.getUserid(), url)) { + String oldAvatarUrl = loginUser.getSysUser().getAvatar(); + if (StringUtils.isNotEmpty(oldAvatarUrl)) + { + remoteFileService.delete(oldAvatarUrl); + } AjaxResult ajax = AjaxResult.success(); ajax.put("imgUrl", url); // 更新缓存用户头像 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPermissionServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPermissionServiceImpl.java index 5a0c0b257..36b6dbf84 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPermissionServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPermissionServiceImpl.java @@ -6,6 +6,7 @@ import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.system.api.domain.SysRole; @@ -41,7 +42,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService // 管理员拥有所有权限 if (user.isAdmin()) { - roles.add("admin"); + roles.add(Constants.SUPER_ADMIN); } else { @@ -63,7 +64,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService // 管理员拥有所有权限 if (user.isAdmin()) { - perms.add("*:*:*"); + perms.add(Constants.ALL_PERMISSION); } else { diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 6570fe421..b76b623a2 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi", - "version": "3.6.5", + "version": "3.6.7", "description": "若依管理系统", "author": "若依", "license": "MIT", diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index 5562a276c..b05777747 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -130,6 +130,16 @@ 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) { .pagination-container .el-pagination > .el-pagination__jump { display: none !important; diff --git a/ruoyi-ui/src/assets/styles/sidebar.scss b/ruoyi-ui/src/assets/styles/sidebar.scss index f1c821f15..419e374cb 100644 --- a/ruoyi-ui/src/assets/styles/sidebar.scss +++ b/ruoyi-ui/src/assets/styles/sidebar.scss @@ -61,7 +61,7 @@ } .svg-icon { - margin-right: 16px; + margin-right: 10px !important; } .el-menu { @@ -116,15 +116,17 @@ margin-left: 54px; } - .submenu-title-noDropdown { - padding: 0 !important; - position: relative; - - .el-tooltip { + .el-menu:not(.el-menu--horizontal) { + .submenu-title-noDropdown { padding: 0 !important; + position: relative; - .svg-icon { - margin-left: 20px; + .el-tooltip { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } } } } diff --git a/ruoyi-ui/src/components/Breadcrumb/index.vue b/ruoyi-ui/src/components/Breadcrumb/index.vue index cd2841468..6b56f5148 100644 --- a/ruoyi-ui/src/components/Breadcrumb/index.vue +++ b/ruoyi-ui/src/components/Breadcrumb/index.vue @@ -94,7 +94,6 @@ export default { display: inline-block; font-size: 14px; line-height: 50px; - margin-left: 8px; .no-redirect { color: #97a8be; cursor: text; diff --git a/ruoyi-ui/src/components/DictTag/index.vue b/ruoyi-ui/src/components/DictTag/index.vue index 4d90ac637..3b630ff15 100644 --- a/ruoyi-ui/src/components/DictTag/index.vue +++ b/ruoyi-ui/src/components/DictTag/index.vue @@ -1,7 +1,7 @@