更新至最新的RuoYi版本
This commit is contained in:
parent
3d7fa110f2
commit
c62fdd4218
@ -5,7 +5,7 @@ ruoyi:
|
|||||||
# 版本
|
# 版本
|
||||||
version: 3.8.5
|
version: 3.8.5
|
||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2023
|
copyrightYear: 2024
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
profile: D:/ruoyi/uploadPath
|
profile: D:/ruoyi/uploadPath
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
|
@ -8,6 +8,7 @@ import java.math.RoundingMode;
|
|||||||
|
|
||||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||||
|
|
||||||
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
|
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,7 +173,7 @@ public @interface Excel
|
|||||||
|
|
||||||
public enum ColumnType
|
public enum ColumnType
|
||||||
{
|
{
|
||||||
NUMERIC(0), STRING(1), IMAGE(2);
|
NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
ColumnType(int value)
|
ColumnType(int value)
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.ruoyi.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
|
||||||
|
import com.ruoyi.common.enums.DesensitizedType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据脱敏注解
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@JacksonAnnotationsInside
|
||||||
|
@JsonSerialize(using = SensitiveJsonSerializer.class)
|
||||||
|
public @interface Sensitive
|
||||||
|
{
|
||||||
|
DesensitizedType desensitizedType();
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.ruoyi.common.config.serializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.BeanProperty;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||||
|
import com.ruoyi.common.annotation.Sensitive;
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.enums.DesensitizedType;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据脱敏序列化过滤
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
|
||||||
|
{
|
||||||
|
private DesensitizedType desensitizedType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
|
||||||
|
{
|
||||||
|
if (desensitization())
|
||||||
|
{
|
||||||
|
gen.writeString(desensitizedType.desensitizer().apply(value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gen.writeString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
|
||||||
|
throws JsonMappingException
|
||||||
|
{
|
||||||
|
Sensitive annotation = property.getAnnotation(Sensitive.class);
|
||||||
|
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
|
||||||
|
{
|
||||||
|
this.desensitizedType = annotation.desensitizedType();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return prov.findValueSerializer(property.getType(), property);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要脱敏处理
|
||||||
|
*/
|
||||||
|
private boolean desensitization()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LoginUser securityUser = SecurityUtils.getLoginUser();
|
||||||
|
// 管理员不脱敏
|
||||||
|
return !securityUser.getUser().isAdmin();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.ruoyi.common.constant;
|
package com.ruoyi.common.constant;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,6 +20,11 @@ public class Constants {
|
|||||||
*/
|
*/
|
||||||
public static final String GBK = "GBK";
|
public static final String GBK = "GBK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统语言
|
||||||
|
*/
|
||||||
|
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www主域
|
* www主域
|
||||||
*/
|
*/
|
||||||
@ -156,7 +163,7 @@ public class Constants {
|
|||||||
/**
|
/**
|
||||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||||
*/
|
*/
|
||||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
|
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务违规的字符
|
* 定时任务违规的字符
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.ruoyi.common.enums;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import com.ruoyi.common.utils.DesensitizedUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脱敏类型
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public enum DesensitizedType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 姓名,第2位星号替换
|
||||||
|
*/
|
||||||
|
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码,全部字符都用*代替
|
||||||
|
*/
|
||||||
|
PASSWORD(DesensitizedUtil::password),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证,中间10位星号替换
|
||||||
|
*/
|
||||||
|
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号,中间4位星号替换
|
||||||
|
*/
|
||||||
|
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
|
||||||
|
*/
|
||||||
|
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 银行卡号,保留最后4位,其他星号替换
|
||||||
|
*/
|
||||||
|
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌号码,包含普通车辆、新能源车辆
|
||||||
|
*/
|
||||||
|
CAR_LICENSE(DesensitizedUtil::carLicense);
|
||||||
|
|
||||||
|
private final Function<String, String> desensitizer;
|
||||||
|
|
||||||
|
DesensitizedType(Function<String, String> desensitizer)
|
||||||
|
{
|
||||||
|
this.desensitizer = desensitizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<String, String> desensitizer()
|
||||||
|
{
|
||||||
|
return desensitizer;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脱敏工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class DesensitizedUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 密码的全部字符都用*代替,比如:******
|
||||||
|
*
|
||||||
|
* @param password 密码
|
||||||
|
* @return 脱敏后的密码
|
||||||
|
*/
|
||||||
|
public static String password(String password)
|
||||||
|
{
|
||||||
|
if (StringUtils.isBlank(password))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return StringUtils.repeat('*', password.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌中间用*代替,如果是错误的车牌,不处理
|
||||||
|
*
|
||||||
|
* @param carLicense 完整的车牌号
|
||||||
|
* @return 脱敏后的车牌
|
||||||
|
*/
|
||||||
|
public static String carLicense(String carLicense)
|
||||||
|
{
|
||||||
|
if (StringUtils.isBlank(carLicense))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
// 普通车牌
|
||||||
|
if (carLicense.length() == 7)
|
||||||
|
{
|
||||||
|
carLicense = StringUtils.hide(carLicense, 3, 6);
|
||||||
|
}
|
||||||
|
else if (carLicense.length() == 8)
|
||||||
|
{
|
||||||
|
// 新能源车牌
|
||||||
|
carLicense = StringUtils.hide(carLicense, 3, 7);
|
||||||
|
}
|
||||||
|
return carLicense;
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,9 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.text.StrFormatter;
|
import com.ruoyi.common.core.text.StrFormatter;
|
||||||
|
|
||||||
@ -23,6 +25,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
/** 下划线 */
|
/** 下划线 */
|
||||||
private static final char SEPARATOR = '_';
|
private static final char SEPARATOR = '_';
|
||||||
|
|
||||||
|
/** 星号 */
|
||||||
|
private static final char ASTERISK = '*';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取参数不为空值
|
* 获取参数不为空值
|
||||||
*
|
*
|
||||||
@ -163,6 +168,49 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
return (str == null ? "" : str.trim());
|
return (str == null ? "" : str.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换指定字符串的指定区间内字符为"*"
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param startInclude 开始位置(包含)
|
||||||
|
* @param endExclude 结束位置(不包含)
|
||||||
|
* @return 替换后的字符串
|
||||||
|
*/
|
||||||
|
public static String hide(CharSequence str, int startInclude, int endExclude)
|
||||||
|
{
|
||||||
|
if (isEmpty(str))
|
||||||
|
{
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
final int strLength = str.length();
|
||||||
|
if (startInclude > strLength)
|
||||||
|
{
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
if (endExclude > strLength)
|
||||||
|
{
|
||||||
|
endExclude = strLength;
|
||||||
|
}
|
||||||
|
if (startInclude > endExclude)
|
||||||
|
{
|
||||||
|
// 如果起始位置大于结束位置,不替换
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
final char[] chars = new char[strLength];
|
||||||
|
for (int i = 0; i < strLength; i++)
|
||||||
|
{
|
||||||
|
if (i >= startInclude && i < endExclude)
|
||||||
|
{
|
||||||
|
chars[i] = ASTERISK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chars[i] = str.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 截取字符串
|
* 截取字符串
|
||||||
*
|
*
|
||||||
|
@ -23,7 +23,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||||
@ -39,6 +39,7 @@ import org.apache.poi.ss.usermodel.Cell;
|
|||||||
import org.apache.poi.ss.usermodel.CellStyle;
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
import org.apache.poi.ss.usermodel.CellType;
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormat;
|
||||||
import org.apache.poi.ss.usermodel.DataValidation;
|
import org.apache.poi.ss.usermodel.DataValidation;
|
||||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||||
@ -69,6 +70,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|||||||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
|
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import com.ruoyi.common.annotation.Excel.ColumnType;
|
import com.ruoyi.common.annotation.Excel.ColumnType;
|
||||||
import com.ruoyi.common.annotation.Excel.Type;
|
import com.ruoyi.common.annotation.Excel.Type;
|
||||||
@ -85,6 +87,8 @@ import com.ruoyi.common.utils.file.FileUtils;
|
|||||||
import com.ruoyi.common.utils.file.ImageUtils;
|
import com.ruoyi.common.utils.file.ImageUtils;
|
||||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel相关处理
|
* Excel相关处理
|
||||||
*
|
*
|
||||||
@ -288,9 +292,23 @@ public class ExcelUtil<T>
|
|||||||
* @param is 输入流
|
* @param is 输入流
|
||||||
* @return 转换后集合
|
* @return 转换后集合
|
||||||
*/
|
*/
|
||||||
public List<T> importExcel(InputStream is) throws Exception
|
public List<T> importExcel(InputStream is)
|
||||||
{
|
{
|
||||||
return importExcel(is, 0);
|
List<T> list = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
list = importExcel(is, 0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("导入Excel异常{}", e.getMessage());
|
||||||
|
throw new UtilException(e.getMessage());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,7 +354,6 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
|
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
|
||||||
int rows = sheet.getLastRowNum();
|
int rows = sheet.getLastRowNum();
|
||||||
|
|
||||||
if (rows > 0)
|
if (rows > 0)
|
||||||
{
|
{
|
||||||
// 定义一个map用于存放excel列的序号和field.
|
// 定义一个map用于存放excel列的序号和field.
|
||||||
@ -383,8 +400,7 @@ public class ExcelUtil<T>
|
|||||||
Object val = this.getCellValue(row, entry.getKey());
|
Object val = this.getCellValue(row, entry.getKey());
|
||||||
|
|
||||||
// 如果不存在实例则新建.
|
// 如果不存在实例则新建.
|
||||||
entity = (entity == null ? clazz.getDeclaredConstructor().newInstance()
|
entity = (entity == null ? clazz.newInstance() : entity);
|
||||||
: entity);
|
|
||||||
// 从map中得到对应列的field.
|
// 从map中得到对应列的field.
|
||||||
Field field = (Field) entry.getValue()[0];
|
Field field = (Field) entry.getValue()[0];
|
||||||
Excel attr = (Excel) entry.getValue()[1];
|
Excel attr = (Excel) entry.getValue()[1];
|
||||||
@ -452,7 +468,7 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
propertyName = field.getName() + "." + attr.targetAttr();
|
propertyName = field.getName() + "." + attr.targetAttr();
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
||||||
{
|
{
|
||||||
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
|
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
|
||||||
}
|
}
|
||||||
@ -462,7 +478,7 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
|
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
|
||||||
{
|
{
|
||||||
val = dataFormatHandlerAdapter(val, attr);
|
val = dataFormatHandlerAdapter(val, attr, null);
|
||||||
}
|
}
|
||||||
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
|
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
|
||||||
{
|
{
|
||||||
@ -771,6 +787,8 @@ public class ExcelUtil<T>
|
|||||||
titleFont.setFontHeightInPoints((short) 16);
|
titleFont.setFontHeightInPoints((short) 16);
|
||||||
titleFont.setBold(true);
|
titleFont.setBold(true);
|
||||||
style.setFont(titleFont);
|
style.setFont(titleFont);
|
||||||
|
DataFormat dataFormat = wb.createDataFormat();
|
||||||
|
style.setDataFormat(dataFormat.getFormat("@"));
|
||||||
styles.put("title", style);
|
styles.put("title", style);
|
||||||
|
|
||||||
style = wb.createCellStyle();
|
style = wb.createCellStyle();
|
||||||
@ -850,34 +868,66 @@ public class ExcelUtil<T>
|
|||||||
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
|
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
|
||||||
for (Object[] os : fields)
|
for (Object[] os : fields)
|
||||||
{
|
{
|
||||||
|
Field field = (Field) os[0];
|
||||||
Excel excel = (Excel) os[1];
|
Excel excel = (Excel) os[1];
|
||||||
String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
|
if (Collection.class.isAssignableFrom(field.getType()))
|
||||||
if (!styles.containsKey(key))
|
|
||||||
{
|
{
|
||||||
CellStyle style = wb.createCellStyle();
|
ParameterizedType pt = (ParameterizedType) field.getGenericType();
|
||||||
style.setAlignment(excel.align());
|
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
|
||||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
|
||||||
style.setBorderRight(BorderStyle.THIN);
|
for (Field subField : subFields)
|
||||||
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
{
|
||||||
style.setBorderLeft(BorderStyle.THIN);
|
Excel subExcel = subField.getAnnotation(Excel.class);
|
||||||
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
annotationDataStyles(styles, subField, subExcel);
|
||||||
style.setBorderTop(BorderStyle.THIN);
|
}
|
||||||
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
}
|
||||||
style.setBorderBottom(BorderStyle.THIN);
|
else
|
||||||
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
{
|
||||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
annotationDataStyles(styles, field, excel);
|
||||||
style.setFillForegroundColor(excel.backgroundColor().getIndex());
|
|
||||||
Font dataFont = wb.createFont();
|
|
||||||
dataFont.setFontName("Arial");
|
|
||||||
dataFont.setFontHeightInPoints((short) 10);
|
|
||||||
dataFont.setColor(excel.color().index);
|
|
||||||
style.setFont(dataFont);
|
|
||||||
styles.put(key, style);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return styles;
|
return styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据Excel注解创建表格列样式
|
||||||
|
*
|
||||||
|
* @param styles 自定义样式列表
|
||||||
|
* @param field 属性列信息
|
||||||
|
* @param excel 注解信息
|
||||||
|
*/
|
||||||
|
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
|
||||||
|
{
|
||||||
|
String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
|
||||||
|
if (!styles.containsKey(key))
|
||||||
|
{
|
||||||
|
CellStyle style = wb.createCellStyle();
|
||||||
|
style.setAlignment(excel.align());
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
style.setBorderRight(BorderStyle.THIN);
|
||||||
|
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderLeft(BorderStyle.THIN);
|
||||||
|
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderTop(BorderStyle.THIN);
|
||||||
|
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderBottom(BorderStyle.THIN);
|
||||||
|
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||||
|
style.setFillForegroundColor(excel.backgroundColor().getIndex());
|
||||||
|
Font dataFont = wb.createFont();
|
||||||
|
dataFont.setFontName("Arial");
|
||||||
|
dataFont.setFontHeightInPoints((short) 10);
|
||||||
|
dataFont.setColor(excel.color().index);
|
||||||
|
style.setFont(dataFont);
|
||||||
|
if (ColumnType.TEXT == excel.cellType())
|
||||||
|
{
|
||||||
|
DataFormat dataFormat = wb.createDataFormat();
|
||||||
|
style.setDataFormat(dataFormat.getFormat("@"));
|
||||||
|
}
|
||||||
|
styles.put(key, style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建单元格
|
* 创建单元格
|
||||||
*/
|
*/
|
||||||
@ -892,7 +942,7 @@ public class ExcelUtil<T>
|
|||||||
if (isSubList())
|
if (isSubList())
|
||||||
{
|
{
|
||||||
// 填充默认样式,防止合并单元格样式失效
|
// 填充默认样式,防止合并单元格样式失效
|
||||||
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
|
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
|
||||||
if (attr.needMerge())
|
if (attr.needMerge())
|
||||||
{
|
{
|
||||||
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
|
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
|
||||||
@ -910,7 +960,7 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
public void setCellVo(Object value, Excel attr, Cell cell)
|
public void setCellVo(Object value, Excel attr, Cell cell)
|
||||||
{
|
{
|
||||||
if (ColumnType.STRING == attr.cellType())
|
if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
|
||||||
{
|
{
|
||||||
String cellValue = Convert.toStr(value);
|
String cellValue = Convert.toStr(value);
|
||||||
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
|
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
|
||||||
@ -1022,7 +1072,7 @@ public class ExcelUtil<T>
|
|||||||
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
|
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
|
||||||
sheet.addMergedRegion(cellAddress);
|
sheet.addMergedRegion(cellAddress);
|
||||||
}
|
}
|
||||||
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
|
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
|
||||||
|
|
||||||
// 用于读取对象中的属性
|
// 用于读取对象中的属性
|
||||||
Object value = getTargetValue(vo, field, attr);
|
Object value = getTargetValue(vo, field, attr);
|
||||||
@ -1050,11 +1100,10 @@ public class ExcelUtil<T>
|
|||||||
else if (value instanceof BigDecimal && -1 != attr.scale())
|
else if (value instanceof BigDecimal && -1 != attr.scale())
|
||||||
{
|
{
|
||||||
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
|
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
|
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
|
||||||
{
|
{
|
||||||
cell.setCellValue(dataFormatHandlerAdapter(value, attr));
|
cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1267,13 +1316,13 @@ public class ExcelUtil<T>
|
|||||||
* @param excel 数据注解
|
* @param excel 数据注解
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String dataFormatHandlerAdapter(Object value, Excel excel)
|
public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Object instance = excel.handler().getDeclaredConstructor().newInstance();
|
Object instance = excel.handler().newInstance();
|
||||||
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class });
|
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
|
||||||
value = formatMethod.invoke(instance, value, excel.args());
|
value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||||
|
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||||
|
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源文件配置加载
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class I18nConfig implements WebMvcConfigurer
|
||||||
|
{
|
||||||
|
@Bean
|
||||||
|
public LocaleResolver localeResolver()
|
||||||
|
{
|
||||||
|
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||||
|
// 默认语言
|
||||||
|
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
|
||||||
|
return slr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||||
|
{
|
||||||
|
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||||
|
// 参数名
|
||||||
|
lci.setParamName("lang");
|
||||||
|
return lci;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry)
|
||||||
|
{
|
||||||
|
registry.addInterceptor(localeChangeInterceptor());
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
|
order by create_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectJobLogAll" resultMap="SysJobLogResult">
|
<select id="selectJobLogAll" resultMap="SysJobLogResult">
|
||||||
|
Loading…
Reference in New Issue
Block a user