diff --git a/pom.xml b/pom.xml
index 7a9af117..f7a7e08e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,31 +6,35 @@
com.ruoyi
ruoyi
- 3.8.8
+ 3.8.9
ruoyi
http://www.ruoyi.vip
若依管理系统
- 3.8.8
+ 3.8.9
UTF-8
UTF-8
1.8
3.1.1
- 5.3.33
- 5.7.12
+ 2.5.15
1.2.23
1.21
3.0.0
2.3.3
1.4.7
- 2.0.43
- 6.6.3
+ 2.0.53
+ 6.6.5
2.13.0
4.1.2
2.3
0.9.1
+
+ 9.0.102
+ 1.2.13
+ 5.7.12
+ 5.3.39
6.8.0
@@ -38,7 +42,7 @@
-
+
org.springframework
spring-framework-bom
@@ -47,7 +51,7 @@
import
-
+
org.springframework.security
spring-security-bom
@@ -60,11 +64,43 @@
org.springframework.boot
spring-boot-dependencies
- 2.5.15
+ ${spring-boot.version}
pom
import
+
+
+ ch.qos.logback
+ logback-core
+ ${logback.version}
+
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ ${tomcat.version}
+
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-el
+ ${tomcat.version}
+
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-websocket
+ ${tomcat.version}
+
+
com.alibaba
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 3a3385f0..77dc6720 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.8
+ 3.8.9
4.0.0
jar
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index dab2bf87..e575d287 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -12,9 +12,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
+import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
/**
@@ -34,6 +36,9 @@ public class SysLoginController
@Autowired
private SysPermissionService permissionService;
+ @Autowired
+ private TokenService tokenService;
+
/**
* 登录方法
*
@@ -59,11 +64,17 @@ public class SysLoginController
@GetMapping("getInfo")
public AjaxResult getInfo()
{
- SysUser user = SecurityUtils.getLoginUser().getUser();
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ SysUser user = loginUser.getUser();
// 角色集合
Set roles = permissionService.getRolePermission(user);
// 权限集合
Set permissions = permissionService.getMenuPermission(user);
+ if (!loginUser.getPermissions().equals(permissions))
+ {
+ loginUser.setPermissions(permissions);
+ tokenService.refreshToken(loginUser);
+ }
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
ajax.put("roles", roles);
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
index cd8abd6f..89e9bd33 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -1,5 +1,6 @@
package com.ruoyi.web.controller.system;
+import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -87,8 +88,10 @@ public class SysProfileController extends BaseController
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd")
- public AjaxResult updatePwd(String oldPassword, String newPassword)
+ public AjaxResult updatePwd(@RequestBody Map params)
{
+ String oldPassword = params.get("oldPassword");
+ String newPassword = params.get("newPassword");
LoginUser loginUser = getLoginUser();
String userName = loginUser.getUsername();
String password = loginUser.getPassword();
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index 24aafae7..11790f9b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -101,18 +101,18 @@ public class SysUserController extends BaseController
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{
- userService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success();
- List roles = roleService.selectRoleAll();
- ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
- ajax.put("posts", postService.selectPostAll());
if (StringUtils.isNotNull(userId))
{
+ userService.checkUserDataScope(userId);
SysUser sysUser = userService.selectUserById(userId);
ajax.put(AjaxResult.DATA_TAG, sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
}
+ List roles = roleService.selectRoleAll();
+ ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+ ajax.put("posts", postService.selectPostAll());
return ajax;
}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index ac86f04e..5cd90580 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -3,9 +3,9 @@ ruoyi:
# 名称
name: RuoYi
# 版本
- version: 3.8.8
+ version: 3.8.9
# 版权年份
- copyrightYear: 2024
+ copyrightYear: 2025
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 56c3f819..b0dddd96 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.8
+ 3.8.9
4.0.0
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
index 0d69d394..cfb5f9c9 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
@@ -83,6 +83,11 @@ public @interface Excel
*/
public String prompt() default "";
+ /**
+ * 是否允许内容换行
+ */
+ public boolean wrapText() default false;
+
/**
* 设置只能选择不能输入的列内容.
*/
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
index 4a59e402..a762704c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
@@ -4,8 +4,10 @@ import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.utils.StringUtils;
/**
* Treeselect树结构实体类
@@ -22,6 +24,9 @@ public class TreeSelect implements Serializable
/** 节点名称 */
private String label;
+ /** 节点禁用 */
+ private boolean disabled = false;
+
/** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List children;
@@ -35,6 +40,7 @@ public class TreeSelect implements Serializable
{
this.id = dept.getDeptId();
this.label = dept.getDeptName();
+ this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
@@ -65,6 +71,16 @@ public class TreeSelect implements Serializable
this.label = label;
}
+ public boolean isDisabled()
+ {
+ return disabled;
+ }
+
+ public void setDisabled(boolean disabled)
+ {
+ this.disabled = disabled;
+ }
+
public List getChildren()
{
return children;
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
index a3487b8e..f0befe7c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
@@ -37,7 +37,7 @@ public class TableDataInfo implements Serializable
* @param list 列表数据
* @param total 总记录数
*/
- public TableDataInfo(List> list, int total)
+ public TableDataInfo(List> list, long total)
{
this.rows = list;
this.total = total;
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
index 938d0c9f..03073474 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -541,7 +541,7 @@ public class Convert
/**
* 转换为boolean
- * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * String支持的值为:true、false、yes、ok、no、1、0、是、否, 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @param value 被转换的值
@@ -570,10 +570,12 @@ public class Convert
case "yes":
case "ok":
case "1":
+ case "是":
return true;
case "false":
case "no":
case "0":
+ case "否":
return false;
default:
return defaultValue;
@@ -796,14 +798,23 @@ public class Convert
{
return (String) obj;
}
- else if (obj instanceof byte[])
+ else if (obj instanceof byte[] || obj instanceof Byte[])
{
- return str((byte[]) obj, charset);
- }
- else if (obj instanceof Byte[])
- {
- byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
- return str(bytes, charset);
+ if (obj instanceof byte[])
+ {
+ return str((byte[]) obj, charset);
+ }
+ else
+ {
+ Byte[] bytes = (Byte[]) obj;
+ int length = bytes.length;
+ byte[] dest = new byte[length];
+ for (int i = 0; i < length; i++)
+ {
+ dest[i] = bytes[i];
+ }
+ return str(dest, charset);
+ }
}
else if (obj instanceof ByteBuffer)
{
@@ -959,9 +970,7 @@ public class Convert
c[i] = (char) (c[i] - 65248);
}
}
- String returnString = new String(c);
-
- return returnString;
+ return new String(c);
}
/**
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
index 45081229..07f02eeb 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
@@ -23,7 +23,7 @@ public enum DesensitizedType
/**
* 身份证,中间10位星号替换
*/
- ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
+ ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
/**
* 手机号,中间4位星号替换
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
index b6326c2b..9f95c0f3 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
@@ -108,7 +108,6 @@ public class Arith
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
- BigDecimal one = BigDecimal.ONE;
- return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
+ return b.divide(BigDecimal.ONE, scale, RoundingMode.HALF_UP).doubleValue();
}
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
index fc6c6b5e..920968fa 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -286,6 +286,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return str.substring(start, end);
}
+ /**
+ * 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
+ *
+ * @param str 要截取的字符串
+ * @param open 起始字符串
+ * @param close 结束字符串
+ * @return 截取结果
+ */
+ public static String substringBetweenLast(final String str, final String open, final String close)
+ {
+ if (isEmpty(str) || isEmpty(open) || isEmpty(close))
+ {
+ return NULLSTR;
+ }
+ final int start = str.indexOf(open);
+ if (start != INDEX_NOT_FOUND)
+ {
+ final int end = str.lastIndexOf(close);
+ if (end != INDEX_NOT_FOUND)
+ {
+ return str.substring(start + open.length(), end);
+ }
+ }
+ return NULLSTR;
+ }
+
/**
* 判断是否为空,并且不是空白字符
*
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
index d3b61cad..d5057891 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -21,6 +21,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
+import org.springframework.http.MediaType;
/**
* 通用http发送方法
@@ -125,6 +126,19 @@ public class HttpUtils
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
+ {
+ return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数
+ * @param contentType 内容类型
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendPost(String url, String param, String contentType)
{
PrintWriter out = null;
BufferedReader in = null;
@@ -138,7 +152,7 @@ public class HttpUtils
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
- conn.setRequestProperty("contentType", "utf-8");
+ conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
@@ -190,6 +204,11 @@ public class HttpUtils
}
public static String sendSSLPost(String url, String param)
+ {
+ return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
+ }
+
+ public static String sendSSLPost(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
@@ -204,7 +223,7 @@ public class HttpUtils
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
- conn.setRequestProperty("contentType", "utf-8");
+ conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index 64f97baa..9191c7a1 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -194,6 +194,11 @@ public class ExcelUtil
*/
public Class clazz;
+ /**
+ * 需要显示列属性
+ */
+ public String[] includeFields;
+
/**
* 需要排除列属性
*/
@@ -204,11 +209,20 @@ public class ExcelUtil
this.clazz = clazz;
}
+ /**
+ * 仅在Excel中显示列属性
+ *
+ * @param fields 列属性名 示例[单个"name"/多个"id","name"]
+ */
+ public void showColumn(String... fields)
+ {
+ this.includeFields = fields;
+ }
+
/**
* 隐藏Excel中列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
- * @throws Exception
*/
public void hideColumn(String... fields)
{
@@ -238,8 +252,6 @@ public class ExcelUtil
{
if (StringUtils.isNotEmpty(title))
{
- subMergedFirstRowNum++;
- subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
@@ -250,7 +262,7 @@ public class ExcelUtil
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
- sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
+ sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
}
}
@@ -261,23 +273,31 @@ public class ExcelUtil
{
if (isSubList())
{
- subMergedFirstRowNum++;
- subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum);
- int excelNum = 0;
+ int column = 0;
+ int subFieldSize = subFields != null ? subFields.size() : 0;
for (Object[] objects : fields)
{
+ Field field = (Field) objects[0];
Excel attr = (Excel) objects[1];
- Cell headCell1 = subRow.createCell(excelNum);
- headCell1.setCellValue(attr.name());
- headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
- excelNum++;
- }
- int headFirstRow = excelNum - 1;
- int headLastRow = headFirstRow + subFields.size() - 1;
- if (headLastRow > headFirstRow)
- {
- sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
+ 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())));
+ if (subFieldSize > 1)
+ {
+ CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
+ sheet.addMergedRegion(cellAddress);
+ }
+ column += subFieldSize;
+ }
+ else
+ {
+ Cell cell = subRow.createCell(column++);
+ cell.setCellValue(attr.name());
+ cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+ }
}
rownum++;
}
@@ -290,11 +310,23 @@ public class ExcelUtil
* @return 转换后集合
*/
public List importExcel(InputStream is)
+ {
+ return importExcel(is, 0);
+ }
+
+ /**
+ * 对excel表单默认第一个索引名转换成list
+ *
+ * @param is 输入流
+ * @param titleNum 标题占用行数
+ * @return 转换后集合
+ */
+ public List importExcel(InputStream is, int titleNum)
{
List list = null;
try
{
- list = importExcel(is, 0);
+ list = importExcel(StringUtils.EMPTY, is, titleNum);
}
catch (Exception e)
{
@@ -308,18 +340,6 @@ public class ExcelUtil
return list;
}
- /**
- * 对excel表单默认第一个索引名转换成list
- *
- * @param is 输入流
- * @param titleNum 标题占用行数
- * @return 转换后集合
- */
- public List importExcel(InputStream is, int titleNum) throws Exception
- {
- return importExcel(StringUtils.EMPTY, is, titleNum);
- }
-
/**
* 对excel表单指定表格索引名转换成list
*
@@ -711,66 +731,93 @@ public class ExcelUtil
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
- int rowNo = (1 + rownum) - startNo;
+ int currentRowNum = rownum + 1; // 从标题行后开始
+
for (int i = startNo; i < endNo; i++)
{
- rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
- row = sheet.createRow(rowNo);
- // 得到导出对象.
+ row = sheet.createRow(currentRowNum);
T vo = (T) list.get(i);
- Collection> subList = null;
- if (isSubList())
- {
- if (isSubListValue(vo))
- {
- subList = getListCellValue(vo);
- subMergedLastRowNum = subMergedLastRowNum + subList.size();
- }
- else
- {
- subMergedFirstRowNum++;
- subMergedLastRowNum++;
- }
- }
int column = 0;
+ int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
- if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
+ if (Collection.class.isAssignableFrom(field.getType()))
{
- boolean subFirst = false;
- for (Object obj : subList)
+ try
{
- if (subFirst)
+ Collection> subList = (Collection>) getTargetValue(vo, field, excel);
+ if (subList != null && !subList.isEmpty())
{
- rowNo++;
- row = sheet.createRow(rowNo);
- }
- List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
- int subIndex = 0;
- for (Field subField : subFields)
- {
- if (subField.isAnnotationPresent(Excel.class))
+ int subIndex = 0;
+ for (Object subVo : subList)
{
- subField.setAccessible(true);
- Excel attr = subField.getAnnotation(Excel.class);
- this.addCell(attr, row, (T) obj, subField, column + subIndex);
+ Row subRow = sheet.getRow(currentRowNum + subIndex);
+ if (subRow == null)
+ {
+ subRow = sheet.createRow(currentRowNum + subIndex);
+ }
+
+ int subColumn = column;
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
+ }
+ subIndex++;
}
- subIndex++;
+ column += subFields.size();
}
- subFirst = true;
}
- this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
+ catch (Exception e)
+ {
+ log.error("填充集合数据失败", e);
+ }
}
else
{
- this.addCell(excel, row, vo, field, column++);
+ // 创建单元格并设置值
+ addCell(excel, row, vo, field, column);
+ if (maxSubListSize > 1 && excel.needMerge())
+ {
+ sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
+ }
+ column++;
}
}
+ currentRowNum += maxSubListSize;
}
}
+ /**
+ * 获取子列表最大数
+ */
+ private int getCurrentMaxSubListSize(T vo)
+ {
+ int maxSubListSize = 1;
+ for (Object[] os : fields)
+ {
+ Field field = (Field) os[0];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ try
+ {
+ Collection> subList = (Collection>) getTargetValue(vo, field, (Excel) os[1]);
+ if (subList != null && !subList.isEmpty())
+ {
+ maxSubListSize = Math.max(maxSubListSize, subList.size());
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("获取集合大小失败", e);
+ }
+ }
+ }
+ return maxSubListSize;
+ }
+
/**
* 创建表格样式
*
@@ -903,7 +950,7 @@ public class ExcelUtil
*/
public void annotationDataStyles(Map styles, Field field, Excel excel)
{
- String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
+ String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
@@ -919,6 +966,7 @@ public class ExcelUtil
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex());
+ style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
@@ -947,7 +995,7 @@ public class ExcelUtil
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
- sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
+ sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -1085,10 +1133,12 @@ public class ExcelUtil
cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{
- CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
- sheet.addMergedRegion(cellAddress);
+ if (subMergedLastRowNum >= subMergedFirstRowNum)
+ {
+ sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
+ }
}
- cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
+ cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
@@ -1098,6 +1148,7 @@ public class ExcelUtil
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
+ cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value));
}
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
@@ -1398,8 +1449,7 @@ public class ExcelUtil
*/
public String encodingFilename(String filename)
{
- filename = UUID.randomUUID() + "_" + filename + ".xlsx";
- return filename;
+ return UUID.randomUUID() + "_" + filename + ".xlsx";
}
/**
@@ -1429,6 +1479,7 @@ public class ExcelUtil
*/
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{
+ field.setAccessible(true);
Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr()))
{
@@ -1488,46 +1539,83 @@ public class ExcelUtil
List tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
- for (Field field : tempFields)
+ if (StringUtils.isNotEmpty(includeFields))
{
- if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+ for (Field field : tempFields)
{
- // 单注解
- if (field.isAnnotationPresent(Excel.class))
+ if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
{
- Excel attr = field.getAnnotation(Excel.class);
- if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+ addField(fields, field);
+ }
+ }
+ }
+ else if (StringUtils.isNotEmpty(excludeFields))
+ {
+ for (Field field : tempFields)
+ {
+ if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+ {
+ addField(fields, field);
+ }
+ }
+ }
+ else
+ {
+ for (Field field : tempFields)
+ {
+ addField(fields, field);
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * 添加字段信息
+ */
+ public void addField(List