刘光辉
12 小时以前 34981c30a78e8bbd7791131059a9210f9928b62c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package jnpf.onlinedev.util;
 
import jnpf.model.visualjson.FieLdsModel;
import jnpf.util.JsonUtil;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
 
/**
 * 非持久化字段过滤。原始配置用于识别展示/虚拟属性,字段模型用于阻止相关字段参与 SQL。
 */
public final class DisplayOnlyFieldUtils {
 
    private static final String CONFIG = "__config__";
    private static final String CHILDREN = "children";
    private static final String DISPLAY_ONLY = "isDisplayOnly";
    private static final String VIRTUAL_FIELD = "isVirtualField";
    private static final String CONTROL_KEY = "controlKey";
    private static final String JNPF_KEY = "jnpfKey";
    private static final String TABLE = "table";
    private static final String V_MODEL = "__vModel__";
 
    private DisplayOnlyFieldUtils() {
    }
 
    public static void filter(String fieldsJson, List<FieLdsModel> fields, Map<String, Object> data) {
        if (fieldsJson == null || fieldsJson.isEmpty()) {
            return;
        }
        filterFields(JsonUtil.getJsonToListMap(fieldsJson), fields, data, true);
    }
 
    /**
     * 查询列表、编辑和详情数据前移除虚拟字段模型,展示字段仍需正常查询回显。
     */
    public static void filterVirtualFields(String fieldsJson, List<FieLdsModel> fields) {
        if (fieldsJson == null || fieldsJson.isEmpty()) {
            return;
        }
        filterFields(JsonUtil.getJsonToListMap(fieldsJson), fields, null, false);
    }
 
    /**
     * 生成不含虚拟字段的表单配置副本,供编辑查询等基础模块解析使用。
     */
    public static String filterVirtualFormData(String formDataJson) {
        if (formDataJson == null || formDataJson.isEmpty()) {
            return formDataJson;
        }
        Map<String, Object> formData = JsonUtil.stringToMap(formDataJson);
        Object fieldsValue = formData.get("fields");
        List<Map<String, Object>> fields = fieldsValue instanceof String
                ? JsonUtil.getJsonToListMap((String) fieldsValue) : asMapList(fieldsValue);
        removeVirtualRawFields(fields);
        formData.put("fields", fieldsValue instanceof String ? JsonUtil.getObjectToString(fields) : fields);
        return JsonUtil.getObjectToString(formData);
    }
 
    /**
     * 从列表查询字段中移除虚拟字段,避免列表配置残留时将 controlKey 当成数据库列。
     */
    public static void filterVirtualFieldKeys(String fieldsJson, Collection<String> fieldKeys) {
        if (fieldsJson == null || fieldsJson.isEmpty() || fieldKeys == null || fieldKeys.isEmpty()) {
            return;
        }
        Set<String> virtualKeys = new HashSet<>();
        collectVirtualFieldKeys(JsonUtil.getJsonToListMap(fieldsJson), null, false, virtualKeys);
        fieldKeys.removeIf(virtualKeys::contains);
    }
 
    public static boolean isVirtualFieldKey(String fieldsJson, String fieldKey) {
        if (fieldsJson == null || fieldsJson.isEmpty() || fieldKey == null || fieldKey.isEmpty()) {
            return false;
        }
        Set<String> virtualKeys = new HashSet<>();
        collectVirtualFieldKeys(JsonUtil.getJsonToListMap(fieldsJson), null, false, virtualKeys);
        return virtualKeys.contains(fieldKey);
    }
 
    private static void collectVirtualFieldKeys(List<Map<String, Object>> fields, String parentKey,
                                                boolean parentVirtual, Set<String> virtualKeys) {
        for (Map<String, Object> field : fields) {
            Map<String, Object> config = asMap(field.get(CONFIG));
            if (config == null) {
                continue;
            }
            String vModel = asString(field.get(V_MODEL));
            String controlKey = asString(field.get(CONTROL_KEY));
            String fieldKey = controlKey != null ? controlKey : vModel;
            boolean virtualField = parentVirtual || Boolean.TRUE.equals(config.get(VIRTUAL_FIELD));
            if (virtualField) {
                addVirtualKey(virtualKeys, parentKey, vModel);
                addVirtualKey(virtualKeys, parentKey, controlKey);
            }
            String childParentKey = fieldKey != null ? fieldKey : parentKey;
            collectVirtualFieldKeys(asMapList(config.get(CHILDREN)), childParentKey, virtualField, virtualKeys);
        }
    }
 
