first commit
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ClassScannerUtil implements ResourceLoaderAware {
|
||||
private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();
|
||||
private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
|
||||
|
||||
public static Set<Class> scan(String[] basePackages,
|
||||
Class<? extends Annotation>... annotations) {
|
||||
ClassScannerUtil cs = new ClassScannerUtil();
|
||||
if (ArrayUtils.isNotEmpty(annotations)) {
|
||||
for (Class anno : annotations) {
|
||||
cs.addIncludeFilter(new AnnotationTypeFilter(anno));
|
||||
}
|
||||
}
|
||||
Set<Class> classes = new HashSet<Class>();
|
||||
for (String s : basePackages) {
|
||||
classes.addAll(cs.doScan(s));
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
public static Set<Class> scan(String basePackages, Class<? extends Annotation>... annotations) {
|
||||
return ClassScannerUtil.scan(StringUtils.tokenizeToStringArray(basePackages, ",; \t\n"), annotations);
|
||||
}
|
||||
|
||||
public final ResourceLoader getResourceLoader() {
|
||||
return this.resourcePatternResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils
|
||||
.getResourcePatternResolver(resourceLoader);
|
||||
this.metadataReaderFactory = new CachingMetadataReaderFactory(
|
||||
resourceLoader);
|
||||
}
|
||||
|
||||
public void addIncludeFilter(TypeFilter includeFilter) {
|
||||
this.includeFilters.add(includeFilter);
|
||||
}
|
||||
|
||||
public void addExcludeFilter(TypeFilter excludeFilter) {
|
||||
this.excludeFilters.add(0, excludeFilter);
|
||||
}
|
||||
|
||||
public void resetFilters(boolean useDefaultFilters) {
|
||||
this.includeFilters.clear();
|
||||
this.excludeFilters.clear();
|
||||
}
|
||||
|
||||
public Set<Class> doScan(String basePackage) {
|
||||
Set<Class> classes = new HashSet<Class>();
|
||||
try {
|
||||
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
|
||||
+ org.springframework.util.ClassUtils
|
||||
.convertClassNameToResourcePath(SystemPropertyUtils
|
||||
.resolvePlaceholders(basePackage))
|
||||
+ "/**/*.class";
|
||||
Resource[] resources = this.resourcePatternResolver
|
||||
.getResources(packageSearchPath);
|
||||
|
||||
for (Resource resource : resources) {
|
||||
if (resource.isReadable()) {
|
||||
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
|
||||
if ((includeFilters.size() == 0 && excludeFilters.size() == 0)
|
||||
|| matches(metadataReader)) {
|
||||
try {
|
||||
classes.add(Class.forName(metadataReader
|
||||
.getClassMetadata().getClassName()));
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"I/O failure during classpath scanning", ex);
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
protected boolean matches(MetadataReader metadataReader) throws IOException {
|
||||
for (TypeFilter tf : this.excludeFilters) {
|
||||
if (tf.match(metadataReader, this.metadataReaderFactory)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (TypeFilter tf : this.includeFilters) {
|
||||
if (tf.match(metadataReader, this.metadataReaderFactory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
*
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
*
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文件下载工具类,使用本类前,对参数校验的异常使用CommonResponseUtil.renderError()方法进行渲染
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2020/8/5 21:45
|
||||
*/
|
||||
@Slf4j
|
||||
public class CommonDownloadUtil {
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param file 要下载的文件
|
||||
* @param response 响应
|
||||
* @author xuyuxiang
|
||||
* @date 2020/8/5 21:46
|
||||
*/
|
||||
public static void download(File file, HttpServletResponse response) {
|
||||
download(file.getName(), FileUtil.readBytes(file), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param fileName
|
||||
* @param workbook
|
||||
* @param response
|
||||
*/
|
||||
public static void download(String fileName, Workbook workbook, HttpServletResponse response) {
|
||||
ByteArrayOutputStream byteOs = new ByteArrayOutputStream();
|
||||
try {
|
||||
workbook.write(byteOs);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(">>> 文件下载异常:", e);
|
||||
} finally {
|
||||
try {
|
||||
workbook.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
IoUtil.close(byteOs);
|
||||
}
|
||||
download(fileName, byteOs.toByteArray(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/7/31 10:57
|
||||
*/
|
||||
public static void download(String fileName, byte[] fileBytes, HttpServletResponse response) {
|
||||
try {
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode(fileName));
|
||||
response.addHeader("Content-Length", "" + fileBytes.length);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
response.setContentType("application/octet-stream;charset=UTF-8");
|
||||
IoUtil.write(response.getOutputStream(), true, fileBytes);
|
||||
} catch (IOException e) {
|
||||
log.error(">>> 文件下载异常:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.param.Condition;
|
||||
import com.budwk.app.base.param.ConditionGroup;
|
||||
import com.budwk.app.sys.param.SysDataUserUpdateParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
|
||||
/**
|
||||
* 条件组处理工具类
|
||||
* 用于处理复杂的条件组和条件,生成对应的SQL条件
|
||||
*/
|
||||
@Slf4j
|
||||
public class ConditionGroupUtil {
|
||||
|
||||
/**
|
||||
* 处理条件组,将条件组转换为Cnd条件
|
||||
*
|
||||
* @param cnd 原始条件
|
||||
* @param group 条件组
|
||||
* @return 处理后的条件
|
||||
*/
|
||||
public static Cnd applyConditionGroup(Cnd cnd, ConditionGroup group) {
|
||||
if (group == null) {
|
||||
return cnd;
|
||||
}
|
||||
|
||||
SqlExpressionGroup expGroup = new SqlExpressionGroup();
|
||||
|
||||
// 处理条件列表
|
||||
if (group.getConditions() != null && !group.getConditions().isEmpty()) {
|
||||
for (Condition condition : group.getConditions()) {
|
||||
expGroup = applyCondition(expGroup, condition, group.getLogic());
|
||||
}
|
||||
}
|
||||
|
||||
// 处理嵌套条件组
|
||||
if (group.getGroups() != null && !group.getGroups().isEmpty()) {
|
||||
for (ConditionGroup nestedGroup : group.getGroups()) {
|
||||
// 创建子条件
|
||||
Cnd subCnd = Cnd.NEW();
|
||||
subCnd = applyConditionGroup(subCnd, nestedGroup);
|
||||
|
||||
// 将子条件的表达式组添加到当前表达式组
|
||||
if ("OR".equalsIgnoreCase(group.getLogic())) {
|
||||
expGroup.or(subCnd.where());
|
||||
} else {
|
||||
expGroup.and(subCnd.where());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将表达式组添加到主条件
|
||||
cnd.and(expGroup);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个条件
|
||||
*
|
||||
* @param expGroup 表达式组
|
||||
* @param condition 条件
|
||||
* @param logic 逻辑类型 (AND/OR)
|
||||
* @return 处理后的表达式组
|
||||
*/
|
||||
public static SqlExpressionGroup applyCondition(SqlExpressionGroup expGroup, Condition condition, String logic) {
|
||||
String field = condition.getField();
|
||||
String operator = condition.getOperator();
|
||||
Object value = condition.getValue();
|
||||
|
||||
// 根据操作符处理条件
|
||||
switch (operator.toUpperCase()) {
|
||||
case "=":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "=", value);
|
||||
} else {
|
||||
expGroup.and(field, "=", value);
|
||||
}
|
||||
break;
|
||||
case "!=":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "!=", value);
|
||||
} else {
|
||||
expGroup.and(field, "!=", value);
|
||||
}
|
||||
break;
|
||||
case ">":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, ">", value);
|
||||
} else {
|
||||
expGroup.and(field, ">", value);
|
||||
}
|
||||
break;
|
||||
case "<":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "<", value);
|
||||
} else {
|
||||
expGroup.and(field, "<", value);
|
||||
}
|
||||
break;
|
||||
case ">=":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, ">=", value);
|
||||
} else {
|
||||
expGroup.and(field, ">=", value);
|
||||
}
|
||||
break;
|
||||
case "<=":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "<=", value);
|
||||
} else {
|
||||
expGroup.and(field, "<=", value);
|
||||
}
|
||||
break;
|
||||
case "LIKE":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "LIKE", "%" + value + "%");
|
||||
} else {
|
||||
expGroup.and(field, "LIKE", "%" + value + "%");
|
||||
}
|
||||
break;
|
||||
case "IN":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "IN", ObjectUtil.isNotNull(value) ? value.toString().split(",") : new String[0]);
|
||||
} else {
|
||||
expGroup.and(field, "IN", ObjectUtil.isNotNull(value) ? value.toString().split(",") : new String[0]);
|
||||
}
|
||||
break;
|
||||
case "NOT IN":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "NOT IN", ObjectUtil.isNotNull(value) ? value.toString().split(",") : new String[0]);
|
||||
} else {
|
||||
expGroup.and(field, "NOT IN", ObjectUtil.isNotNull(value) ? value.toString().split(",") : new String[0]);
|
||||
}
|
||||
break;
|
||||
case "IS NULL":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "IS", null);
|
||||
} else {
|
||||
expGroup.and(field, "IS", null);
|
||||
}
|
||||
break;
|
||||
case "IS NOT NULL":
|
||||
if ("OR".equalsIgnoreCase(logic)) {
|
||||
expGroup.or(field, "IS NOT", null);
|
||||
} else {
|
||||
expGroup.and(field, "IS NOT", null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log.warn("不支持的操作符: {}", operator);
|
||||
}
|
||||
|
||||
return expGroup;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.nutz.lang.Times;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2016/6/24.
|
||||
*/
|
||||
public class DateUtil {
|
||||
private static final Locale DEFAULT_LOCALE = Locale.CHINA;
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
/**
|
||||
* 获取当前时间(HH:mm:ss)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getDate() {
|
||||
return DateFormatUtils.format(new Date(), "yyyy-MM-dd", DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间(HH:mm:ss)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getTime() {
|
||||
return DateFormatUtils.format(new Date(), "HH:mm:ss", DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间(yyyy-MM-dd HH:mm:ss)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getDateTime() {
|
||||
return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss", DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换日期格式(yyyy-MM-dd HH:mm:ss)
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static String formatDateTime(Date date) {
|
||||
if (date == null) return "";
|
||||
return DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss", DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换日期格式(yyyy-MM-dd HH:mm:ss)
|
||||
*
|
||||
* @param date
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
public static String format(Date date, String f) {
|
||||
if (date == null) return "";
|
||||
return DateFormatUtils.format(date, f, DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳日期
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String getDate(long time) {
|
||||
return DateFormatUtils.format(new Date(time * 1000), "yyyy-MM-dd HH:mm:ss", DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳日期
|
||||
*
|
||||
* @param time
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
public static String getDate(long time, String f) {
|
||||
return DateFormatUtils.format(new Date(time * 1000), f, DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过字符串时间获取时间戳 nutzwk5.0改为long
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static long getTime(String date) {
|
||||
try {
|
||||
return Times.parse(sdf, date).getTime() / 1000;
|
||||
} catch (ParseException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过字符串时间获取时间戳 nutzwk5.0改为long
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static long getTime(SimpleDateFormat sdf, String date) {
|
||||
try {
|
||||
return Times.parse(sdf, date).getTime() / 1000;
|
||||
} catch (ParseException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算两个时间差
|
||||
*/
|
||||
public static String getDatePoor(Date endDate, Date nowDate) {
|
||||
long nd = 1000 * 24 * 60 * 60;
|
||||
long nh = 1000 * 60 * 60;
|
||||
long nm = 1000 * 60;
|
||||
// long ns = 1000;
|
||||
// 获得两个时间的毫秒时间差异
|
||||
long diff = endDate.getTime() - nowDate.getTime();
|
||||
// 计算差多少天
|
||||
long day = diff / nd;
|
||||
// 计算差多少小时
|
||||
long hour = diff % nd / nh;
|
||||
// 计算差多少分钟
|
||||
long min = diff % nd % nh / nm;
|
||||
// 计算差多少秒//输出结果
|
||||
// long sec = diff % nd % nh % nm / ns;
|
||||
return day + "天" + hour + "小时" + min + "分钟";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DynamicFormFieldParserUtil {
|
||||
|
||||
@Data
|
||||
public static class FieldInfo {
|
||||
private String key; // key
|
||||
private String title; // 标题
|
||||
private String type; // 字段类型 (text,number,date,select,checkbox,radio,textarea,file,tableForm)
|
||||
private Object value; // 字段值 原始值,处理select,checkbox,radio,tableForm 等负责情况
|
||||
private String info; // 字段说明
|
||||
private Boolean required; // 是否必填
|
||||
private String displayValue; // 用于显示的值(label) 基本类型使用该字段
|
||||
|
||||
private JSONObject props; //属性
|
||||
|
||||
private String parentId = ""; // 父级字段id
|
||||
|
||||
private Map<String, Object> tableData; // 存储tableForm类型的columns和rows
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表单规则和数据
|
||||
*
|
||||
* @param config 表单规则JSON对象
|
||||
* @param formDataJson 表单数据JSON字符串
|
||||
* @return 字段信息Map
|
||||
*/
|
||||
public static Map<String, FieldInfo> parseFormFields(JSONObject config, String formDataJson) {
|
||||
Map<String, FieldInfo> fieldInfoMap = new HashMap<>();
|
||||
|
||||
// 解析表单数据
|
||||
// 用户数据
|
||||
JSONObject formData = JSONUtil.parseObj(formDataJson);
|
||||
|
||||
//表单配置
|
||||
JSONArray rules = JSONUtil.parseArray(config.getStr("rule"));
|
||||
|
||||
Map<String, Map<String, String>> optionsMap = new HashMap<>();
|
||||
Map<String, List<TreeNode>> treeDataMap = new HashMap<>();
|
||||
|
||||
extractFieldInfoAndOptions(rules, fieldInfoMap, optionsMap, treeDataMap, null);
|
||||
|
||||
// 解析表单值
|
||||
for (Map.Entry<String, Object> entry : formData.entrySet()) {
|
||||
String field = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (fieldInfoMap.containsKey(field)) {
|
||||
FieldInfo fieldInfo = fieldInfoMap.get(field);
|
||||
fieldInfo.setKey(field);
|
||||
fieldInfo.setValue(value);
|
||||
// 处理值及显示值
|
||||
processFieldValue(fieldInfo, value, optionsMap, treeDataMap, fieldInfoMap);
|
||||
}
|
||||
}
|
||||
return fieldInfoMap;
|
||||
}
|
||||
|
||||
private static void processFieldValue(FieldInfo fieldInfo, Object value,
|
||||
Map<String, Map<String, String>> optionsMap,
|
||||
Map<String, List<TreeNode>> treeDataMap,
|
||||
Map<String, FieldInfo> fieldInfoMap) { // 添加 fieldInfoMap 参数
|
||||
// 处理 tableForm 类型
|
||||
if (fieldInfo.getType().equals("tableForm") && value instanceof List) {
|
||||
List<Map<String, Object>> rows = (List<Map<String, Object>>) value;
|
||||
|
||||
// 初始化 tableData
|
||||
Map<String, Object> tableData = new HashMap<>();
|
||||
List<FieldInfo> columns = new ArrayList<>();
|
||||
|
||||
// 获取并存储列信息
|
||||
if (fieldInfoMap.containsKey(fieldInfo.getKey())) {
|
||||
// 假设 columns 是一个包含 FieldInfo 的结构
|
||||
for (Map.Entry<String, FieldInfo> entry : fieldInfoMap.entrySet()) {
|
||||
if (!entry.getKey().equals(fieldInfo.getKey()) && StrUtil.isNotBlank(entry.getValue().getParentId()) && entry.getValue().getParentId().equals(fieldInfo.getKey())) {
|
||||
FieldInfo columnFieldInfo = entry.getValue();
|
||||
columnFieldInfo.setKey(entry.getKey());
|
||||
|
||||
//找老爹要table的label属性
|
||||
FieldInfo parentFieldInfo = fieldInfoMap.get(columnFieldInfo.getParentId());
|
||||
if(null != parentFieldInfo){
|
||||
columnFieldInfo.setTitle(parentFieldInfo.getTitle());
|
||||
}
|
||||
|
||||
columns.add(columnFieldInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tableData.put("columns", columns); // 存储列信息
|
||||
tableData.put("rows", rows); // 存储行数据
|
||||
fieldInfo.setTableData(tableData); // 设置 tableData
|
||||
|
||||
StringBuilder displayValueBuilder = new StringBuilder();
|
||||
|
||||
for (Map<String, Object> row : rows) {
|
||||
StringBuilder rowDisplay = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : row.entrySet()) {
|
||||
String columnField = entry.getKey();
|
||||
Object columnValue = entry.getValue();
|
||||
|
||||
// 获取字段信息
|
||||
FieldInfo columnFieldInfo = fieldInfoMap.get(columnField);
|
||||
if (columnFieldInfo != null) {
|
||||
// 设置原始值
|
||||
columnFieldInfo.setValue(columnValue);
|
||||
|
||||
// 处理显示值
|
||||
processColumnValue(columnFieldInfo, columnValue, optionsMap, treeDataMap);
|
||||
|
||||
// 追加到行显示值
|
||||
rowDisplay.append(columnFieldInfo.getTitle())
|
||||
.append(": ")
|
||||
.append(columnFieldInfo.getDisplayValue())
|
||||
.append(", ");
|
||||
}
|
||||
}
|
||||
// 去除末尾的逗号和空格
|
||||
if (rowDisplay.length() > 0) {
|
||||
rowDisplay.setLength(rowDisplay.length() - 2);
|
||||
}
|
||||
displayValueBuilder.append("行: [").append(rowDisplay.toString()).append("]").append("\n");
|
||||
}
|
||||
|
||||
fieldInfo.setDisplayValue(displayValueBuilder.toString());
|
||||
}
|
||||
// 处理复选框和选择器
|
||||
else if (value instanceof List && optionsMap.containsKey(fieldInfo.getKey())) {
|
||||
List<String> values = (List<String>) value;
|
||||
Map<String, String> options = optionsMap.get(fieldInfo.getKey());
|
||||
|
||||
List<String> labels = values.stream()
|
||||
.map(v -> options.getOrDefault(v, v))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
fieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
}
|
||||
// 处理单选框
|
||||
else if (value instanceof String && optionsMap.containsKey(fieldInfo.getTitle())) {
|
||||
Map<String, String> options = optionsMap.get(fieldInfo.getTitle());
|
||||
String valueStr = (String) value;
|
||||
fieldInfo.setDisplayValue(options.getOrDefault(valueStr, valueStr));
|
||||
}
|
||||
// 处理树形控件
|
||||
else if (value instanceof List && treeDataMap.containsKey(fieldInfo.getTitle())) {
|
||||
List<String> selectedIds = (List<String>) value;
|
||||
List<TreeNode> treeNodes = treeDataMap.get(fieldInfo.getTitle());
|
||||
|
||||
Map<String, String> idToLabelMap = new HashMap<>();
|
||||
buildIdToLabelMap(treeNodes, idToLabelMap);
|
||||
|
||||
List<String> labels = selectedIds.stream()
|
||||
.map(id -> idToLabelMap.getOrDefault(id, id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
fieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
}
|
||||
// 处理普通文本字段
|
||||
else {
|
||||
fieldInfo.setDisplayValue(value != null ? value.toString() : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 树节点结构
|
||||
*/
|
||||
@Data
|
||||
private static class TreeNode {
|
||||
private String id;
|
||||
private String label;
|
||||
private List<TreeNode> children;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归构建ID到Label的映射
|
||||
*/
|
||||
private static void buildIdToLabelMap(List<TreeNode> nodes, Map<String, String> idToLabelMap) {
|
||||
if (nodes == null) return;
|
||||
|
||||
for (TreeNode node : nodes) {
|
||||
if (node.getId() != null && node.getLabel() != null) {
|
||||
idToLabelMap.put(node.getId(), node.getLabel());
|
||||
}
|
||||
buildIdToLabelMap(node.getChildren(), idToLabelMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归解析树节点
|
||||
*/
|
||||
private static List<TreeNode> parseTreeData(JSONArray treeData) {
|
||||
List<TreeNode> result = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < treeData.size(); i++) {
|
||||
JSONObject item = treeData.getJSONObject(i);
|
||||
TreeNode node = new TreeNode();
|
||||
node.setId(item.getStr("id"));
|
||||
node.setLabel(item.getStr("label"));
|
||||
|
||||
if (item.containsKey("children") && item.get("children") instanceof JSONArray) {
|
||||
node.setChildren(parseTreeData(item.getJSONArray("children")));
|
||||
}
|
||||
|
||||
result.add(node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归提取字段信息和选项映射
|
||||
*/
|
||||
private static void extractFieldInfoAndOptions(JSONArray items, Map<String, FieldInfo> fieldInfoMap,
|
||||
Map<String, Map<String, String>> optionsMap,
|
||||
Map<String, List<TreeNode>> treeDataMap, String parentId) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
JSONObject item = items.getJSONObject(i);
|
||||
|
||||
// 如果有子元素,递归处理
|
||||
if (item.containsKey("children")) {
|
||||
extractFieldInfoAndOptions(item.getJSONArray("children"), fieldInfoMap, optionsMap, treeDataMap, item.getStr("field"));
|
||||
}
|
||||
|
||||
// 如果是表单,递归处理
|
||||
if(item.containsKey("props") && item.getJSONObject("props").containsKey("columns") && !item.getJSONObject("props").getJSONArray("columns").isEmpty()){
|
||||
extractFieldInfoAndOptions(item.getJSONObject("props").getJSONArray("columns"), fieldInfoMap, optionsMap, treeDataMap, item.getStr("field"));
|
||||
}
|
||||
|
||||
|
||||
// 提取字段信息
|
||||
if (item.containsKey("field") && item.containsKey("title")) {
|
||||
String field = item.getStr("field");
|
||||
String type = item.getStr("type");
|
||||
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
fieldInfo.setTitle(item.getStr("title"));
|
||||
fieldInfo.setType(type);
|
||||
fieldInfo.setInfo(item.getStr("info"));
|
||||
fieldInfo.setParentId(parentId);
|
||||
fieldInfo.setProps(item.getJSONObject("props"));
|
||||
|
||||
// 处理必填字段
|
||||
Object required = item.get("$required");
|
||||
if (required != null) {
|
||||
fieldInfo.setRequired(required instanceof Boolean ? (Boolean) required : true);
|
||||
}
|
||||
|
||||
fieldInfoMap.put(field, fieldInfo);
|
||||
|
||||
// 处理表格类型
|
||||
// if ("tableForm".equals(type) && item.containsKey("props")) {
|
||||
// JSONObject props = item.getJSONObject("props");
|
||||
// if (props.containsKey("columns") && props.get("columns") instanceof JSONArray) {
|
||||
// JSONArray columns = props.getJSONArray("columns");
|
||||
// for (int j = 0; j < columns.size(); j++) {
|
||||
// JSONObject column = columns.getJSONObject(j);
|
||||
// if (column.containsKey("rule") && column.get("rule") instanceof JSONArray) {
|
||||
// extractFieldInfoAndOptions(column.getJSONArray("rule"), fieldInfoMap, optionsMap, treeDataMap, field);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 处理带选项的字段(如checkbox、radio、select等)
|
||||
if (item.containsKey("options") && item.get("options") instanceof JSONArray) {
|
||||
JSONArray options = item.getJSONArray("options");
|
||||
Map<String, String> valueToLabelMap = new HashMap<>();
|
||||
|
||||
for (int j = 0; j < options.size(); j++) {
|
||||
JSONObject option = options.getJSONObject(j);
|
||||
if (option.containsKey("value") && option.containsKey("label")) {
|
||||
String value = option.getStr("value");
|
||||
String label = option.getStr("label");
|
||||
valueToLabelMap.put(value, label);
|
||||
}
|
||||
}
|
||||
|
||||
if (!valueToLabelMap.isEmpty()) {
|
||||
optionsMap.put(field, valueToLabelMap);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理树形控件
|
||||
if ("tree".equals(type) && item.containsKey("props")) {
|
||||
JSONObject props = item.getJSONObject("props");
|
||||
if (props.containsKey("data") && props.get("data") instanceof JSONArray) {
|
||||
List<TreeNode> treeNodes = parseTreeData(props.getJSONArray("data"));
|
||||
treeDataMap.put(field, treeNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从formConfig JSONObject中提取所有表单字段的详细信息
|
||||
*
|
||||
* @param formConfigJson formConfig JSONObject对象
|
||||
* @return 字段信息列表,每个字段包含其所有属性
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
public static List<Map<String, Object>> extractFormFields(JSONObject formConfigJson) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
// 从JSONObject获取rule字符串
|
||||
String ruleStr = formConfigJson.getStr("rule");
|
||||
|
||||
// 解析rule
|
||||
JsonNode ruleNode = mapper.readTree(ruleStr);
|
||||
|
||||
// 提取字段信息
|
||||
List<Map<String, Object>> fieldsList = new ArrayList<>();
|
||||
traverseAndCollectFields(ruleNode, fieldsList);
|
||||
|
||||
return fieldsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历表单规则结构,收集所有的字段信息
|
||||
*
|
||||
* @param node 当前节点
|
||||
* @param fieldsList 收集字段的列表
|
||||
*/
|
||||
private static void traverseAndCollectFields(JsonNode node, List<Map<String, Object>> fieldsList) {
|
||||
if (node.isArray()) {
|
||||
// 处理数组节点
|
||||
for (JsonNode item : node) {
|
||||
traverseAndCollectFields(item, fieldsList);
|
||||
}
|
||||
} else if (node.isObject()) {
|
||||
// 检查是否是表单字段(具有field和title属性的节点)
|
||||
if (node.has("field") && node.has("title")) {
|
||||
Map<String, Object> fieldInfo = new HashMap<>();
|
||||
|
||||
// 遍历当前节点的所有属性并保存
|
||||
node.fields().forEachRemaining(entry -> {
|
||||
String key = entry.getKey();
|
||||
JsonNode value = entry.getValue();
|
||||
|
||||
if (value.isTextual()) {
|
||||
fieldInfo.put(key, value.asText());
|
||||
} else if (value.isBoolean()) {
|
||||
fieldInfo.put(key, value.asBoolean());
|
||||
} else if (value.isInt()) {
|
||||
fieldInfo.put(key, value.asInt());
|
||||
} else if (value.isObject() || value.isArray()) {
|
||||
// 对于复杂对象,转换为字符串
|
||||
fieldInfo.put(key, value.toString());
|
||||
}
|
||||
});
|
||||
|
||||
fieldsList.add(fieldInfo);
|
||||
}
|
||||
|
||||
// 递归处理子节点
|
||||
if (node.has("children")) {
|
||||
traverseAndCollectFields(node.get("children"), fieldsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void processColumnValue(FieldInfo columnFieldInfo, Object columnValue,
|
||||
Map<String, Map<String, String>> optionsMap,
|
||||
Map<String, List<TreeNode>> treeDataMap) {
|
||||
// 处理复选框和选择器
|
||||
if (columnValue instanceof List && optionsMap.containsKey(columnFieldInfo.getTitle())) {
|
||||
List<String> values = (List<String>) columnValue;
|
||||
Map<String, String> options = optionsMap.get(columnFieldInfo.getTitle());
|
||||
|
||||
List<String> labels = values.stream()
|
||||
.map(v -> options.getOrDefault(v, v))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
columnFieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
}
|
||||
// 处理单选框
|
||||
else if (columnValue instanceof String && optionsMap.containsKey(columnFieldInfo.getKey())) {
|
||||
Map<String, String> options = optionsMap.get(columnFieldInfo.getTitle());
|
||||
String valueStr = (String) columnValue;
|
||||
columnFieldInfo.setDisplayValue(options.getOrDefault(valueStr, valueStr));
|
||||
}
|
||||
// 处理树形控件
|
||||
else if (columnValue instanceof List && treeDataMap.containsKey(columnFieldInfo.getTitle())) {
|
||||
List<String> selectedIds = (List<String>) columnValue;
|
||||
List<TreeNode> treeNodes = treeDataMap.get(columnFieldInfo.getTitle());
|
||||
|
||||
Map<String, String> idToLabelMap = new HashMap<>();
|
||||
buildIdToLabelMap(treeNodes, idToLabelMap);
|
||||
|
||||
List<String> labels = selectedIds.stream()
|
||||
.map(id -> idToLabelMap.getOrDefault(id, id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
columnFieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
}
|
||||
// 处理普通文本字段
|
||||
else {
|
||||
columnFieldInfo.setDisplayValue(columnValue != null ? columnValue.toString() : "");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用示例
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// 表单数据
|
||||
String formDataJson = """
|
||||
{"F7m3m8744w1nb7c": [{"F93zm8744xc3bcc": "1", "Fifam87455auboc": "2", "Fp5mm8745476blc": "1"}, {"F93zm8744xc3bcc": "2", "Fifam87455auboc": "3", "Fp5mm8745476blc": "2"}], "Fc4lm87457knbuc": "2", "Fkdtm87456owbrc": "1"}
|
||||
""";
|
||||
|
||||
// 规则数据 (这里应该是完整的规则JSON字符串)
|
||||
String ruleJson = """
|
||||
{"rule": "[{\\"type\\":\\"tableForm\\",\\"field\\":\\"F7m3m8744w1nb7c\\",\\"title\\":\\"表格表单\\",\\"info\\":\\"\\",\\"props\\":{\\"columns\\":[{\\"label\\":\\"自定义名称\\",\\"required\\":false,\\"style\\":{\\"width\\":\\"auto\\"},\\"rule\\":[{\\"type\\":\\"input\\",\\"field\\":\\"F93zm8744xc3bcc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":false,\\"_fc_id\\":\\"id_Fklbm8744xc3bdc\\",\\"name\\":\\"ref_F2g2m8744xc3bec\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"}]},{\\"label\\":\\"自定义名称\\",\\"required\\":false,\\"style\\":{\\"width\\":\\"auto\\"},\\"rule\\":[{\\"type\\":\\"input\\",\\"field\\":\\"Fp5mm8745476blc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":false,\\"_fc_id\\":\\"id_Fkb2m8745476bmc\\",\\"name\\":\\"ref_F0ntm8745476bnc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"}]},{\\"label\\":\\"自定义名称\\",\\"required\\":false,\\"style\\":{\\"width\\":\\"auto\\"},\\"rule\\":[{\\"type\\":\\"radio\\",\\"field\\":\\"Fifam87455auboc\\",\\"title\\":\\"单选框\\",\\"info\\":\\"\\",\\"effect\\":{\\"fetch\\":\\"\\"},\\"$required\\":false,\\"options\\":[{\\"label\\":\\"选项01\\",\\"value\\":\\"1\\"},{\\"label\\":\\"选项02\\",\\"value\\":\\"2\\"},{\\"label\\":\\"选项03\\",\\"value\\":\\"3\\"}],\\"_fc_id\\":\\"id_Fl2im87455aubpc\\",\\"name\\":\\"ref_Fz4em87455aubqc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"radio\\"}]}]},\\"_fc_id\\":\\"id_F7eym8744w1nb8c\\",\\"name\\":\\"ref_Fj8jm8744w1nb9c\\",\\"$required\\":false,\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"tableForm\\"},{\\"type\\":\\"input\\",\\"field\\":\\"Fkdtm87456owbrc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":true,\\"_fc_id\\":\\"id_F1hjm87456owbsc\\",\\"name\\":\\"ref_Fsj4m87456owbtc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"},{\\"type\\":\\"input\\",\\"field\\":\\"Fc4lm87457knbuc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":true,\\"_fc_id\\":\\"id_F592m87457knbvc\\",\\"name\\":\\"ref_Fxu3m87457knbwc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"}]", "options": "{\\"form\\":{\\"inline\\":false,\\"hideRequiredAsterisk\\":false,\\"labelPosition\\":\\"right\\",\\"size\\":\\"default\\",\\"labelWidth\\":\\"125px\\"},\\"language\\":{},\\"resetBtn\\":{\\"show\\":false,\\"innerText\\":\\"重置\\"},\\"submitBtn\\":{\\"show\\":false,\\"innerText\\":\\"提交\\"}}"}
|
||||
""";
|
||||
|
||||
JSONObject config = JSONUtil.parseObj(ruleJson);
|
||||
|
||||
// 解析字段信息
|
||||
Map<String, FieldInfo> fieldInfoMap = parseFormFields(config, formDataJson);
|
||||
|
||||
// 打印结果
|
||||
for (Map.Entry<String, FieldInfo> entry : fieldInfoMap.entrySet()) {
|
||||
System.out.println("字段: " + entry.getKey());
|
||||
System.out.println("标题: " + entry.getValue().getTitle());
|
||||
System.out.println("类型: " + entry.getValue().getType());
|
||||
System.out.println("原始值: " + entry.getValue().getValue());
|
||||
System.out.println("显示值: " + entry.getValue().getDisplayValue());
|
||||
System.out.println("表格数据: " + entry.getValue().getTableData());
|
||||
System.out.println("---");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DynamicFormFieldParserUtil2 {
|
||||
|
||||
@Data
|
||||
public static class FieldInfo {
|
||||
private String title; // 标题
|
||||
private String type; // 字段类型
|
||||
private Object value; // 字段值
|
||||
private String info; // 字段说明
|
||||
private Boolean required; // 是否必填
|
||||
private String displayValue; // 用于显示的值(label)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表单规则和数据
|
||||
* @param config 表单规则JSON对象
|
||||
* @param formDataJson 表单数据JSON字符串
|
||||
* @return 字段信息Map
|
||||
*/
|
||||
public static Map<String, FieldInfo> parseFormFields(JSONObject config, String formDataJson) {
|
||||
Map<String, FieldInfo> fieldInfoMap = new HashMap<>();
|
||||
|
||||
// 解析表单数据
|
||||
JSONObject formData = JSONUtil.parseObj(formDataJson);
|
||||
|
||||
// 解析规则
|
||||
JSONArray rules = JSONUtil.parseArray(config.getStr("rule"));
|
||||
|
||||
// 保存字段选项映射(value -> label)
|
||||
Map<String, Map<String, String>> optionsMap = new HashMap<>();
|
||||
|
||||
// 保存树形数据
|
||||
Map<String, List<TreeNode>> treeDataMap = new HashMap<>();
|
||||
|
||||
// 先提取字段信息和选项映射
|
||||
extractFieldInfoAndOptions(rules, fieldInfoMap, optionsMap, treeDataMap);
|
||||
|
||||
// 添加表单值并处理显示值
|
||||
for (Map.Entry<String, Object> entry : formData.entrySet()) {
|
||||
String field = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (fieldInfoMap.containsKey(field)) {
|
||||
FieldInfo fieldInfo = fieldInfoMap.get(field);
|
||||
fieldInfo.setValue(value);
|
||||
|
||||
// 处理checkbox、select等选项类控件
|
||||
if (value instanceof List && optionsMap.containsKey(field)) {
|
||||
List<String> values = (List<String>) value;
|
||||
Map<String, String> options = optionsMap.get(field);
|
||||
|
||||
List<String> labels = values.stream()
|
||||
.map(v -> options.getOrDefault(v, v))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
fieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
}
|
||||
// 处理单选
|
||||
else if (value instanceof String && optionsMap.containsKey(field)) {
|
||||
Map<String, String> options = optionsMap.get(field);
|
||||
String valueStr = (String) value;
|
||||
fieldInfo.setDisplayValue(options.getOrDefault(valueStr, valueStr));
|
||||
}
|
||||
// 处理树形控件
|
||||
else if (value instanceof List && treeDataMap.containsKey(field)) {
|
||||
List<String> selectedIds = (List<String>) value;
|
||||
List<TreeNode> treeNodes = treeDataMap.get(field);
|
||||
|
||||
// 构建ID到Label的映射
|
||||
Map<String, String> idToLabelMap = new HashMap<>();
|
||||
buildIdToLabelMap(treeNodes, idToLabelMap);
|
||||
|
||||
// 将ID转换为对应的Label
|
||||
List<String> labels = selectedIds.stream()
|
||||
.map(id -> idToLabelMap.getOrDefault(id, id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
fieldInfo.setDisplayValue(String.join(", ", labels));
|
||||
} else {
|
||||
// 对于普通文本字段,显示值与值相同
|
||||
fieldInfo.setDisplayValue(value != null ? value.toString() : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldInfoMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 树节点结构
|
||||
*/
|
||||
@Data
|
||||
private static class TreeNode {
|
||||
private String id;
|
||||
private String label;
|
||||
private List<TreeNode> children;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归构建ID到Label的映射
|
||||
*/
|
||||
private static void buildIdToLabelMap(List<TreeNode> nodes, Map<String, String> idToLabelMap) {
|
||||
if (nodes == null) return;
|
||||
|
||||
for (TreeNode node : nodes) {
|
||||
if (node.getId() != null && node.getLabel() != null) {
|
||||
idToLabelMap.put(node.getId(), node.getLabel());
|
||||
}
|
||||
buildIdToLabelMap(node.getChildren(), idToLabelMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归解析树节点
|
||||
*/
|
||||
private static List<TreeNode> parseTreeData(JSONArray treeData) {
|
||||
List<TreeNode> result = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < treeData.size(); i++) {
|
||||
JSONObject item = treeData.getJSONObject(i);
|
||||
TreeNode node = new TreeNode();
|
||||
node.setId(item.getStr("id"));
|
||||
node.setLabel(item.getStr("label"));
|
||||
|
||||
if (item.containsKey("children") && item.get("children") instanceof JSONArray) {
|
||||
node.setChildren(parseTreeData(item.getJSONArray("children")));
|
||||
}
|
||||
|
||||
result.add(node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归提取字段信息和选项映射
|
||||
*/
|
||||
private static void extractFieldInfoAndOptions(JSONArray items, Map<String, FieldInfo> fieldInfoMap,
|
||||
Map<String, Map<String, String>> optionsMap,
|
||||
Map<String, List<TreeNode>> treeDataMap) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
JSONObject item = items.getJSONObject(i);
|
||||
|
||||
// 如果有子元素,递归处理
|
||||
if (item.containsKey("children")) {
|
||||
extractFieldInfoAndOptions(item.getJSONArray("children"), fieldInfoMap, optionsMap, treeDataMap);
|
||||
}
|
||||
|
||||
// 提取字段信息
|
||||
if (item.containsKey("field") && item.containsKey("title")) {
|
||||
String field = item.getStr("field");
|
||||
String type = item.getStr("type");
|
||||
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
fieldInfo.setTitle(item.getStr("title"));
|
||||
fieldInfo.setType(type);
|
||||
fieldInfo.setInfo(item.getStr("info"));
|
||||
|
||||
// 处理必填字段
|
||||
Object required = item.get("$required");
|
||||
if (required != null) {
|
||||
if (required instanceof Boolean) {
|
||||
fieldInfo.setRequired((Boolean) required);
|
||||
} else {
|
||||
fieldInfo.setRequired(true); // 如果$required存在但不是布尔值,视为必填
|
||||
}
|
||||
}
|
||||
|
||||
fieldInfoMap.put(field, fieldInfo);
|
||||
|
||||
// 处理带选项的字段(如checkbox、radio、select等)
|
||||
if (item.containsKey("options") && item.get("options") instanceof JSONArray) {
|
||||
JSONArray options = item.getJSONArray("options");
|
||||
Map<String, String> valueToLabelMap = new HashMap<>();
|
||||
|
||||
for (int j = 0; j < options.size(); j++) {
|
||||
JSONObject option = options.getJSONObject(j);
|
||||
if (option.containsKey("value") && option.containsKey("label")) {
|
||||
String value = option.getStr("value");
|
||||
String label = option.getStr("label");
|
||||
valueToLabelMap.put(value, label);
|
||||
}
|
||||
}
|
||||
|
||||
if (!valueToLabelMap.isEmpty()) {
|
||||
optionsMap.put(field, valueToLabelMap);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理树形控件
|
||||
if ("tree".equals(type) && item.containsKey("props")) {
|
||||
JSONObject props = item.getJSONObject("props");
|
||||
if (props.containsKey("data") && props.get("data") instanceof JSONArray) {
|
||||
List<TreeNode> treeNodes = parseTreeData(props.getJSONArray("data"));
|
||||
treeDataMap.put(field, treeNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从formConfig JSONObject中提取所有表单字段的详细信息
|
||||
*
|
||||
* @param formConfigJson formConfig JSONObject对象
|
||||
* @return 字段信息列表,每个字段包含其所有属性
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
public static List<Map<String, Object>> extractFormFields(JSONObject formConfigJson) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
// 从JSONObject获取rule字符串
|
||||
String ruleStr = formConfigJson.getStr("rule");
|
||||
|
||||
// 解析rule
|
||||
JsonNode ruleNode = mapper.readTree(ruleStr);
|
||||
|
||||
// 提取字段信息
|
||||
List<Map<String, Object>> fieldsList = new ArrayList<>();
|
||||
traverseAndCollectFields(ruleNode, fieldsList);
|
||||
|
||||
return fieldsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历表单规则结构,收集所有的字段信息
|
||||
*
|
||||
* @param node 当前节点
|
||||
* @param fieldsList 收集字段的列表
|
||||
*/
|
||||
private static void traverseAndCollectFields(JsonNode node, List<Map<String, Object>> fieldsList) {
|
||||
if (node.isArray()) {
|
||||
// 处理数组节点
|
||||
for (JsonNode item : node) {
|
||||
traverseAndCollectFields(item, fieldsList);
|
||||
}
|
||||
} else if (node.isObject()) {
|
||||
// 检查是否是表单字段(具有field和title属性的节点)
|
||||
if (node.has("field") && node.has("title")) {
|
||||
Map<String, Object> fieldInfo = new HashMap<>();
|
||||
|
||||
// 遍历当前节点的所有属性并保存
|
||||
node.fields().forEachRemaining(entry -> {
|
||||
String key = entry.getKey();
|
||||
JsonNode value = entry.getValue();
|
||||
|
||||
if (value.isTextual()) {
|
||||
fieldInfo.put(key, value.asText());
|
||||
} else if (value.isBoolean()) {
|
||||
fieldInfo.put(key, value.asBoolean());
|
||||
} else if (value.isInt()) {
|
||||
fieldInfo.put(key, value.asInt());
|
||||
} else if (value.isObject() || value.isArray()) {
|
||||
// 对于复杂对象,转换为字符串
|
||||
fieldInfo.put(key, value.toString());
|
||||
}
|
||||
});
|
||||
|
||||
fieldsList.add(fieldInfo);
|
||||
}
|
||||
|
||||
// 递归处理子节点
|
||||
if (node.has("children")) {
|
||||
traverseAndCollectFields(node.get("children"), fieldsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用示例
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// 表单数据
|
||||
String formDataJson = """
|
||||
{
|
||||
"F0qpm83seg72c8c": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"],
|
||||
"F9epm83rypzsazc": ["1", "2"],
|
||||
"Fctxm83ryd5catc": "1",
|
||||
"Fdqgm83scr4ebgc": "11",
|
||||
"Frhum83scsvabjc": "1"
|
||||
}
|
||||
""";
|
||||
|
||||
// 规则数据 (这里应该是完整的规则JSON字符串)
|
||||
String ruleJson = """
|
||||
{
|
||||
"rule": "[{\\"type\\":\\"input\\",\\"field\\":\\"Fctxm83ryd5catc\\",\\"title\\":\\"孩子身份证\\",\\"info\\":\\"\\",\\"$required\\":false,\\"_fc_id\\":\\"id_F6d7m83ryd5cauc\\",\\"name\\":\\"ref_Filom83ryd5davc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"},{\\"type\\":\\"checkbox\\",\\"field\\":\\"F9epm83rypzsazc\\",\\"title\\":\\"衣服尺码\\",\\"info\\":\\"\\",\\"effect\\":{\\"fetch\\":\\"\\"},\\"$required\\":true,\\"options\\":[{\\"label\\":\\"M\\",\\"value\\":\\"1\\"},{\\"label\\":\\"L\\",\\"value\\":\\"2\\"},{\\"label\\":\\"XL\\",\\"value\\":\\"3\\"}],\\"_fc_id\\":\\"id_F6zwm83rypzsb0c\\",\\"name\\":\\"ref_F0x3m83rypzsb1c\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"checkbox\\"},{\\"type\\":\\"fcRow\\",\\"children\\":[{\\"type\\":\\"col\\",\\"props\\":{\\"span\\":12},\\"children\\":[{\\"type\\":\\"input\\",\\"field\\":\\"Fdqgm83scr4ebgc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":false,\\"_fc_id\\":\\"id_F97bm83scr4ebhc\\",\\"name\\":\\"ref_Fbljm83scr4ebic\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"}],\\"_fc_id\\":\\"id_Fip5m83sclr8bcc\\",\\"name\\":\\"ref_Fhxvm83sclr8bdc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"col\\"},{\\"type\\":\\"col\\",\\"props\\":{\\"span\\":12},\\"children\\":[{\\"type\\":\\"input\\",\\"field\\":\\"Frhum83scsvabjc\\",\\"title\\":\\"输入框\\",\\"info\\":\\"\\",\\"$required\\":false,\\"_fc_id\\":\\"id_Fdaqm83scsvabkc\\",\\"name\\":\\"ref_Fagdm83scsvablc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"input\\"}],\\"_fc_id\\":\\"id_Flw4m83sclr8bec\\",\\"name\\":\\"ref_F894m83sclr8bfc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"col\\"}],\\"_fc_id\\":\\"id_Fpqmm83sclr7bac\\",\\"name\\":\\"ref_Fo5ym83sclr7bbc\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"fcRow\\"},{\\"type\\":\\"tree\\",\\"field\\":\\"F0qpm83seg72c8c\\",\\"title\\":\\"树形控件\\",\\"info\\":\\"\\",\\"effect\\":{\\"fetch\\":\\"\\"},\\"$required\\":false,\\"props\\":{\\"props\\":{\\"label\\":\\"label\\"},\\"showCheckbox\\":true,\\"nodeKey\\":\\"id\\",\\"data\\":[{\\"label\\":\\"选项201\\",\\"id\\":\\"1\\",\\"children\\":[{\\"label\\":\\"选项101\\",\\"id\\":\\"2\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"3\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"4\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"5\\"}]},{\\"label\\":\\"选项102\\",\\"id\\":\\"6\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"7\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"8\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"9\\"}]},{\\"label\\":\\"选项103\\",\\"id\\":\\"10\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"11\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"12\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"13\\"}]}]},{\\"label\\":\\"选项202\\",\\"id\\":\\"14\\",\\"children\\":[{\\"label\\":\\"选项101\\",\\"id\\":\\"15\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"16\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"17\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"18\\"}]},{\\"label\\":\\"选项102\\",\\"id\\":\\"19\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"20\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"21\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"22\\"}]},{\\"label\\":\\"选项103\\",\\"id\\":\\"23\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"24\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"25\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"26\\"}]}]},{\\"label\\":\\"选项203\\",\\"id\\":\\"27\\",\\"children\\":[{\\"label\\":\\"选项101\\",\\"id\\":\\"28\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"29\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"30\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"31\\"}]},{\\"label\\":\\"选项102\\",\\"id\\":\\"32\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"33\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"34\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"35\\"}]},{\\"label\\":\\"选项103\\",\\"id\\":\\"36\\",\\"children\\":[{\\"label\\":\\"选项01\\",\\"id\\":\\"37\\"},{\\"label\\":\\"选项02\\",\\"id\\":\\"38\\"},{\\"label\\":\\"选项03\\",\\"id\\":\\"39\\"}]}]}]},\\"_fc_id\\":\\"id_Fbq9m83seg72c9c\\",\\"name\\":\\"ref_Fkgqm83seg72cac\\",\\"display\\":true,\\"hidden\\":false,\\"_fc_drag_tag\\":\\"tree\\"}]",
|
||||
"options": "{\\"form\\":{\\"inline\\":false,\\"hideRequiredAsterisk\\":false,\\"labelPosition\\":\\"right\\",\\"size\\":\\"default\\",\\"labelWidth\\":\\"125px\\"},\\"language\\":{},\\"resetBtn\\":{\\"show\\":false,\\"innerText\\":\\"重置\\"},\\"submitBtn\\":{\\"show\\":false,\\"innerText\\":\\"提交\\"}}"
|
||||
}
|
||||
""";
|
||||
|
||||
JSONObject config = JSONUtil.parseObj(ruleJson);
|
||||
|
||||
// 解析字段信息
|
||||
Map<String, FieldInfo> fieldInfoMap = parseFormFields(config, formDataJson);
|
||||
|
||||
// 打印结果
|
||||
for (Map.Entry<String, FieldInfo> entry : fieldInfoMap.entrySet()) {
|
||||
System.out.println("字段: " + entry.getKey());
|
||||
System.out.println("标题: " + entry.getValue().getTitle());
|
||||
System.out.println("类型: " + entry.getValue().getType());
|
||||
System.out.println("原始值: " + entry.getValue().getValue());
|
||||
System.out.println("显示值: " + entry.getValue().getDisplayValue());
|
||||
System.out.println("---");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import com.alibaba.excel.EasyExcelFactory;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author zzr
|
||||
* @name:EasyExcelUtil
|
||||
* @Date 2024/10/14 13:51
|
||||
* @注释
|
||||
*/
|
||||
public class EasyExcelUtil {
|
||||
|
||||
public EasyExcelUtil() {
|
||||
}
|
||||
|
||||
public static List<T> syncReadModel(String filePath, Class clazz) {
|
||||
return EasyExcelFactory.read(filePath).sheet().head(clazz).doReadSync();
|
||||
}
|
||||
|
||||
public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo) {
|
||||
return EasyExcelFactory.read(filePath).sheet(sheetNo).head(clazz).doReadSync();
|
||||
}
|
||||
|
||||
public static List<T> syncReadModel(InputStream inputStream, Class clazz, Integer sheetNo, Integer headRowNum) {
|
||||
return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
|
||||
}
|
||||
|
||||
public static List<T> syncReadModel(File file, Class clazz, Integer sheetNo, Integer headRowNum) {
|
||||
return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
|
||||
}
|
||||
|
||||
public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo, Integer headRowNum) {
|
||||
return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 枚举工具类
|
||||
*/
|
||||
public class EnumUtil {
|
||||
|
||||
/**
|
||||
* 将枚举转换为列表
|
||||
* @param enumClass
|
||||
* @return
|
||||
* @param <E>
|
||||
*/
|
||||
public static <E> List<Map<String, Object>> transToList(Class<E> enumClass) {
|
||||
Assert.isTrue(enumClass.isEnum(), String.format("%s not a enum", enumClass.getSimpleName()));
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
E[] enumConstants = enumClass.getEnumConstants();
|
||||
for (E enumConstant : enumConstants) {
|
||||
Map<String, Object> map = NutMap.NEW();
|
||||
// 获取枚举实例的所有字段
|
||||
// Field[] fields = enumClass.getDeclaredFields();
|
||||
Field[] fields = ReflectUtil.getFields(enumClass);
|
||||
for (Field field : fields) {
|
||||
try {
|
||||
field.setAccessible(true); // 使私有字段可访问
|
||||
map.put(field.getName(), field.get(enumConstant)); // 获取字段值并添加到map中
|
||||
} catch (Exception e) {
|
||||
// 如果无法访问字段,可以选择忽略或处理异常
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
result.add(map);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author wizzer@qq.com
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
/**
|
||||
* 分页获取文件列表
|
||||
*
|
||||
* @param basePath 目录
|
||||
* @param pageNumber 页码
|
||||
* @param pageSize 页大小
|
||||
* @param sort 按文件名排序
|
||||
* @return 列表
|
||||
* @throws Exception
|
||||
*/
|
||||
public static NutMap readListPage(String basePath, Integer pageNumber, Integer pageSize, String sort)
|
||||
throws Exception {
|
||||
int offset = (pageNumber - 1) * pageSize;
|
||||
int limit = pageNumber * pageSize;
|
||||
long total = 0;
|
||||
List<NutMap> list = new ArrayList<>();
|
||||
Comparator<Path> comparator = Comparator.naturalOrder();
|
||||
if ("desc".equals(sort)) {
|
||||
comparator = Comparator.reverseOrder();
|
||||
}
|
||||
try (Stream<Path> fileList = Files.list(Paths.get(basePath))) {
|
||||
total = fileList.count();
|
||||
}
|
||||
try (Stream<Path> fileList = Files.list(Paths.get(basePath)).sorted(comparator).skip(offset)
|
||||
.limit(limit)) {
|
||||
fileList.forEach(file -> {
|
||||
NutMap nutMap = NutMap.NEW();
|
||||
String fileName = file.getFileName().toString();
|
||||
nutMap.addv("fileName", fileName);
|
||||
if (Files.isDirectory(file.toAbsolutePath())) {
|
||||
nutMap.addv("folder", true);
|
||||
nutMap.addv("suffix", "folder");
|
||||
} else {
|
||||
String suffix = fileName.substring(fileName.indexOf(".") + 1).toLowerCase();
|
||||
nutMap.addv("folder", false);
|
||||
nutMap.addv("suffix", suffix);
|
||||
}
|
||||
list.add(nutMap);
|
||||
});
|
||||
return NutMap.NEW().addv("total", total).addv("list", list);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import com.budwk.app.base.config.ThreadPoolConfig;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author zzr
|
||||
* @name:ManyAddOrRenewUtil
|
||||
* @Date 2024/7/24 16:16
|
||||
* @注释 多线程批量新增或更新
|
||||
*/
|
||||
@IocBean
|
||||
public class ManyAddOrRenewUtil {
|
||||
|
||||
@Inject
|
||||
private ThreadPoolConfig threadPoolConfig;
|
||||
|
||||
|
||||
/**
|
||||
* 批量快速插入,异步执行
|
||||
*
|
||||
* @param list 泛型list,任意实体类集合
|
||||
* @param batchSize 期望单次操作的数量,默认200
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void asyncExecuteFastInsert(List<T> list, Integer batchSize) {
|
||||
threadPoolConfig.asyncExecute(list, batchSize, "insert", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量插入(非快速),异步执行
|
||||
*
|
||||
* @param list 泛型list,任意实体类集合
|
||||
* @param batchSize 期望单次操作的数量,默认200
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void asyncExecuteInsert(List<T> list, Integer batchSize) {
|
||||
threadPoolConfig.asyncExecute(list, batchSize, "insert", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量修改(忽略空值),异步执行
|
||||
*
|
||||
* @param list 泛型list,任意实体类集合
|
||||
* @param batchSize 期望单次操作的数量,默认200
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void asyncExecuteUpdateIgnoreNull(List<T> list, Integer batchSize) {
|
||||
threadPoolConfig.asyncExecute(list, batchSize, "update", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量修改(不忽略空值),异步执行
|
||||
*
|
||||
* @param list 泛型list,任意实体类集合
|
||||
* @param batchSize 期望单次操作的数量,默认200
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void asyncExecuteUpdate(List<T> list, Integer batchSize) {
|
||||
threadPoolConfig.asyncExecute(list, batchSize, "update", false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增或修改,异步执行
|
||||
*
|
||||
* @param list 泛型list,任意实体类集合
|
||||
* @param batchSize 期望单次操作的数量,默认200
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void asyncExecuteInsertOrUpdate(List<T> list, Integer batchSize) {
|
||||
threadPoolConfig.asyncExecute(list, batchSize, "insertOrUpdate", false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2017/7/21.
|
||||
*/
|
||||
public class MapUtil {
|
||||
/**
|
||||
* 使用 Map按key进行排序
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> sortMapByKey(Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> sortMap = new TreeMap<>(
|
||||
new MapKeyComparator());
|
||||
sortMap.putAll(map);
|
||||
return sortMap;
|
||||
}
|
||||
}
|
||||
|
||||
class MapKeyComparator implements Comparator<String> {
|
||||
@Override
|
||||
public int compare(String str1, String str2) {
|
||||
return str1.compareTo(str2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.aspose.cells.PdfSaveOptions;
|
||||
import com.aspose.cells.Workbook;
|
||||
import com.aspose.words.Document;
|
||||
import com.aspose.words.SaveFormat;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文档转换
|
||||
*/
|
||||
@Slf4j
|
||||
public class OfficePlusUtil {
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*
|
||||
* @param sourcePath 源文件路径
|
||||
* @param targetPath 目标文件路径
|
||||
*/
|
||||
public static void convert(String sourcePath, String targetPath) {
|
||||
String suffix = FileUtil.getSuffix(sourcePath);
|
||||
if (suffix.equals("doc") || suffix.equals("docx")) {
|
||||
wordConvertPdf(sourcePath, targetPath);
|
||||
} else if (suffix.equals("xls") || suffix.equals("xlsx")) {
|
||||
excelConvertPdf(sourcePath, targetPath);
|
||||
} else {
|
||||
throw new BaseException("不支持的文档格式");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* excel转pdf
|
||||
*
|
||||
* @param sourcePath 源文件路径
|
||||
* @param targetPath 目标文件路径
|
||||
*/
|
||||
public static void excelConvertPdf(String sourcePath, String targetPath) {
|
||||
FileOutputStream fileOS = null;
|
||||
try {
|
||||
Workbook wb = new Workbook(sourcePath);
|
||||
fileOS = new FileOutputStream(targetPath);
|
||||
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
|
||||
pdfSaveOptions.setOnePagePerSheet(true);
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
|
||||
// wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
|
||||
// }
|
||||
// for (int i = 1; i < wb.getWorksheets().getCount(); i++) {
|
||||
// wb.getWorksheets().get(i).setVisible(false);
|
||||
// }
|
||||
wb.getWorksheets().get(0).setVisible(true);
|
||||
wb.save(fileOS, pdfSaveOptions);
|
||||
fileOS.flush();
|
||||
} catch (Exception e) {
|
||||
log.info("转换pdf报错", e);
|
||||
} finally {
|
||||
if (fileOS != null) {
|
||||
try {
|
||||
fileOS.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* word转pdf
|
||||
*
|
||||
* @param sourcePath 源文件路径
|
||||
* @param targetPath 目标文件路径
|
||||
*/
|
||||
public static void wordConvertPdf(String sourcePath, String targetPath) {
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
File file = new File(targetPath);
|
||||
os = new FileOutputStream(file);
|
||||
Document doc = new Document(sourcePath);
|
||||
doc.save(os, SaveFormat.PDF);
|
||||
} catch (Exception e) {
|
||||
log.info("转换pdf报错", e);
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2018.09
|
||||
*/
|
||||
public class PageUtil {
|
||||
|
||||
static NutMap map = NutMap.NEW().addv("ascending", "asc").addv("descending", "desc");
|
||||
|
||||
public static String getOrder(String key) {
|
||||
return map.getString(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2017/5/24.
|
||||
*/
|
||||
@IocBean
|
||||
public class PinyinUtil {
|
||||
/**
|
||||
* 将汉字转换为全拼
|
||||
*/
|
||||
public static String getPingYin(String name) {
|
||||
char[] charArray = name.toCharArray();
|
||||
StringBuilder pinyin = new StringBuilder();
|
||||
for (int i = 0; i < charArray.length; i++) {
|
||||
if (Character.toString(charArray[i]).matches("[\\u4E00-\\u9FA5]+")) {
|
||||
pinyin.append(PinyinHelper.toHanyuPinyinStringArray(charArray[i])[0]);
|
||||
} else {
|
||||
pinyin.append(charArray[i]);
|
||||
}
|
||||
}
|
||||
return pinyin.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回中文的首字母
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String getPinYinHeadChar(String str) {
|
||||
|
||||
String convert = "";
|
||||
for (int j = 0; j < str.length(); j++) {
|
||||
char word = str.charAt(j);
|
||||
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
|
||||
if (pinyinArray != null) {
|
||||
convert += pinyinArray[0].charAt(0);
|
||||
} else {
|
||||
convert += word;
|
||||
}
|
||||
}
|
||||
return convert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转移为ASCII码
|
||||
*
|
||||
* @param cnStr
|
||||
* @return
|
||||
*/
|
||||
public static String getCnASCII(String cnStr) {
|
||||
StringBuffer strBuf = new StringBuffer();
|
||||
byte[] bGBK = cnStr.getBytes();
|
||||
for (int i = 0; i < bGBK.length; i++) {
|
||||
strBuf.append(Integer.toHexString(bGBK[i] & 0xff));
|
||||
}
|
||||
return strBuf.toString();
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// System.out.println(getPingYin("綦江qq县"));
|
||||
// System.out.println(getPinYinHeadChar("綦江县"));
|
||||
// System.out.println(getCnASCII("綦江县"));
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.lang.Lang;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 为老兼容老的密码加密方式
|
||||
*
|
||||
* @author wizzer@qq.com
|
||||
*/
|
||||
@Slf4j
|
||||
public class PwdUtil {
|
||||
|
||||
private static final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
|
||||
private static final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
private static final String DIGITS = "0123456789";
|
||||
private static final String SPECIAL = "!@#$%^&*()-_=+{};:,<.>";
|
||||
private static final String ALL = LOWERCASE + UPPERCASE + DIGITS + SPECIAL;
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
|
||||
public static String getPassword(String passowrd, String salt) {
|
||||
byte[] bytes = hash(passowrd.getBytes(), salt.getBytes(), 1024);
|
||||
if (bytes != null) {
|
||||
return Lang.fixedHexString(bytes);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static byte[] hash(byte[] bytes, byte[] salt, int hashIterations) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
if (salt != null) {
|
||||
digest.reset();
|
||||
digest.update(salt);
|
||||
}
|
||||
|
||||
byte[] hashed = digest.digest(bytes);
|
||||
int iterations = hashIterations - 1;
|
||||
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
digest.reset();
|
||||
hashed = digest.digest(hashed);
|
||||
}
|
||||
return hashed;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static String generate(int length) {
|
||||
if (length < 8 || length > 20) {
|
||||
throw new IllegalArgumentException("密码长度必须在8到20之间");
|
||||
}
|
||||
|
||||
List<Character> passwordChars = new ArrayList<>();
|
||||
|
||||
// 保证每类字符至少一个
|
||||
passwordChars.add(randomCharFrom(LOWERCASE));
|
||||
passwordChars.add(randomCharFrom(UPPERCASE));
|
||||
passwordChars.add(randomCharFrom(DIGITS));
|
||||
passwordChars.add(randomCharFrom(SPECIAL));
|
||||
|
||||
// 剩余位置随机填充
|
||||
for (int i = passwordChars.size(); i < length; i++) {
|
||||
passwordChars.add(randomCharFrom(ALL));
|
||||
}
|
||||
|
||||
// 打乱顺序以避免固定模式
|
||||
Collections.shuffle(passwordChars);
|
||||
|
||||
// 构建字符串
|
||||
StringBuilder password = new StringBuilder();
|
||||
for (char ch : passwordChars) {
|
||||
password.append(ch);
|
||||
}
|
||||
|
||||
return password.toString();
|
||||
}
|
||||
|
||||
private static char randomCharFrom(String chars) {
|
||||
return chars.charAt(random.nextInt(chars.length()));
|
||||
}
|
||||
|
||||
// 示例主方法
|
||||
public static void main(String[] args) {
|
||||
System.out.println("生成的密码: " + generate(12));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.nutz.lang.Lang;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2018/6/28.
|
||||
*/
|
||||
public class SignUtil {
|
||||
|
||||
public static String createSign(String appkey, Map<String, Object> params) {
|
||||
Map<String, Object> map = MapUtil.sortMapByKey(params);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Set<String> keySet = map.keySet();
|
||||
Iterator<String> it = keySet.iterator();
|
||||
while (it.hasNext()) {
|
||||
String k = it.next();
|
||||
String v = (String) map.get(k);
|
||||
if (null != v && !"".equals(v)
|
||||
&& !"sign".equals(k)) {
|
||||
sb.append(k + "=" + v + "&");
|
||||
}
|
||||
}
|
||||
sb.append("appkey=" + appkey);
|
||||
String sign = Lang.md5(sb.toString());
|
||||
return sign;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.json.JsonFormat;
|
||||
import org.nutz.lang.Strings;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by wizzer on 2018/3/17.
|
||||
*/
|
||||
public class StringUtil {
|
||||
/**
|
||||
* 去掉URL中?后的路径
|
||||
*
|
||||
* @param p
|
||||
* @return
|
||||
*/
|
||||
public static String getPath(String p) {
|
||||
if (Strings.sNull(p).contains("?")) {
|
||||
return p.substring(0, p.indexOf("?"));
|
||||
}
|
||||
return Strings.sNull(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得父节点ID
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String getParentId(String s) {
|
||||
if (!Strings.isEmpty(s) && s.length() > 4) {
|
||||
return s.substring(0, s.length() - 4);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到n位随机数
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String getRndNumber(int s) {
|
||||
Random ra = new Random();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < s; i++) {
|
||||
sb.append(String.valueOf(ra.nextInt(8)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否以字符串开头
|
||||
*
|
||||
* @param str
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public boolean startWith(String str, String s) {
|
||||
return Strings.sNull(str).startsWith(Strings.sNull(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含字符串
|
||||
*
|
||||
* @param str
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(String str, String s) {
|
||||
return Strings.sNull(str).contains(Strings.sNull(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转为JSON字符串(页面上使用)
|
||||
*
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
public String toJson(Object obj) {
|
||||
return Json.toJson(obj, JsonFormat.compact());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.sys.models.Sys_file;
|
||||
import com.budwk.app.sys.models.Sys_office_template;
|
||||
import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
||||
import com.deepoove.poi.data.ByteArrayPictureRenderData;
|
||||
import com.deepoove.poi.data.PictureRenderData;
|
||||
import com.deepoove.poi.data.PictureType;
|
||||
import com.deepoove.poi.data.style.PictureStyle;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 系统导出模板管理工具类
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean
|
||||
public class SysOfficeTemplateUtil {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
/**
|
||||
* 获取模板文件输入流
|
||||
*
|
||||
* @param templateCode 模板编码
|
||||
*/
|
||||
public InputStream getTemplate(String templateCode) {
|
||||
Sys_office_template officeTemplate = dao.fetch(Sys_office_template.class, Cnd.where(Sys_office_template::getTemplateCode, "=", templateCode));
|
||||
if (ObjectUtil.isNull(officeTemplate)) {
|
||||
throw new BaseException("代码为:{}的模板不存在", templateCode);
|
||||
}
|
||||
String templatePath = officeTemplate.getTemplatePath();
|
||||
int startIndex = templatePath.indexOf("id=") + "id=".length();
|
||||
String id = templatePath.substring(startIndex);
|
||||
Sys_file sysFile = dao.fetch(Sys_file.class, id);
|
||||
if (ObjectUtil.isEmpty(sysFile)) {
|
||||
throw new BaseException("模板文件不存在");
|
||||
}
|
||||
byte[] fileBytes = SysFileMinIoUtil.getFileBytes(sysFile.getBucket(), sysFile.getStoragePath());
|
||||
return new ByteArrayInputStream(fileBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签字url转换为poi的图片对象
|
||||
*
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param url url
|
||||
* @return
|
||||
*/
|
||||
public PictureRenderData createPictureRenderData(int width, int height, String url) {
|
||||
try {
|
||||
byte[] bytes = getFileBytesByUrl(url);
|
||||
// if (StrUtil.isBlank(url)) {
|
||||
// return null;
|
||||
// }
|
||||
// int startIndex = url.indexOf("id=") + "id=".length();
|
||||
// String id = url.substring(startIndex);
|
||||
// Sys_file sysFile = dao.fetch(Sys_file.class, id);
|
||||
// byte[] bytes = SysFileMinIoUtil.getFileBytes(sysFile.getBucket(), sysFile.getStoragePath());
|
||||
ByteArrayPictureRenderData pictureRenderData = new ByteArrayPictureRenderData(bytes, PictureType.PNG);
|
||||
PictureStyle pictureStyle = new PictureStyle();
|
||||
pictureStyle.setWidth(width);
|
||||
pictureStyle.setHeight(height);
|
||||
pictureRenderData.setPictureStyle(pictureStyle);
|
||||
return pictureRenderData;
|
||||
} catch (Exception e) {
|
||||
log.error("文件转换PictureRenderData错误,文件路径:{},{}", url, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PictureRenderData createPictureRenderData(String url) {
|
||||
return createPictureRenderData(70, 30, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将富文本转换为doc文本 富文本里的图片是链接 需要转换成base64格式
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String convertRichTextToDocText(String text) {
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return text;
|
||||
}
|
||||
try {
|
||||
Pattern pattern = Pattern.compile("(<img\\s+[^>]*src\\s*=\\s*[\"'])(/platform/sys/file/download\\?id=.*?)(\"[^>]*>)", Pattern.CASE_INSENSITIVE);
|
||||
Matcher briefMatcher = pattern.matcher(text);
|
||||
StringBuilder briefResult = new StringBuilder();
|
||||
while (briefMatcher.find()) {
|
||||
String originalSrc = briefMatcher.group(2);
|
||||
byte[] image = createPictureRenderData(originalSrc).readPictureData();
|
||||
String base64 = cn.hutool.core.codec.Base64.encodeStr(image, false, false);
|
||||
String base64Src = "data:image/png;base64," + base64;
|
||||
String newImgTag = briefMatcher.group(1) + base64Src + briefMatcher.group(3);
|
||||
briefMatcher.appendReplacement(briefResult, Matcher.quoteReplacement(newImgTag));
|
||||
}
|
||||
briefMatcher.appendTail(briefResult);
|
||||
return briefResult.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("富文本转换为doc文本错误,富文本:{}", text);
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据url获取文件字节数组 minio
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public byte[] getFileBytesByUrl(String url) {
|
||||
try {
|
||||
if (StrUtil.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
int startIndex = url.indexOf("id=") + "id=".length();
|
||||
String id = url.substring(startIndex);
|
||||
Sys_file sysFile = dao.fetch(Sys_file.class, id);
|
||||
return SysFileMinIoUtil.getFileBytes(sysFile.getBucket(), sysFile.getStoragePath());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.budwk.app.base.utils;
|
||||
|
||||
import org.nutz.json.JsonFormat;
|
||||
import org.nutz.lang.Encoding;
|
||||
import org.nutz.mvc.view.UTF8JsonView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author wizzer@qq.com
|
||||
*/
|
||||
public class WebUtil {
|
||||
|
||||
public static String AjaxEncode = Encoding.UTF8;
|
||||
|
||||
public static boolean isAjax(HttpServletRequest req) {
|
||||
String value = req.getHeader("X-Requested-With");
|
||||
return value != null && "XMLHttpRequest".equalsIgnoreCase(value.trim());
|
||||
}
|
||||
|
||||
public static void rendAjaxResp(HttpServletRequest req, HttpServletResponse resp, Object re) {
|
||||
try {
|
||||
if (AjaxEncode != null) {
|
||||
resp.setCharacterEncoding(AjaxEncode);
|
||||
}
|
||||
(new UTF8JsonView(JsonFormat.compact())).render(req, resp, re);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user