Browse Source

feat(online): 增强在线表单列表查询功能支持自定义排序过滤

- 新增 baseFormId 参数传递支持关联表单数据权限过滤
- 实现 tableWidget 组件配置的默认排序和过滤条件功能
- 添加关联组件(402)的默认排序/过滤条件读取支持
- 实现子表控件的默认排序/过滤条件收集和应用
- 增强日期时间字段显示格式支持区分日期和日期时间
- 添加表单名称查询接口支持模糊匹配
- 优化数据权限规则匹配逻辑支持基础数据权限场景
- 完善过滤条件占位符解析和表名限定功能
feature/2026-08/0812-ccc-dev
chenchuchuan 2 days ago
parent
commit
8857f60f44
  1. 155
      common/common-online/src/main/java/apelet/common/online/abstractplugin/ListDataOrmService.java
  2. 2
      common/common-online/src/main/java/apelet/common/online/abstractplugin/ListDataService.java
  3. 18
      common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java
  4. 100
      common/common-online/src/main/java/apelet/common/online/controller/OnlineOperationController.java
  5. 9
      common/common-online/src/main/java/apelet/common/online/service/OnlineFormService.java
  6. 8
      common/common-online/src/main/java/apelet/common/online/service/impl/OnlineFormServiceImpl.java
  7. 12
      common/common-online/src/main/java/apelet/common/online/service/impl/OnlineOperationServiceImpl.java
  8. 193
      common/common-online/src/main/java/apelet/common/online/util/WidgetJsonUtil.java

155
common/common-online/src/main/java/apelet/common/online/abstractplugin/ListDataOrmService.java

