Skip to content

HENGSHI SENSE 嵌入式数据分析场景解决方案

方案概览

要点方案参考备注
账号打通对接 SSO 认证方式,解决应用身份与用户身份的统一认证问题,提供安全可靠的用户身份认证和用户身份传递SSO 文档
单点登录对接 SSO 认证方式,解决应用身份与用户身份的统一认证问题,提供安全可靠的用户身份认证和用户身份传递SSO 文档
功能权限利用用户角色管理用户管理文档
数据权限利用数据连接;
或者利用应用发布权限控制;
或者直接使用发布页面嵌入的参数控制
连接权限权限
发布权限控制
本文档“发布页面嵌入数据过滤指南”部分
创作页面嵌入将衡石产品的链接嵌入 iframe,并加属性 name="export".例如 https://preview.hengshi.com/app 的 iframe 写成 <iframe src="https://preview.hengshi.com/app" name="export"></iframe>创作区页面不支持移动端嵌入
发布页面嵌入支持类似创作区页面的嵌入方式;或者利用发布区页面的分享按钮获取嵌入链接,用 iframe 方式嵌入应用分享嵌入发布区页面支持页面自适应适配
API 支持衡石系统支持客户端模式的 Restful APIAPI 文档

备注:

  1. 页面嵌入支持参数,包括数据过滤和样式定制化两类,下面会分别阐述
  2. 需要的 API 清单需要集成方从产品角度考虑,建议尽量采用页面集成的方式,避免 API 的复杂性;
  3. 在用户角色用户组端,集成方需要考虑功能权限的问题:将用户信息同步到衡石系统;用户注册/删除都将触发衡石 API 的调用,用户角色修改;用户组的协调

分层级嵌入的功能

1. 平台整体嵌入

在这种应用场景中,把所有功能通过 iframe 的方式都开放给登陆用户,嵌入的示例如下:

html
<iframe name="" src="https://preview.hengshi.com/app/1">

img

2. 单个模块嵌入

在这种应用场景中,把一个一级功能通过 iframe 的方式开放给登陆用户,嵌入的示例如下:

html
<iframe name="export,noHeader" src="https://preview.hengshi.com/app/1">

通过指定name="noHeader",嵌入的页面将隐藏最顶端的 banner 以及一级功能的切换菜单。

img

2. 单个实体嵌入

html
<iframe name="export,noHeader,noRoute" src="https://preview.hengshi.com/app/1"></div>

在这种应用场景中,把一个实体通过 iframe 的方式开放给登陆用户。实体的种类可以是一个 app,或者一个数据连接,或者是一个数据科学笔记本,也可以是一个已发布的应用。 嵌入的示例如下:

img

通过指定name="noRoute",嵌入的页面将隐藏功能目录切换的入口。用户的操作就限制在一个应用内部。

使用 appParam 传入参数信息

在仪表盘制作过程中会使用参数控制仪表盘内容的展示。在嵌入场景下,可以通过 appParam 将参数信息拼接到 URL 后面,系统在预览时会将 appParam 中的参数信息转发到最终执行的 SQL 代码中,查看不同参数值下的仪表盘数据信息。

appParam 是数组,可包含多个项目,每个项目是一个 object,为一个参数信息,由3个键值构成。参数可通过 id 或 name 来指定,所以 appParam 的 object 支持两种形式{"appId":1,"id":1,"value":"参数值"}{"appId":1,"name":"参数名称","value":"参数值"}]

每个键值代表的含义如下:

  • appId 是创建参数的数据包或应用的 ID。
  • id 是参数的id,可通过网络请求消息获取。
  • name是参数名称。
  • value是参数值,类型与参数类型保持一致。

嵌入的 URL 和 appParam 拼接后格式为嵌入 url?appParam=[{"appId":1,"name":"参数名称","value":"参数值"}]

提示

appParam 使用说明

  1. appParam 中可使用参数 id 或参数 name 来确定参数,二者选一个即可。
  2. appParam 的 appId 指的是参数创建时的应用 ID,不是参数使用中的应用 ID。如参数在数据集市中数据包 A(appId 为3)中创建,在应用创作中应用 A(appId 为5)中使用,那么在 appParam 中需要输入的 appId 为3。
  3. appParam 的 appId 和参数 id(或参数名称)一起确定参数,如果 appId 省略,可能会导致结果不正确。
  4. appParam 中支持传入多个参数。

appParam 举例

