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

1.1. 方案概览

要点 方案 参考 备注
账号打通 对接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 API API文档

备注:

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

1.2. 分层级嵌入的功能

1.2.1. 1. 平台整体嵌入

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

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

img

1.2.2. 2. 单个模块嵌入

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

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

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

img

1.2.3. 2. 单个实体嵌入

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

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

img

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

1.3. 使用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中支持传入多个参数。

1.3.1. 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":["北京","天津"]}],仪表盘展示如下。

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

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

1.4.1. 示例

{%raw%}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}]{%endraw%}

这个例子里,具体参数为

[
    {"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参数即可,参考上面的示例。

1.4.2. 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 的操作:

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

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

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

或者

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

或dataset5.field

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

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

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

当然, 也可以缩写成:

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

或者

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

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

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

当然, 也可以缩写成:

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

或者

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

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

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

img

1.5.1. 定制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

1.5.2. 定制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)。 图表背景色会被图表使用的主题背景色覆盖。

1.6. 动态改变嵌入URL指南

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

1.6.1. PostMessage

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

URL push

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

<!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,参考示例如下。

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

1.6.2. 直接修改iframe.src

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

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

1.7. 嵌入页面的外部控制

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

1.7.1. 刷新页面

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

<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>

1.7.2. 导出仪表盘PDF/PNG

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

<!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>

1.8. 监听嵌入页面的事件

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

  1. 点击系统元素,点击对象为应用、文件夹、仪表盘、图表、数据集
  2. URL change

handlePostMessage 收到的 event 是 JavaScript 的 MessageEvent,其中 event.data 即为广播内容,event.data 是经过序列化的 JSON 字符串,经过 JSON.parse(event.data) 即可使用。

1.8.1. 点击系统元素

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

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

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

results matching ""

    No results matching ""

    开发场景 HENGSHI SENSE 数据权限解决方案