前言
在制作 BI 报表时,我们常需要在数据引擎上封装一层 API,透过界面上的参数变化查询 API,拿到数据进行渲染。DataWorks 数据服务提供了快速封装 API 的能力,且能在上面进行开发、上线、下线、版本比对等操作。基于采用不同类型的 BI 报表,调试 API 的方式也不同,有一些 BI 平台已经内建了数据服务能力、有一些则是依赖三方的数据服务平台,而后者又分为自建 BI 报表或使用 BI 平台的方式。本文将对自建 BI 报表及使用 BI 平台的两种方式与 DataWorks 数据服务如何进行调试进行说明。
BI 平台 + DataWorks 数据服务
目前数据源类型明确支持 DataWorks 数据服务的 BI 平台有 DataV,如果 BI 平台支持 API 为数据源的也是在此类的范畴中,DataV 很好地支持 DataWorks 数据服务,包含能透过下拉框的方式选用已上线 API,且还封装了 API 的 AK,这边以 DataV 的操作方式为范例。
创建数据源
进入工作台,于左侧选择数据源、新建数据源,于右侧数据源类型选择 DataWorks 数据服务,进行添加。

创建 API
进入 DataWorks 数据服务选用数据引擎、撰写 SQL 并上线一个 API。

搭建报表
进去 DataV 开发报表,从左侧组件库拖拽图型后,对此图型选用我们上述添加的 DataWorks 数据服务的数据源及新增加的 API。

比较需要注意的是设定过滤器的部份,因为 API 出来的格式是固定的,BI 报表上不一样的图表需要的格式却不一定,我们需要用过滤器将格式整理一下。
每个组件会附上查看示例的内容,如折线图的格式为 { "x", "y", "colorField"}。

我们新建一个过滤器将 API 返回的 data 字段转成 { "x", "y", "colorField"} 格式。

整理好格式后,DataWorks 数据服务的接口数据就能放到 DataV 上,并能快速地使用上 DataV 提供的能力。

自建 BI 报表 + DataWorks 数据服务
另外一种是用户自建 BI 报表,也可能是自建一个报表再透过 IFrame 的方式放到其它 BI 平台,如 Grafana。此方式通常需要用户自己搭建开发环境进行接口调试,这边我们提供使用 VSCode 开发工具、图形则使用 AntV 为例。
VSCode
VSCode 是前端热门的开发工具,且提供很多利于开发的插件,这边我们使用 Live Server (Five Server) 插件来负责建立本地 Server 的联调工作 (它提供了运行本地 Server 与 支持 PHP,能帮助做到如动态页面内容、封装 API AK 等能力)。

AntV
AntV 是蚂蚁集团支持的可视化工具包,里面有各式各样的可视化组件,我们这边主要以 G2 和 G2 Plot 为例 (G2 图形交互设定弹性高但不好上手,G2Plot 是简化设定的版本)。下面为 G2 / G2 Plot 的范例页面,我们能从里面挑选出例子来搭建我们的 BI 报表。
环境设定
-
下载 VSCode 并安装 Live Server (Five Server) 插件。
-
安装 php (以 mac 为例)
brew install php
-
建立文件夹 bi-report,并使用 VSCode 打开,在 bi-report 下建立 www 文件夹。

- 于 bi-report 文件夹下建立 fiveserver.config.json,并设定入口文件 index.html 与 php 指令的运行路径。
arduino
module.exports = {
root: 'www',
open: 'index.html',
php: "/opt/homebrew/bin/php",
higlight: true,
injectBody: true,
};

搭建 API
至 DataWorks 数据服务搭建 API 并上线,点击带参数运行地址,拷贝 API 的 URL。

调示 API 及可视化渲染
于 index.html 设定引入 AntV 的包
下面我们以 G2 Plot 为例,参考此热力图范例。
xml
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/g2plot/2.4.31/g2plot.min.js" chartset="utf-8"></script>
</head>
<body>
<div id="chart"></div>
<script src="./index.js" chartset="utf-8"></script>
</body>
</html>
将图表渲染逻辑放在 index.js 里。
javascript
const { Heatmap } = G2Plot;
// 此 url 为 DataWorks 数据服务上线 API 点击带参数运行地址,拷贝的 API URL。
fetch('http://xxx-cn-shanghai.alicloudapi.com/B/west-lake-people-heatmap?appCode=xxx')
.then((res) => res.json())
.then((data) => {
const heatmapPlot = new Heatmap(document.getElementById('chart'), {
data,
type: 'density',
xField: 'g',
yField: 'l',
colorField: 'tmp',
color: '#F51D27-#FA541C-#FF8C12-#FFC838-#FAFFA8-#80FF73-#12CCCC-#1890FF-#6E32C2',
legend: {
position: 'bottom',
},
annotations: [
{
type: 'image',
start: ['min', 'max'],
end: ['max', 'min'],
src: 'https://gw.alipayobjects.com/zos/rmsportal/NeUTMwKtPcPxIFNTWZOZ.png',
},
],
});
heatmapPlot.render();
});
在 VSCode 左侧 bi-report 文件夹空白处点右键,选择 Open with Five Server (root),运行本地 Server。