参数控制仪表盘内容展示的方式有很多种,可参照参数使用场景中介绍的方法。 下面以数据集制作图表过程中使用参数为例,介绍如何在嵌入场景下通过 appParam 传入参数。

如图所示,在某医院的就诊信息展示过程中,诊室和出诊医生信息使用科室参数进行内容控制,当改变科室参数时,图表的信息会跟随改变。

仪表盘的 URL 地址为https://develop.hengshi.org/app/127572/dashboard/93,展示内容如下:

使用 appParam 传入科室参数,仅展示消化内科、神经内科两个科室的信息,在 URL 后面拼接 appParam 为https://develop.hengshi.org/app/127572/dashboard/93?appParam=[{"appId":127572,"name":"科室参数","value":["消化内科","神经内科"]}],仪表盘展示如下。

当 appParam 中包含多个参数,如通过科室参数控制科室相关信息,通过地域参数控制就诊用户地域相关信息。 此时拼接后的 URL 为https://develop.hengshi.org/app/127572/dashboard/93?appParam=[{"appId":127572,"name":"科室参数","value":["消化内科","神经内科"]},{"appId":127572,"name":"地域参数","value":["北京","天津"]}],仪表盘展示如下。

发布页面嵌入数据过滤指南

在访问或者嵌入衡石智能分析平台仪表盘/图表的时候,可以在 URL 中添加参数,实现和仪表盘/图表中过滤器类似的功能。下面列举示例介绍,并做详细解释。

示例

https://preview.hengshi.com/share/3B4888A0/dashboard/FC3BBDE7?where=[{%22args%22:[{%22kind%22:%22field%22,%22op%22:%22_c7%22},{%22kind%22:%22constant%22,%22op%22:[%22%E7%AB%A3%E5%B7%A5%22]}],%22datasetId%22:961,%22fieldName%22:%22_c7%22,%22kind%22:%22function%22,%22op%22:%22in%22,%22use%22:%22checkbox%22}]

这个例子里,具体参数为

js
[
    {
        "args": [
            {
                "kind": "field",
                "op": "_c7"
            },
            {
                "kind": "constant",
                "op": [
                    "竣工"
                ]
            }
        ],
        "datasetId": 961,
        "fieldName": "_c7",
        "kind": "function",
        "op": "in",
        "use": "checkbox"
    }
]

含义为过滤_c7字段值为"竣工"的记录。参数的具体解释参考下面的 HQL 部分。

下面介绍下获取这个参数的一个简单方法:

打开 Chrome 浏览器的“开发者工具”,输入 URL: https://preview.hengshi.com/share/3B4888A0/dashboard/FC3BBDE7

打开过滤器,选择项目阶段,并选择值为“竣工”

img

然后查看"开发者工具"的"Network" tab,选择对应的 chart data 接口,查看 Headers 里面的请求参数:

img

找到如上图所示的 where 部分,将它的值 JSON.stringify 后传给 URL 的 where 参数即可,参考上面的示例。

HQL 简介

仪表盘 URL 参数值的语法用的是衡石计算过程描述语言 Hengshi SENSE Query Language (HQL) 。在这里,简单介绍一下 HQL 的语法规则,详情请参考API 文档

语法规定

使用统一的 JSON 来描述各个计算过程. HQL 由多个递归的 HE (Hengshi Expression) 组成.

定义
HE: {
    "uid": "本节点的全局唯一标识符",
    "kind" "节点类型, 可以是 function, field, constant, setgroup, rangegroup, formula, reference 中的任意一种",
    "op", "function 类型的函数名, field 类型的字段名, constant 类型的具体值, setgroup 和 rangegroup 的来源列, formula 的公式, reference 的指向 uid",
    "args": "function 类型的参数, 其他类型节点此项为 null",
    "type": "指定这个节点的数据类型, 可以是 string, number, integer, date, time, json, bool 中的一种",
    "value": "只有 rangegroup 和 setgroup 有这个字段"
    "其他": "特定类型的字段还有各自额外的参数, 另行约定"
}
quickstart

下面看具体的例子. 比如, 我要执行一个 select f1, f2::float * 100 as percent from table 的操作:

js
options.axes = [
    {
        "kind": "field",
        "op": "f1",
    },
    {
        "kind": "field",
        "op": "*",
        "type": "integer",
        "args": [
            {
                "kind": "field",
                "op": "f2",
                "type": "number"
            },
            {
                "kind": "constant",
                "op": 100
            }
        ],
        "uid": "percent"
    }
]

