自定义筛选器插件开发指南
1. 概述
自定义筛选器用于扩展筛选器的交互形式,需要通过插件代码的形式提交。只要插件代码中通过 OpenSDK 向 BI 注册了自定义筛选器,在仪表板中新建筛选器时就可以选择和配置自定义筛选器。
本文将通过多选表格筛选器的案例来指导大家如何编写自定义筛选器插件代码。
目前自定义筛选器仅支持选择筛选器。
2. 使用指导
观远提供自定义筛选器插件代码模板,您可通过插件代码模板进行拓展开发。
自定义筛选器插件开发操作步骤如下:
- 参照插件代码模板编写组件基础结构
- 基于WebComponent 和 Lit 框架,实现组件渲染
- 通过 BI 提供的方法和属性,进行数据加载
- 用户操作后,将指定格式的筛选条件提交给 BI
- 完成配置表单的 Schema 编写,以及应用用户在配置表单中填写的值
- 补充操作细节,完整代码
3. 开发案例:多选表格交互筛选器
本章将通过代码示例展示如何通过筛选器插件能力来开发一个多选表格筛选器。
需要实现的功能
- 将【使用字段】中的所有字段都列在表格中并按行勾选,可勾选多行,每行的【联动字段】联合起来作为筛选条件;
- 数据量较大时可以分页,每页的行数可以在配置筛选器时由用户自行配置。
筛选器配置

筛选器使用效果

