Browse Source

refactor(online): 将WidgetJson解析逻辑提取为独立工具类

- 提取字典ID解析逻辑到WidgetJsonUtil.extractDictIdSet方法
- 移除OnlineFormController中的extractDictIdSetFromWidgetJson私有方法
- 提取字段名收集逻辑到WidgetJsonUtil.collectBindColumnNames方法
- 移除OnlineFormController中的collectAllBindColumnNames私有方法
- 提取移动端字段名收集逻辑到WidgetJsonUtil.buildMobileColumnNameWidgetMap方法
- 移除OnlineFormController中的collectMobileBindColumnNames私有方法
- 提取子表属性收集逻辑到WidgetJsonUtil.collectSubTableProps方法
- 移除OnlineFormController中的collectSubTableAndPropMap私有方法
- 提取字段名到控件映射构建逻辑到多个WidgetJsonUtil静态方法
- 移除OnlineFormController中相关的私有方法实现
- 添加字段路径步骤解析功能支持PC和移动端不同结构
- 实现统一的控件树遍历和递归处理机制
feature/2026-07-ccc-dev
chenchuchuan 2 days ago
parent
commit
618f14aced
  1. 350
      common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java
  2. 457
      common/common-online/src/main/java/apelet/common/online/util/WidgetJsonUtil.java

350
common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java