对于上述例子, 我们可以对其进行简写:

js
options.axes = [
    "f1",
    {
        "kind": "function",
        "op": "*",
        "args": ["f2", 100]
    }
]

或者

js
options.axes = [
    "f1",
    {
        "kind": "formula",
        "op": "{f2} * 100"
    }
]
field
js
{
  "kind": "field",
  "op": "field1"
}

或 dataset5.field

js
{
  "kind": "field",
  "op": "field1",
  "args": [{"kind":"dataset", "op":5}]
}
where 过滤

如果需要过滤 price > 20 的商品:

js
where = [
    {
        "kind": "function",
        "op": ">",
        "args": [
            {
                "kind":"field",
                "op": "price",
            },
            {
                "kind": "constant",
                "op": 20
            }
        ]
    }
]

当然, 也可以缩写成:

js
where = [
  {
    "kind": "function",
    "op": ">",
    "args": [
      "time",
      {
        "kind":"constant",
        "op":"2018-12-31",
        "type": "date"
      }
    ]
  }
]

或者

js
where = [
    {
        "kind": "formula",
        "op": "{price} > 20"
    }
]
having 过滤

如果需要过滤 price > 20 的商品:

js
having = [
    {
        "kind": "function",
        "op": "notin",
        args[
            {
                "kind":"reference",
                "op": "x1",
            },
            {
                "kind": "constant",
                "op": [1, 2, 3]
            }
        ]
    }
]

当然, 也可以缩写成:

js
having = [
    {
        "kind": "function",
        "op": "notin",
        "args": [
          {"kind": "reference"},
          [1, 2, 3]
        ]
    }
]

或者

js
having = [
    {
        "kind": "formula",
        "op": "{x1} notin [1, 2, 3]"
    }
]

发布页面嵌入样式定制化指南­

使用衡石智能分析平台制作好 Dashboard 和 Chart 以后,可以通过 iframe 的方式嵌入到已有系统中。为了达到风格统一,嵌入 iframe 的时候支持丰富的定制化选项。

img

定制 Dashboard 的 iframe

参数列表

仪表盘嵌入时支持以下参数。

参数名参数作用参数类型参数值
copyright该参数控制仪表盘页头、页脚显示状态。Boolean参数取值:
true 显示页头页脚,默认为 true。
false 不显示页头页脚。
header该参数控制仪表盘页头显示状态。Boolean参数取值:
true 显示页头,默认为 true。
false 不显示页头。
pager该参数控制仪表盘翻页器显示状态。Boolean参数取值:
true 显示翻页器,默认为 true。
false 不显示翻页器。
scrollable该参数控制仪表盘内滚动行为。Boolean参数取值:
true 支持在仪表盘内滚动,默认为 true。
false 不支持在仪表盘内滚动。
chartAccessible该参数控制仪表盘的图表交互行为。Boolean参数取值:
true 支持打开图表,进行图标交互。 默认为 true。
false 不支持打开图表进行图表交互。
background通过该参数设置仪表盘背景色,如果仪表盘主题已经设置背景色,则该参数不生效。String参数取值样式为 rgba(255,255,255,1)。
wrapperBackground通过该参数设置仪表盘父级 div 元素背景色,可以覆盖仪表盘主题背景色。String参数取值样式为 rgba(255,255,255,1)。
chartTitleColor通过该参数可以设置图表标题颜色,作用范围是仪表盘内所有图表标题(过滤器除外),请谨慎使用。String参数取值样式为 rgba(255,255,255,1)。
chartGap通过该参数可以设置仪表盘内图表之间的间距。String参数使用时需要包含像素信息,如10px。

以下是仪表盘嵌入场景中的废弃参数。

参数名参数作用参数类型参数值废弃说明
padding该参数设置仪表盘内边距。String<number>参数取值样例0 0 0 0不再支持该参数。
chartBackground该参数设置内图表控件背景色。String参数取值样例 rgba(255,255,255,1)不再支持该参数。
chartPadding该参数设置图表内边距。String<number>参数取值样例0 0 0 0不再支持该参数。
borderRadius该参数设置图表控件圆角大小。String参数取值样例2px遵循仪表盘主题设置。
borderWidth该参数设置图表外边框大小。String参数取值样例1px遵循仪表盘主题设置。
borderColor该参数设置图表外边框颜色。String参数取值样式 rgba(255,255,255,1)遵循仪表盘主题设置。
borderStyle该参数设置图表外边框样式。String可设置 solid、dashed、dotted遵循仪表盘主题设置。
filterPadding该参数设置过滤器内边距。String<number>参数取值样例0 0 0 0不再支持该参数。