@ -13,6 +13,7 @@ import apelet.common.online.model.constant.FieldFilterType; @@ -13,6 +13,7 @@ import apelet.common.online.model.constant.FieldFilterType;
import apelet.common.online.model.constant.RelationType;
import apelet.common.orm.impl.*;
import apelet.common.orm.parser.FilterParser;
import apelet.common.online.util.WidgetJsonUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
@ -20,9 +21,12 @@ import cn.hutool.core.util.StrUtil; @@ -20,9 +21,12 @@ import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@ -32,6 +36,7 @@ import java.util.stream.Collectors; @@ -32,6 +36,7 @@ import java.util.stream.Collectors;
* @version 1.0
* Create by 2024/10/24 10:46
*/
@Slf4j
public class ListDataOrmService extends ListDataService {
public ListDataOrmService(OnlineEventPluginExecuteDto dto) {
super(dto);
@ -76,20 +81,34 @@ public class ListDataOrmService extends ListDataService { @@ -76,20 +81,34 @@ public class ListDataOrmService extends ListDataService {
JSONObject widgetList = widgetJson.getJSONObject("pc").getJSONObject("tableWidget");
Set<String> selectorSet = new TreeSet<>();
getOrmSelector(widgetList, selectorSet, masterTable, new HashMap<>());
Filter filter = buildFilter();
Filter filter = buildFilter(onlineForm);
Sorter sorter = new Sorter();
if (orderParam != null) {
// 排序:前端传了排序 → 按前端排(保留 create_time 兜底);没传且表单配了 sortField → 用它(值带方向则解析,默认 desc);否则 create_time DESC 兜底。
if (CollUtil.isNotEmpty(orderParam)) {
for (MyOrderParam.OrderInfo orderInfo : orderParam) {
SorterItem sorterItem = new SorterItem(orderInfo.getFieldName());
sorterItem.setSortType(orderInfo.getAsc() ? SortType._ASC : SortType._DESC);
sorter.add(sorterItem);
}
}
if (!sorter.startsWithKey("create_time")) {
SorterItem sorterItem = new SorterItem("create_time");
sorterItem.setSortType(SortType._DESC);
sorter.add(sorterItem);
if (!sorter.startsWithKey("create_time")) {
SorterItem sorterItem = new SorterItem("create_time");
sorterItem.setSortType(SortType._DESC);
sorter.add(sorterItem);
}
} else {
// 排序优先级:关联组件(402).sortField > tableWidget.sortField > create_time DESC 兜底。
String sortField = this.getRelativeFormSortFilter().get("sortField");
if (StrUtil.isBlank(sortField)) {
sortField = this.getTableWidgetSortField(onlineForm);
}
if (StrUtil.isNotBlank(sortField)) {
sorter.add(this.buildSorterItemFromSortField(sortField));
} else {
SorterItem sorterItem = new SorterItem("create_time");
sorterItem.setSortType(SortType._DESC);
sorter.add(sorterItem);
}
}
Selector selector = new Selector();
selectorSet.forEach(f -> selector.getList().add(new SelectorItem(f)));
@ -115,14 +134,16 @@ public class ListDataOrmService extends ListDataService { @@ -115,14 +134,16 @@ public class ListDataOrmService extends ListDataService {
/**
* 构建列表查询过滤条件用户过滤条件 + 数据权限规则 loadGridData 共用
*/
private Filter buildFilter() {
private Filter buildFilter(OnlineForm onlineForm) {
// 根据当前用户角色 + 当前表单匹配权限规则:非空→基础数据权限,为空→列表权限
List<PermissionDataRuleSchema> ruleSchemaList = this.getRuleSchemaListByCurrentRole();
String conditionExpression = null;
if (CollUtil.isNotEmpty(ruleSchemaList)) {
List<PermissionDataRuleSchema> filtered = new ArrayList<>();
if (StrUtil.isNotBlank(metaCode)) {
filtered = ruleSchemaList.stream().filter(s -> DataRuleType.BASIC_DATA == s.getRuleType() && metaCode.equals(s.getMetaCode())).collect(Collectors.toList());
filtered = ruleSchemaList.stream().filter(s -> DataRuleType.BASIC_DATA == s.getRuleType()
&& metaCode.equals(s.getMetaCode())
&& this.matchBaseFormId(s.getFormIdList())).collect(Collectors.toList());
}
if (CollUtil.isEmpty(filtered)) {
filtered = ruleSchemaList.stream().filter(s -> DataRuleType.LIST == s.getRuleType()).collect(Collectors.toList());
@ -139,6 +160,28 @@ public class ListDataOrmService extends ListDataService { @@ -139,6 +160,28 @@ public class ListDataOrmService extends ListDataService {
Filter parsed = FilterParser.parse(conditionExpression);
filter = filter.and(parsed);
}
// 表单 tableWidget 配置的默认过滤条件(如 name = ${userName}),占位符取 tokenData,拼接到查询条件后面。
String filterField = this.getTableWidgetFilterField(onlineForm);
if (StrUtil.isNotBlank(filterField)) {
try {
String resolved = this.resolveFilterFieldPlaceholders(filterField, TokenData.takeFromRequest());
Filter parsed = FilterParser.parse(resolved);
filter = filter.and(parsed);
} catch (Exception e) {
log.warn("tableWidget 默认过滤条件解析失败,跳过。filterField={}", filterField, e);
}
}
// 关联组件(402)配置的默认过滤条件,从 baseFormId 表单里匹配 onlineFormId == formId 的组件读取。
String relativeFilterField = this.getRelativeFormSortFilter().get("filterField");
if (StrUtil.isNotBlank(relativeFilterField)) {
try {
String resolved = this.resolveFilterFieldPlaceholders(relativeFilterField, TokenData.takeFromRequest());
Filter parsed = FilterParser.parse(resolved);
filter = filter.and(parsed);
} catch (Exception e) {
log.warn("关联组件默认过滤条件解析失败,跳过。filterField={}", relativeFilterField, e);
}
}
return filter;
}
@ -149,7 +192,7 @@ public class ListDataOrmService extends ListDataService { @@ -149,7 +192,7 @@ public class ListDataOrmService extends ListDataService {
*/
public int countGridData() {
OnlineTable masterTable = datasourceResult.getData().getMasterTable();
return ormDataSourceUtil.count(masterTable.getTableName(), buildFilter());
return ormDataSourceUtil.count(masterTable.getTableName(), buildFilter(this.getCurrentOnlineForm()));
}
/**
@ -160,7 +203,7 @@ public class ListDataOrmService extends ListDataService { @@ -160,7 +203,7 @@ public class ListDataOrmService extends ListDataService {
*/
public BigDecimal sumGridData(String sumColumn) {
OnlineTable masterTable = datasourceResult.getData().getMasterTable();
return ormDataSourceUtil.sum(masterTable.getTableName(), sumColumn, buildFilter());
return ormDataSourceUtil.sum(masterTable.getTableName(), sumColumn, buildFilter(this.getCurrentOnlineForm()));
}
/**
@ -179,6 +222,79 @@ public class ListDataOrmService extends ListDataService { @@ -179,6 +222,79 @@ public class ListDataOrmService extends ListDataService {
}
/**
* 读取表单 tableWidget 组件配置的默认排序字段props.sortField读取失败返回 null
*/
private String getTableWidgetSortField(OnlineForm onlineForm) {
return this.getTableWidgetConfig(onlineForm, "sortField");
}
/**
* 读取表单 tableWidget 组件配置的默认过滤条件props.filterField读取失败返回 null
*/
private String getTableWidgetFilterField(OnlineForm onlineForm) {
return this.getTableWidgetConfig(onlineForm, "filterField");
}
/**
* zz_online_form.widgetJson tableWidget.props 读取指定配置项
*/
private String getTableWidgetConfig(OnlineForm onlineForm, String key) {
if (onlineForm == null || StrUtil.isBlank(onlineForm.getWidgetJson())) {
return null;
}
return WidgetJsonUtil.getTableWidgetConfig(onlineForm.getWidgetJson(), key);
}
/**
* 取当前请求对应的在线表单count/sum 等无 widgetJson 入口时使用
*/
private OnlineForm getCurrentOnlineForm() {
return onlineFormService.getOnlineFormFromCache(dto.getFormId());
}
/**
* 读取关联组件402配置的默认排序/过滤 baseFormId 表单的 widgetJson 里匹配 onlineFormId == formId 的组件
*/
private Map<String, String> getRelativeFormSortFilter() {
if (baseFormId == null) {
return Collections.emptyMap();
}
OnlineForm baseForm = onlineFormService.getOnlineFormFromCache(baseFormId);
if (baseForm == null || StrUtil.isBlank(baseForm.getWidgetJson())) {
return Collections.emptyMap();
}
return WidgetJsonUtil.getRelativeOnlineFormSortFilter(baseForm.getWidgetJson(), dto.getFormId());
}
/**
* 解析 sortField SorterItem值带方向"field desc"/"field asc"则用之没带默认 desc
*/
private SorterItem buildSorterItemFromSortField(String sortField) {
String[] parts = sortField.trim().split("\\s+");
String fieldName = parts[0];
boolean asc = parts.length > 1 && "asc".equalsIgnoreCase(parts[1]);
SorterItem sorterItem = new SorterItem(fieldName);
sorterItem.setSortType(asc ? SortType._ASC : SortType._DESC);
return sorterItem;
}
/**
* 解析 filterField 表达式中的 ${字段名} 占位符取值转成带引号的字符串满足 FilterParser 值只接受字符串/null
* 兼容已带引号'${xxx}'与未带引号${xxx}两种存法
*/
private String resolveFilterFieldPlaceholders(String expression, TokenData tokenData) {
Matcher matcher = Pattern.compile("'?\\$\\{(\\w+)\\}'?").matcher(expression);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
Object value = BeanUtil.getProperty(tokenData, matcher.group(1));
String replacement = value == null ? "null" : "'" + value.toString().replace("'", "''") + "'";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 根据当前登录用户角色查询启用的数据规则并按当前表单匹配
* 兜底角色未绑定任何数据规则时返回空列表不做数据权限过滤
*/
@ -214,7 +330,11 @@ public class ListDataOrmService extends ListDataService { @@ -214,7 +330,11 @@ public class ListDataOrmService extends ListDataService {
if (!Objects.equals(rule.getFormHeadId(), onlFormHead.getId())) {
return false;
}
// 2. 再按 form_id_list 筛选
// 2. 基础数据权限:form_id_list 存的是「适用基础在线表单id」,由 buildFilter 按 baseFormId 匹配,这里不拦
if (DataRuleType.BASIC_DATA == rule.getRuleType()) {
return true;
}
// 3. 列表权限:再按 form_id_list 筛选目标表单
if (StrUtil.isBlank(rule.getFormIdList())) {
return true;
}
@ -225,6 +345,17 @@ public class ListDataOrmService extends ListDataService { @@ -225,6 +345,17 @@ public class ListDataOrmService extends ListDataService {
return StrUtil.split(rule.getFormIdList(), ',').stream().map(Long::valueOf).collect(Collectors.toSet()).contains(currentFormId);
}
/**
* 判断基础数据权限规则的 form_id_list逗号分隔集合适用基础在线表单id是否匹配请求的 baseFormId
* form_id_list 未配置或请求未传 baseFormId 时视为匹配兼容旧规则
*/
private boolean matchBaseFormId(String ruleFormIdList) {
if (StrUtil.isBlank(ruleFormIdList) || baseFormId == null) {
return true;
}
return StrUtil.split(ruleFormIdList, ',').stream().map(Long::valueOf).collect(Collectors.toSet()).contains(baseFormId);
}
public void getOrmSelector(JSONObject jsonObject, Set<String> selectorSet, OnlineTable masterTable, Map<String, Object> entryIdMap) {
Map<Long, OnlineColumn> columnMap = masterTable.getColumnMap();
JSONArray array = jsonObject.getJSONArray("childWidgetList");

2
common/common-online/src/main/java/apelet/common/online/abstractplugin/ListDataService.java

@ -38,6 +38,7 @@ public abstract class ListDataService { @@ -38,6 +38,7 @@ public abstract class ListDataService {
protected TraceParamDto traceParamDto;
protected OnlFormHead onlFormHead;
protected String metaCode;
protected Long baseFormId;
protected OrmDataSourceUtil ormDataSourceUtil;
@ -64,6 +65,7 @@ public abstract class ListDataService { @@ -64,6 +65,7 @@ public abstract class ListDataService {
datasourceResult =
(ResponseResult<OnlineDatasource>) listParams.get("datasourceResult");
metaCode = (String) listParams.get("metaCode");
baseFormId = (Long) listParams.get("baseFormId");
onlineFormService = ApplicationContextHolder.getBean("onlineFormService");
onlFormFieldService = ApplicationContextHolder.getBean("onlFormFieldServiceImpl");

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

@ -1424,4 +1424,22 @@ public class OnlineFormController { @@ -1424,4 +1424,22 @@ public class OnlineFormController {
return ResponseResult.success(formList);
}
@PostMapping("/queryListFormByFormName")
public ResponseResult<List<OnlineForm>> queryListFormByFormName(@MyRequestBody String formName) {
List<OnlineForm> formList = onlineFormService.queryByFormName(formName);
if (CollUtil.isEmpty(formList)) {
return ResponseResult.success(new ArrayList<>());
}
formList.forEach(item -> {
item.setWidgetJson(null);
item.setParamsJson(null);
item.setCreateTime(null);
item.setUpdateTime(null);
item.setCreateUserId(null);
item.setUpdateUserId(null);
});
return ResponseResult.success(formList);
}
}

100
common/common-online/src/main/java/apelet/common/online/controller/OnlineOperationController.java

@ -39,10 +39,13 @@ import apelet.common.online.model.constant.RelationType; @@ -39,10 +39,13 @@ import apelet.common.online.model.constant.RelationType;
import apelet.common.online.service.*;
import apelet.common.online.util.OnlineConstant;
import apelet.common.online.util.OnlineOperationHelper;
import apelet.common.online.util.WidgetJsonUtil;
import apelet.common.online.vo.OnlineEventPluginExecuteVo;
import apelet.common.orm.impl.*;
import apelet.common.orm.parser.FilterParser;
import apelet.common.redis.cache.SessionCacheHelper;
import apelet.common.redis.util.CommonRedisUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrFormatter;
@ -69,6 +72,8 @@ import java.io.IOException; @@ -69,6 +72,8 @@ import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@ -818,7 +823,8 @@ public class OnlineOperationController { @@ -818,7 +823,8 @@ public class OnlineOperationController {
@MyRequestBody String ignoreMaskFields,
@MyRequestBody TraceParamDto traceParamDto,
@MyRequestBody OnlineEventPluginExecuteDto onlineEventPluginExecuteDto,
@MyRequestBody String metaCode
@MyRequestBody String metaCode,
@MyRequestBody(required = true) Long baseFormId
) {
// 1. 验证数据源及其关联
ResponseResult<OnlineDatasource> datasourceResult =
@ -830,7 +836,7 @@ public class OnlineOperationController { @@ -830,7 +836,7 @@ public class OnlineOperationController {
if (!filterDtoListResult.isSuccess()) {
return ResponseResult.errorFrom(filterDtoListResult);
}
// 透传 metaCode 到 ListDataOrmService,用于权限规则类型过滤
// 透传 metaCode、baseFormId 到 ListDataOrmService,用于权限规则类型过滤及关联组件过滤排序
if (onlineEventPluginExecuteDto == null) {
onlineEventPluginExecuteDto = new OnlineEventPluginExecuteDto();
}
@ -840,6 +846,7 @@ public class OnlineOperationController { @@ -840,6 +846,7 @@ public class OnlineOperationController {
onlineEventPluginExecuteDto.setListParams(listParams);
}
listParams.put("metaCode", metaCode);
listParams.put("baseFormId", baseFormId);
OnlFormHead onlFormHead = onlFormHeadService.getFormHeadByDatasource(datasourceId);
GridData pluginData = this.exeListPlugin(formId,filterDtoList,orderParam,pageParam,
traceParamDto,onlFormHead,datasourceResult,onlineEventPluginExecuteDto
@ -1062,10 +1069,39 @@ public class OnlineOperationController { @@ -1062,10 +1069,39 @@ public class OnlineOperationController {
JSONObject jsonObject = (JSONObject) l;
getOrmSelector(jsonObject, selectorSet, masterTable, entryIdMap);
});
// 收集各分录组件配置的默认排序/过滤条件(pc/mobile 控件树,按 bindData.tableId 区分主表与分录表)。
Map<String, String> entryFilterFieldMap = new HashMap<>();
Map<String, String> entrySortFieldMap = new HashMap<>();
WidgetJsonUtil.collectSubTableSortFilter(widgetJson, masterTable.getTableId(),
tableId -> {
OnlineTable t = onlineTableService.getOnlineTableFromCache(tableId);
return t == null ? null : t.getTableName();
},
entryFilterFieldMap, entrySortFieldMap);
// 附表过滤(SQL 层):列名限定为 分录表名.列名,解析后拼接到查询条件。
for (Map.Entry<String, String> entry : entryFilterFieldMap.entrySet()) {
try {
String resolved = this.resolveFilterFieldPlaceholders(entry.getValue(), TokenData.takeFromRequest());
String qualified = this.qualifyProperties(resolved, entry.getKey());
filter = filter.and(FilterParser.parse(qualified));
} catch (Exception e) {
log.warn("附表过滤条件解析失败,跳过。tableName={}, filterField={}", entry.getKey(), entry.getValue(), e);
}
}
Selector selector = getSelector(selectorSet, masterTable,true);
// 附表排序(SQL 层):配置了 sortField 的分录表按 分录表名.字段 排序。
Sorter sorter = null;
if (!entrySortFieldMap.isEmpty()) {
sorter = new Sorter();
for (Map.Entry<String, String> entry : entrySortFieldMap.entrySet()) {
sorter.add(this.buildSorterItemFromSortField(entry.getValue(), entry.getKey()));
}
}
HashMap<String, Object> rowData = new HashMap<>();
HashMap<String, Object> listData = new HashMap<>();
ObjectCollection collection = ormGenDataSourceUtil.query(masterTable.getTableName(), filter, selector);
ObjectCollection collection = (sorter != null && sorter.size() > 0)
? ormGenDataSourceUtil.query(masterTable.getTableName(), filter, selector, sorter)
: ormGenDataSourceUtil.query(masterTable.getTableName(), filter, selector);
if (collection.isEmpty()) {
JSONObject jsonObject = new JSONObject();
rowData.put("id", id);
@ -1088,12 +1124,15 @@ public class OnlineOperationController { @@ -1088,12 +1124,15 @@ public class OnlineOperationController {
ObjectCollection entryCollection = (ObjectCollection) map.get(k);
List<Map<String, Object>> entryList = new ArrayList<>();
onlineOperationService.collectionToJson(entryCollection, entryList);
String sort = "seq";
entryList = entryList.stream().sorted(
Comparator.comparing(m -> m.containsKey(sort) && m.get(sort) != null && StringUtils.isNotBlank(m.get(sort).toString())
? Double.valueOf(m.get(sort).toString()) : null,
Comparator.nullsLast(Double::compareTo)))
.collect(Collectors.toList());
// 附表配置了 sortField 时已在 SQL 层排序,这里不再按 seq 内存排序。
if (!entrySortFieldMap.containsKey(k)) {
String sort = "seq";
entryList = entryList.stream().sorted(
Comparator.comparing(m -> m.containsKey(sort) && m.get(sort) != null && StringUtils.isNotBlank(m.get(sort).toString())
? Double.valueOf(m.get(sort).toString()) : null,
Comparator.nullsLast(Double::compareTo)))
.collect(Collectors.toList());
}
// 分录的附件上传/图片上传字段同样回填,online_table_id 用分录表自己的tableId。
Object entryTableId = entryIdMap.get(k);
if (entryTableId != null) {
@ -1172,6 +1211,49 @@ public class OnlineOperationController { @@ -1172,6 +1211,49 @@ public class OnlineOperationController {
}
/**
* 解析过滤表达式中的 ${字段名} 占位符取值转成带引号的字符串满足 FilterParser 值只接受字符串/null
* 兼容已带引号'${xxx}'与未带引号${xxx}两种存法
*/
public String resolveFilterFieldPlaceholders(String expression, TokenData tokenData) {
Matcher matcher = Pattern.compile("'?\\$\\{(\\w+)\\}'?").matcher(expression);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
Object value = BeanUtil.getProperty(tokenData, matcher.group(1));
String replacement = value == null ? "null" : "'" + value.toString().replace("'", "''") + "'";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 把过滤表达式中的列名限定为 表名.列名已带点限定的列跳过供附表 SQL 过滤使用
*/
public String qualifyProperties(String expression, String tableName) {
Pattern p = Pattern.compile("(^|[(]|\\b(?:and|or)\\s+)([A-Za-z_]\\w*)(?=\\s*(?:=|!=|<=|>=|<|>|like|not\\s+like|in|not\\s+in|exists|not\\s+exists|is\\s+null|is\\s+not\\s+null)\\b)");
Matcher m = p.matcher(expression);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, Matcher.quoteReplacement(m.group(1) + tableName + "." + m.group(2)));
}
m.appendTail(sb);
return sb.toString();
}
/**
* 解析 sortField SorterItem值带方向"field desc"/"field asc"则用之没带默认 desc可选加表名前缀
*/
public SorterItem buildSorterItemFromSortField(String sortField, String tablePrefix) {
String[] parts = sortField.trim().split("\\s+");
String fieldName = parts[0];
boolean asc = parts.length > 1 && "asc".equalsIgnoreCase(parts[1]);
String fullName = StrUtil.isBlank(tablePrefix) ? fieldName : tablePrefix + "." + fieldName;
SorterItem sorterItem = new SorterItem(fullName);
sorterItem.setSortType(asc ? SortType._ASC : SortType._DESC);
return sorterItem;
}
public Selector getSelector(Set<String> selectorSet, OnlineTable masterTable,boolean b) {
Selector selector = new Selector();
EntityTable entityTable = ormGenDataSourceUtil.getEntityTable(masterTable.getTableName());

9
common/common-online/src/main/java/apelet/common/online/service/OnlineFormService.java

@ -157,4 +157,13 @@ public interface OnlineFormService extends IBaseService<OnlineForm, Long> { @@ -157,4 +157,13 @@ public interface OnlineFormService extends IBaseService<OnlineForm, Long> {
* @see apelet.common.online.model.constant.FormType
*/
List<OnlineForm> queryByTableName(String tableName, int formType);
/**
* 根据表单名称查询表单
*
* @param formName 表单名称
* @return 表单
*/
List<OnlineForm> queryByFormName(String formName);
}

8
common/common-online/src/main/java/apelet/common/online/service/impl/OnlineFormServiceImpl.java

@ -518,6 +518,14 @@ public class OnlineFormServiceImpl extends BaseService<OnlineForm, Long> impleme @@ -518,6 +518,14 @@ public class OnlineFormServiceImpl extends BaseService<OnlineForm, Long> impleme
return Collections.emptyList();
}
@Override
public List<OnlineForm> queryByFormName(String formName) {
LambdaQueryWrapper<OnlineForm> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.likeRight(StringUtils.isNotBlank(formName), OnlineForm::getFormName, formName);
return onlineFormMapper.selectList(queryWrapper);
}
/**
* 设置关联表字段转换为对象
*

12
common/common-online/src/main/java/apelet/common/online/service/impl/OnlineOperationServiceImpl.java

@ -77,6 +77,7 @@ import javax.annotation.Resource; @@ -77,6 +77,7 @@ import javax.annotation.Resource;
import java.io.File;
import java.io.Serializable;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@ -696,7 +697,16 @@ public class OnlineOperationServiceImpl implements OnlineOperationService { @@ -696,7 +697,16 @@ public class OnlineOperationServiceImpl implements OnlineOperationService {
}else if(objectValue.get(string) == null){
jsonObject.put(string, "");
}else if(objectValue.get(string) instanceof Date){
jsonObject.put(string,DateTimeUtils.format((Date) objectValue.get(string) ,"yyyy-MM-dd"));
Date date = (Date) objectValue.get(string);
String timeStr = new SimpleDateFormat("HH:mm:ss").format(date);
String value = null;
// 判断时间是否为 00:00:00
if ("00:00:00".equals(timeStr)) {
value = DateTimeUtils.format(date, "yyyy-MM-dd");
} else {
value = DateTimeUtils.format(date, "yyyy-MM-dd HH:mm:ss");
}
jsonObject.put(string, value);
}else{
jsonObject.put(string, values.get(string));
}

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

@ -16,6 +16,7 @@ import java.util.List; @@ -16,6 +16,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* widgetJson 数据操作工具类
@ -96,6 +97,198 @@ public class WidgetJsonUtil { @@ -96,6 +97,198 @@ public class WidgetJsonUtil {
}
/**
* 读取 pc/mobile tableWidget 组件 props 中的配置项 sortField/filterField
* 优先 pcpc 未配置时回退 mobile与列表查询读取保持一致
*
* @param widgetJson 在线表单的 widgetJson
* @param key props 中的配置项 key
* @return 配置值widgetJson 为空或两端的 tableWidget/props 均不存在时返回 null
*/
public static String getTableWidgetConfig(String widgetJson, String key) {
if (StrUtil.isBlank(widgetJson) || StrUtil.isBlank(key)) {
return null;
}
try {
JSONObject root = JSON.parseObject(widgetJson);
String value = readTableWidgetConfig(root.getJSONObject("pc"), key);
if (StrUtil.isNotBlank(value)) {
return value;
}
return readTableWidgetConfig(root.getJSONObject("mobile"), key);
} catch (Exception e) {
return null;
}
}
private static String readTableWidgetConfig(JSONObject modeObj, String key) {
if (modeObj == null) {
return null;
}
JSONObject tableWidget = modeObj.getJSONObject("tableWidget");
if (tableWidget == null) {
return null;
}
JSONObject props = tableWidget.getJSONObject("props");
if (props == null) {
return null;
}
return props.getString(key);
}
/**
* 收集子表控件配置的默认排序/过滤条件props.sortField / props.filterField
* 递归遍历 pc/mobile 两端的 widgetList tableWidget.childWidgetList
* bindData.tableId != 主表 tableId 识别子表控件以子表物理表名为 key 回填两个 Map仅含非空配置
* 子表物理表名优先用 tableNameResolver 解析缺失时兜底 bindData.tableName
* 同一子表在 pc/mobile 均出现时以先遍历到的 pc 配置为准putIfAbsent
*
* @param widgetJson 在线表单的 widgetJson
* @param masterTableId 主表 tableId用于排除主表字段控件
* @param tableNameResolver 子表 tableId 物理表名 的解析函数可传 null
* @param filterFieldMap 输出子表物理表名 filterField
* @param sortFieldMap 输出子表物理表名 sortField
*/
public static void collectSubTableSortFilter(JSONObject widgetJson, Long masterTableId,
Function<Long, String> tableNameResolver,
Map<String, String> filterFieldMap, Map<String, String> sortFieldMap) {
if (widgetJson == null) {
return;
}
for (String mode : new String[]{"pc", "mobile"}) {
JSONObject modeObj = widgetJson.getJSONObject(mode);
if (modeObj == null) {
continue;
}
collectSubTableSortFilter(modeObj.getJSONArray("widgetList"), masterTableId, tableNameResolver, filterFieldMap, sortFieldMap);
JSONObject tableWidget = modeObj.getJSONObject("tableWidget");
if (tableWidget != null) {
collectSubTableSortFilter(tableWidget.getJSONArray("childWidgetList"), masterTableId, tableNameResolver, filterFieldMap, sortFieldMap);
}
}
}
private static void collectSubTableSortFilter(JSONArray widgetList, Long masterTableId,
Function<Long, String> tableNameResolver,
Map<String, String> filterFieldMap, Map<String, String> sortFieldMap) {
if (CollUtil.isEmpty(widgetList)) {
return;
}
for (int i = 0; i < widgetList.size(); i++) {
JSONObject widget = widgetList.getJSONObject(i);
if (widget == null) {
continue;
}
JSONArray childList = widget.getJSONArray("childWidgetList");
if (CollUtil.isNotEmpty(childList)) {
collectSubTableSortFilter(childList, masterTableId, tableNameResolver, filterFieldMap, sortFieldMap);
}
JSONObject bindData = widget.getJSONObject("bindData");
if (bindData == null || bindData.isEmpty() || !bindData.containsKey("tableId")) {
continue;
}
Long tableId = bindData.getLong("tableId");
if (tableId == null || tableId.equals(masterTableId)) {
continue;
}
JSONObject props = widget.getJSONObject("props");
if (props == null) {
continue;
}
String tableName = tableNameResolver == null ? null : tableNameResolver.apply(tableId);
if (StrUtil.isEmpty(tableName)) {
tableName = bindData.getString("tableName");
}
if (StrUtil.isEmpty(tableName)) {
continue;
}
String filterField = props.getString("filterField");
String sortField = props.getString("sortField");
if (StrUtil.isNotBlank(filterField)) {
filterFieldMap.putIfAbsent(tableName, filterField);
}
if (StrUtil.isNotBlank(sortField)) {
sortFieldMap.putIfAbsent(tableName, sortField);
}
}
}
/**
* 读取关联组件widgetType=402props.relativeTable.relativeFormType==6 onlineFormId 匹配上配置的默认排序/过滤
* 遍历 pc/mobile widgetList tableWidget.childWidgetList
*
* @param widgetJson 在线表单的 widgetJson
* @param targetFormId 目标在线表单id匹配 relativeTable.onlineFormId
* @return Mapkey sortField/filterField仅含非空项找不到返回空 map
*/
public static Map<String, String> getRelativeOnlineFormSortFilter(String widgetJson, Long targetFormId) {
Map<String, String> config = new HashMap<>();
if (StrUtil.isBlank(widgetJson) || targetFormId == null) {
return config;
}
try {
JSONObject root = JSON.parseObject(widgetJson);
for (String mode : new String[]{"pc", "mobile"}) {
JSONObject modeObj = root.getJSONObject(mode);
if (modeObj == null) {
continue;
}
collectRelativeOnlineFormSortFilter(modeObj.getJSONArray("widgetList"), targetFormId, config);
JSONObject tableWidget = modeObj.getJSONObject("tableWidget");
if (tableWidget != null) {
collectRelativeOnlineFormSortFilter(tableWidget.getJSONArray("childWidgetList"), targetFormId, config);
}
}
} catch (Exception e) {
// 忽略解析异常,返回已收集到的配置
}
return config;
}
private static void collectRelativeOnlineFormSortFilter(JSONArray widgetList, Long targetFormId, Map<String, String> config) {
if (CollUtil.isEmpty(widgetList)) {
return;
}
for (int i = 0; i < widgetList.size(); i++) {
JSONObject widget = widgetList.getJSONObject(i);
if (widget == null) {
continue;
}
JSONArray childList = widget.getJSONArray("childWidgetList");
if (CollUtil.isNotEmpty(childList)) {
collectRelativeOnlineFormSortFilter(childList, targetFormId, config);
}
Integer widgetType = widget.getInteger("widgetType");
if (widgetType == null || widgetType != 402) {
continue;
}
JSONObject props = widget.getJSONObject("props");
if (props == null) {
continue;
}
JSONObject relativeTable = props.getJSONObject("relativeTable");
if (relativeTable == null) {
continue;
}
Integer formType = relativeTable.getInteger("relativeFormType");
String onlineFormId = relativeTable.getString("onlineFormId");
if (formType == null || formType != 6 || StrUtil.isBlank(onlineFormId)) {
continue;
}
if (!targetFormId.toString().equals(onlineFormId)) {
continue;
}
String sortField = props.getString("sortField");
String filterField = props.getString("filterField");
if (StrUtil.isNotBlank(sortField)) {
config.putIfAbsent("sortField", sortField);
}
if (StrUtil.isNotBlank(filterField)) {
config.putIfAbsent("filterField", filterField);
}
}
}
/**
* 收集子表控件(widgetType=100) bindData.tableName 的名称集合
*
* @param widgetJson 在线表单的 widgetJson

Loading…
Cancel
Save