Browse Source

feat(common): 支持移动端表单字段同步功能

- 新增 collectMobileBindColumnNames 方法收集移动端列名
- 新增 mapMobileColumnNameToWidget 方法构建移动端列名到组件映射
- 实现 createNewSubTables 方法统一处理子表创建逻辑
- 添加 syncMobileSubTables 方法同步移动端子表和字段
- 实现 backfillMobileSubTableId 方法回写移动端子表ID
- 完善 syncMobileSubTableNewFields 方法处理移动端子表新增字段
- 重构 SysUserService 接口移除组织ID参数
- 优化 TaskInfoVo 类型添加解析后任务标题字段
feature/2026-07-ccc-dev
chenchuchuan 1 week ago
parent
commit
39e1d5ce3d
  1. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java
  2. 10
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/service/SysUserService.java
  3. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/service/impl/SysUserServiceImpl.java
  4. 6
      common/common-flow/src/main/java/apelet/common/flow/vo/TaskInfoVo.java
  5. 328
      common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java

@ -70,7 +70,6 @@ public class SysUserController {
* @param deptPostIdListString 逗号分隔的部门岗位Id列表 * @param deptPostIdListString 逗号分隔的部门岗位Id列表
* @param dataPermIdListString 逗号分隔的数据权限Id列表 * @param dataPermIdListString 逗号分隔的数据权限Id列表
* @param roleIdListString 逗号分隔的角色Id列表 * @param roleIdListString 逗号分隔的角色Id列表
* @param deptIdListString 逗号分隔的组织Id列表可选写入SysUserRole.deptId
* @return 应答结果对象包含新增用户的主键Id * @return 应答结果对象包含新增用户的主键Id
*/ */
@ApiOperationSupport(ignoreParameters = { @ApiOperationSupport(ignoreParameters = {
@ -83,26 +82,21 @@ public class SysUserController {
@MyRequestBody SysUserDto sysUserDto, @MyRequestBody SysUserDto sysUserDto,
@MyRequestBody String deptPostIdListString, @MyRequestBody String deptPostIdListString,
@MyRequestBody String dataPermIdListString, @MyRequestBody String dataPermIdListString,
@MyRequestBody String roleIdListString, @MyRequestBody String roleIdListString) {
@MyRequestBody String deptIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysUserDto); String errorMessage = MyCommonUtil.getModelValidationError(sysUserDto);
if (errorMessage != null) { if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
} }
SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class); SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class);
CallResult result = sysUserService.verifyRelatedData( CallResult result = sysUserService.verifyRelatedData(
sysUser, null, roleIdListString, deptPostIdListString, dataPermIdListString, deptIdListString); sysUser, null, roleIdListString, deptPostIdListString, dataPermIdListString);
if (!result.isSuccess()) { if (!result.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage()); return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage());
} }
Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){}); Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){});
Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){}); Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){});
Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){}); Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){});
Set<Long> deptIdSet = null; sysUserService.saveNew(sysUser, roleIdSet, deptPostIdSet, dataPermIdSet);
if (result.getData().containsKey("deptIdSet")) {
deptIdSet = result.getData().getObject("deptIdSet", new TypeReference<Set<Long>>(){});
}
sysUserService.saveNew(sysUser, roleIdSet, deptPostIdSet, dataPermIdSet, deptIdSet);
return ResponseResult.success(sysUser.getUserId()); return ResponseResult.success(sysUser.getUserId());
} }
@ -126,14 +120,14 @@ public class SysUserController {
} }
SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class); SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class);
CallResult result = sysUserService.verifyRelatedData( CallResult result = sysUserService.verifyRelatedData(
sysUser, null, "1801273688285270000", "1821796396504723500", "1821788867364139000", null); sysUser, null, "1801273688285270000", "1821796396504723500", "1821788867364139000");
if (!result.isSuccess()) { if (!result.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage()); return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage());
} }
Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){}); Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){});
Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){}); Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){});
Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){}); Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){});
SysUser sysUserO = sysUserService.saveNew(sysUser, roleIdSet, deptPostIdSet, dataPermIdSet, null); SysUser sysUserO = sysUserService.saveNew(sysUser, roleIdSet, deptPostIdSet, dataPermIdSet);
try { try {
ObjectValue userInfoObj = new ObjectValue("sys_user_info"); ObjectValue userInfoObj = new ObjectValue("sys_user_info");
@ -160,7 +154,6 @@ public class SysUserController {
* @param deptPostIdListString 逗号分隔的部门岗位Id列表 * @param deptPostIdListString 逗号分隔的部门岗位Id列表
* @param dataPermIdListString 逗号分隔的数据权限Id列表 * @param dataPermIdListString 逗号分隔的数据权限Id列表
* @param roleIdListString 逗号分隔的角色Id列表 * @param roleIdListString 逗号分隔的角色Id列表
* @param deptIdListString 逗号分隔的组织Id列表可选写入SysUserRole.deptId
* @return 应答结果对象 * @return 应答结果对象
*/ */
@ApiOperationSupport(ignoreParameters = { @ApiOperationSupport(ignoreParameters = {
@ -172,8 +165,7 @@ public class SysUserController {
@MyRequestBody SysUserDto sysUserDto, @MyRequestBody SysUserDto sysUserDto,
@MyRequestBody String deptPostIdListString, @MyRequestBody String deptPostIdListString,
@MyRequestBody String dataPermIdListString, @MyRequestBody String dataPermIdListString,
@MyRequestBody String roleIdListString, @MyRequestBody String roleIdListString) {
@MyRequestBody String deptIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysUserDto, true); String errorMessage = MyCommonUtil.getModelValidationError(sysUserDto, true);
if (errorMessage != null) { if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
@ -184,18 +176,14 @@ public class SysUserController {
} }
SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class); SysUser sysUser = MyModelUtil.copyTo(sysUserDto, SysUser.class);
CallResult result = sysUserService.verifyRelatedData( CallResult result = sysUserService.verifyRelatedData(
sysUser, originalUser, roleIdListString, deptPostIdListString, dataPermIdListString, deptIdListString); sysUser, originalUser, roleIdListString, deptPostIdListString, dataPermIdListString);
if (!result.isSuccess()) { if (!result.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage()); return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage());
} }
Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){}); Set<Long> roleIdSet = result.getData().getObject("roleIdSet", new TypeReference<Set<Long>>(){});
Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){}); Set<Long> deptPostIdSet = result.getData().getObject("deptPostIdSet", new TypeReference<Set<Long>>(){});
Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){}); Set<Long> dataPermIdSet = result.getData().getObject("dataPermIdSet", new TypeReference<Set<Long>>(){});
Set<Long> deptIdSet = null; if (!sysUserService.update(sysUser, originalUser, roleIdSet, deptPostIdSet, dataPermIdSet)) {
if (result.getData().containsKey("deptIdSet")) {
deptIdSet = result.getData().getObject("deptIdSet", new TypeReference<Set<Long>>(){});
}
if (!sysUserService.update(sysUser, originalUser, roleIdSet, deptPostIdSet, dataPermIdSet, deptIdSet)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
} }
return ResponseResult.success(); return ResponseResult.success();