例子

如下图所示仪表盘,在嵌入时对其背景颜色及图表标题颜色进行修改 。

原始仪表盘链接及样式:

   https://preview.hengshi.com/private/share/E454FF2E910B7B9445C8F66391B25CCA/dashboard/EC0E826AB75FD2AA2C3D755CF8374DD6C

img

嵌入后仪表盘链接及样式:

   https://preview.hengshi.com/private/share/E454FF2E910B7B9445C8F66391B25CCA/dashboard/EC0E826AB75FD2AA2C3D755CF8374DD6C?wrapperBackground=rgba(180,246,254,1)&chartTitleColor=rgb(0,0,0)&copyright=false&scrollable=false>

img

定制 Chart 的 iframe

参数列表

图表嵌入时支持以下参数。

参数名参数作用参数类型参数值
showAction该参数设置右上角交互按钮。Boolean参数取值:
true 显示右上角交互按钮,默认为 true。
false 不显示右上角交互按钮。
chartPadding该参数设置图表内边距。String<number>参数取值样例0 0 0 0。

以下参数为废弃参数,不再支持。

参数名参数作用参数类型参数值废弃说明
noFilter该参数控制是否展示过滤器。Boolean参数取值:
true 显示过滤器,默认为 true。
false 不显示过滤器。
嵌入图表时不再支持展示过滤器。
titleColor该参数设置图表标题颜色展示。String参数取值样式 rgba(255,255,255,1)。嵌入页面不再展示图表标题。
chartBackground该参数设置图表背景色。String参数取值样式 rgba(255,255,255,1)。图表背景色会被图表使用的主题背景色覆盖。

动态改变嵌入 URL 指南

嵌入场景中,经常会遇到根据业务和交互需要,动态修改嵌入页面 URL 的情况。针对这种需求,HENGSHI SENSE 嵌入的页面支持以下2种方式动态修改嵌入 iFrame 的 URL。

PostMessage

嵌入过程中可以使用 PostMessage 动态修改嵌入页面的 URL,支持hs_urlpushhs_urlchange两种方式。使用 PostMessage 动态修改嵌入页面 URL 时不会重新加载页面。

URL push

下面是在 PostMessage 中使用hs_urlpush方式动态修改页面 URL 的示例。

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Local Test</title>
  <style>
    h2 {
      font-size: 16px;
      font-weight: normal;
      color: #999;
    }
    h2 i {
      color: #333;
    }
  </style>
</head>
<body>
  <button onClick="onUrlFilterChange()">发事件</button>
  <iframe
    allowFullScreen="true"
    width="1280"
    height="800"
    frameborder="0"
    id="iframe"
    src="http://192.168.2.243:9998/share/2351A2F5/infographic/46CA0B3B">
  </iframe>
  <script>
    var $iframe = document.getElementById('iframe');
    function onUrlFilterChange() {
      var pathname = '/share/2351A2F5/infographic/46CA0B3B';
      var search = `?where=[{"field":{"fieldName":"_c6","dataset":39713,"label":"time","type":"date"},"dataset":39713,"kind":"function","op":"in","args":[{"kind":"function","op":"dow","args":[{"kind":"field","op":"_c6","dataset":39713}]},{"kind":"constant","op":[${randomNumber(1, 7)}, ${randomNumber(1, 7)}]}]}]`;
      $iframe.contentWindow.postMessage(JSON.stringify({
        event: 'dispatchCustomEvent',
        data: ['hs_urlpush', {
          pathname: pathname,
          search: search,
        }],
      }), '*');
    }
    function randomNumber(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    }
  </script>
</body>
</html>

URL change

系统也支持在 PostMessage 中使用hs_urlchange方式动态修改页面 URL,参考示例如下。

javascript
// JSON.parse(event.data) 后:
{
  event: 'HengshiInteractiveEvent',
  data: {
    event: 'hs_urlchange',
    data: {
      pathname: '/app/xxx?aa=bb',
      search: '?aa=bb'
      query: {
        aa: 'bb',
      },
    },
  },
}

直接修改 iframe.src

可以通过直接编辑 iframe url 来实现嵌入页面 URL 的动态变化,效果和使用 ontentWindow.postMessage 是一样的,只是该方法会使页面重新加载,对性能会略有影响。