    private static void addVirtualKey(Set<String> virtualKeys, String parentKey, String fieldKey) {
        if (fieldKey == null) {
            return;
        }
        virtualKeys.add(fieldKey);
        if (parentKey != null) {
            virtualKeys.add(parentKey + "-" + fieldKey);
            virtualKeys.add(parentKey + "." + fieldKey);
        }
    }
 
    private static void removeVirtualRawFields(List<Map<String, Object>> fields) {
        if (fields == null || fields.isEmpty()) {
            return;
        }
        fields.removeIf(field -> {
            Map<String, Object> config = asMap(field.get(CONFIG));
            return config != null && Boolean.TRUE.equals(config.get(VIRTUAL_FIELD));
        });
        for (Map<String, Object> field : fields) {
            Map<String, Object> config = asMap(field.get(CONFIG));
            if (config == null) {
                continue;
            }
            List<Map<String, Object>> children = asMapList(config.get(CHILDREN));
            removeVirtualRawFields(children);
            config.put(CHILDREN, children);
        }
    }
 
    private static void filterFields(List<Map<String, Object>> rawFields, List<FieLdsModel> fields,
                                     Map<String, Object> data, boolean filterDisplayOnly) {
        if (rawFields == null || rawFields.isEmpty()) {
            return;
        }
        for (Map<String, Object> rawField : rawFields) {
            Map<String, Object> config = asMap(rawField.get(CONFIG));
            if (config == null) {
                continue;
            }
            String vModel = asString(rawField.get(V_MODEL));
            String controlKey = asString(rawField.get(CONTROL_KEY));
            FieLdsModel modelField = findModelField(rawField, config, fields);
            boolean virtualField = Boolean.TRUE.equals(config.get(VIRTUAL_FIELD));
            boolean displayOnly = Boolean.TRUE.equals(config.get(DISPLAY_ONLY));
            if (virtualField || (filterDisplayOnly && displayOnly)) {
                if (data != null) {
                    if (vModel != null) {
                        data.remove(vModel);
                    }
                    if (controlKey != null) {
                        data.remove(controlKey);
                    }
                }
                if (fields != null && modelField != null) {
                    fields.remove(modelField);
                }
                continue;
            }
 
            List<Map<String, Object>> rawChildren = asMapList(config.get(CHILDREN));
            if (rawChildren.isEmpty()) {
                continue;
            }
            List<FieLdsModel> modelChildren = modelField != null && modelField.getConfig() != null
                    ? modelField.getConfig().getChildren() : null;
            if (TABLE.equals(asString(config.get(JNPF_KEY))) && vModel != null) {
                filterFields(rawChildren, modelChildren, null, filterDisplayOnly);
                if (data != null && data.get(vModel) instanceof List) {
                    for (Object row : (List<?>) data.get(vModel)) {
                        Map<String, Object> rowMap = asMap(row);
                        if (rowMap != null) {
                            filterFields(rawChildren, null, rowMap, filterDisplayOnly);
                        }
                    }
                }
            } else {
                filterFields(rawChildren, modelChildren, data, filterDisplayOnly);
            }
        }
    }
 
    private static FieLdsModel findModelField(Map<String, Object> rawField, Map<String, Object> config,
                                               List<FieLdsModel> fields) {
        if (fields == null || fields.isEmpty()) {
            return null;
        }
        String vModel = asString(rawField.get(V_MODEL));
        String formId = asString(config.get("formId"));
        String id = asString(rawField.get("id"));
        for (FieLdsModel field : fields) {
            if (vModel != null && Objects.equals(vModel, field.getVModel())) {
                return field;
            }
            if (formId != null && field.getConfig() != null
                    && Objects.equals(formId, field.getConfig().getFormId())) {
                return field;
            }
            if (id != null && Objects.equals(id, field.getId())) {
                return field;
            }
        }
        return null;
    }
 
    @SuppressWarnings("unchecked")
    private static Map<String, Object> asMap(Object value) {
        return value instanceof Map ? (Map<String, Object>) value : null;
    }
 
    private static List<Map<String, Object>> asMapList(Object value) {
        List<Map<String, Object>> result = new ArrayList<>();
        if (!(value instanceof List)) {
            return result;
        }
        for (Object item : (List<?>) value) {
            Map<String, Object> map = asMap(item);
            if (map != null) {
                result.add(map);
            }
        }
        return result;
    }
 
    private static String asString(Object value) {
        if (value == null) {
            return null;
        }
        String text = String.valueOf(value);
        return text.isEmpty() ? null : text;
    }
}