10
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/service/SysUserService.java

@ -32,11 +32,10 @@ public interface SysUserService extends IBaseService<SysUser, Long> {
* @param user 新增的用户对象 * @param user 新增的用户对象
* @param roleIdSet 用户角色Id集合 * @param roleIdSet 用户角色Id集合
* @param deptPostIdSet 部门岗位Id集合 * @param deptPostIdSet 部门岗位Id集合
* @param dataPermIdSet 数据权限Id集合
* @param deptIdSet 组织Id集合写入SysUserRole.deptId * @param deptIdSet 组织Id集合写入SysUserRole.deptId
* @return 新增后的用户对象 * @return 新增后的用户对象
*/ */
SysUser saveNew(SysUser user, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet, Set<Long> deptIdSet); SysUser saveNew(SysUser user, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet);
/** /**
* 更新用户对象 * 更新用户对象
@ -46,10 +45,9 @@ public interface SysUserService extends IBaseService<SysUser, Long> {
* @param roleIdSet 用户角色Id列表 * @param roleIdSet 用户角色Id列表
* @param deptPostIdSet 部门岗位Id集合 * @param deptPostIdSet 部门岗位Id集合
* @param dataPermIdSet 数据权限Id集合 * @param dataPermIdSet 数据权限Id集合
* @param deptIdSet 组织Id集合写入SysUserRole.deptId
* @return 更新成功返回true否则false * @return 更新成功返回true否则false
*/ */
boolean update(SysUser user, SysUser originalUser, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet, Set<Long> deptIdSet); boolean update(SysUser user, SysUser originalUser, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet);
/** /**
* 修改用户密码 * 修改用户密码
@ -229,11 +227,9 @@ public interface SysUserService extends IBaseService<SysUser, Long> {
* @param roleIds 逗号分隔的角色Id列表字符串 * @param roleIds 逗号分隔的角色Id列表字符串
* @param deptPostIds 逗号分隔的部门岗位Id列表字符串 * @param deptPostIds 逗号分隔的部门岗位Id列表字符串
* @param dataPermIds 逗号分隔的数据权限Id列表字符串 * @param dataPermIds 逗号分隔的数据权限Id列表字符串
* @param deptIds 逗号分隔的组织Id列表字符串可选写入SysUserRole.deptId
* @return 验证结果 * @return 验证结果
*/ */
CallResult verifyRelatedData( CallResult verifyRelatedData(SysUser sysUser, SysUser originalSysUser, String roleIds, String deptPostIds, String dataPermIds);
SysUser sysUser, SysUser originalSysUser, String roleIds, String deptPostIds, String dataPermIds, String deptIds);
/** /**
* 根据云之家openId获取当前用户信息 * 根据云之家openId获取当前用户信息

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/service/impl/SysUserServiceImpl.java

@ -198,7 +198,7 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public SysUser saveNew(SysUser user, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet, Set<Long> deptIdSet) { public SysUser saveNew(SysUser user, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet) {
user.setUserId(idGenerator.nextLongId()); user.setUserId(idGenerator.nextLongId());
user.setPassword(passwordEncoder.encode(user.getPassword())); user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setUserStatus(SysUserStatus.STATUS_NORMAL); user.setUserStatus(SysUserStatus.STATUS_NORMAL);
@ -246,7 +246,7 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public boolean update(SysUser user, SysUser originalUser, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet, Set<Long> deptIdSet) { public boolean update(SysUser user, SysUser originalUser, Set<Long> roleIdSet, Set<Long> deptPostIdSet, Set<Long> dataPermIdSet) {
user.setLoginName(originalUser.getLoginName()); user.setLoginName(originalUser.getLoginName());
user.setPassword(originalUser.getPassword()); user.setPassword(originalUser.getPassword());
MyModelUtil.fillCommonsForUpdate(user, originalUser); MyModelUtil.fillCommonsForUpdate(user, originalUser);
@ -567,12 +567,11 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
* @param originalSysUser 原有对象 * @param originalSysUser 原有对象
* @param roleIds 逗号分隔的角色Id列表字符串 * @param roleIds 逗号分隔的角色Id列表字符串
* @param deptPostIds 逗号分隔的部门岗位Id列表字符串 * @param deptPostIds 逗号分隔的部门岗位Id列表字符串
* @param dataPermIds 逗号分隔的数据权限Id列表字符串
* @return 验证结果 * @return 验证结果
*/ */
@Override @Override
public CallResult verifyRelatedData( public CallResult verifyRelatedData(
SysUser sysUser, SysUser originalSysUser, String roleIds, String deptPostIds, String dataPermIds, String deptIds) { SysUser sysUser, SysUser originalSysUser, String roleIds, String deptPostIds, String dataPermIds) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
if (StrUtil.isBlank(deptPostIds)) { if (StrUtil.isBlank(deptPostIds)) {
return CallResult.error("数据验证失败,用户的部门岗位数据不能为空!"); return CallResult.error("数据验证失败,用户的部门岗位数据不能为空!");
@ -605,14 +604,6 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
&& !sysDeptService.existId(sysUser.getDeptId())) { && !sysDeptService.existId(sysUser.getDeptId())) {
return CallResult.error("数据验证失败,关联的用户部门Id并不存在,请刷新后重试!"); return CallResult.error("数据验证失败,关联的用户部门Id并不存在,请刷新后重试!");
} }
// 验证组织ID(可选,写入SysUserRole.deptId)
if (StrUtil.isNotBlank(deptIds)) {
Set<Long> deptIdSet = Arrays.stream(deptIds.split(",")).map(Long::valueOf).collect(Collectors.toSet());
if (!sysDeptService.existAllPrimaryKeys(deptIdSet)) {
return CallResult.error("数据验证失败,存在不合法的组织数据,请刷新后重试!");
}
jsonObject.put("deptIdSet", deptIdSet);
}
return CallResult.ok(jsonObject); return CallResult.ok(jsonObject);
} }

