From f7a8995b4b86003b8eee23fc000cc9851e5a6a6b Mon Sep 17 00:00:00 2001 From: jimmychai Date: Fri, 14 Jul 2023 12:53:30 +0800 Subject: [PATCH] =?UTF-8?q?BI-126685=20fix:=20=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.xml | 146 ++++++++++++ plugin.xml | 37 ++- pom.xml | 42 ++++ readme.md | 152 +++++++++++- .../custom/component/CustomComponent.java | 27 +++ .../component/DemoComponentProvider.java | 86 +++++++ .../plugin/custom/component/config.json | 196 ++++++++++++++++ .../finebi/plugin/custom/component/demo.css | 3 + .../finebi/plugin/custom/component/demo.js | 219 ++++++++++++++++++ 9 files changed, 886 insertions(+), 22 deletions(-) create mode 100644 build.xml create mode 100644 pom.xml create mode 100644 src/main/java/com/finebi/plugin/custom/component/CustomComponent.java create mode 100644 src/main/java/com/finebi/plugin/custom/component/DemoComponentProvider.java create mode 100644 src/main/resources/com/finebi/plugin/custom/component/config.json create mode 100644 src/main/resources/com/finebi/plugin/custom/component/demo.css create mode 100644 src/main/resources/com/finebi/plugin/custom/component/demo.js diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..63891a2 --- /dev/null +++ b/build.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin.xml b/plugin.xml index 3c14771..9190080 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,26 +1,21 @@ - - com.fanruan.plugin.template.uuid - + + + com.finebi.plugin.custom.chart.demo.v6 + yes - 1.0.0 - 10.0 - 2020-08-08 - author - + 1.6.0 + 11.0~11.0 + 6.0~ + 2023-05-16 + fanruan + + [2023-06-01] demo ]]> - - - - - - - - - - - - + com + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..60d6137 --- /dev/null +++ b/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.finebi.project + nuclear-maven + 5.0-RELEASE-SNAPSHOT + ../nuclear-maven/pom.xml + + + plugin-bi-custom-chart-demo + + + 8 + 8 + UTF-8 + + + + com.finebi + common-service + 5.0-RELEASE-SNAPSHOT + compile + + + + + D:\apache-tomcat-9.0.73\webapps\webroot\WEB-INF/plugins/plugin-com.finebi.plugin.custom.chart.demo.v6/classes + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md index b4ba7fd..09217cb 100644 --- a/readme.md +++ b/readme.md @@ -6,4 +6,154 @@ ## 插件使用简介 -请在这里提供一个简要的插件使用教程。 \ No newline at end of file +### config.json 配置解释 +{ + /** + * 自定义横纵轴名称 + */ + "dataRegions": [ + { + "name": "自定义数据1" + }, + { + "name": "自定义数据2" + } +], + /** + * 自定义图形属性 + * 两种方式: + * 1. 可选配置。通过 settings 指定,有 color、size、symbol 三种可选配置,取 BI 图表默认实现 + * 2. 可配配置。通过 settings 指定,有 Checkbox、RadioGroup、Segment、Select、ColorPicker、Input 六种基本组件 + */ + "attrRegions": [ + { + "name": "颜色1", // 属性名称 + "multiFields": false, // 是否可以拖入多个字段 + "settings": "color" + }, + { + "name": "大小1", + "multiFields": true, + "settings": "size" + }, + { + "name": "形状1", + "multiFields": false, + "settings": "symbol" + }, + { + "name": "自定选项", + "multiFields": false, + "settings": [ + { + "name": "Checkbox", + "type": "Checkbox", + "defaultValue": ["2", "3"], + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + }, + { + "text": "选项2", + "value": "3" + } + ] + }, + { + "name": "RadioGroup", + "type": "RadioGroup", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Segment", + "type": "Segment", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Select", + "type": "Select", + "defaultValue": "1", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "ColorPicker", + "type": "ColorPicker", + "defaultValue": "#ffffff" + }, + { + "name": "Input", + "type": "Input", + "defaultValue": "test" + } + ] + }, + { + "name": "属性1属性1属性1", + "multiFields": true + }, + { + "name": "属性2", + "multiFields": false + } +], + /** + * 自定义组件样式 + * 方式同自定义图形属性中的可配配置 + */ + "chartStyles": [ + { + "name": "自定义1", + "settings": [ + { + "name": "RadioGroup", + "type": "RadioGroup", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + } + ] + } +] +} \ No newline at end of file diff --git a/src/main/java/com/finebi/plugin/custom/component/CustomComponent.java b/src/main/java/com/finebi/plugin/custom/component/CustomComponent.java new file mode 100644 index 0000000..2c9de9e --- /dev/null +++ b/src/main/java/com/finebi/plugin/custom/component/CustomComponent.java @@ -0,0 +1,27 @@ +package com.finebi.plugin.custom.component; + +import com.fr.web.struct.AssembleComponent; +import com.fr.web.struct.Atom; +import com.fr.web.struct.browser.RequestClient; +import com.fr.web.struct.category.ParserType; +import com.fr.web.struct.category.ScriptPath; +import com.fr.web.struct.category.StylePath; + +public class CustomComponent extends AssembleComponent { + public static final CustomComponent KEY = new CustomComponent(); + + @Override + public Atom[] refer() { + return new Atom[0]; + } + + @Override + public ScriptPath script(RequestClient req) { + return ScriptPath.build("/com/finebi/plugin/custom/component/demo.js"); + } + + @Override + public StylePath style(RequestClient req) { + return StylePath.build("/com/finebi/plugin/custom/component/demo.css", ParserType.DYNAMIC); + } +} diff --git a/src/main/java/com/finebi/plugin/custom/component/DemoComponentProvider.java b/src/main/java/com/finebi/plugin/custom/component/DemoComponentProvider.java new file mode 100644 index 0000000..8ea8035 --- /dev/null +++ b/src/main/java/com/finebi/plugin/custom/component/DemoComponentProvider.java @@ -0,0 +1,86 @@ +package com.finebi.plugin.custom.component; + +import com.finebi.common.api.service.plugin.common.context.OperationContext; +import com.finebi.common.api.service.plugin.component.AbstractCustomComponentProvider; +import com.fr.general.IOUtils; +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.web.struct.AssembleComponent; + +@FunctionRecorder +public class DemoComponentProvider extends AbstractCustomComponentProvider{ + /** + * 自定义图表名称 + */ + @Override + public String getName() { + return "自定义图表demo"; + } + + /** + * 自定义图表类型 + */ + @Override + public String getType() { + return "demo"; + } + + /** + * 自定义图表 icon + */ + @Override + public String getIcon() { + return "http://webapi.amap.com/theme/v1.3/mapinfo_05.png"; + } + + /** + * 空自定义图表提示,不写默认取 icon + */ + @Override + public String getPreviewIcon() { + return "http://webapi.amap.com/theme/v1.3/mapinfo_05.png"; + } + + /** + * 自定义图表预览 dom,注入依赖文件和挂载节点,可以获取 context + * @param context 上下文 + */ + @ExecuteFunctionRecord + @Override + public String getPreviewPageHTML(OperationContext context) { + return "" + + "" + + "
context:
" + context.getSystemInfo() + context.getUserInfo() + + "
这是预览
"; + } + + /** + * 自定义图表编辑 dom,不写默认取预览 + * @param context 上下文 + */ + @ExecuteFunctionRecord + @Override + public String getEditPageHTML(OperationContext context) { + return "" + + "" + + "
context:
" + context.getSystemInfo() + context.getUserInfo() + + "
这是编辑
"; + } + + /** + * 自定义图表渲染 js、css 注入 + * @param context 上下文 + */ + @Override + public AssembleComponent previewClient(OperationContext context) { + return CustomComponent.KEY; + } + + /** + * 自定义图表配置文件 + */ + @Override + public String config() { + return IOUtils.readResourceAsString("com/finebi/plugin/custom/component/config.json"); + } +} diff --git a/src/main/resources/com/finebi/plugin/custom/component/config.json b/src/main/resources/com/finebi/plugin/custom/component/config.json new file mode 100644 index 0000000..f19da9e --- /dev/null +++ b/src/main/resources/com/finebi/plugin/custom/component/config.json @@ -0,0 +1,196 @@ +{ + "dataRegions": [ + { + "name": "自定义数据1" + }, + { + "name": "自定义数据2" + } + ], + "attrRegions": [ + { + "name": "颜色1", + "multiFields": false, + "settings": "color" + }, + { + "name": "大小1", + "multiFields": true, + "settings": "size" + }, + { + "name": "形状1", + "multiFields": false, + "settings": "symbol" + }, + { + "name": "自定选项", + "multiFields": false, + "settings": [ + { + "name": "Checkbox", + "type": "Checkbox", + "defaultValue": ["2", "3"], + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + }, + { + "text": "选项2", + "value": "3" + } + ] + }, + { + "name": "RadioGroup", + "type": "RadioGroup", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Segment", + "type": "Segment", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Select", + "type": "Select", + "defaultValue": "1", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "ColorPicker", + "type": "ColorPicker", + "defaultValue": "#ffffff" + }, + { + "name": "Input", + "type": "Input", + "defaultValue": "test" + } + ] + }, + { + "name": "属性1属性1属性1", + "multiFields": true + }, + { + "name": "属性2", + "multiFields": false + } + ], + "chartStyles": [ + { + "name": "自定选项", + "settings": [ + { + "name": "Checkbox", + "type": "Checkbox", + "defaultValue": ["2", "3"], + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + }, + { + "text": "选项2", + "value": "3" + } + ] + }, + { + "name": "RadioGroup", + "type": "RadioGroup", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Segment", + "type": "Segment", + "defaultValue": "2", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "Select", + "type": "Select", + "defaultValue": "1", + "items": [ + { + "text": "选项1", + "value": "1" + }, + { + "text": "选项2", + "value": "2" + } + ] + }, + { + "name": "ColorPicker", + "type": "ColorPicker", + "defaultValue": "#ffffff" + }, + { + "name": "Input", + "type": "Input", + "defaultValue": "test" + } + ] + } + ] +} diff --git a/src/main/resources/com/finebi/plugin/custom/component/demo.css b/src/main/resources/com/finebi/plugin/custom/component/demo.css new file mode 100644 index 0000000..57ce250 --- /dev/null +++ b/src/main/resources/com/finebi/plugin/custom/component/demo.css @@ -0,0 +1,3 @@ +*{ + font-size: 20px; +} \ No newline at end of file diff --git a/src/main/resources/com/finebi/plugin/custom/component/demo.js b/src/main/resources/com/finebi/plugin/custom/component/demo.js new file mode 100644 index 0000000..07da8a0 --- /dev/null +++ b/src/main/resources/com/finebi/plugin/custom/component/demo.js @@ -0,0 +1,219 @@ +function render( + data, + config, + saveSessionCallback, + // 暂时没用 + closeSessionCallBack, + extensionCallBack +) { + const { + // 数据,若横纵轴多指标时图表属性有维度字段,dataModels 为以图表属性为分组的多组数据 + dataModels, + // 横纵轴拖入字段的维度 id + dataMapping, + // 图表属性拖入字段的维度 id + chartAttrMapping, + // 图表点击值 + clicked + } = data; + + const { + // 组件 id + widgetId, + // 全局样式中图表最终样式 + globalStyles, + // 图表属性配置所选值 + chartAttr, + // 图表样式配置所选值 + chartStyle, + // 图标属性中使用形状时的图标映射 + symbolIconMap, + // 自定义保存的值(saveSessionCallback) + customConfig + } = config; + + const refs = {}; + + // demo 仅使用表格模拟 + BI.createWidget({ + type: 'bi.vertical', + element: '#container', + items: [ + { + type: 'bi.label', + text: + 'dataMapping(横纵轴拖入字段的维度 id): ' + + JSON.stringify(dataMapping) + }, + { + type: 'bi.label', + text: + 'chartAttrMapping(图表属性拖入字段的维度 id): ' + + JSON.stringify(chartAttrMapping) + }, + { + type: 'bi.label', + text: 'widgetId(组件 id): ' + JSON.stringify(widgetId) + }, + { + type: 'bi.label', + text: + 'globalStyles(全局样式中图表最终样式): ' + + JSON.stringify(globalStyles) + }, + { + type: 'bi.label', + text: + 'chartAttr(图表属性配置所选值): ' + + JSON.stringify(chartAttr) + }, + { + type: 'bi.label', + text: + 'chartStyle(图表样式配置所选值): ' + + JSON.stringify(chartStyle) + }, + { + type: 'bi.label', + text: + 'symbolIconMap(图标属性中使用形状时的图标映射): ' + + JSON.stringify(symbolIconMap) + }, + { + type: 'bi.label', + text: + 'customConfig(自定义保存的值(saveSessionCallback)): ' + + JSON.stringify(customConfig) + }, + { + type: 'bi.vertical', + items: dataModels.map(dataModel => { + const { fields, colData } = dataModel; + + return { + type: 'bi.vertical', + items: [ + { + type: 'bi.vertical_adapt', + items: fields.map(field => { + return { + type: 'bi.label', + text: field.name, + rgap: 5 + }; + }) + }, + { + type: 'bi.vertical_adapt', + items: colData.map((data, colIndex) => { + // 维度id + const dId = fields[colIndex].id; + + return { + type: 'bi.vertical', + items: data.map((text, dataIndex) => { + const key = + '' + colIndex + dataIndex; + + // 构造当前联动点击值对象 + const value = []; + for ( + let i = 0; + i <= colIndex; + i++ + ) { + // 当前维度和之前维度的id及对应值 + value.push({ + dId: fields[i].id, + text: colData[i][dataIndex] + }); + } + // 联动点击值对象 + const currentClicked = { + dId, + value + }; + + return { + type: 'bi.label', + height: 30, + rgap: 5, + text, + cls: isClicked( + clicked, + currentClicked + ) + ? 'bi-border' + : '', + ref: ref => { + refs[key] = ref; + }, + handler: () => { + BI.each(refs, (_, ref) => { + ref.element.removeClass( + 'bi-border' + ); + }); + refs[key].element.addClass( + 'bi-border' + ); + + // 触发联动 + extensionCallBack( + 'click', + currentClicked + ); + + // 模拟自定义保存值,可以是任意值,通过 customConfig 原样返回 + saveSessionCallback({ + saveValue: + currentClicked + }); + } + }; + }) + }; + }) + } + ] + }; + }) + } + ] + }); +} +// 注册渲染方法 +new BIPlugin().init(render); + +// 判断当前数据是否为点击值 +function isClicked(clicked, currentClicked) { + function valueEq(v1, v2) { + if (v1 === v2) { + return true; + } + if (!BI.isArray(v1) || !BI.isArray(v2)) { + return false; + } + if (v1.length !== v2.length) { + return false; + } + + return !BI.some(v1, (i, v) => { + const textEq = BI.isNull(v.text) + ? BI.isNull(v.text) !== BI.isNull(v2[i].text) + : v.text !== v2[i].text; + + return v.dId !== v2[i].dId || textEq; + }); + } + + if (BI.isNull(clicked) || BI.isNull(currentClicked)) { + return false; + } + + return ( + clicked.dId === currentClicked.dId && + valueEq(clicked.value, currentClicked.value) + ); +} +