|
|
|
@ -13,6 +13,7 @@ import apelet.common.online.model.constant.FieldFilterType; |
|
|
|
import apelet.common.online.model.constant.RelationType; |
|
|
|
import apelet.common.online.model.constant.RelationType; |
|
|
|
import apelet.common.orm.impl.*; |
|
|
|
import apelet.common.orm.impl.*; |
|
|
|
import apelet.common.orm.parser.FilterParser; |
|
|
|
import apelet.common.orm.parser.FilterParser; |
|
|
|
|
|
|
|
import apelet.common.online.util.WidgetJsonUtil; |
|
|
|
import cn.hutool.core.bean.BeanUtil; |
|
|
|
import cn.hutool.core.bean.BeanUtil; |
|
|
|
import cn.hutool.core.collection.CollUtil; |
|
|
|
import cn.hutool.core.collection.CollUtil; |
|
|
|
import cn.hutool.core.util.ReUtil; |
|
|
|
import cn.hutool.core.util.ReUtil; |
|
|
|
@ -20,9 +21,12 @@ import cn.hutool.core.util.StrUtil; |
|
|
|
import com.alibaba.fastjson.JSON; |
|
|
|
import com.alibaba.fastjson.JSON; |
|
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.util.*; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
import java.util.regex.Matcher; |
|
|
|
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -32,6 +36,7 @@ import java.util.stream.Collectors; |
|
|
|
* @version 1.0 |
|
|
|
* @version 1.0 |
|
|
|
* Create by 2024/10/24 10:46 |
|
|
|
* Create by 2024/10/24 10:46 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
@Slf4j |
|
|
|
public class ListDataOrmService extends ListDataService { |
|
|
|
public class ListDataOrmService extends ListDataService { |
|
|
|
public ListDataOrmService(OnlineEventPluginExecuteDto dto) { |
|
|
|
public ListDataOrmService(OnlineEventPluginExecuteDto dto) { |
|
|
|
super(dto); |
|
|
|
super(dto); |
|
|
|
@ -76,20 +81,34 @@ public class ListDataOrmService extends ListDataService { |
|
|
|
JSONObject widgetList = widgetJson.getJSONObject("pc").getJSONObject("tableWidget"); |
|
|
|
JSONObject widgetList = widgetJson.getJSONObject("pc").getJSONObject("tableWidget"); |
|
|
|
Set<String> selectorSet = new TreeSet<>(); |
|
|
|
Set<String> selectorSet = new TreeSet<>(); |
|
|
|
getOrmSelector(widgetList, selectorSet, masterTable, new HashMap<>()); |
|
|
|
getOrmSelector(widgetList, selectorSet, masterTable, new HashMap<>()); |
|
|
|
Filter filter = buildFilter(); |
|
|
|
Filter filter = buildFilter(onlineForm); |
|
|
|
|
|
|
|
|
|
|
|
Sorter sorter = new Sorter(); |
|
|
|
Sorter sorter = new Sorter(); |
|
|
|
if (orderParam != null) { |
|
|
|
// 排序:前端传了排序 → 按前端排(保留 create_time 兜底);没传且表单配了 sortField → 用它(值带方向则解析,默认 desc);否则 create_time DESC 兜底。
|
|
|
|
|
|
|
|
if (CollUtil.isNotEmpty(orderParam)) { |
|
|
|
for (MyOrderParam.OrderInfo orderInfo : orderParam) { |
|
|
|
for (MyOrderParam.OrderInfo orderInfo : orderParam) { |
|
|
|
SorterItem sorterItem = new SorterItem(orderInfo.getFieldName()); |
|
|
|
SorterItem sorterItem = new SorterItem(orderInfo.getFieldName()); |
|
|
|
sorterItem.setSortType(orderInfo.getAsc() ? SortType._ASC : SortType._DESC); |
|
|
|
sorterItem.setSortType(orderInfo.getAsc() ? SortType._ASC : SortType._DESC); |
|
|
|
sorter.add(sorterItem); |
|
|
|
sorter.add(sorterItem); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (!sorter.startsWithKey("create_time")) { |
|
|
|
if (!sorter.startsWithKey("create_time")) { |
|
|
|
SorterItem sorterItem = new SorterItem("create_time"); |
|
|
|
SorterItem sorterItem = new SorterItem("create_time"); |
|
|
|
sorterItem.setSortType(SortType._DESC); |
|
|
|
sorterItem.setSortType(SortType._DESC); |
|
|
|
sorter.add(sorterItem); |
|
|
|
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(); |
|
|
|
Selector selector = new Selector(); |
|
|
|
selectorSet.forEach(f -> selector.getList().add(new SelectorItem(f))); |
|
|
|
selectorSet.forEach(f -> selector.getList().add(new SelectorItem(f))); |
|
|
|
@ -115,14 +134,16 @@ public class ListDataOrmService extends ListDataService { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 构建列表查询过滤条件:用户过滤条件 + 数据权限规则(与 loadGridData 共用)。 |
|
|
|
* 构建列表查询过滤条件:用户过滤条件 + 数据权限规则(与 loadGridData 共用)。 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private Filter buildFilter() { |
|
|
|
private Filter buildFilter(OnlineForm onlineForm) { |
|
|
|
// 根据当前用户角色 + 当前表单匹配权限规则:非空→基础数据权限,为空→列表权限
|
|
|
|
// 根据当前用户角色 + 当前表单匹配权限规则:非空→基础数据权限,为空→列表权限
|
|
|
|
List<PermissionDataRuleSchema> ruleSchemaList = this.getRuleSchemaListByCurrentRole(); |
|
|
|
List<PermissionDataRuleSchema> ruleSchemaList = this.getRuleSchemaListByCurrentRole(); |
|
|
|
String conditionExpression = null; |
|
|
|
String conditionExpression = null; |
|
|
|
if (CollUtil.isNotEmpty(ruleSchemaList)) { |
|
|
|
if (CollUtil.isNotEmpty(ruleSchemaList)) { |
|
|
|
List<PermissionDataRuleSchema> filtered = new ArrayList<>(); |
|
|
|
List<PermissionDataRuleSchema> filtered = new ArrayList<>(); |
|
|
|
if (StrUtil.isNotBlank(metaCode)) { |
|
|
|
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)) { |
|
|
|
if (CollUtil.isEmpty(filtered)) { |
|
|
|
filtered = ruleSchemaList.stream().filter(s -> DataRuleType.LIST == s.getRuleType()).collect(Collectors.toList()); |
|
|
|
filtered = ruleSchemaList.stream().filter(s -> DataRuleType.LIST == s.getRuleType()).collect(Collectors.toList()); |
|
|
|
@ -139,6 +160,28 @@ public class ListDataOrmService extends ListDataService { |
|
|
|
Filter parsed = FilterParser.parse(conditionExpression); |
|
|
|
Filter parsed = FilterParser.parse(conditionExpression); |
|
|
|
filter = filter.and(parsed); |
|
|
|
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; |
|
|
|
return filter; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -149,7 +192,7 @@ public class ListDataOrmService extends ListDataService { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public int countGridData() { |
|
|
|
public int countGridData() { |
|
|
|
OnlineTable masterTable = datasourceResult.getData().getMasterTable(); |
|
|
|
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 { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public BigDecimal sumGridData(String sumColumn) { |
|
|
|
public BigDecimal sumGridData(String sumColumn) { |
|
|
|
OnlineTable masterTable = datasourceResult.getData().getMasterTable(); |
|
|
|
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 { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|
|
|
|
* 读取表单 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 { |
|
|
|
if (!Objects.equals(rule.getFormHeadId(), onlFormHead.getId())) { |
|
|
|
if (!Objects.equals(rule.getFormHeadId(), onlFormHead.getId())) { |
|
|
|
return false; |
|
|
|
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())) { |
|
|
|
if (StrUtil.isBlank(rule.getFormIdList())) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -225,6 +345,17 @@ public class ListDataOrmService extends ListDataService { |
|
|
|
return StrUtil.split(rule.getFormIdList(), ',').stream().map(Long::valueOf).collect(Collectors.toSet()).contains(currentFormId); |
|
|
|
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) { |
|
|
|
public void getOrmSelector(JSONObject jsonObject, Set<String> selectorSet, OnlineTable masterTable, Map<String, Object> entryIdMap) { |
|
|
|
Map<Long, OnlineColumn> columnMap = masterTable.getColumnMap(); |
|
|
|
Map<Long, OnlineColumn> columnMap = masterTable.getColumnMap(); |
|
|
|
JSONArray array = jsonObject.getJSONArray("childWidgetList"); |
|
|
|
JSONArray array = jsonObject.getJSONArray("childWidgetList"); |
|
|
|
|