6
common/common-flow/src/main/java/apelet/common/flow/vo/TaskInfoVo.java

@ -76,4 +76,10 @@ public class TaskInfoVo {
*/ */
@Schema(description = "任务节点的自定义变量列表") @Schema(description = "任务节点的自定义变量列表")
List<JSONObject> variableList; List<JSONObject> variableList;
/**
* 解析后的任务标题
*/
@Schema(description = "解析后的任务标题")
private String title;
} }

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

@ -760,7 +760,11 @@ public class OnlineFormController {
boolean changed = false; boolean changed = false;
// === Diff 新增字段 === // === Diff 新增字段 ===
// 这里是取pc 的 还要取一下 moblie的
Set<String> widgetColumnNames = collectAllBindColumnNames(widgetJson); Set<String> widgetColumnNames = collectAllBindColumnNames(widgetJson);
// 收集 mobile 端的列名(遍历 childWidgetList 路径)
widgetColumnNames.addAll(collectMobileBindColumnNames(widgetJson));
List<OnlFormField> existingFields = onlFormFieldService.list( List<OnlFormField> existingFields = onlFormFieldService.list(
new LambdaQueryWrapper<OnlFormField>().eq(OnlFormField::getHeadId, onlFormHead.getId())); new LambdaQueryWrapper<OnlFormField>().eq(OnlFormField::getHeadId, onlFormHead.getId()));
Set<String> existingFieldNames = existingFields.stream() Set<String> existingFieldNames = existingFields.stream()
@ -786,12 +790,17 @@ public class OnlineFormController {
} }
if (!newColumnNames.isEmpty()) { if (!newColumnNames.isEmpty()) {
Map<String, JSONObject> nameToWidget = mapColumnNameToWidget(widgetJson); Map<String, JSONObject> nameToWidget = mapColumnNameToWidget(widgetJson);
// 收集 mobile 端的 widget 映射(遍历 childWidgetList 路径)
Map<String, JSONObject> mobileNameToWidget = mapMobileColumnNameToWidget(widgetJson);
OnlineDblink dblink = onlineDblinkService.getById(datasource.getDblinkId()); OnlineDblink dblink = onlineDblinkService.getById(datasource.getDblinkId());
// 预校验:过滤掉 widgetType 不在映射中的控件,避免 getFieldTypeId 抛异常导致部分数据已入库 // 预校验:过滤掉 widgetType 不在映射中的控件,避免 getFieldTypeId 抛异常导致部分数据已入库
Set<String> validColumnNames = new LinkedHashSet<>(); Set<String> validColumnNames = new LinkedHashSet<>();
for (String fieldName : newColumnNames) { for (String fieldName : newColumnNames) {
JSONObject widget = nameToWidget.get(fieldName); JSONObject widget = nameToWidget.get(fieldName);
if (widget == null) {
widget = mobileNameToWidget.get(fieldName);
}
Integer widgetType = widget != null ? widget.getInteger("widgetType") : null; Integer widgetType = widget != null ? widget.getInteger("widgetType") : null;
if (widgetType == null || !WidgetFieldTypeMapping.isDataWidget(widgetType)) { if (widgetType == null || !WidgetFieldTypeMapping.isDataWidget(widgetType)) {
continue; continue;
@ -804,6 +813,9 @@ public class OnlineFormController {
for (String fieldName : validColumnNames) { for (String fieldName : validColumnNames) {
JSONObject widget = nameToWidget.get(fieldName); JSONObject widget = nameToWidget.get(fieldName);
if (widget == null) {
widget = mobileNameToWidget.get(fieldName);
}
// 从 widget 的 bindData.columnComment 设置字段备注 // 从 widget 的 bindData.columnComment 设置字段备注
JSONObject bindData = widget.getJSONObject("bindData"); JSONObject bindData = widget.getJSONObject("bindData");
String ref = bindData.containsKey("slaveTableId") ? bindData.getString("slaveTableId") : null; String ref = bindData.containsKey("slaveTableId") ? bindData.getString("slaveTableId") : null;
@ -829,15 +841,26 @@ public class OnlineFormController {
for (String fieldName : validColumnNames) { for (String fieldName : validColumnNames) {
SqlTableColumn sqlCol = columnMap.get(fieldName.toLowerCase()); SqlTableColumn sqlCol = columnMap.get(fieldName.toLowerCase());
if (sqlCol != null) { if (sqlCol != null) {
// 回填 columnId 到 widgetJson
JSONObject widget = nameToWidget.get(fieldName); JSONObject widget = nameToWidget.get(fieldName);
String showName = widget == null ? null : widget.getString("showName"); JSONObject mobileWidget = mobileNameToWidget.get(fieldName);
String showName = widget != null ? widget.getString("showName") : (mobileWidget != null ? mobileWidget.getString("showName") : null);
long columnId = onlineColumnService.saveBySqlTable(sqlCol, onlineTable.getTableId(), showName); long columnId = onlineColumnService.saveBySqlTable(sqlCol, onlineTable.getTableId(), showName);
// 回写 pc 端 widget
if (widget != null) { if (widget != null) {
JSONObject bindData2 = widget.getJSONObject("bindData"); JSONObject bindData2 = widget.getJSONObject("bindData");
if (bindData2 != null) { if (bindData2 != null) {
bindData2.put("columnId", columnId); bindData2.put("columnId", columnId);
bindData2.put("tableId", onlineTable.getTableId()); bindData2.put("tableId", onlineTable.getTableId());
bindData2.put("columnFieldName", fieldName);
}
}
// 回写 mobile 端 widget
if (mobileWidget != null) {
JSONObject mobileBindData = mobileWidget.getJSONObject("bindData");
if (mobileBindData != null) {
mobileBindData.put("columnId", columnId);
mobileBindData.put("tableId", onlineTable.getTableId());
mobileBindData.put("columnFieldName", fieldName);
} }
} }
} }
@ -968,12 +991,35 @@ public class OnlineFormController {
} }
} }
//step2 : 不存在的附表,新增 //step2 : 不存在的附表,新增
changed |= createNewSubTables(widgetJson, onlFormHead, datasource, newSubTableNames);
} else {
// tableIdAndPropMap 为空,说明走 tableId 取值没取到,兜底通过 tableName 收集附表并创建
changed |= createNewSubTables(widgetJson, onlFormHead, datasource, new HashSet<>());
}
// === Diff mobile 端子表 ===
// 路径: mobile -> widgetList -> [widgetType=102] -> bindData -> tableName/tableId
changed |= syncMobileSubTables(widgetJson, onlFormHead, datasource);
return changed ? widgetJson : null;
}
/**
* 创建不存在的附表新建 OnlFormHead/OnlineTable绑定数据源关系回填 relationId 并追加 childName
* newSubTableNames 为空tableIdAndPropMap tableId 取值没取到兜底通过 tableName 收集附表
*
* @param widgetJson 表单 JSON
* @param onlFormHead 主表
* @param datasource 数据源
* @param newSubTableNames 附表名集合可为空
* @return 是否有变更
*/
private boolean createNewSubTables(JSONObject widgetJson, OnlFormHead onlFormHead, OnlineDatasource datasource, Set<String> newSubTableNames) {
if (newSubTableNames.isEmpty()) { if (newSubTableNames.isEmpty()) {
//如果他为空,说明我们走tableId取值没取到,我们就去一下 tableName; // 如果他为空,说明我们走tableId取值没取到,我们就去一下 tableName;
newSubTableNames = this.collectSubTableName(widgetJson); newSubTableNames = this.collectSubTableName(widgetJson);
} }
if (!newSubTableNames.isEmpty()) { if (newSubTableNames.isEmpty()) {
return false;
}
for (String subTableName : newSubTableNames) { for (String subTableName : newSubTableNames) {
OnlFormHead subHead = onlFormHeadService.createMetaAndSync(subTableName, onlFormHead.getTableTxt() + "附表", CustomUtil.MetaType_Entry, onlFormHead.getTableName()); OnlFormHead subHead = onlFormHeadService.createMetaAndSync(subTableName, onlFormHead.getTableTxt() + "附表", CustomUtil.MetaType_Entry, onlFormHead.getTableName());
// 获取子表的 OnlineTable // 获取子表的 OnlineTable
@ -1001,10 +1047,7 @@ public class OnlineFormController {
onlFormHead.setChildName(newSubTableName); onlFormHead.setChildName(newSubTableName);
} }
onlFormHeadService.updateById(onlFormHead); onlFormHeadService.updateById(onlFormHead);
changed = true; return true;
}
}
return changed ? widgetJson : null;
} }
@ -1232,4 +1275,271 @@ public class OnlineFormController {
} }
} }
// ============ mobile 端子表同步相关方法 ============
/**
* 同步 mobile 端的子表(新增子表 + 已有子表的新增字段)
* 子表: mobile -> widgetList -> [widgetType=102] -> bindData -> tableName/tableId
* 字段: mobile -> widgetList -> childWidgetList -> childWidgetList -> bindData -> columnName
*/
private boolean syncMobileSubTables(JSONObject widgetJson, OnlFormHead onlFormHead, OnlineDatasource datasource) {
JSONObject mobile = widgetJson.getJSONObject("mobile");
if (mobile == null) {
return false;
}
JSONArray mobileWidgetList = mobile.getJSONArray("widgetList");
if (mobileWidgetList == null) {
return false;
}
boolean changed = false;
Set<String> newSubTableNames = new LinkedHashSet<>();
Set<Long> existingSubTableIds = new LinkedHashSet<>();
for (int i = 0; i < mobileWidgetList.size(); i++) {
JSONObject widget = mobileWidgetList.getJSONObject(i);
if (widget.getInteger("widgetType") == null || widget.getInteger("widgetType") != 102) {
continue;
}
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableName = bindData.getString("tableName");
String tableIdStr = bindData.getString("tableId");
if (StrUtil.isNotEmpty(tableName) && StrUtil.isEmpty(tableIdStr)) {
newSubTableNames.add(tableName);
} else if (StrUtil.isNotEmpty(tableIdStr)) {
existingSubTableIds.add(Long.valueOf(tableIdStr));
}
}
// 处理新子表: 创建后回写 tableId + masterColumnName
if (!newSubTableNames.isEmpty()) {
changed |= createNewSubTables(widgetJson, onlFormHead, datasource, newSubTableNames);
backfillMobileSubTableId(widgetJson, newSubTableNames);
}
// 处理已有子表的新增字段
if (!existingSubTableIds.isEmpty()) {
changed |= syncMobileSubTableNewFields(widgetJson, datasource, existingSubTableIds);
}
return changed;
}
/**
* 回写 mobile 端子表的 tableId masterColumnName
* 路径: mobile -> widgetList -> [widgetType=102] -> bindData
*/
private void backfillMobileSubTableId(JSONObject widgetJson, Set<String> newSubTableNames) {
JSONObject mobile = widgetJson.getJSONObject("mobile");
if (mobile == null) {
return;
}
JSONArray mobileWidgetList = mobile.getJSONArray("widgetList");
if (mobileWidgetList == null) {
return;
}
for (int i = 0; i < mobileWidgetList.size(); i++) {
JSONObject widget = mobileWidgetList.getJSONObject(i);
if (widget.getInteger("widgetType") == null || widget.getInteger("widgetType") != 102) {
continue;
}
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableName = bindData.getString("tableName");
if (StrUtil.isEmpty(tableName) || !newSubTableNames.contains(tableName)) {
continue;
}
// createNewSubTables 已通过 backfillRelationId 回写了 tableId,这里只需补 masterColumnName
if (!bindData.containsKey("tableId")) {
OnlineTable subTable = onlineTableService.getOne(new LambdaQueryWrapper<OnlineTable>().eq(OnlineTable::getTableName, tableName.toLowerCase()));
if (subTable != null) {
bindData.put("tableId", subTable.getTableId());
}
}
bindData.put("masterColumnName", "id");
}
}
/**
* 同步 mobile 端已有子表的新增字段
* 字段路径: mobile -> widgetList -> [widgetType=102] -> childWidgetList -> childWidgetList -> bindData -> columnName
*/
private boolean syncMobileSubTableNewFields(JSONObject widgetJson, OnlineDatasource datasource, Set<Long> existingSubTableIds) {
// 查询已有子表信息
List<OnlineTable> subTables = onlineTableService.listByIds(existingSubTableIds);
if (CollUtil.isEmpty(subTables)) {
return false;
}
Map<Long, String> tableIdToName = subTables.stream().collect(Collectors.toMap(OnlineTable::getTableId, OnlineTable::getTableName));
List<String> tableNames = subTables.stream().map(OnlineTable::getTableName).collect(Collectors.toList());
List<OnlFormHead> subHeads = onlFormHeadService.list(new LambdaQueryWrapper<OnlFormHead>().in(OnlFormHead::getTableName, tableNames));
Map<String, OnlFormHead> tableNameToHead = subHeads.stream().collect(Collectors.toMap(OnlFormHead::getTableName, Function.identity()));
OnlineDblink dblink = onlineDblinkService.getById(datasource.getDblinkId());
// 遍历 mobile 端已有子表 widget, 搜集新增字段
JSONObject mobile = widgetJson.getJSONObject("mobile");
JSONArray mobileWidgetList = mobile.getJSONArray("widgetList");
boolean changed = false;
for (int i = 0; i < mobileWidgetList.size(); i++) {
JSONObject widget = mobileWidgetList.getJSONObject(i);
if (widget.getInteger("widgetType") == null || widget.getInteger("widgetType") != 102) {
continue;
}
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null) {
continue;
}
String tableIdStr = bindData.getString("tableId");
if (StrUtil.isEmpty(tableIdStr)) {
continue;
}
Long tableId = Long.valueOf(tableIdStr);
String tableName = tableIdToName.get(tableId);
if (tableName == null) {
continue;
}
OnlFormHead subHead = tableNameToHead.get(tableName);
if (subHead == null) {
continue;
}
// 搜集该子表下无 columnId 的字段
List<JSONObject> newFieldWidgets = new ArrayList<>();
JSONArray cardList = widget.getJSONArray("childWidgetList");
if (cardList != null) {
for (int j = 0; j < cardList.size(); j++) {
JSONObject card = cardList.getJSONObject(j);
JSONArray fieldList = card.getJSONArray("childWidgetList");
if (fieldList == null) {
continue;
}
for (int k = 0; k < fieldList.size(); k++) {
JSONObject field = fieldList.getJSONObject(k);
JSONObject fieldBd = field.getJSONObject("bindData");
if (fieldBd != null && fieldBd.containsKey("columnName") && !fieldBd.containsKey("columnId")) {
newFieldWidgets.add(field);
}
}
}
}
if (newFieldWidgets.isEmpty()) {
continue;
}
// 创建字段记录
for (JSONObject fieldWidget : newFieldWidgets) {
JSONObject fieldBd = fieldWidget.getJSONObject("bindData");
String columnName = fieldBd.getString("columnName");
String showName = fieldWidget.getString("showName");
this.saveField(fieldWidget.getInteger("widgetType"), fieldBd.getString("columnComment"), showName, subHead, columnName, null);
}
// ALTER TABLE ADD COLUMN
onlFormHeadService.syncDB(subHead, 0L);
// 批量获取列信息
List<SqlTableColumn> allColumns = onlineDblinkService.getDblinkTableColumnList(dblink, tableName);
Map<String, SqlTableColumn> columnMap = new HashMap<>();
if (CollUtil.isNotEmpty(allColumns)) {
for (SqlTableColumn col : allColumns) {
if (col.getColumnName() != null) {
columnMap.put(col.getColumnName().toLowerCase(), col);
}
}
}
// 创建 OnlineColumn + 回写
for (JSONObject fieldWidget : newFieldWidgets) {
JSONObject fieldBd = fieldWidget.getJSONObject("bindData");
String columnName = fieldBd.getString("columnName");
SqlTableColumn sqlCol = columnMap.get(columnName.toLowerCase());
if (sqlCol != null) {
String showName = fieldWidget.getString("showName");
long columnId = onlineColumnService.saveBySqlTable(sqlCol, tableId, showName);
fieldBd.put("columnId", columnId);
fieldBd.put("tableId", tableId);
fieldBd.put("columnFieldName", columnName);
}
}
// 删除缓存
redissonClient.getBucket(OnlineRedisKeyUtil.makeOnlineTableKey(tableId)).delete();
redissonClient.getBucket(CacheKey.makeTableKey(tableName)).delete();
redissonClient.getBucket(CacheKey.makeChildFieldListKey(subHead.getId())).delete();
metaCacheService.removeData(tableName);
changed = true;
}
return changed;
}
/**
* 遍历 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;
}
} }

Loading…
Cancel
Save