js
$iframe.src = 'http://preview.hengshi.com' + pathname + search;

嵌入页面的外部控制

衡石支持使用外部按钮来操作嵌入页面,包括刷新页面内容、导出页面 PDF、PNG 等。

刷新页面

客户嵌入的页面需要刷新仪表盘数据,但是又不希望重新加载 iframe,此时可以通过外部按钮进行刷新。下面是通过外部按钮刷新嵌入页面的代码示例和展示样式,供参考。

html
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button>Refresh</button>
  <iframe
    frameborder="0"
    importance="high"
    allowFullScreen="true"
    width="1080"
    height="800"
    src="https://develop.hengshi.org/private/share/app/EAD43BC71B87137928BB1D7D62E639078">
    </iframe>
  <script>
    const button = document.querySelector('button');
    // 1. 从 iframe 外部点击按钮
    button.addEventListener('click', () => {
      const iframe = document.querySelector('iframe');
      // 2. 给 iframe 发送刷新仪表盘的信息
      iframe.contentWindow.postMessage(JSON.stringify({
        event: 'dispatchCustomEvent',
        // 3. 刷新仪表盘标识符 `hs_dashboard_refresh`
        data: ['hs_dashboard_refresh', {}]
      }), '*');
    });
  </script>
</body>
</html>

导出仪表盘 PDF/PNG

嵌入页面可以通过外部按钮导出仪表盘的 PDF 和 PNG。下面是相关代码示例和展示截图。

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button id="exportPNG">Export PNG</button>
  <button id="exportPDF">Export PDF</button>
  <iframe
    frameborder="0"
    importance="high"
    allowFullScreen="true"
    width="1080"
    height="800"
    src="https://develop.hengshi.org/private/share/app/EAD43BC71B87137928BB1D7D62E639078">
    </iframe>
  <script>
    document.addEventListener('click', e => {
      if (!['exportPNG', 'exportPDF'].includes(e.target.id)) return;
      // 获取导出类型、pdf 或 png
      const type = e.target.id === 'exportPNG' ? 'png' : 'pdf';
      const iframe = document.querySelector('iframe');
      // 发送导出事件 message
      iframe.contentWindow.postMessage(JSON.stringify({
        event: 'dispatchCustomEvent',
        data: ['hs_dashboard_export', {
          type,
        }]
      }), '*');
    });
  </script>
</body>

</html>

监听嵌入页面的事件

在页面交互过程中,使用 postMessage 广播以下事件以方便更好的与业务融合,在业务页面使用 window.addEventListener('message', function handlePostMessage(event) {}) 来监听我们广播出的事件。目前嵌入场景支持以下事件。

  1. 目录、应用变更,包括目录文件夹、应用的新增、修改和删除,应用重新发布。
  2. 点击系统元素,点击对象为应用、文件夹、仪表盘、图表、数据集
  3. URL change handlePostMessage 收到的 event 是 JavaScript 的 MessageEvent,其中 event.data 即为广播内容,event.data 是经过序列化的 JSON 字符串,经过 JSON.parse(event.data) 即可使用。

目录、应用变更

目录、应用变更通过以下结构传递信息,其中 data 是 stringify 的对象,JSON.parse 后可以得到该信息。

  • data.event 是事件类型,包括 updateFolder 文件夹变更、updateApp 应用变更、updatePublish 应用发布变更三种类型。
  • data.data 是事件的具体信息,包括 insert、update、delete、duplicate 四种类型。
javascript
{
  "event": "HengshiInteractiveEvent", // 衡石交互事件标准
	"type": "HengshiInteractiveEvent",
	"data": {
		"event": "updateFolder",    // 事件类型,增删改目录 'updateFolder';增删改应用 'updateApp'; 更新发布 'updatePublish'
		"data": "insert_2198"       // 事件的具体信息,insert、update、delete、duplicate
  }
}

点击系统元素

javascript
// JSON.parse(event.data) 后:
{
  event: 'HengshiInteractiveEvent',
  data: {
    event: 'clickItem',
    data: {
      type: 'app',
      data: {
        id: xxx,
        ...
      },
    },
  },
}

其中 type 是指所点击元素的类型,除 app 外还有

  • publishApp: 发布的应用
  • dashboard: 仪表盘
  • chart: 图表
  • publishChart: 发布的图表
  • dataset: 数据集
  • folder: 文件夹
  • datamart: 数据包

衡石分析平台使用手册