动态联调 BI 内容

封装 API AK
上面的例子是直接将 API 的调用 AK 暴露在 HTML 请求上,安全性不高,如果要防止 AK 被拿走有以下几种方式。
建立登录态
透过登录机制来访问 BI 报表,此方式可以参考此文 developer.aliyun.com/article/138...。
透过注册 API
于 DataWorks 数据服务注册 API,并将调用 AK 的信息封装在常量参数里,但此方式无法管理调用来源。

透过 PHP
此方式基于 Live Server (Five Server) 插件提供的 PHP 能力,建立一个 PHP Server,将调用的请求工作在 Server 内完成,用户无法查看到实际接口请求的过程。此方式一样无法管理调用来源,但少了注册 API 与开发登录态代码的麻烦。
这边我们以 G2 为例,范例为此中国地图。
xml
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antv-g2/5.1.19/g2.min.js" chartset="utf-8"></script>
<script src="https://cdn.jsdelivr.net/npm/@antv/data-set@0.8.7/dist/data-set.min.js" chartset="utf-8"></script>
</head>
<body>
<script>
<?php
include('get.php');
?>
</script>
<div id="chart"></div>
<script src="index.js" chartset="utf-8"></script>
</body>
</html>
将数据放在 dataStr ,并写入 HTML 上。
php
<?php
// $page = $_GET['page']; // use php command to run app and request index.php?page=1, can use $_GET['page'] to get value.
$url = 'http://xxx-cn-shanghai.alicloudapi.com/B/west-lake-people-heatmap?appCode=xxx';
// use key 'http' even if you send the request to https://...
$options = [
'http' => [
'method' => 'GET',
],
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === false) {
/* Handle error */
echo "var dataStr = '[]';";
return;
}
function append_string ($str1, $str2) {
// Using Concatenation assignment
// operator (.=)
$str1 .=$str2;
// Returning the result
return $str1;
}
$export = append_string("var dataStr = ", json_encode($result, true));
$export = append_string($export, ";");
echo $export;
?>
从 HTML 拿到 dataStr,放到 AntV 上。
php
const { Chart } = G2;
const chart = new Chart({
container: 'chart',
autoFit: true,
});
// 从 dataStr 拿到数据
const data = dataStr ? JSON.parse(dataStr) : [];
chart
.polygon()
.data({
type: 'fetch',
value: data,
transform: [
{
type: 'custom',
callback: (data) => {
const dv = new DataSet.View().source(data).transform({
type: 'bin.hexagon',
fields: ['longitude', 'latitude'],
binWidth: [2, 3],
as: ['longitude', 'latitude', 'count'],
});
return dv.rows;
},
},
],
})
.encode('x', 'longitude')
.encode('y', 'latitude')
.encode('color', 'count')
.scale('color', {
range: '#BAE7FF-#1890FF-#0050B3',
})
.style('lineWidth', 5)
.style('stroke', '#fff')
.axis(false)
.legend(false)
.tooltip({
field: 'count',
})
.state('active', { fill: 'orange' })
.state('inactive', { opacity: 0.8 })
.interaction('elementHighlight', true);
chart.render();

上线 BI Report
此处使用 PHP Server 为例,也可以使用其他方式如 nodejs 或 nginx 等。建立一台服务器,并安装 php,将上文 bi-report 文件夹拷贝到此服务器,于此文件夹下执行指令,打通服务器的网络,即可将此 BI 报表透过 IFrame 的方式输出。
php -S localhost:9000
其它
页面参数
fiveserver 本地调试的时候,PHP 不支持页面参数,如 index.php?page=2,取不到 page 参数。但报表上线后,可透过 $_GET 拿到页面参数。
post 方法的 PHP 写法
php
<?php
// $page = $_GET['page']; // use php command to run app and request index.php?page=1, can use $_GET['page'] to get value.
$url = 'https://url.xxx/xxx';
$data = ['key1' => 'value1', 'key2' => 'value2'];
// use key 'http' even if you send the request to https://...
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'GET',
'content' => http_build_query($data),
],
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === false) {
/* Handle error */
echo "var dataStr = '[]';";
return;
}
function append_string ($str1, $str2) {
// Using Concatenation assignment
// operator (.=)
$str1 .=$str2;
// Returning the result
return $str1;
}
$export = append_string("var dataStr = ", json_encode($result, true));
$export = append_string($export, ";");
echo $export;
?>