开发者中心包含此范例模板(双十一销量实时统计图表),请前往开发者中心下载学习。
Index
前言
echarts 是apache的一个孵化项目,这次我们将它和kintone进行整合,实现了kintone门户页面的双十一的销量实时统计的Dashboard 。
我们先看下效果图。
折线图显示了双十一期间的产品销量走势,而饼图则显示了各渠道的产品销量的占比,同时他们都是实时变化的。
接下来我们就来看下它是怎么实现的。
公用的库
下面是我们要用到的库:
※ 这里不对这两个库做具体介绍,如果还不熟悉它们,请先参阅相关文档。
应用的自定义开发
我们先来模拟一个kintone的销量统计的应用。
Stp1: 创建新应用
选择“通过导入模板文件创建”。
Step2: 通过导入模板文件创建
选择模板压缩文件后,点击创建应用,便创建完成了。
(模板下载地址:双十一销量统计模板)
Step3: 创建JavaScript文件
graph.js
(应用列表页和应用详情页显示绘图的js,为了方便这边将pc端和mobile端的代码整合到了一起。)
(function () { 'use strict'; kintone.events.on(['app.record.detail.show', 'app.record.edit.show'], function (res) { const pcSetting = { type: 'pc', showContent: true, style: "width: 600px;height:400px;", }; generateDetail(pcSetting, res); }); kintone.events.on(['mobile.app.record.detail.show', 'mobile.app.record.edit.show'], function (res) { const mobileSetting = { type: 'mobile', showContent: false, style: "width: 350px;height:400px;", }; generateDetail(mobileSetting, res); }); kintone.events.on(['app.record.index.show'], function (res) { const pcSetting = { type: 'pc', showContent: true, style: "width: 900px;height:400px;" }; generateTotal(pcSetting); }); kintone.events.on(['mobile.app.record.index.show'], function (res) { const mobileSetting = { type: 'mobile', showContent: false, style: "width: 350px;height:400px;" }; generateTotal(mobileSetting); }); function generateDetail(setting, res) { var record = res.record; var report_el; if (setting.type === "mobile") { report_el = kintone.mobile.app.record.getSpaceElement("report"); } else { report_el = kintone.app.record.getSpaceElement("report"); } var report_div = document.createElement('div'); report_div.id = "graph"; report_div.style = setting.style; var myChart = echarts.init(report_div); var option = { title: { text: '各渠道销量统计', x: 'center' }, tooltip: { trigger: 'item', formatter: "{a} <br/>{b} : {c} ({d}%)", showContent: setting.showContent }, legend: { orient: 'vertical', left: 'left', data: ['京东', '淘宝', '拼多多', '天猫', '考拉'] }, series: [ { name: '假期类型', type: 'pie', radius: '55%', center: ['50%', '60%'], data: [ { value: record.channel1.value, name: '京东' }, { value: record.channel2.value, name: '淘宝' }, { value: record.channel3.value, name: '拼多多' }, { value: record.channel4.value, name: '天猫' }, { value: record.channel5.value, name: '考拉' } ], itemStyle: { emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }; myChart.setOption(option); report_el.appendChild(report_div); } function generateTotal(setting) { if (document.getElementById('graph') !== null) { return; } var graph = document.createElement('div'); graph.id = 'graph'; graph.style = setting.style; var app; if (setting.type === "mobile") { kintone.mobile.app.getHeaderSpaceElement().appendChild(graph); app = kintone.mobile.app.getId(); } else { kintone.app.getHeaderSpaceElement().appendChild(graph); app = kintone.app.getId(); } var myChart = echarts.init(graph); var kintoneRecord = new kintoneJSSDK.Record(); var rcOption = { app: app, query: 'order by date asc' }; kintoneRecord.getAllRecordsByCursor(rcOption).then((rsp) => { var records = rsp.records; var graphData = { 'channel1': [], 'channel2': [], 'channel3': [], 'channel4': [], 'channel5': [] }; var dateArray = []; for (var j = 0; j < records.length; j++) { var record = records[j]; var dateKey = record.date.value; graphData.channel1.push(record.channel1.value); graphData.channel2.push(record.channel2.value); graphData.channel3.push(record.channel3.value); graphData.channel4.push(record.channel4.value); graphData.channel5.push(record.channel5.value); dateArray.push(dateKey); } var option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, showContent: setting.showContent }, legend: { data: ['京东', '淘宝', '拼多多', '天猫', '考拉'] }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: { type: 'value' }, yAxis: { type: 'category', data: dateArray }, series: [ { name: '京东', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'insideRight' } }, data: graphData.channel1 }, { name: '淘宝', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'insideRight' } }, data: graphData.channel2 }, { name: '拼多多', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'insideRight' } }, data: graphData.channel3 }, { name: '天猫', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'insideRight' } }, data: graphData.channel4 }, { name: '考拉', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'insideRight' } }, data: graphData.channel5 } ] }; myChart.setOption(option); }).catch((err) => { document.getElementById('graph').innerText = "获取数据失败"; }); } }());
addData.js
(这部分代码只是为了模拟自动更新数据。当画面停留在应用列表页,会定时更新数据来模拟销量的变化。)
(function () { 'use strict'; kintone.events.on(['app.record.index.show'], function (res) { var kintoneRecord = new kintoneJSSDK.Record(); var app = xxx; var id = x; setInterval(function updateData() { kintoneRecord.getRecord({ app, id }).then((rsp) => { var data = rsp.record; var channel1Data = Number(data.channel1.value) + Number(random(1, 10)); var channel2Data = Number(data.channel1.value) + Number(random(1, 20)); var channel3Data = Number(data.channel1.value) + Number(random(1, 10)); var channel4Data = Number(data.channel1.value) + Number(random(1, 10)); var channel5Data = Number(data.channel1.value) + Number(random(1, 10)); var record = { "channel1": { "value": channel1Data }, "channel2": { "value": channel2Data }, "channel3": { "value": channel3Data }, "channel4": { "value": channel4Data }, "channel5": { "value": channel5Data } } var revision = -1; kintoneRecord.updateRecordByID({ app, id, record, revision }).then((rsp) => { console.log(rsp); }).catch((err) => { // This SDK return err with KintoneAPIException console.log(err); }); }).catch((err) => { // This SDK return err with KintoneAPIException console.log(err); }); return updateData; }(), 3000) }); function random(lower, upper) { return Math.floor(Math.random() * (upper - lower)) + lower; } }());
注意:请注意修改 app 和 id 这两个变量的值,分别是这个应用的id和要更新的记录的id。
Step4: 导入自定义开发文件到kintone
· 因为代码已经对应了手机端和电脑端,所以可以使用相同的js文件。
· 请注意文件的导入顺序。
step5: 添加模拟数据
接下来让我们来添加一些模拟数据吧。
请添加2019-11-05~2019-11-11 这几天的模拟数据:
详情页和列表页显示效果
完成自定义和添加数据之后,在列表页和详情页就能看到通过echars生成的图表了。
应用详情页
应用列表页
手机端画面
门户的自定义开发
应用完成之后,我们现在就来利用kintone的门户首页显示事件来自定义首页的Dashboard 。
注意:此开发需有系统管理员权限。
Step1: 创建JavaScript文件
portal.js
(function () { 'use strict'; kintone.events.on('portal.show', function (res) { const pcSetting = { type: 'pc', legend: { top: '10%' }, grid: { left: '10%', width: '35%', top: '25%' }, pie: { center: ['70%', '60%'], radius: '50%' }, style: "width: auto;height:400px;background-color:#fff;margin: 16px 16px 0 16px;" }; init(pcSetting); generateGraph(pcSetting); }); kintone.events.on('mobile.portal.show', function (res) { const mobileSetting = { type: 'mobile', legend: { top: '5%' }, grid: { left: '10%', height: '40%', top: '18%' }, pie: { center: ['50%', '80%'], radius: '30%' }, style: "width: auto;height:600px;background-color:#fff;margin: 10px 10px 0 10px;border-radius: 6px" }; init(mobileSetting); generateGraph(mobileSetting); }); function generateGraph(setting) { var kintoneRecord = new kintoneJSSDK.Record(); var rcOption = { app: xxx, query: 'order by date asc' }; var myChart = echarts.init(document.getElementById('graph')); myChart.on('updateAxisPointer', function (event) { var xAxisInfo = event.axesInfo[0]; if (xAxisInfo) { var dimension = xAxisInfo.value + 1; myChart.setOption({ series: { id: 'pie', label: { formatter: '{b}: {@[' + dimension + ']} ({d}%)' }, encode: { value: dimension, tooltip: dimension } } }); } }); setInterval(function setchart() { kintoneRecord.getAllRecordsByCursor(rcOption).then((rsp) => { var records = rsp.records; var graphData = { 'channel1': ['京东'], 'channel2': ['淘宝'], 'channel3': ['拼多多'], 'channel4': ['天猫'], 'channel5': ['考拉'] }; var dateArray = ['渠道']; for (var record of records) { var dateKey = record.date.value; graphData.channel1.push(record.channel1.value); graphData.channel2.push(record.channel2.value); graphData.channel3.push(record.channel3.value); graphData.channel4.push(record.channel4.value); graphData.channel5.push(record.channel5.value); dateArray.push(dateKey); } var option = { legend: setting.legend, title: { text: '2019双十一各渠道实时销量统计', left: 'center' }, tooltip: { trigger: 'axis', showContent: false }, dataset: { source: [ dateArray, graphData.channel1, graphData.channel2, graphData.channel3, graphData.channel4, graphData.channel5 ] }, xAxis: { type: 'category' }, yAxis: { gridIndex: 0, name: '单位(万台)' }, grid: setting.grid, series: [ { type: 'line', smooth: true, seriesLayoutBy: 'row' }, { type: 'line', smooth: true, seriesLayoutBy: 'row' }, { type: 'line', smooth: true, seriesLayoutBy: 'row' }, { type: 'line', smooth: true, seriesLayoutBy: 'row' }, { type: 'line', smooth: true, seriesLayoutBy: 'row' }, { type: 'pie', id: 'pie', radius: setting.pie.radius, center: setting.pie.center, label: { formatter: '{b}: {@2019-11-11} ({d}%)' }, encode: { itemName: '渠道', value: '2019-11-11', tooltip: '2019-11-11' } } ] }; myChart.setOption(option); }).catch((err) => { document.getElementById('graph').innerText = "获取数据失败"; }); return setchart; }(), 3000) } function init(setting) { if (document.getElementById('graph') !== null) { return; } var graph = document.createElement('div'); graph.id = 'graph'; graph.style = setting.style; if (setting.type === "mobile") { kintone.mobile.portal.getContentSpaceElement().appendChild(graph); } else { kintone.portal.getContentSpaceElement().appendChild(graph); } } }());
注意:请注意修改 app 这个变量的值,是这个应用的id。
Step2: 导入自定义开发文件到kintone
首页的自定义开发是在系统管理里进行导入的。
同样,我们的代码已经对应了手机端和电脑端,可以使用相同的js文件。
Step3: 删除之前应用里导入的相同的文件
因为上面的自定义开发文件同样会在kintone的应用内部生效,所以我们可以把之前“双十一销量统计”这个应用内的两个js文件(kintone-js-sdk.min.js和echarts.common.js )删除掉以避免重复调用。
验证
请同时打开两个画面:
· 画面1:应用列表页(用来模拟数据的自动添加)
· 画面2:首页
这样我们就能看到文章开头的那个首页实时销量统计的效果了。
代码下载
总结
这里我们用echarts开源画图库举了一个小小的例子。其实它的表现形式非常多,还可以和kintone整合实现更多酷炫有趣的图表效果。
真的是又方便又好用,大家可以根据自己的实际需求实践起来,一起实现自己想要的BI报表吧!
注意事项
本示例代码不保证其运行。
我们不为本示例代码提供技术支持。