@ -29,6 +29,7 @@ import apelet.common.online.model.constant.FormType; @@ -29,6 +29,7 @@ import apelet.common.online.model.constant.FormType;
import apelet.common.online.service.*;
import apelet.common.online.util.OnlineRedisKeyUtil;
import apelet.common.online.util.WidgetFieldTypeMapping;
import apelet.common.online.util.WidgetJsonUtil;
import apelet.common.online.vo.OnlineFormVo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
@ -56,7 +57,6 @@ import org.springframework.web.bind.annotation.*; @@ -56,7 +57,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.groups.Default;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -519,7 +519,7 @@ public class OnlineFormController { @@ -519,7 +519,7 @@ public class OnlineFormController {
jsonObject.put("onlineVirtualColumnList", virtualColumnList);
Set<Long> dictIdSet = onlineColumnList.stream()
.filter(c -> c.getDictId() != null).map(OnlineColumn::getDictId).collect(Collectors.toSet());
Set<Long> widgetDictIdSet = this.extractDictIdSetFromWidgetJson(onlineForm.getWidgetJson());
Set<Long> widgetDictIdSet = WidgetJsonUtil.extractDictIdSet(onlineForm.getWidgetJson());
CollUtil.addAll(dictIdSet, widgetDictIdSet);
if (CollUtil.isNotEmpty(dictIdSet)) {
List<OnlineDict> onlineDictList = onlineDictService.getOnlineDictListFromCache(dictIdSet);
@ -660,46 +660,6 @@ public class OnlineFormController { @@ -660,46 +660,6 @@ public class OnlineFormController {
return ResponseResult.success(datasourceIdSet);
}
private Set<Long> extractDictIdSetFromWidgetJson(String widgetJson) {
Set<Long> dictIdSet = new HashSet<>();
if (StrUtil.isBlank(widgetJson)) {
return dictIdSet;
}
JSONObject allData = JSON.parseObject(widgetJson);
JSONObject pcData = allData.getJSONObject(AppDeviceType.getDeviceType());
if (MapUtil.isEmpty(pcData)) {
return dictIdSet;
}
JSONArray widgetListArray = pcData.getJSONArray("widgetList");
if (CollUtil.isEmpty(widgetListArray)) {
return dictIdSet;
}
for (int i = 0; i < widgetListArray.size(); i++) {
this.recursiveExtractDictId(widgetListArray.getJSONObject(i), dictIdSet);
}
return dictIdSet;
}
private void recursiveExtractDictId(JSONObject widgetData, Set<Long> dictIdSet) {
JSONObject propsData = widgetData.getJSONObject("props");
if (MapUtil.isNotEmpty(propsData)) {
JSONObject dictInfoData = propsData.getJSONObject("dictInfo");
if (MapUtil.isNotEmpty(dictInfoData)) {
Long dictId = dictInfoData.getLong("dictId");
if (dictId != null) {
dictIdSet.add(dictId);
}
}
}
JSONArray childWidgetArray = widgetData.getJSONArray("childWidgetList");
if (CollUtil.isNotEmpty(childWidgetArray)) {
for (int i = 0; i < childWidgetArray.size(); i++) {
this.recursiveExtractDictId(childWidgetArray.getJSONObject(i), dictIdSet);
}
}
}
/**
* 获取流程对应的在线表单
* @param bosType
@ -761,19 +721,16 @@ public class OnlineFormController { @@ -761,19 +721,16 @@ public class OnlineFormController {
boolean changed = false;
// === Diff 新增字段 ===
// 这里是取pc 的 还要取一下 moblie的
Set<String> widgetColumnNames = collectAllBindColumnNames(widgetJson);
// 收集 mobile 端的列名(遍历 childWidgetList 路径)
widgetColumnNames.addAll(collectMobileBindColumnNames(widgetJson));
// 收集 pc/mobile 端所有绑定的字段列名
Set<String> widgetColumnNames = WidgetJsonUtil.collectBindColumnNames(widgetJson);
List<OnlFormField> existingFields = onlFormFieldService.list(
new LambdaQueryWrapper<OnlFormField>().eq(OnlFormField::getHeadId, onlFormHead.getId()));
List<OnlFormField> existingFields = onlFormFieldService.list(new LambdaQueryWrapper<OnlFormField>().eq(OnlFormField::getHeadId, onlFormHead.getId()));
Set<String> existingFieldNames = existingFields.stream()
.map(OnlFormField::getFieldName).collect(Collectors.toSet());
Set<String> newColumnNames = new HashSet<>(widgetColumnNames);
newColumnNames.removeAll(existingFieldNames);
// 主表/单表已有字段:如果绑定了从表(slaveTableId),同步更新 refPropert
Map<String, JSONObject> fieldNameToWidget = mapFieldNameToWidget(widgetJson);
Map<String, JSONObject> fieldNameToWidget = WidgetJsonUtil.buildFieldNameWidgetMap(widgetJson);
for (OnlFormField existingField : existingFields) {
JSONObject widget = fieldNameToWidget.get(existingField.getFieldName());
if (widget == null) {
@ -790,9 +747,9 @@ public class OnlineFormController { @@ -790,9 +747,9 @@ public class OnlineFormController {
}
}
if (!newColumnNames.isEmpty()) {
Map<String, JSONObject> nameToWidget = mapColumnNameToWidget(widgetJson);
Map<String, JSONObject> nameToWidget = WidgetJsonUtil.buildColumnNameWidgetMap(widgetJson);
// 收集 mobile 端的 widget 映射(遍历 childWidgetList 路径)
Map<String, JSONObject> mobileNameToWidget = mapMobileColumnNameToWidget(widgetJson);
Map<String, JSONObject> mobileNameToWidget = WidgetJsonUtil.buildMobileColumnNameWidgetMap(widgetJson);
OnlineDblink dblink = onlineDblinkService.getById(datasource.getDblinkId());
// 预校验:过滤掉 widgetType 不在映射中的控件,避免 getFieldTypeId 抛异常导致部分数据已入库
@ -876,7 +833,7 @@ public class OnlineFormController { @@ -876,7 +833,7 @@ public class OnlineFormController {
// === Diff 新增子表 ===
// 取 widgetList->bindData -> tableId 在去 zz_online_table 查询,这样就可以判断哪些是新增,哪些是 已有的表
// 如果存在附表
Map<String, JSONObject> tableIdAndPropMap = collectSubTableAndPropMap(widgetJson);
Map<String, JSONObject> tableIdAndPropMap = WidgetJsonUtil.collectSubTableProps(widgetJson);
if (MapUtil.isNotEmpty(tableIdAndPropMap)) {
//搜集的所有tableId, 要么是 tableId(已存在),要么是 tableName(不存在)
@ -900,7 +857,7 @@ public class OnlineFormController { @@ -900,7 +857,7 @@ public class OnlineFormController {
List<OnlFormHead> onlFormHeadList = onlFormHeadService.list(new LambdaQueryWrapper<OnlFormHead>().in(OnlFormHead::getTableName, tableNames));
Map<String, OnlFormHead> tableNameAndHeadIdMap = onlFormHeadList.stream().collect(Collectors.toMap(OnlFormHead::getTableName, Function.identity()));
//因为这里是zz_online_column.column_id 的id和 列名的混合,我只要列名
Map<String, JSONObject> nameToWidget = mapColumnIdAndWidget(widgetJson);
Map<String, JSONObject> nameToWidget = WidgetJsonUtil.buildSubTableColumnWidgetMap(widgetJson);
Set<String> newSubColumnNameSet = nameToWidget.keySet().stream().filter(s -> !s.matches("\\d+")).collect(Collectors.toSet());
//这里要走 新增逻辑
if (!newSubColumnNameSet.isEmpty()) {
@ -1016,7 +973,7 @@ public class OnlineFormController { @@ -1016,7 +973,7 @@ public class OnlineFormController {
private boolean createNewSubTables(JSONObject widgetJson, OnlFormHead onlFormHead, OnlineDatasource datasource, Set<String> newSubTableNames) {
if (newSubTableNames.isEmpty()) {
// 如果他为空,说明我们走tableId取值没取到,我们就去一下 tableName;
newSubTableNames = this.collectSubTableName(widgetJson);
newSubTableNames = WidgetJsonUtil.collectSubTableNames(widgetJson);
}
if (newSubTableNames.isEmpty()) {
return false;
@ -1036,7 +993,7 @@ public class OnlineFormController { @@ -1036,7 +993,7 @@ public class OnlineFormController {
onlineDatasourceRelationService.addOnlineDatasourceRelation(onlFormHead, datasource, null, dblink);
if (subOnlineTable != null) {
backfillRelationId(widgetJson, subTableName, subOnlineTable.getTableId());
WidgetJsonUtil.backfillTableId(widgetJson, subTableName, subOnlineTable.getTableId());
}
}
@ -1077,210 +1034,6 @@ public class OnlineFormController { @@ -1077,210 +1034,6 @@ public class OnlineFormController {
onlFormFieldService.save(field);
}
/**
* 遍历 pc/mobile widget 收集所有 bindData.columnName
*/
private Set<String> collectAllBindColumnNames(JSONObject widgetJson) {
Set<String> names = new HashSet<>();
walkAllModes(widgetJson, widget -> {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
names.add(name);
}
}
});
return names;
}
/**
* 遍历 pc/mobile widget 收集 widgetType=100 (TableContainer) bindData 下的 tableId
*/
private Map<String, JSONObject> collectSubTableAndPropMap(JSONObject widgetJson) {
Map<String, JSONObject> resultMap = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList != null) {
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理widgetType为100的子表
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableId = bindData.getString("tableId");
if (StrUtil.isBlank(tableId)) {
continue;
}
JSONObject props = childWidget.getJSONObject("props");
if (props != null) {
resultMap.put(tableId, props);
}
}
}
});
return resultMap;
}
private Set<String> collectSubTableName(JSONObject widgetJson) {
Set<String> tableNameSet = new HashSet<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList != null) {
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理widgetType为100的子表
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
if (bindData.containsKey("tableName")) {
tableNameSet.add(bindData.getString("tableName"));
}
}
}
});
return tableNameSet;
}
/**
* 构建 columnName widget 的映射
*/
private Map<String, JSONObject> mapColumnNameToWidget(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
map.put(name, widget);
}
}
});
return map;
}
/**
* 构建 fieldName widget 的映射用于主表已有字段匹配
* key 优先取 bindData.columnFieldName兼容 bindData.columnName
*/
private Map<String, JSONObject> mapFieldNameToWidget(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null) {
return;
}
String fieldName = bindData.getString("columnFieldName");
if (StrUtil.isEmpty(fieldName)) {
fieldName = bindData.getString("columnName");
}
if (StrUtil.isNotEmpty(fieldName)) {
map.put(fieldName, widget);
}
});
return map;
}
private Map<String, JSONObject> mapColumnIdAndWidget(JSONObject widgetJson) {
Map<String, JSONObject> resultMap = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList != null) {
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理widgetType为100的子表
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableId = bindData.getString("tableId");
if (StrUtil.isBlank(tableId)) {
continue;
}
JSONObject props = childWidget.getJSONObject("props");
if (props == null) {
continue;
}
JSONArray tableColumnList = props.getJSONArray("tableColumnList");
for (int j = 0; j < tableColumnList.size(); j++) {
JSONObject tableColumn = tableColumnList.getJSONObject(j);
// 过滤掉 fieldType=1 的列(如序号、合计等非真实字段),避免被识别为需要新增的字段
Integer fieldType = tableColumn.getInteger("fieldType");
if (fieldType != null && fieldType == 1) {
continue;
}
resultMap.put(tableColumn.getString("columnId"), tableColumn);
}
}
}
});
return resultMap;
}
/**
* widgetJson 中查找匹配 tableName TableContainer 控件回填 tableId
*/
private void backfillRelationId(JSONObject widgetJson, String tableName, Long tableId) {
walkAllModes(widgetJson, widget -> {
if (widget.getInteger("widgetType") != null && 100 == widget.getInteger("widgetType")) {
JSONObject props = widget.getJSONObject("bindData");
if (props != null && tableName.equals(props.getString("tableName"))) {
props.put("tableId", tableId);
}
}
});
}
/**
* 遍历 "pc" "mobile" 两个模式的控件树
*/
private void walkAllModes(JSONObject widgetJson, Consumer<JSONObject> visitor) {
for (String mode : new String[]{"pc", "mobile"}) {
JSONObject modeObj = widgetJson.getJSONObject(mode);
if (modeObj != null) {
walkWidgets(modeObj, visitor);
}
}
}
/**
* 递归遍历控件树访问每个控件及其子控件(widgetList)
*/
private void walkWidgets(JSONObject node, Consumer<JSONObject> visitor) {
if (node == null) {
return;
}
visitor.accept(node);
JSONArray children = node.getJSONArray("widgetList");
if (children != null) {
for (int i = 0; i < children.size(); i++) {
walkWidgets(children.getJSONObject(i), visitor);
}
}
}
// ============ mobile 端子表同步相关方法 ============
/**
@ -1355,7 +1108,7 @@ public class OnlineFormController { @@ -1355,7 +1108,7 @@ public class OnlineFormController {
if (StrUtil.isEmpty(tableName) || !newSubTableNames.contains(tableName)) {
continue;
}
// createNewSubTables 已通过 backfillRelationId 回写了 tableId,这里只需补 masterColumnName
// createNewSubTables 已通过 WidgetJsonUtil.backfillTableId 回写了 tableId,这里只需补 masterColumnName
if (!bindData.containsKey("tableId")) {
OnlineTable subTable = onlineTableService.getOne(new LambdaQueryWrapper<OnlineTable>().eq(OnlineTable::getTableName, tableName.toLowerCase()));
if (subTable != null) {
@ -1473,83 +1226,6 @@ public class OnlineFormController { @@ -1473,83 +1226,6 @@ public class OnlineFormController {
}
/**
* 遍历 mobile widget 收集所有 bindData.columnName
* 路径: mobile -> tableWidget -> childWidgetList -> childWidgetList -> bindData -> columnName
*/
private Set<String> collectMobileBindColumnNames(JSONObject widgetJson) {
Set<String> names = new HashSet<>();
JSONObject mobile = widgetJson.getJSONObject("mobile");
if (mobile == null) {
return names;
}
JSONObject tableWidget = mobile.getJSONObject("tableWidget");
if (tableWidget == null) {
return names;
}
JSONArray cardList = tableWidget.getJSONArray("childWidgetList");
if (cardList == null) {
return names;
}
for (int i = 0; i < cardList.size(); i++) {
JSONObject cardWidget = cardList.getJSONObject(i);
JSONArray fieldList = cardWidget.getJSONArray("childWidgetList");
if (fieldList == null) {
continue;
}
for (int j = 0; j < fieldList.size(); j++) {
JSONObject fieldWidget = fieldList.getJSONObject(j);
JSONObject bindData = fieldWidget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
names.add(name);
}
}
}
}
return names;
}
/**
* 构建 mobile columnName widget 的映射
* 路径: mobile -> tableWidget -> childWidgetList -> childWidgetList -> bindData -> columnName
*/
private Map<String, JSONObject> mapMobileColumnNameToWidget(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
JSONObject mobile = widgetJson.getJSONObject("mobile");
if (mobile == null) {
return map;
}
JSONObject tableWidget = mobile.getJSONObject("tableWidget");
if (tableWidget == null) {
return map;
}
JSONArray cardList = tableWidget.getJSONArray("childWidgetList");
if (cardList == null) {
return map;
}
for (int i = 0; i < cardList.size(); i++) {
JSONObject cardWidget = cardList.getJSONObject(i);
JSONArray fieldList = cardWidget.getJSONArray("childWidgetList");
if (fieldList == null) {
continue;
}
for (int j = 0; j < fieldList.size(); j++) {
JSONObject fieldWidget = fieldList.getJSONObject(j);
JSONObject bindData = fieldWidget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
map.put(name, fieldWidget);
}
}
}
}
return map;
}
/**
* 查询指定表名的列表表单
*
* @param tableName 表名

457
common/common-online/src/main/java/apelet/common/online/util/WidgetJsonUtil.java

@ -0,0 +1,457 @@ @@ -0,0 +1,457 @@
package apelet.common.online.util;
import apelet.common.core.constant.AppDeviceType;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
/**
* widgetJson 数据操作工具类
* 提供从在线表单 widgetJson 中提取字典绑定字段子表控件等信息的纯数据操作方法
*
* @author chenchuchuan
* @date 2026-08-06
*/
public class WidgetJsonUtil {
private WidgetJsonUtil() {
}
/**
* widgetJson 中提取所有控件绑定的字典Id
* 仅遍历当前设备端(widgetList childWidgetList)控件树中 props.dictInfo.dictId
*
* @param widgetJson 在线表单的 widgetJson
* @return 字典Id集合
*/
public static Set<Long> extractDictIdSet(String widgetJson) {
Set<Long> dictIdSet = new HashSet<>();
if (StrUtil.isBlank(widgetJson)) {
return dictIdSet;
}
JSONObject deviceData = JSON.parseObject(widgetJson).getJSONObject(AppDeviceType.getDeviceType());
if (MapUtil.isEmpty(deviceData)) {
return dictIdSet;
}
JSONArray widgetListArray = deviceData.getJSONArray("widgetList");
if (CollUtil.isEmpty(widgetListArray)) {
return dictIdSet;
}
for (int i = 0; i < widgetListArray.size(); i++) {
extractDictIdRecursively(widgetListArray.getJSONObject(i), dictIdSet);
}
return dictIdSet;
}
/**
* 递归提取单个控件及其子控件中的字典Id
*/
private static void extractDictIdRecursively(JSONObject widgetData, Set<Long> dictIdSet) {
JSONObject propsData = widgetData.getJSONObject("props");
if (MapUtil.isNotEmpty(propsData)) {
JSONObject dictInfoData = propsData.getJSONObject("dictInfo");
if (MapUtil.isNotEmpty(dictInfoData)) {
Long dictId = dictInfoData.getLong("dictId");
if (dictId != null) {
dictIdSet.add(dictId);
}
}
}
JSONArray childWidgetArray = widgetData.getJSONArray("childWidgetList");
if (CollUtil.isNotEmpty(childWidgetArray)) {
for (int i = 0; i < childWidgetArray.size(); i++) {
extractDictIdRecursively(childWidgetArray.getJSONObject(i), dictIdSet);
}
}
}
/**
* 遍历 pc/mobile 控件树收集所有控件 bindData.columnName
* <p>
* 每个读取源用"设备端 + 字段步骤链"描述步骤支持对象字段 obj() 和数组字段 arr()
* <pre>
* pc: widgetList -> bindData -> columnName
* mobile: tableWidget -> childWidgetList -> childWidgetList -> bindData -> columnName
* mobile: widgetList -> childWidgetList -> bindData -> columnName
* </pre>
* 后续新增读取源 otherWidgetList只需在下方追加一行
* {@code collectColumnNamesByPath(widgetJson, names, "other", arr("otherWidgetList"))}
*
* @param widgetJson 在线表单的 widgetJson
* @return 绑定的字段名列集合
*/
public static Set<String> collectBindColumnNames(JSONObject widgetJson) {
Set<String> names = new HashSet<>();
if (widgetJson == null) {
return names;
}
// pc 端: widgetList -> bindData -> columnName
collectColumnNamesByPath(widgetJson, names, "pc", arr("widgetList"));
// mobile 端(原 tableWidget 结构): tableWidget -> childWidgetList -> childWidgetList -> bindData -> columnName
collectColumnNamesByPath(widgetJson, names, "mobile", obj("tableWidget"), arr("childWidgetList"), arr("childWidgetList"));
// mobile 端(兜底 widgetList 结构): widgetList -> childWidgetList -> bindData -> columnName
collectColumnNamesByPath(widgetJson, names, "mobile", arr("widgetList"), arr("childWidgetList"));
return names;
}
/**
* "设备端 + 字段步骤链"读取 columnName
* widgetJson mode 节点开始依次下钻 steps 中的每个字段步骤
* 最后一个步骤的节点即为控件取其 bindData.columnName
*
* @param widgetJson widgetJson 根对象
* @param names 收集结果
* @param mode 设备端 key pc/mobile
* @param steps 字段步骤链支持对象字段 obj() 与数组字段 arr()
*/
private static void collectColumnNamesByPath(JSONObject widgetJson, Set<String> names, String mode, PathStep... steps) {
JSONObject modeObj = widgetJson.getJSONObject(mode);
if (modeObj == null) {
return;
}
collectColumnNamesByStep(modeObj, 0, steps, names);
}
/**
* 逐层下钻字段步骤链到达末尾时读取控件的 bindData.columnName
*/
private static void collectColumnNamesByStep(JSONObject node, int index, PathStep[] steps, Set<String> names) {
if (index >= steps.length) {
addColumnName(node, names);
return;
}
PathStep step = steps[index];
if (step.isArray) {
JSONArray array = node.getJSONArray(step.field);
if (CollUtil.isEmpty(array)) {
return;
}
for (int i = 0; i < array.size(); i++) {
collectColumnNamesByStep(array.getJSONObject(i), index + 1, steps, names);
}
} else {
JSONObject child = node.getJSONObject(step.field);
if (child == null) {
return;
}
collectColumnNamesByStep(child, index + 1, steps, names);
}
}
/**
* 读取路径步骤对象字段(obj) 数组字段(arr)
*/
private static class PathStep {
final boolean isArray;
final String field;
private PathStep(boolean isArray, String field) {
this.isArray = isArray;
this.field = field;
}
}
/** 对象字段步骤,如 tableWidget。 */
private static PathStep obj(String field) {
return new PathStep(false, field);
}
/** 数组字段步骤,如 widgetList、childWidgetList。 */
private static PathStep arr(String field) {
return new PathStep(true, field);
}
/**
* 从控件对象中提取 bindData.columnName
*/
private static void addColumnName(JSONObject widget, Set<String> names) {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData != null) {
String columnName = bindData.getString("columnName");
if (StrUtil.isNotEmpty(columnName)) {
names.add(columnName);
}
}
}
/**
* 收集子表控件(widgetType=100) bindData.tableId props 映射
*
* @param widgetJson 在线表单的 widgetJson
* @return tableId 子表控件 props 的映射
*/
public static Map<String, JSONObject> collectSubTableProps(JSONObject widgetJson) {
Map<String, JSONObject> resultMap = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList == null) {
return;
}
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理 widgetType=100 的子表控件
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableId = bindData.getString("tableId");
if (StrUtil.isBlank(tableId)) {
continue;
}
JSONObject props = childWidget.getJSONObject("props");
if (props != null) {
resultMap.put(tableId, props);
}
}
});
return resultMap;
}
/**
* 收集子表控件(widgetType=100) bindData.tableName 的名称集合
*
* @param widgetJson 在线表单的 widgetJson
* @return 子表名称集合
*/
public static Set<String> collectSubTableNames(JSONObject widgetJson) {
Set<String> tableNameSet = new HashSet<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList == null) {
return;
}
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理 widgetType=100 的子表控件
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
if (bindData.containsKey("tableName")) {
tableNameSet.add(bindData.getString("tableName"));
}
}
});
return tableNameSet;
}
/**
* 构建 columnName 控件 widget 的映射
*
* @param widgetJson 在线表单的 widgetJson
* @return 字段名 widget 的映射
*/
public static Map<String, JSONObject> buildColumnNameWidgetMap(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
map.put(name, widget);
}
}
});
return map;
}
/**
* 构建 fieldName widget 的映射用于主表已有字段匹配
* key 优先取 bindData.columnFieldName兼容 bindData.columnName
*
* @param widgetJson 在线表单的 widgetJson
* @return 字段名 widget 的映射
*/
public static Map<String, JSONObject> buildFieldNameWidgetMap(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null) {
return;
}
String fieldName = bindData.getString("columnFieldName");
if (StrUtil.isEmpty(fieldName)) {
fieldName = bindData.getString("columnName");
}
if (StrUtil.isNotEmpty(fieldName)) {
map.put(fieldName, widget);
}
});
return map;
}
/**
* 构建子表控件 tableColumnList columnId 列对象 映射
* 过滤掉 fieldType=1 的列如序号合计等非真实字段
*
* @param widgetJson 在线表单的 widgetJson
* @return columnId 子表列对象 的映射
*/
public static Map<String, JSONObject> buildSubTableColumnWidgetMap(JSONObject widgetJson) {
Map<String, JSONObject> resultMap = new HashMap<>();
walkAllModes(widgetJson, widget -> {
JSONArray widgetList = widget.getJSONArray("widgetList");
if (widgetList == null) {
return;
}
for (int i = 0; i < widgetList.size(); i++) {
JSONObject childWidget = widgetList.getJSONObject(i);
// 只处理 widgetType=100 的子表控件
Integer widgetType = childWidget.getInteger("widgetType");
if (widgetType == null || widgetType != 100) {
continue;
}
JSONObject bindData = childWidget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableId = bindData.getString("tableId");
if (StrUtil.isBlank(tableId)) {
continue;
}
JSONObject props = childWidget.getJSONObject("props");
if (props == null) {
continue;
}
JSONArray tableColumnList = props.getJSONArray("tableColumnList");
for (int j = 0; j < tableColumnList.size(); j++) {
JSONObject tableColumn = tableColumnList.getJSONObject(j);
// 过滤掉 fieldType=1 的列(如序号、合计等非真实字段),避免被识别为需要新增的字段
Integer fieldType = tableColumn.getInteger("fieldType");
if (fieldType != null && fieldType == 1) {
continue;
}
resultMap.put(tableColumn.getString("columnId"), tableColumn);
}
}
});
return resultMap;
}
/**
* 构建 mobile columnName widget 的映射
* 兼容两种结构:
* 1. mobile -> tableWidget -> childWidgetList -> childWidgetList -> bindData -> columnName
* 2. mobile -> widgetList -> childWidgetList -> bindData -> columnName (缺少 tableWidget )
*
* @param widgetJson 在线表单的 widgetJson
* @return mobile 端字段名 widget 的映射
*/
public static Map<String, JSONObject> buildMobileColumnNameWidgetMap(JSONObject widgetJson) {
Map<String, JSONObject> map = new HashMap<>();
JSONObject mobile = widgetJson.getJSONObject("mobile");
if (mobile == null) {
return map;
}
// 优先走原有结构: mobile.tableWidget
JSONObject tableWidget = mobile.getJSONObject("tableWidget");
if (tableWidget != null) {
JSONArray cardList = tableWidget.getJSONArray("childWidgetList");
if (cardList != null) {
for (int i = 0; i < cardList.size(); i++) {
JSONObject cardWidget = cardList.getJSONObject(i);
JSONArray fieldList = cardWidget.getJSONArray("childWidgetList");
if (fieldList == null) {
continue;
}
for (int j = 0; j < fieldList.size(); j++) {
JSONObject fieldWidget = fieldList.getJSONObject(j);
JSONObject bindData = fieldWidget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
map.put(name, fieldWidget);
}
}
}
}
}
return map;
}
// 兜底走新结构: mobile.widgetList -> childWidgetList -> bindData.columnName
JSONArray widgetList = mobile.getJSONArray("widgetList");
if (widgetList != null) {
for (int i = 0; i < widgetList.size(); i++) {
JSONObject containerWidget = widgetList.getJSONObject(i);
JSONArray childWidgetList = containerWidget.getJSONArray("childWidgetList");
if (childWidgetList == null) {
continue;
}
for (int j = 0; j < childWidgetList.size(); j++) {
JSONObject fieldWidget = childWidgetList.getJSONObject(j);
JSONObject bindData = fieldWidget.getJSONObject("bindData");
if (bindData != null && bindData.containsKey("columnName")) {
String name = bindData.getString("columnName");
if (StrUtil.isNotEmpty(name)) {
map.put(name, fieldWidget);
}
}
}
}
}
return map;
}
/**
* widgetJson 中查找匹配 tableName 的子表控件(widgetType=100)回填 bindData.tableId
*
* @param widgetJson 在线表单的 widgetJson
* @param tableName 子表名称
* @param tableId 子表Id
*/
public static void backfillTableId(JSONObject widgetJson, String tableName, Long tableId) {
walkAllModes(widgetJson, widget -> {
if (widget.getInteger("widgetType") != null && 100 == widget.getInteger("widgetType")) {
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData != null && tableName.equals(bindData.getString("tableName"))) {
bindData.put("tableId", tableId);
}
}
});
}
/**
* 遍历 "pc" "mobile" 两个模式的控件树
*/
private static void walkAllModes(JSONObject widgetJson, Consumer<JSONObject> visitor) {
for (String mode : new String[]{"pc", "mobile"}) {
JSONObject modeObj = widgetJson.getJSONObject(mode);
if (modeObj != null) {
walkWidgets(modeObj, visitor);
}
}
}
/**
* 递归遍历控件树访问每个控件及其子控件(widgetList)
*/
private static void walkWidgets(JSONObject node, Consumer<JSONObject> visitor) {
if (node == null) {
return;
}
visitor.accept(node);
JSONArray children = node.getJSONArray("widgetList");
if (children != null) {
for (int i = 0; i < children.size(); i++) {
walkWidgets(children.getJSONObject(i), visitor);
}
}
}
}
Loading…
Cancel
Save