feat(core):优化表格构建逻辑以支持字段过滤与描述映射
- 在 `FsTableUtil` 中移除冗余的 `getHeadTemplateBuilder` 重载方法,统一构建入口 - 新增 `getIncludeFieldHeaders` 方法,增强字段包含逻辑,支持驼峰与下划线格式匹配 -修复表头排序问题,确保启用描述时正确应用字段顺序 - 在 `PropertyUtil` 中新增 `getHeaders`重载方法,支持传入字段过滤列表 -`优化 `SheetBuilder 构建流程,使其能正确传递 `includeFields` 并应用字段描述映射 - 移除不必要的包导入与空行,提升代码可读性- 增加 `@NotNull` 注解以强化静态检查能力
This commit is contained in:
		
							parent
							
								
									6d9908bfbb
								
							
						
					
					
						commit
						c8e2e2dc5e
					
				@ -24,17 +24,17 @@ import java.util.stream.Collectors;
 | 
			
		||||
 * 提供链式调用方式创建飞书表格,支持字段过滤等高级功能。
 | 
			
		||||
 */
 | 
			
		||||
public class SheetBuilder<T> {
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    private final String sheetName;
 | 
			
		||||
    private final String spreadsheetToken;
 | 
			
		||||
    private final Class<T> clazz;
 | 
			
		||||
    private List<String> includeFields;
 | 
			
		||||
    private final Map<String, Object> customProperties = new HashMap<>();
 | 
			
		||||
    private final Map<String, String> fieldDescriptions = new HashMap<>();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构造函数
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param sheetName 工作表名称
 | 
			
		||||
     * @param spreadsheetToken 电子表格Token
 | 
			
		||||
     * @param clazz 实体类Class对象
 | 
			
		||||
@ -44,12 +44,12 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.spreadsheetToken = spreadsheetToken;
 | 
			
		||||
        this.clazz = clazz;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置包含的字段列表
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 指定要包含在表格中的字段名称列表。如果不设置,则包含所有带有@TableProperty注解的字段。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param fields 要包含的字段名称列表
 | 
			
		||||
     * @return SheetBuilder实例,支持链式调用
 | 
			
		||||
     */
 | 
			
		||||
@ -57,12 +57,12 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.includeFields = new ArrayList<>(fields);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置自定义属性
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 添加一个自定义属性,可以在构建表格时使用
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param key 属性键
 | 
			
		||||
     * @param value 属性值
 | 
			
		||||
     * @return SheetBuilder实例,支持链式调用
 | 
			
		||||
@ -71,12 +71,12 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.customProperties.put(key, value);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 批量设置自定义属性
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 批量添加自定义属性,可以在构建表格时使用
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param properties 自定义属性映射
 | 
			
		||||
     * @return SheetBuilder实例,支持链式调用
 | 
			
		||||
     */
 | 
			
		||||
@ -84,34 +84,34 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.customProperties.putAll(properties);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取自定义属性
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 根据键获取已设置的自定义属性值
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param key 属性键
 | 
			
		||||
     * @return 属性值,如果不存在则返回null
 | 
			
		||||
     */
 | 
			