代码示例
步骤一:编写组件基础结构
这部分内容基于插件代码模板扩展,包含了:
-
基于 Web Component 和 Lit 框架的筛选器组件
MultiSelectTable; -
加载 Lit、Shoelace 等所需资源,注册 Web Component;
- 资源加载方式和注册时机可按需调整;
- Shoelace 的组件有自动的按需加载功能,
<sl-element>初次渲染时会自动发送请求拉取一些代码。正常使用无需注意,但在其他 shadow root 内部是不会生效,所以插件需要手动调用一下shoelace-autoloader内的 discover 方法,详细信息见这里; - discover 需要注意调用时机。如果有些 Shoelace 组件仅当有数据时才会渲染,可能会错过首次渲染的 discover 时间点;开发时可以考虑多次调用
shoelaceAutoloader.discover,或者额外添加一个display: none的元素供 discover 使用; - Shoelace 组件按需加载时会动一下,可以适当给一个 CSS 样式遮挡,参考这里;
-
通过注册自定义筛选器
GD.registerCustomSelector向 BI 注册插件,注册时请注意:
const registerMultiSelectTable = async () => {
// 加载必要的资源
await GD.asyncLoadScript(GD.getResourceUrl('lit'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-light'), { tagName: 'link' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-dark'), { tagName: 'link' })
const { LitElement, html, css } = window.lit
const { discover } = window.shoelaceAutoloader || {}
// 定义 Web Component 类
class MultiSelectTable extends LitElement {
static properties = {
// 联动字段,选择筛选器中只有一个联动字段
linkColumns: { type: Array },
// 显示字段,只有设置了显示字段才会有值
displayColumns: { type: Array },
// 所有字段,该数据集的所有字段
allColumns: { type: Array },
// 获取明细表数据
fetchData: { type: Function },
// 获取单个字段的可选值列表
fetchFieldValues: { type: Function },
// 获取多个字段的可选值列表
fetchTreeValues: { type: Function },
// 输出筛选值,类型为选择筛选器,需按照选择筛选器的格式返回
onConfirm: { type: Function },
// 初始化筛选值,类型和 onConfirm 参数一致
initialFilterValue: { type: Array },
// 初始化显示字段的值 只有设置了显示字段才会有值
initialDisplayValue: { type: Array },
// 自定义配置
customConfig: { type: Object },
// 使用字段
columns: { type: Array },
// 分页属性
pageSize: { type: Number },
currentPage: { type: Number },
total: { type: Number },
};
constructor() {
super();
// 初始化属性
this.linkColumns = [];
this.displayColumns = [];
this.allColumns = [];
this.fetchData = null;
this.onConfirm = null;
this.initialFilterValue = [];
this.initialDisplayValue = [];
this.pageSize = 10;
this.currentPage = 1;
this.total = 0;
this.data = [];
this.customConfig = {};
this.columns = [];
// 用于存储选中的数据
this._selectedData = new Map();
}
static styles = css`
/* 基本样式定义 */
table {
width: 100%;
border-collapse: collapse;
}
/* ... */
`;
// 生命周期方法:组件首次更新
firstUpdated() {
super.firstUpdated()
// 加载初始数据
this.refreshData()
// 激活 Shoelace 组件
discover?.(this.shadowRoot)
}
// 组件渲染方法
render() {
// 渲染实现将在后续步骤添加
return html``;
}
}
// 注册 Web Component
customElements.define('multi-select-table', MultiSelectTable);
}
// 配置表单定义
const configSchema = []
// 注册插件
GD.registerCustomSelector({
id: 'multi-select-table-selector',
title: '多选表格筛选器',
tagName: 'multi-select-table',
desc: '通过表格展示数据,支持多选的筛选器',
configFormSchema: configSchema,
load: registerMultiSelectTable
})
步骤二:实现表格渲染
- 使用 Lit 框架时,组件渲染由 render 方法负责,表格渲染的主体部分在这里实现;
- 由于在代码开头已经引用了 Lit 和 Shoelace ,这里可以使用
html``模板语法、@sl-change等 Lit 语法特性,以及<sl-checkbox>等 Shoelace 组件。
render() {
const totalPages = Math.ceil(this.total / this.pageSize);
return html`
<div>
<table>
<thead>
<tr>
<th>
<sl-checkbox
?checked="${this.isCurrentPageAllSelected()}"
@sl-change="${this.handleSelectAll}"
></sl-checkbox>
</th>
${this.columns.map((col) => html`
<th>${col.name}</th>
`)}
</tr>
</thead>
<tbody>
${this.data.map((item, index) => {
const globalIndex = (this.currentPage - 1) * this.pageSize + index;
return html`
<tr>
<td>
<sl-checkbox
?checked="${this._selectedData.has(globalIndex)}"
@sl-change="${(e) => this.handleCheckboxChange(e, item, globalIndex)}"
></sl-checkbox>
</td>
${this.columns.map((col, colIndex) => html`
<td>${item[colIndex]}</td>
`)}
</tr>
`;
})}
</tbody>
</table>
<div class="pagination">
<sl-button
?disabled="${this.currentPage === 1}"
@click="${() => this.handlePageChange(this.currentPage - 1)}"
>上一页</sl-button>
<span>第 ${this.currentPage} 页,共 ${totalPages} 页</span>
<sl-button
?disabled="${this.currentPage === totalPages}"
@click="${() => this.handlePageChange(this.currentPage + 1)}"
>下一页</sl-button>
</div>
<div class="actions">
<sl-button variant="primary" @click="${this.handleSubmit}">确定</sl-button>
</div>
</div>
`;
}
步骤三:实现数据加载功能
为了获取表格明细数据,这里需要使用 fetchData 方法 请求数据,再读取所有字段 allColumns 和初始化联动条件 initialFilterValue 等属性来将数据写入到组件状态中。
这些在组件中可访问的属性和方法的细节可以在这里查阅。
async refreshData() {
if (!this.fetchData) return;
try {
const offset = (this.currentPage - 1) * this.pageSize;
const result = await this.fetchData({
limit: this.pageSize,
offset: offset
});
// 更新总数据量
this.total = result.rowCount || 0;
// 映射数据列
const columnIndexMap = this.columns.map(targetCol =>
result.columns.findIndex(col => col.fdId === targetCol.fdId)
);
// 根据映射重组数据
this.data = result.data.map(row =>
columnIndexMap.map(index => index >= 0 ? row[index] : '')
);
// 解析 initialFilterValue,处理初始值
const linkedIndex = this.columns.findIndex(col => col.fdId === this.linkColumns[0].fdId);
this.data.forEach((item, idx) => {
if (this.initialFilterValue.includes(item[linkedIndex])) {
this._selectedData.set(offset + idx, item);
}
});
this.requestUpdate();
} catch (error) {
console.error('获取数据失败:', error);
}
}
步骤四:处理筛选条件提交
由于功能需要满足多行勾选 + 多字段,最终生成的筛选条件格式也很复杂,这里需要有一段代码来处理表格选中数据和输出数据结构(组合筛选器格式)相互格式转换。
最终会使用 onConfirm 方法来提交当前组合好的筛选条件。
// 处理提交按钮点击
handleSubmit() {
// 获取所有选中行的数据
const selectedData = Array.from(this._selectedData.values()).map(selectedItem => {
return this.linkColumns.map(col => {
const colIndex = this.columns.findIndex(allCol => allCol.fdId === col.fdId);
return colIndex >= 0 ? selectedItem[colIndex] : '';
});
});
// 对数据进行去重
const uniqueSelectedData = /* 数据去重逻辑 */;
const filterValue = [];
const displayValue = [];
uniqueSelectedData.forEach(res => {
filterValue.push(res[0])
if (res.length === 2) {
displayValue.push(res[1])
}
})
// 调用外部传入的 onConfirm
if (this.onConfirm) {
const otherState = this.displayColumns.length > 0 ? { displayValue } : {}
this.onConfirm(filterValue, otherState);
}
}
// 生成随机ID (用于筛选条件)
generateId(length = 6) {
// ...
}
步骤五:完成配置表单定义
- 使用方法和可视化插件的图表配置项一致;
- 基于一个约定式的配置描述,产出一个可交互的UI,用于构建目标对象;
- 在插件开发中用于生成插件配置,也可以用于展示一些提示信息。
// 配置表单定义
const configSchema = [
{
fieldName: 'pageSize',
label: '每页显示条数',
type: "NUMBER",
defaultValue: 10,
placeholder: '请输入每页显示的数据条数',
rules: [
{
required: true,
message: '请输入每页显示的数据条数'
},
{
type: 'number',
min: 1,
max: 100,
message: '每页显示条数需在1-100之间'
}
]
},
{
type: 'FIELDS_SELECT',
fieldName: 'tableFields',
label: '使用字段',
model: {
single: false,
}
}
]
拓展组件
此拓展组件仅在自定义筛选器中可用,若在可视化插件中使用不生效。
选择数据集字段的Select
需要定义type为 FIELDS_SELECT,其他配置参照SELECT就行,选中的信息会包含name、fdId、fdType
const legoDefs = [
{
type: 'FIELDS_SELECT',
fieldName: 'tFields',
label: 'xxx字段',
model: {
single: true, // 表示单选,不定义则为多选。
}
}
]
选中的配置会在customConfig中传入,结构如下:
const customConfig = {
...,
tFields: [
{ name: '字段名称', fdId: 'xxxx', fdType: 'xxx' },
...
]
}
步骤六:补充操作细节,输出完整代码
const registerMultiSelectTable = async () => {
// 加载必要的资源
await GD.asyncLoadScript(GD.getResourceUrl('lit'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-light'), { tagName: 'link' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-dark'), { tagName: 'link' })
const { LitElement, html, css } = window.lit
const { discover } = window.shoelaceAutoloader || {}
// 定义 Web Component 类
class MultiSelectTable extends LitElement {
static properties = {
// 联动字段,选择筛选器中只有一个联动字段
linkColumns: { type: Array },
// 显示字段,只有设置了显示字段才会有值
displayColumns: { type: Array },
// 所有字段,该数据集的所有字段
allColumns: { type: Array },
// 获取明细表数据
fetchData: { type: Function },
// 获取单个字段的可选值列表
fetchFieldValues: { type: Function },
// 获取多个字段的可选值列表
fetchTreeValues: { type: Function },
// 输出筛选值,类型为选择筛选器,需按照选择筛选器的格式返回
onConfirm: { type: Function },
// 初始化筛选值,类型和 onConfirm 参数一致
initialFilterValue: { type: Array },
// 初始化显示字段的值 只有设置了显示字段才会有值
initialDisplayValue: { type: Array },
// 自定义配置
customConfig: { type: Object },
// 使用字段
columns: { type: Array },
// 分页属性
pageSize: { type: Number },
currentPage: { type: Number },
total: { type: Number },
};
constructor() {
super();
// 初始化属性
this.linkColumns = [];
this.displayColumns = [];
this.allColumns = [];
this.fetchData = null;
this.fetchFieldValues = null;
this.fetchTreeValues = null;
this.onConfirm = null;
this.initialFilterValue = [];
this.initialDisplayValue = [];
this.customConfig = {};
this.pageSize = 10;
this.currentPage = 1;
this.total = 0;
this.data = [];
this.columns = [];
// 用于存储选中的数据
this._selectedData = new Map();
this._filterConditions = null;
this._checkedIndices = new Set();
}
static styles = css`
:host {
display: block;
font-family: var(--sl-font-sans);
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 16px;
}
th, td {
padding: 8px;
text-align: left;
border: 1px solid var(--sl-color-neutral-300);
}
th {
background-color: var(--sl-color-neutral-100);
font-weight: var(--sl-font-weight-semibold);
}
tr:nth-child(even) {
background-color: var(--sl-color-neutral-50);
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 16px;
gap: 8px;
}
.pagination-info {
margin: 0 16px;
color: var(--sl-color-neutral-700);
}
.actions {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
sl-checkbox {
--sl-input-border-color: var(--sl-color-neutral-400);
}
sl-button::part(base) {
cursor: pointer;
}
`;
// 生命周期方法:组件首次更新
firstUpdated() {
super.firstUpdated();
// 设置页面大小
if (this.customConfig && this.customConfig.pageSize) {
this.pageSize = this.customConfig.pageSize;
}
// 加载初始数据
this.refreshData();
// 激活 Shoelace 组件
discover?.(this.shadowRoot);
}
async refreshData() {
if (!this.fetchData) return;
try {
const offset = (this.currentPage - 1) * this.pageSize;
const result = await this.fetchData({
limit: this.pageSize,
offset: offset
});
// 更新总数据量
this.total = result.rowCount || 0;
// 映射数据列
const columnIndexMap = this.columns.map(targetCol =>
result.columns.findIndex(col => col.fdId === targetCol.fdId)
);
// 根据映射重组数据
this.data = result.data.map(row =>
columnIndexMap.map(index => index >= 0 ? row[index] : '')
);
const linkedIndex = this.columns.findIndex(col => col.fdId === this.linkColumns[0].fdId);
this.data.forEach((item, idx) => {
if (this.initialFilterValue.includes(item[linkedIndex])) {
this._selectedData.set(offset + idx, item);
}
});
this.requestUpdate();
} catch (error) {
console.error('获取数据失败:', error);
}
}
// 检查当前页是否全选
isCurrentPageAllSelected() {
if (!this.data.length) return false;
const start = (this.currentPage - 1) * this.pageSize;
return this.data.every((_, index) => this._selectedData.has(start + index));
}
// 处理全选/取消全选
handleSelectAll(e) {
const start = (this.currentPage - 1) * this.pageSize;
if (e.target.checked) {
// 选中当前页所有数据
this.data.forEach((item, index) => {
this._selectedData.set(start + index, item);
});
} else {
// 取消选中当前页所有数据
this.data.forEach((_, index) => {
this._selectedData.delete(start + index);
});
}
this.requestUpdate();
}
// 处理单个选择框变化
handleCheckboxChange(e, item, globalIndex) {
if (e.target.checked) {
this._selectedData.set(globalIndex, item);
} else {
this._selectedData.delete(globalIndex);
}
this.requestUpdate();
}
// 处理页面切换
async handlePageChange(newPage) {
this.currentPage = newPage;
await this.refreshData();
}
// 处理提交按钮点击
handleSubmit() {
// 获取所有选中行的数据
const selectedData = Array.from(this._selectedData.values()).map(selectedItem => {
return this.linkColumns.map(col => {
const colIndex = this.columns.findIndex(allCol => allCol.fdId === col.fdId);
return colIndex >= 0 ? selectedItem[colIndex] : '';
});
});
// 对数据进行去重
const uniqueSelectedData = selectedData.filter((item, index) => {
const stringifiedItem = JSON.stringify(item);
return selectedData.findIndex(elem => JSON.stringify(elem) === stringifiedItem) === index;
});
const filterValue = [];
const displayValue = [];
uniqueSelectedData.forEach(res => {
filterValue.push(res[0])
if (res.length === 2) {
displayValue.push(res[1])
}
})
// 调用外部传入的 onConfirm
if (this.onConfirm) {
const otherState = this.displayColumns.length > 0 ? { displayValue } : {}
this.onConfirm(filterValue, otherState);
}
}
// 生成随机ID (用于筛选条件)
generateId(length = 6) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// 组件渲染方法
render() {
const totalPages = Math.ceil(this.total / this.pageSize);
return html`
<div>
<table>
<thead>
<tr>
<th>
<sl-checkbox
?checked="${this.isCurrentPageAllSelected()}"
@sl-change="${this.handleSelectAll}"
></sl-checkbox>
</th>
${this.columns.map((col) => html`
<th>${col.name}</th>
`)}
</tr>
</thead>
<tbody>
${this.data.map((item, index) => {
const globalIndex = (this.currentPage - 1) * this.pageSize + index;
return html`
<tr>
<td>
<sl-checkbox
?checked="${this._selectedData.has(globalIndex)}"
@sl-change="${(e) => this.handleCheckboxChange(e, item, globalIndex)}"
></sl-checkbox>
</td>
${this.columns.map((col, colIndex) => html`
<td>${item[colIndex]}</td>
`)}
</tr>
`;
})}
</tbody>
</table>
<div class="pagination">
<sl-button
?disabled="${this.currentPage === 1}"
@click="${() => this.handlePageChange(this.currentPage - 1)}"
>上一页</sl-button>
<span class="pagination-info">第 ${this.currentPage} 页,共 ${totalPages} 页</span>
<sl-button
?disabled="${this.currentPage === totalPages || totalPages === 0}"
@click="${() => this.handlePageChange(this.currentPage + 1)}"
>下一页</sl-button>
</div>
<div class="actions">
<sl-button variant="primary" @click="${this.handleSubmit}">确定</sl-button>
</div>
</div>
`;
}
}
// 注册 Web Component
customElements.define('multi-select-table', MultiSelectTable);
}
// 配置表单定义
const configSchema = [
{
fieldName: 'pageSize',
label: '每页显示条数',
type: "NUMBER",
defaultValue: 10,
placeholder: '请输入每页显示的数据条数',
rules: [
{
required: true,
message: '请输入每页显示的数据条数'
},
{
type: 'number',
min: 1,
max: 100,
message: '每页显示条数需在1-100之间'
}
]
},
{
type: 'FIELDS_SELECT',
fieldName: 'tableFields',
label: '使用字段',
model: {
single: false,
}
}
]
// 注册插件
GD.registerCustomSelector({
id: 'multi-select-table-selector',
title: '多选表格筛选器',
tagName: 'multi-select-table',
desc: '通过表格展示数据,支持多选的筛选器,可配置页面大小',
configFormSchema: configSchema,
load: registerMultiSelectTable
})
4. 参考材料
插件代码模板
const registerCustomSelector = async () => {
// 加载 BI 平台提供的资源
await GD.asyncLoadScript(GD.getResourceUrl('lit'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace'), { type: 'module' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-light'), { tagName: 'link' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-dark'), { tagName: 'link' })
const { LitElement, html, css } = window.lit
const { discover } = window.shoelaceAutoloader || {}
// 定义 Web Component 类 CustomSelectorComponent
class CustomSelectorComponent extends LitElement {
static properties = {
// 联动字段
linkColumns: { type: Array },
// 显示字段
displayColumns: { type: Array },
// 所有字段
allColumns: { type: Array },
// 获取明细表数据
fetchData: { type: Function },
// 获取单个字段的可选值列表
fetchFieldValues: { type: Function },
// 获取多个字段的可选值列表
fetchTreeValues: { type: Function },
// 输出筛选值,类型为选择筛选器,需按照选择筛选器的格式返回
onConfirm: { type: Function },
// 初始化筛选值,类型和 onConfirm 参数一致
initialFilterValue: { type: Array },
// 初始化显示值
initialDisplayValue: { type: Array },
};
constructor() {
super();
this.linkColumns = [];
this.displayColumns = [];
this.allColumns = [];
this.fetchData = null;
this.onConfirm = null;
this.initialFilterValue = [];
this.initialDisplayValue = [];
}
static styles = css`
.custom-selector-container {
width: 100%;
height: 100%;
}
`;
firstUpdated() {
super.firstUpdated()
// 如果使用 shoelace 组件,需要调用 autoloader.discover 方法触发 shoelace 组件的自动加载
discover?.(this.shadowRoot)
}
render() {
return html`
<div class="custom-selector-container">
自定义筛选器
</div>
`;
}
}
// 将 Web Component 注册到当前页面
customElements.define('define-your-tagName', CustomSelectorComponent);
}
// 用于展示文本说明和填充自定义配置
const legoDefs = [
// 配置格式参考 https://guandata.yuque.com/guandataweb/dsebtl/iefgq3
]
// 将 Web Component 和自定义配置表单注册到 BI 平台
GD.registerCustomSelector({
id: 'unique-id',
title: '插件标题展示',
tagName: 'define-your-tagName',
desc: '插件功能描述',
configFormSchema: legoDefs,
load: registerCustomSelector
})
WebComponent
- 使用自定义元素-MDN文档;
- 自定义筛选器的实现原理为,先在插件代码中通过
customElements.define定义WebComponet,再由BI平台渲染到对应筛选器卡片中。
Lit
- Lit框架官方文档;
- WebComponent开发框架,大幅提升开发体验;
- BI平台提供v3.2.1版本,进行了一些修改和适配,需要通过
GD.asyncLoadScript和GD.getResourceUrl('lit')引入; - 需注意BI平台插件代码中不支持Decorator语法,原因是该语法需要Typescript或Babel生效;其余语法没有限制。
await GD.asyncLoadScript(GD.getResourceUrl('lit'),{type:'module'})
Shoelace
- Shoelace组件库官方文档;
- 类似AntDesign的WebCompoent组件库;
- BI提供2.19.1版本,进行了一些样式修改和适配,会自动切换平台配色(蓝绿)和深浅主题。需要通过异步加载脚本
GD.asyncLoadScript和获取资源链接GD.getResourceUrl('shoelace')等引入。
// 即便不使用 autoloader.discover 也要以 type: module 引用
await GD.asyncLoadScript(GD.getResourceUrl('shoelace'), { type: 'module' })
// light 和 dark 样式需要同时引入
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-light'), { tagName: 'link' })
await GD.asyncLoadScript(GD.getResourceUrl('shoelace-theme-dark'), { tagName: 'link' })
可访问的数据和函数
class CustomSelectorComponent extends LitElement {
static properties = {
// 联动字段
linkColumns: { type: Array },
// 显示字段
displayColumns: { type: Array },
// 所有字段
allColumns: { type: Array },
// 获取明细表数据
fetchData: { type: Function },
// 获取单个字段的可选值列表
fetchFieldValues: { type: Function },
// 获取多个字段的可选值列表
fetchTreeValues: { type: Function },
// 输出筛选值,类型为选择筛选器,需按照选择筛选器的格式返回
onConfirm: { type: Function },
// 初始化筛选值,类型和 onConfirm 参数一致
initialFilterValue: { type: Array },
// 初始化显示值
initialDisplayValue: { type: Array },
// 自定义配置
customConfig: { type: Object },
};
// ...
}
属性
这些属性会作为 HTML 元素的属性,以 JSON 字符串的形式传入元素,可以直接在 HTML 里看到。
如果自定义元素使用了 Lit 框架,组件内部就不需要处理 JSON 字符串的问题,直接访问 this.customConfig 就是正常的 JSON 结构
自定义设置内容customConfig
用户填写的自定义设置内容,格式为 JSON。
组件注册时的 configFormSchema 内容会生成表单供用户填写,填写的结果就从这里得到。
所有字段allColumns
该筛选器所引用数据集的所有字段;
allColumns 仅提供给插件消费,不影响 BI 功能如联动、被联动等。
示例
{
allColumns: [
{
"fdId": "cbe5217f06de44f0f908232a",
"name": "省份",
"fdType": "STRING",
"metaType": "DIM",
"isAggregated": false,
"calculationType": "normal",
"level": "dataset",
"annotation": "",
"dsId": "k5fa308879b364e5bb628f56"
},
{/* ... */}
]
}
联动字段linkColumns
筛选器新建和编辑时设置的【联动字段】,选择筛选器只有一个联动字段。
联动字段 linkColumns 一定是所有字段 allColumns 的子集。
联动字段和其他筛选器的联动字段作用基本一致。自定义筛选器联动其他卡片时,需要给每个联动字段设置关联。
自定义筛选器提交联动条件时,也需要和联动字段 linkColumns 相匹配。示例
{
linkColumns: [
{
"fdId": "cbe5217f06de44f0f908232a",
"name": "省份",
"fdType": "STRING",
"metaType": "DIM",
"isAggregated": false,
"calculationType": "normal",
"level": "dataset",
"annotation": "",
"dsId": "k5fa308879b364e5bb628f56"
},
{/* ... */}
]
}
显示字段 displayColumns
筛选器新建和编辑时设置的【显示字段】,如果没设置则为空。
显示字段和联动字段是一一对应的关系,用来对联动值进行显示,比如:联动字段为省份代码,实际值为“1001”,所对应的显示字段为省份,对应的显示值则为“浙江”。
{
linkColumns: [
{
"fdId": "cbe5217f06de44f0f908232a",
"name": "省份",
"fdType": "STRING",
"metaType": "DIM",
"isAggregated": false,
"calculationType": "normal",
"level": "dataset",
"annotation": "",
"dsId": "k5fa308879b364e5bb628f56"
},
{/* ... */}
]
}
初始化联动条件initialFilterValue
筛选器组件初始化时的联动值,来自于筛选器组件上一次 onConfirm 时的第一个参数输出。
格式为字符串数组。
初始化显示条件 initialDisplayValue
筛选器组件初始化时的显示值,如果没设置显示字段则为空,来自于筛选器组件上一次 onConfirm 时的第二个参数中的displayValue。
格式为字符串数组。
移动端渲染 isMobile
是否来自移动端,bool 类型
方法
这些方法是通过JavaScript写入到元素属性,可以直接调用,如this.fetchData()。
获取明细数据fetchData
功能描述
用于获取数据集明细数据。
使用说明
// 参数示例
// filters 和 treeFilters 格式同 BI web,
// 基本上是 column 信息 + filterType + filterValue
const params = {
offset: 0,
limit: 20,
filters: [
{
fdId: 'dafd2c41b99b44068901b19c',
name: '产品名称',
fdType: 'STRING',
dsId: 's39796a0f96b145e0ab48dc2',
filterType: 'IN',
filterValue: ['伊利酸奶']
}
],
treeFilters: [
{
cdId: 'w5e7e168010b64315a052118',
filterType: 'IN',
fields: [
{
fdId: 'bf4121c487a164c02bd81ee8',
name: '门店',
fdType: 'STRING',
dsId: 's39796a0f96b145e0ab48dc2'
},
{
fdId: 'dafd2c41b99b44068901b19c',
name: '产品名称',
fdType: 'STRING',
dsId: 's39796a0f96b145e0ab48dc2'
}
],
values: [
[
'一号店',
'乐事薯片'
]
],
displayValue: [
[
'一号店',
'乐事薯片'
]
]
}
]
}
const response = await this.fetchData(params)
// 返回值示例
response = {
"columns": [
{
"name": "编号ID",
"fdType": "LONG",
"dsId": "k5fa308879b364e5bb628f56",
"fdId": "s946dbdd2bd644fff93c709c",
"metaType": "METRIC",
},
{
"name": "省份",
"fdType": "STRING",
"dsId": "k5fa308879b364e5bb628f56",
"fdId": "cbe5217f06de44f0f908232a",
"metaType": "DIM",
},
/* ... */
],
"data": [
// data 每个元素代表明细表的一行,数组长度与 columns 长度相同,空值以 null 填充
[ null, "四川省", "510000", "成都市", "50g日本樱花盈润活肤霜" ],
[ null, "浙江省", "330000", "嘉兴市", "50ml欧莱雅深层美白乳霜*日霜" ],
/* ... */
],
"rowCount": 4395, // 总行数,并非 data 长度
}
注意事项
-
返回数据为明细数据,不支持聚合;
-
接口会分页,需要自行维护分页状态,单页上限不超过20000条;
-
筛选器被外部其他筛选器联动时,fetchData传入的参数会与外部筛选条件合并,共同生效。
- filters会和外部筛选条件中的filters合并;
- treeFilters会覆盖外部筛选条件中的treeFilters。
获取指定字段的可选值fetchFieldValues
功能描述
获取指定字段的值列表,可用于在自定义筛选器内部实现单个字段的筛选器。
使用说明
// 参数示例
const params = {
"fieldQuery": {
"name": "省份",
"fdType": "STRING",
"dsId": "k5fa308879b364e5bb628f56",
"fdId": "cbe5217f06de44f0f908232a",
// ...
// 以上即单个 column 的字段
"limit": 50,
"offset": 0,
"search": "" // 用于文本搜索,同 BI 的选择筛选器
}
}
const response = await this.fetchFieldValues(params)
// 返回值示例
response = {
"offset": 0,
"limit": 50,
"count": 4340,
"result": [
{ "value": "四川省" },
{ "value": "湖北省" },
{ "value": "浙江省" },
/* ... */
]
}
获取多个字段的可选值fetchTreeValues
功能描述
获取多个指定字段的值列表,可用于在自定义筛选器内部实现多个字段的树状筛选器。
使用说明
// 参数示例
const params = {
"limit": 50,
"offest": 0,
"fieldQuerySeq": [
{
"name": "省份",
"fdType": "STRING",
"fdId": "cbe5217f06de44f0f908232a",
"dsId": "k5fa308879b364e5bb628f56",
// ...
// 以上即单个 column 的字段
},
{
"name": "城市",
"fdType": "STRING",
"fdId": "k31522e65c9ba4fac9e223d7",
"dsId": "k5fa308879b364e5bb628f56"
// ...
// 以上即单个 column 的字段
}
],
"filters": [], // 同 fetchData 的 filters
"search": "", // 用于文本搜索,同 BI 的树状筛选器
}
const response = await this.fetchTreeValues(params)
// 返回值示例
response = {
"offset": 0,
"limit": 50,
"count": 4340,
"result": [
{
"key": "上海市_0",
"children": [
{
"key": "市辖区_1",
"displayValue": "市辖区"
}
],
"displayValue": "上海市"
},
{
"key": "四川省_0",
"children": [
{
"key": "乐山市_1",
"displayValue": "乐山市"
},
{
"key": "凉山彝族自治州_1",
"displayValue": "凉山彝族自治州"
},
{
"key": "宜宾市_1",
"displayValue": "宜宾市"
},
{
"key": "甘孜藏族自治州_1",
"displayValue": "甘孜藏族自治州"
},
// ...
],
"displayValue": "四川省"
},
// ...
]
}
发起联动onConfirm
功能描述
提交筛选条件,类型要求为ICombinationFilter,和组合筛选器相同(详情可见initialFilterValue的部分);
如果自定义筛选器在Popover中渲染,提交操作会关闭Popover。
使用说明
const filterValue: string[] = [/* ... */]
const displayValue: string[] = [/* ... */]
this.onConfirm(filterValue, { displayValue })
// 无返回值
注意事项
- 如果提交按钮使用,提交按钮需要在插件中自行绘制;
- 外部操作如点击蒙层关闭Popover不会触发onConfirm提交。