需求场景: 报表有个客户id字段, 每个业务人员负责一批客户(这个是动态的, 可能有不同批次), 业务人员需要在报表中筛选自己负责的某批客户. 因此期望筛选器的备选值是批次号, 表格真正刷新时, 是用该批次的客户id进行筛选。
名称: 查询前处理器
作用: 在查询执行前, 处理查询请求. 比如修改条件值.
生效对象: 仪表盘, 即席, 透视的所有组件取数.
包: Commons
路径: smartbix.query.handler
实现: IBaseQueryHandler 空接口
作用: 组件取数前, 对查询请求进行自定义处理, 如修改条件值.
名称 | 类型 | 说明 | |
输入参数 | context | QueryContext | 查询上下文, 包含查询ID, 报表ID, 报表类型, 查询请求. |
返回值 | 无 |
名称: 查询处理器
作用: 自定义组件查询的处理器. 比如自定义筛选器备选值. 一般不直接实现这个接口, 而是实现其抽象类, 减少开放工作量.
生效对象: 仪表盘, 即席, 透视的组件取数.
包: Commons
路径: smartbix.query.handler
作用: 获取查询请求
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | queryOption | IQueryOption | 查询请求, 包含查询条件, 查询字段, 排序, 私有字段, 分页, 数据来源等 |
作用: 执行查询请求, 并返回查询结果集
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | result | Object | 查询结果集, 不同组件查询结果集格式不同. 具体组件具体分析. |
名称: 仪表盘组件查询处理器器抽象类
作用: 仅为仪表盘自定义组件查询的处理器, 实现了ICustomExecutor中的getQueryOption方法, 仅需要补充refresh方法的实现即可.
生效对象: 仪表盘的组件取数
包: Page
路径: smartbix.page.executor2
详见ICustomExecutor
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | result | Object | 非树筛选器/参数 结果集格式: { data: [ [ value: Cell, display: Cell ], // display可以不存, 即 [value: Cell] [value2: Cell, display2: Cell], ... ] } Cell: { value: string | number, displayValue: string } |
树参数 结果集格式: { data: [ [value: Cell], [value2: Cell], .... ] } Cell: { value: string | number, displayValue: string, id: string, parentId: string } | |||
树筛选器 结果集格式: [ value: Cell, value2: Cell, ... ] Cell: { id: string, // 格式: parentId + '$$$^V^$$$' + value parentId: string, value: string, displayValue: string, levelId: string, // 值是该字段的uniqueId children: [Cell] } |
名称: 即席和透视的组件查询处理器抽象类
作用: 仅为即席和透视自定义组件查询的处理器, 实现了ICustomExecutor中的getQueryOption方法, 仅需要补充refresh方法的实现即可.
生效对象: 即席和透视的组件取数
包: ModelQuery
路径: smartbix.analysis.query
详见ICustomExecutor
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | result | Object | 非树筛选器/参数 结果集格式: { data: [value: Cell, value2: Cell, ...] } Cell: { value: string | number, displayValue: string } |
树参数 结果集格式: { data: [value: Cell, value2: Cell, ...] } Cell: { value: string | number, displayValue: string, id: string, parentId: string } | |||
树筛选器 结果集格式: [ value: Cell, value2: Cell, ... ] Cell: { id: string, // 格式: parentId + '$$$^V^$$$' + value parentId: string, value: string, displayValue: string, levelId: string, // 值是该字段的uniqueId children: [Cell] } |
名称: 查询处理器管理类
作用: 用于注册/注销 IBeforeQueryHandler和ICustomExecutor
生效对象: 仪表盘, 即席, 透视
包: Commons
路径: smartbix.query.handler
限制: 注册取数器时, 名称不能含双下划线, 不能与系统中存在的bean名称重复, 因此命名因该特殊些.
作用: 返回一个查询处理器管理类实例
作用: 注册组件查询处理器
名称 | 类型 | 说明 | |
输入参数 | executorName | String | 查询处理器名称, 不允许包含双下划线, 不允许与系统中任何bean命名重复, 因此实际命名时, 请多加限定词. |
executorClass | Class<? extends ICustomExcutor> | 查询处理器类 | |
返回值 | 无 | 注册失败, 会打印日志, 不会报错 |
作用: 注销组件查询处理器
名称 | 类型 | 说明 | |
输入参数 | executorName | String | 查询处理器名称 |
返回值 | succeeded | boolean | 当处理器存在且移除成功, 返回true |
作用: 注册组件查询前处理器
名称 | 类型 | 说明 | |
输入参数 | reportType | String | 报表类型, DETAILED_QUERY 即席查询 AD_HOC_ANALYSIS 透视分析 SMARTBIX_PAGE 仪表盘 |
handler | IBaseQueryHandler | 基础查询处理器的实现类, 如IBeforeQueryHandler | |
返回值 | 无 |
作用: 注销组件查询前处理器
名称 | 类型 | 说明 | |
输入参数 | reportType | String | 报表类型, DETAILED_QUERY 即席查询 AD_HOC_ANALYSIS 透视分析 SMARTBIX_PAGE 仪表盘 |
handler | IBaseQueryHandler | 基础查询处理器的实现类, 如IBeforeQueryHandler | |
返回值 | succeeded | boolean | 处理器存在且注销成功, 则返回true |
名称: 查询上下文
作用: 存储了当前查询的上下文, 包括报表ID, 报表类型, 查询请求, 查询ID
生效对象: 仪表盘, 即席, 透视的组件查询前处理器
包: Commons
路径: smartbix.query.handler
作用: 返回查询ID
作用: 返回报表ID
作用: 返回报表类型, DETAILED_QUERY 即席查询 AD_HOC_ANALYSIS 透视分析 SMARTBIX_PAGE 仪表盘
作用: 返回查询请求
名称: 查询请求
作用: 用于描述组件查询. 包括筛选器/参数搜索时的key, 查询条件, 私有字段, 分页信息, 取数字段, 数据来源, 排序.
生效对象: 仪表盘, 即席, 透视的组件查询前处理器
包: Commons
路径: smartbix.query.handler
作用: 搜索key, 仅针对筛选器和参数的查询接口.
作用: 获取查询条件
作用: 获取私有字段列表
作用: 获取查询字段
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | queryFields | List<IQueryField> | // 参数查询接口, 格式 [{ name: '参数在数据模型中的名称' }] // 其它有字段的查询接口: 格式 [{ id, name, alias, desc, type, ... }] |
作用: 获取数据来源定义
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | dataSource | IDataSource | IDataSource 格式: { id: String, type: String } |
作用: 获取分页信息
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | pagination | Pagination | Pagination 格式: { num: int, size: int }, num >= 0 |
作用: 获取行排序. 通用组件排序都在这里. 但目前只有仪表盘组件支持, 即席透视未支持. 即席透视需要从queryField.orderBy中获取
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | rowQuerySorts | List<IQuerySort> | 行排序 |
作用: 获取列排序
名称: 查询排序
作用: 定义字段排序设置
生效对象: 仪表盘组件查询, (即席透视待支持)
包: Commons
路径: smartbix.query
作用: 获取排序方式
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | sortDirection | SortDirection | 排序方式: ASC 升序, BASC 全局升序, DESC 降序, BDESC 全局降序 |
作用: 获取排序字段
作用: 获取自定义成员排序的成员顺序
作用: 获取排序依据, 如果不存在, 排序字段就是排序依据
作用: 获取排序优先级, 数字越大越优先
作用: 获取表头排序时该列的表头路径
名称: 查询条件
作用: 用于统一查询条件, 所有类型的查询条件都要继承它
生效对象: 仪表盘, 即席, 透视的查询条件
包: Commons
路径: smartbix.query.handler
作用: 判断该条件是否可忽略. 不工作的条件即可忽略, 如带等于操作符的无条件值的字段条件
作用: 获取条件类型
名称 | 类型 | 说明 | |
输入参数 | 无 | ||
返回值 | nodeType | QueryConditionNodeType | 条件类型: RELATION 关系, FIELD_FILTER 字段条件, PARAM_FILTER 参数条件, NONE_FILTER 表达式条件 |
名称: 字段查询条件
作用: 筛选字段值, 继承了IQueryCondition. 来源于字段条件
生效对象: 仪表盘, 即席, 透视的组件查询条件
包: Commons
路径: smartbix.query.handler
作用: 获取比较运算符.
作用: 设置比较运算符
作用: 获取条件值
作用: 设置条件值
作用: 获取筛选字段
作用: 设置筛选字段
名称: 参数查询条件
作用: 筛选参数值, 继承了IQueryCondition, 来源于参数条件
生效对象: 仪表盘, 即席, 透视的组件查询条件
包: Commons
路径: smartbix.query.handler
作用: 获取数据模型参数id, 不一定存在
作用: 获取数据模型参数名称
作用: 获取参数别名, 不一定存在
作用: 获取参数查询条件的值
作用: 设置参数查询条件的值
名称: 表达式条件
作用: 直接使用条件值和比较运算符进行比较, 从而筛选查询结果集. 继承了IQueryCondition
生效对象: 仪表盘树状表的组件查询条件
包: Commons
路径: smartbix.query.handler
作用: 获取条件值, 值必须是两个
作用: 设置条件值, 值必须是两个
作用: 获取比较运算符.(条件第一个值和第二个值比较)
作用: 设置比较运算符(条件第一个值和第二个值比较)
名称: 关系查询条件
作用: 使用OR AND NOR关系组织条件, 做复杂筛选
生效对象: 仪表盘, 即席, 透视的组件查询条件
包: Commons
路径: smartbix.query.handler
作用: 获取条件关系, OR 或, AND 与, NOR 非
作用: 设置条件关系
作用: 获取子条件
作用: 设置子条件
自定义ICustomExecutor, 需要指定查询的executorName, 这一步骤需要前端二开实现.
名称: 仪表盘 或 即席 或 透视 在筛选器初始化时的二开接口的第一个入参
作用: 筛选器和参数的二开接口调用
作用: 设置筛选器查询时的查询器名称
项目 | 说明 |
Commons | 提供IBeforeQueryHandler接口, 用于组件取数前修改查询请求(比如条件值) 提供ICustomExecutor接口, 用于定义组件取数器 提供QueryHandlerManger管理器, 用于注册ICustomExecutor和IBeforeQueryHandler 提供QueryCondtionUtil工具类, 用于修改组件取数请求的条件值 |
Framework.interface | 提供IModule接口, 用于扩展包激活时, 注册组件取数执行器, 组件取数前处理器 提供IShutdownHook接口, 用于扩展包卸载时, 注销组件取数执行器, 组件取数前处理器 |
ModelQuery | 提供即席透视的组件取数器的抽象实现smartbix.analysis.query.AbstractCustomExecutor 想要自定义即席透视组件的取数器时, 需要继承该类 |
Page | 提供仪表盘的组件取数器的抽象实现smartbix.page.executor2.AbstractCustomExecutor 想要自定义仪表盘组件的取数器时, 需要继承该类 |
SmartbiVLibManager | 提供ObjectNode和ArrayNode, 用于包装取数器结果 |
更完整的用例, 请访问扩展包http://10.10.201.35:8888/RD/Extensions的 XPlayWrightExtensionTemplate 项目
1. 新建筛选器取数器, 用于自定义筛选器的备选值
package smartbi.smartbix.extension.custom.analysis; import smartbi.smartbix.extension.custom.StandbyValueProvider; import smartbix.analysis.query.AbstractCustomExecutor; /** * 即席透视列表筛选器(参数)取数器(命名不允许有双下划线) */ public class CustomPortletExecutor extends AbstractCustomExecutor { @Override public Object refresh() { String keyword = this.getQueryOption().getKeyword(); return StandbyValueProvider.getStandbyValue(keyword); } } |
package smartbi.smartbix.extension.custom; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import smartbix.util.SmartbiXObjectMapper; import smartbixlibs.com.fasterxml.jackson.databind.node.ArrayNode; import smartbixlibs.com.fasterxml.jackson.databind.node.ObjectNode; public final class StandbyValueProvider { private StandbyValueProvider() { } /** * 备选值 * @param keyword 搜索关键词 * @return 备选值 */ public static ObjectNode getStandbyValue(String keyword) { List<String> values = getRealValueList(keyword); ObjectNode result = SmartbiXObjectMapper.getInstance().createObjectNode(); ArrayNode data = result.putArray("data"); values.stream().forEach(v -> { ObjectNode col = data.addObject(); col.put("value", v); col.put("displayValue", v); }); return result; } private static List<String> getRealValueList(String keyword) { List<String> values = new ArrayList<>(); values.add("CUSTOM_X北_CUSTOM"); values.add("华南"); values.add("华东"); values.add("西南"); if (keyword == null || "".equals(keyword)) { return values; } return values.stream().filter(v -> v.indexOf(keyword) >= 0) .collect(Collectors.toList()); } } |
2. 新建查询前处理器, 用于修改被该筛选器影响的组件的条件值(比如批次号替换为一系列客户id)
package smartbi.smartbix.extension.custom; import java.util.ArrayList; import java.util.List; import smartbix.query.handler.IBeforeQueryHandler; import smartbix.query.handler.IQueryFieldConditionNode; import smartbix.query.handler.IQueryParamConditionNode; import smartbix.query.handler.QueryConditionUtil; import smartbix.query.handler.QueryContext; /** * 组件查询前处理器 */ public class BeforeQueryHandler implements IBeforeQueryHandler { @Override public void before(QueryContext context) { QueryConditionUtil.handleCondition(context.getQueryOption().getQueryCondition(), (condition) -> { if (condition instanceof IQueryFieldConditionNode) { IQueryFieldConditionNode node = (IQueryFieldConditionNode) condition; node.setValues(processConditionValues(node.getValues())); } else if (condition instanceof IQueryParamConditionNode) { IQueryParamConditionNode node = (IQueryParamConditionNode) condition; node.setValues(processConditionValues(node.getValues())); } return condition; }); } private List<Object> processConditionValues(List<Object> oldValues) { List<Object> newValues = new ArrayList<>(); oldValues.forEach(v -> { if ("CUSTOM_X北_CUSTOM".equals(v)) { newValues.add("华北"); newValues.add("东北"); newValues.add("西北"); } else { newValues.add(v); } }); return newValues; } } |
3. 将上面两个处理器注册
package smartbi.smartbix.extension.custom; import smartbi.framework.IModule; import smartbi.framework.IShutdownHook; import smartbix.query.handler.QueryHandlerManager; /** * 自定义取数器Module */ public class CustomExecutorModule implements IModule, IShutdownHook { private static CustomExecutorModule instance = new CustomExecutorModule(); private BeforeQueryHandler handler = new BeforeQueryHandler(); /** * @return CustomExecutorModule */ public static CustomExecutorModule getInstance() { return instance; } @Override public void shutdown() { QueryHandlerManager.getInstance().remove("DETAILED_QUERY", handler); QueryHandlerManager.getInstance().remove("AD_HOC_ANALYSIS", handler); QueryHandlerManager.getInstance().removeExecutor("Custom_Portlet_Executor"); } @Override public void activate() { QueryHandlerManager.getInstance().add("DETAILED_QUERY", handler); QueryHandlerManager.getInstance().add("AD_HOC_ANALYSIS", handler); QueryHandlerManager.getInstance().addExecutor("Custom_Portlet_Executor", smartbi.smartbix.extension.custom.analysis.CustomPortletExecutor.class); } } |
4. 前端二开设置筛选器取数时, 使用自定义的取数器
// 透视 this.on(AD_HOC_FILTER_ON_INIT, (filter, iAdHocAnalysis) => { filter.setQueryType('Custom_Portlet_Executor') }) |