		||||
    public Object getCustomProperty(String key) {
 | 
			
		||||
        return this.customProperties.get(key);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取所有自定义属性
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @return 包含所有自定义属性的映射
 | 
			
		||||
     */
 | 
			
		||||
    public Map<String, Object> getCustomProperties() {
 | 
			
		||||
        return new HashMap<>(this.customProperties);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置字段描述映射
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 为实体类字段设置自定义描述信息,用于在表格描述行中显示。
 | 
			
		||||
     * 如果字段在映射中存在描述,则使用映射中的描述;否则使用注解中的描述。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldDescriptions 字段名到描述的映射,key为字段名,value为描述文本
 | 
			
		||||
     * @return SheetBuilder实例,支持链式调用
 | 
			
		||||
     */
 | 
			
		||||
@ -119,12 +119,12 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.fieldDescriptions.putAll(fieldDescriptions);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置单个字段描述
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 为指定字段设置自定义描述信息。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldName 字段名
 | 
			
		||||
     * @param description 描述文本
 | 
			
		||||
     * @return SheetBuilder实例,支持链式调用
 | 
			
		||||
@ -133,60 +133,60 @@ public class SheetBuilder<T> {
 | 
			
		||||
        this.fieldDescriptions.put(fieldName, description);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取字段描述映射
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @return 包含所有字段描述的映射
 | 
			
		||||
     */
 | 
			
		||||
    public Map<String, String> getFieldDescriptions() {
 | 
			
		||||
        return new HashMap<>(this.fieldDescriptions);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构建表格并返回工作表ID
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 根据配置的参数创建飞书表格,包括表头、样式、单元格格式和下拉选项等。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @return 创建成功返回工作表ID
 | 
			
		||||
     */
 | 
			
		||||
    public String build() {
 | 
			
		||||
        // 获取所有字段映射
 | 
			
		||||
        Map<String, FieldProperty> allFieldsMap = PropertyUtil.getTablePropertyFieldsMap(clazz);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 根据includeFields过滤字段映射
 | 
			
		||||
        Map<String, FieldProperty> fieldsMap = filterFieldsMap(allFieldsMap);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 生成表头
 | 
			
		||||
        List<String> headers = PropertyUtil.getHeaders(fieldsMap);
 | 
			
		||||
        
 | 
			
		||||
        List<String> headers = PropertyUtil.getHeaders(fieldsMap, includeFields);
 | 
			
		||||
 | 
			
		||||
        // 获取表格配置
 | 
			
		||||
        TableConf tableConf = PropertyUtil.getTableConf(clazz);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 创建飞书客户端
 | 
			
		||||
        FeishuClient client = FsClient.getInstance().getClient();
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 1、创建sheet
 | 
			
		||||
        String sheetId = FsApiUtil.createSheet(sheetName, client, spreadsheetToken);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 2、添加表头数据
 | 
			
		||||
        FsApiUtil.putValues(spreadsheetToken, FsTableUtil.getHeadTemplateBuilder(sheetId, headers, fieldsMap, includeFields, tableConf, fieldDescriptions), client);
 | 
			
		||||
        
 | 
			
		||||
        FsApiUtil.putValues(spreadsheetToken, FsTableUtil.getHeadTemplateBuilder(sheetId, headers, fieldsMap, tableConf, fieldDescriptions), client);
 | 
			
		||||
 | 
			
		||||
        // 3、设置表格样式
 | 
			
		||||
        FsApiUtil.setTableStyle(FsTableUtil.getDefaultTableStyle(sheetId, fieldsMap, tableConf), client, spreadsheetToken);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 4、合并单元格
 | 
			
		||||
        List<CustomCellService.CellRequest> mergeCell = FsTableUtil.getMergeCell(sheetId, fieldsMap);
 | 
			
		||||
        if (!mergeCell.isEmpty()) {
 | 
			
		||||
            mergeCell.forEach(cell -> FsApiUtil.mergeCells(cell, client, spreadsheetToken));
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 5、设置单元格为文本格式
 | 
			
		||||
        if (tableConf.isText()) {
 | 
			
		||||
            String column = FsTableUtil.getColumnNameByNuNumber(headers.size());
 | 
			
		||||
            FsApiUtil.setCellType(sheetId, "@", "A1", column + 200, client, spreadsheetToken);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 6、设置表格下拉
 | 
			
		||||
        try {
 | 
			
		||||
            FsTableUtil.setTableOptions(spreadsheetToken, headers, fieldsMap, sheetId, tableConf.enableDesc(), customProperties);
 | 
			
		||||
@ -196,10 +196,10 @@ public class SheetBuilder<T> {
 | 
			
		||||
 | 
			
		||||
        return sheetId;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据包含字段列表过滤字段映射
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param allFieldsMap 所有字段映射
 | 
			
		||||
     * @return 过滤后的字段映射
 | 
			
		||||
     */
 | 
			
		||||
@ -208,7 +208,7 @@ public class SheetBuilder<T> {
 | 
			
		||||
        if (includeFields == null || includeFields.isEmpty()) {
 | 
			
		||||
            return allFieldsMap;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 根据字段名过滤,保留指定的字段
 | 
			
		||||
        return allFieldsMap.entrySet().stream()
 | 
			
		||||
                .filter(entry -> {
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ import cn.isliu.core.service.CustomValueService;
 | 
			
		||||
import com.google.gson.JsonElement;
 | 
			
		||||
import com.google.gson.JsonParser;
 | 
			
		||||
import com.google.gson.JsonSyntaxException;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
@ -356,18 +357,18 @@ public class FsTableUtil {
 | 
			
		||||
        setTableOptions(spreadsheetToken, headers, fieldsMap, sheetId, enableDesc, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    public static CustomValueService.ValueRequest getHeadTemplateBuilder(String sheetId, List<String> headers,
 | 
			
		||||
//                   Map<String, FieldProperty> fieldsMap, TableConf tableConf) {
 | 
			
		||||
//        return getHeadTemplateBuilder(sheetId, headers, fieldsMap, null, tableConf);
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    public static CustomValueService.ValueRequest getHeadTemplateBuilder(String sheetId, List<String> headers,
 | 
			
		||||
                                                                         Map<String, FieldProperty> fieldsMap, TableConf tableConf) {
 | 
			
		||||
        return getHeadTemplateBuilder(sheetId, headers, fieldsMap, null, tableConf);
 | 
			
		||||
        return getHeadTemplateBuilder(sheetId, headers, fieldsMap, tableConf, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static CustomValueService.ValueRequest getHeadTemplateBuilder(String sheetId, List<String> headers,
 | 
			
		||||
                                                                         Map<String, FieldProperty> fieldsMap, List<String> includeFields, TableConf tableConf) {
 | 
			
		||||
        return getHeadTemplateBuilder(sheetId, headers, fieldsMap, includeFields, tableConf, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static CustomValueService.ValueRequest getHeadTemplateBuilder(String sheetId, List<String> headers,
 | 
			
		||||
                                                                         Map<String, FieldProperty> fieldsMap, List<String> includeFields, TableConf tableConf, Map<String, String> fieldDescriptions) {
 | 
			
		||||
                                                                         Map<String, FieldProperty> fieldsMap, TableConf tableConf, Map<String, String> fieldDescriptions) {
 | 
			
		||||
 | 
			
		||||
        String position = FsTableUtil.getColumnNameByNuNumber(headers.size());
 | 
			
		||||
 | 
			
		||||
@ -378,22 +379,15 @@ public class FsTableUtil {
 | 
			
		||||
        int maxLevel = getMaxLevel(fieldsMap);
 | 
			
		||||
 | 
			
		||||
        if (maxLevel == 1) {
 | 
			
		||||
            // 单层级表头:按order排序的headers
 | 
			
		||||
            List<String> sortedHeaders;
 | 
			
		||||
            if (includeFields != null && !includeFields.isEmpty()) {
 | 
			
		||||
                sortedHeaders = includeFields.stream().sorted(Comparator.comparingInt(headers::indexOf)).collect(Collectors.toList());
 | 
			
		||||
            } else {
 | 
			
		||||
                sortedHeaders = getSortedHeaders(fieldsMap);
 | 
			
		||||
            }
 | 
			
		||||
            int titleRow = tableConf.titleRow();
 | 
			
		||||
            if (tableConf.enableDesc()) {
 | 
			
		||||
                int descRow = titleRow + 1;
 | 
			
		||||
                batchPutValuesBuilder.addRange(sheetId + "!A" + titleRow + ":" + position + descRow);
 | 
			
		||||
                batchPutValuesBuilder.addRow(sortedHeaders.toArray());
 | 
			
		||||
                batchPutValuesBuilder.addRow(getDescArray(sortedHeaders, fieldsMap, fieldDescriptions));
 | 
			
		||||
                batchPutValuesBuilder.addRow(headers.toArray());
 | 
			
		||||
                batchPutValuesBuilder.addRow(getDescArray(headers, fieldsMap, fieldDescriptions));
 | 
			
		||||
            } else {
 | 
			
		||||
                batchPutValuesBuilder.addRange(sheetId + "!A" + titleRow + ":" + position + titleRow);
 | 
			
		||||
                batchPutValuesBuilder.addRow(sortedHeaders.toArray());
 | 
			
		||||
                batchPutValuesBuilder.addRow(headers.toArray());
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
@ -421,21 +415,47 @@ public class FsTableUtil {
 | 
			
		||||
 | 
			
		||||
            // 如果启用了描述,在最后一行添加描述
 | 
			
		||||
            if (tableConf.enableDesc()) {
 | 
			
		||||
                List<String> finalHeaders;
 | 
			
		||||
                if (includeFields != null && !includeFields.isEmpty()) {
 | 
			
		||||
                    finalHeaders = includeFields.stream().sorted(Comparator.comparingInt(headers::indexOf)).collect(Collectors.toList());
 | 
			
		||||
                } else {
 | 
			
		||||
                    finalHeaders = getSortedHeaders(fieldsMap);
 | 
			
		||||
                }
 | 
			
		||||
                int descRow = maxLevel + 1;
 | 
			
		||||
                batchPutValuesBuilder.addRange(sheetId + "!A" + descRow + ":" + position + descRow);
 | 
			
		||||
                batchPutValuesBuilder.addRow(getDescArray(finalHeaders, fieldsMap, fieldDescriptions));
 | 
			
		||||
                batchPutValuesBuilder.addRow(getDescArray(headers, fieldsMap, fieldDescriptions));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return batchPutValuesBuilder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private static List<String> getIncludeFieldHeaders(List<String> headers, Map<String, FieldProperty> fieldsMap, List<String> includeFields) {
 | 
			
		||||
        return includeFields.stream()
 | 
			
		||||
                .map(includeField -> {
 | 
			
		||||
                    // 查找匹配的fieldsMap key
 | 
			
		||||
                    for (Map.Entry<String, FieldProperty> entry : fieldsMap.entrySet()) {
 | 
			
		||||
                        FieldProperty fieldProperty = entry.getValue();
 | 
			
		||||
                        if (fieldProperty != null && fieldProperty.getTableProperty() != null) {
 | 
			
		||||
                            String field = fieldProperty.getField();
 | 
			
		||||
                            if (field != null) {
 | 
			
		||||
                                // 获取最后一个属性并转换为下划线格式
 | 
			
		||||
                                String[] split = field.split("\\.");
 | 
			
		||||
                                String lastValue = split[split.length - 1];
 | 
			
		||||
                                String underscoreFormat = StringUtil.toUnderscoreCase(lastValue);
 | 
			
		||||
                                // 如果匹配,返回fieldsMap的key
 | 
			
		||||
                                if (underscoreFormat.equals(includeField)) {
 | 
			
		||||
                                    return entry.getKey();
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                if (lastValue.equals(includeField)) {
 | 
			
		||||
                                    return entry.getKey();
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // 如果没有匹配到,返回原始值
 | 
			
		||||
                    return includeField;
 | 
			
		||||
                })
 | 
			
		||||
                .sorted(Comparator.comparingInt(includeFields::indexOf))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取按order排序的表头列表
 | 
			
		||||
     *
 | 
			
		||||
@ -480,6 +500,9 @@ public class FsTableUtil {
 | 
			
		||||
                    String fieldPath = fieldProperty.getField();
 | 
			
		||||
                    String fieldName = fieldPath.substring(fieldPath.lastIndexOf(".") + 1);
 | 
			
		||||
                    desc = fieldDescriptions.get(fieldName);
 | 
			
		||||
                    if (desc == null) {
 | 
			
		||||
                        desc = fieldDescriptions.get(StringUtil.toUnderscoreCase(fieldName));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 如果映射中没有找到,则从注解中获取
 | 
			
		||||
 | 
			
		||||
@ -26,14 +26,14 @@ public class PropertyUtil {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取类及其嵌套类上@TableProperty注解的字段映射关系
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * 此方法是入口方法,用于获取一个类及其所有嵌套类中,
 | 
			
		||||
     * 被@TableProperty注解标记的字段的映射关系。
 | 
			
		||||
     * 注解中的值作为key,FieldProperty对象作为value返回。
 | 
			
		||||
     *
 | 
			
		||||
     * 对于嵌套属性,使用'.'连接符来表示层级关系。
 | 
			
		||||
     * 该方法会过滤掉有子级的字段,只返回最底层的字段映射。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param clazz 要处理的类
 | 
			
		||||
     * @return 包含所有@TableProperty注解字段映射关系的Map,嵌套属性使用'.'连接
 | 
			
		||||
     */
 | 
			
		||||
@ -59,7 +59,7 @@ public class PropertyUtil {
 | 
			
		||||
     * 收集所有被@TableProperty注解标记的字段信息。
 | 
			
		||||
     *
 | 
			
		||||
     * 方法会处理循环引用问题,并限制递归深度,防止栈溢出。
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param clazz 当前处理的类
 | 
			
		||||
     * @param result 存储结果的Map
 | 
			
		||||
     * @param keyPrefix key的前缀(使用注解中的值构建)
 | 
			
		||||
@ -73,7 +73,7 @@ public class PropertyUtil {
 | 
			
		||||
        if (!isTargetPackageClass(clazz)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 检测循环引用,限制递归深度
 | 
			
		||||
        Integer currentDepth = depthMap.getOrDefault(clazz, 0);
 | 
			
		||||
        if (currentDepth > 5) { // 限制最大递归深度为5
 | 
			
		||||
@ -129,14 +129,14 @@ public class PropertyUtil {
 | 
			
		||||
        if (clazz == null) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        String className = clazz.getName();
 | 
			
		||||
        // 只处理用户自定义的类,排除系统类
 | 
			
		||||
        return !className.startsWith("java.") && 
 | 
			
		||||
               !className.startsWith("javax.") && 
 | 
			
		||||
               !className.startsWith("sun.") && 
 | 
			
		||||
               !className.startsWith("com.sun.") &&
 | 
			
		||||
               !className.startsWith("jdk.");
 | 
			
		||||
        return !className.startsWith("java.") &&
 | 
			
		||||
                !className.startsWith("javax.") &&
 | 
			
		||||
                !className.startsWith("sun.") &&
 | 
			
		||||
                !className.startsWith("com.sun.") &&
 | 
			
		||||
                !className.startsWith("jdk.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -276,7 +276,7 @@ public class PropertyUtil {
 | 
			
		||||
            // 构建新的前缀
 | 
			
		||||
            String newKeyPrefix;
 | 
			
		||||
            String newValuePrefix = valuePrefix.isEmpty() ? field.getName() : valuePrefix + "." + field.getName();
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            // 关键修改:如果父节点没有注解,则不拼接父节点字段名
 | 
			
		||||
            if (parentHasAnnotation) {
 | 
			
		||||
                // 父节点有注解,需要拼接
 | 
			
		||||
@ -349,7 +349,7 @@ public class PropertyUtil {
 | 
			
		||||
                clazz.equals(Character.class) ||
 | 
			
		||||
                clazz.equals(Byte.class) ||
 | 
			
		||||
                clazz.equals(Short.class) ||
 | 
			
		||||
                clazz.equals(java.util.Date.class) ||
 | 
			
		||||
                clazz.equals(Date.class) ||
 | 
			
		||||
                clazz.equals(java.time.LocalDate.class) ||
 | 
			
		||||
                clazz.equals(java.time.LocalDateTime.class));
 | 
			
		||||
    }
 | 
			
		||||
@ -365,7 +365,70 @@ public class PropertyUtil {
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull
 | 
			
		||||
    public static List<String> getHeaders(Map<String, FieldProperty> fieldsMap) {
 | 
			
		||||
        return getSortedHeaders(fieldsMap);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 从字段属性映射中提取表头列表
 | 
			
		||||
     *
 | 
			
		||||
     * 此方法根据字段的@TableProperty注解中的order属性对字段进行排序,
 | 
			
		||||
     * 返回按顺序排列的表头列表,用于数据展示时的列顺序。
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldsMap 字段属性映射
 | 
			
		||||
     * @return 按顺序排列的表头列表
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull
 | 
			
		||||
    public static List<String> getHeaders(Map<String, FieldProperty> fieldsMap, List<String> includeFields) {
 | 
			
		||||
        List<String> sortedHeaders;
 | 
			
		||||
        if (includeFields != null && !includeFields.isEmpty()) {
 | 
			
		||||
            sortedHeaders = getIncludeFieldHeaders(fieldsMap, includeFields);
 | 
			
		||||
        } else {
 | 
			
		||||
            sortedHeaders = getSortedHeaders(fieldsMap);
 | 
			
		||||
        }
 | 
			
		||||
        return sortedHeaders;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private static List<String> getIncludeFieldHeaders(Map<String, FieldProperty> fieldsMap, List<String> includeFields) {
 | 
			
		||||
        return includeFields.stream()
 | 
			
		||||
                .map(includeField -> {
 | 
			
		||||
                    // 查找匹配的fieldsMap key
 | 
			
		||||
                    for (Map.Entry<String, FieldProperty> entry : fieldsMap.entrySet()) {
 | 
			
		||||
                        FieldProperty fieldProperty = entry.getValue();
 | 
			
		||||
                        if (fieldProperty != null && fieldProperty.getTableProperty() != null) {
 | 
			
		||||
                            String field = fieldProperty.getField();
 | 
			
		||||
                            if (field != null) {
 | 
			
		||||
                                // 获取最后一个属性并转换为下划线格式
 | 
			
		||||
                                String[] split = field.split("\\.");
 | 
			
		||||
                                String lastValue = split[split.length - 1];
 | 
			
		||||
                                String underscoreFormat = StringUtil.toUnderscoreCase(lastValue);
 | 
			
		||||
                                // 如果匹配,返回fieldsMap的key
 | 
			
		||||
                                if (underscoreFormat.equals(includeField)) {
 | 
			
		||||
                                    return entry.getKey();
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                if (lastValue.equals(includeField)) {
 | 
			
		||||
                                    return entry.getKey();
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // 如果没有匹配到,返回原始值
 | 
			
		||||
                    return includeField;
 | 
			
		||||
                })
 | 
			
		||||
                .sorted(Comparator.comparingInt(includeFields::indexOf))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取按order排序的表头列表
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldsMap 字段属性映射
 | 
			
		||||
     * @return 按order排序的表头列表
 | 
			
		||||
     */
 | 
			
		||||
    private static List<String> getSortedHeaders(Map<String, FieldProperty> fieldsMap) {
 | 
			
		||||
        return fieldsMap.entrySet().stream()
 | 
			
		||||
                .filter(entry -> entry.getValue() != null && entry.getValue().getTableProperty() != null)
 | 
			
		||||
                .sorted(Comparator.comparingInt(entry -> entry.getValue().getTableProperty().order()))
 | 
			
		||||
                .map(Map.Entry::getKey)
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user