Skip to content

通过 iframe 集成 ChatBI

iframe 有两种常见用法:

  1. 直接嵌入完整 ChatBI 页面,最快得到一整页问答体验。
  2. 在父页面加载 Copilot JS SDK,再把衡石仪表盘放进 iframe,由父页面 Copilot 接管 iframe 内的智能助理能力。

建议先看总览

如果你们还没判断清楚运行方式和接入方式的关系,建议先读 Data Agent 集成总览

方式一:嵌入完整 ChatBI 页面

这种方式适合:

  • 希望最快上线一个可用入口
  • 前端资源有限,不想自己实现聊天界面
  • 接受直接复用衡石完整页面
  • 不打算把聊天结果拆成自己页面里的多个局部模块

最小示例:

html
<iframe
  src="https://your-hengshi-host/copilot"
  width="100%"
  height="100%"
  style="border: 0;">
</iframe>

只要当前浏览器已经具备衡石登录态,或者你们已经完成了单点登录,页面就可以直接显示 ChatBI。

常用 URL 参数

指定数据来源

与图表所在数据源对话:

text
?appId={应用 ID}&chartId={图表 ID}

与数据包数据模型对话:

text
?dataAppId={数据包 ID}&datasetId={数据集 ID}

与多个数据源对话:

text
?dataSources=[{"dataAppId":{数据包 ID1},"datasetId":{数据集 ID1}},{"dataAppId":{数据包 ID2},"datasetId":{数据集 ID2}}]

提示

dataSources 需要先做 URL encode。

指定图表主题

text
?chartTheme={仪表盘主题 ID}

只显示指定对话

text
?conversationId={对话ID1,对话ID2}&chatUid={uid1,uid2}

登录认证

text
?activeAuth=jwt-param&jwtParam={JWT 参数}

方式二:父页面 Copilot SDK 接管 iframe 仪表盘

如果你们自己的门户页已经通过 JS SDK 集成 放了 Copilot 助手,同时又希望在页面中嵌入衡石仪表盘,就使用这种方式。

这种方式的效果是:

  • Copilot 侧边栏只显示在父页面,不再显示在 iframe 仪表盘里
  • iframe 仪表盘里的“打开助手”“智能解读”“图表解读”等入口会打开父页面 Copilot
  • Agent 需要读取或编辑 iframe 仪表盘时,会通过 iframe 代理出来的业务动作和业务对象完成
  • 父页面路径可以是任意路径,也可以和衡石不同域,不依赖 /sdk/ 这样的测试路径

最小可运行示例

下面示例假设:

  • 父页面是你们自己的门户页面
  • Copilot JS SDK 加载自衡石服务
  • iframe 内嵌的是衡石仪表盘 /app/{appId}/dashboard/{dashboardId}
  • 父页面 Copilot 接管 iframe 内的智能助理能力
html
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <title>Copilot SDK + iframe Dashboard</title>
  <script>
    window.__hs_sdk_base_url__ = 'https://your-hengshi-host';
  </script>
  <script src="https://your-hengshi-host/assets/hengshi-copilot@<version>.js"></script>
  <style>
    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
    }

    #dashboard-frame {
      width: 100%;
      height: 100%;
      border: 0;
    }
  </style>
</head>
<body>
  <div id="copilot-root"></div>
  <iframe id="dashboard-frame" title="HENGSHI Dashboard"></iframe>

  <script>
    const hengshiHost = 'https://your-hengshi-host';
    const appId = 43900;
    const dashboardId = 2;

    const dashboardUrl = new URL(`/app/${appId}/dashboard/${dashboardId}`, hengshiHost);
    dashboardUrl.searchParams.set('agentHost', 'parent');
    dashboardUrl.searchParams.set('parentOrigin', window.location.origin);

    document.getElementById('dashboard-frame').src = dashboardUrl.toString();

    const copilot = new window.Copilot(document.getElementById('copilot-root'), {
      locale: 'zh-CN',
      draggable: {
        enable: true,
        bounds: 'window',
        minWidth: 440,
        minHeight: 440,
        position: { x: window.innerWidth - 480, y: 24 },
        size: { width: 440, height: window.innerHeight - 48 },
      },
    });
  </script>
</body>
</html>

通常不需要手动注册 iframe。父页面加载 hengshi-copilot@<version>.js 后,SDK 会跟踪页面中的 iframe;iframe 页面通过 URL 参数声明由父页面接管后,两边会自动建立通信。

iframe URL 参数

参数是否推荐说明
agentHost=parent推荐让 iframe 内的 Agent / Copilot 能力由父页面 SDK 承接。
copilotHost=parent可用agentHost=parent 的兼容写法。新接入优先使用 agentHost=parent
parentOrigin={父页面 origin}推荐指定允许通信的父页面 origin,例如 https://portal.example.com。只写 origin,不带路径、query 或通配符。
copilotParentOrigin={父页面 origin}可用parentOrigin 的兼容写法。
agentHost=local可用明确让 iframe 页面使用自己的 Copilot,不由父页面接管。
copilotHost=local可用agentHost=local 的兼容写法。
agentBridge=true高级只显式打开 Agent 桥接,不等同于完整的父页面 Copilot 接管。普通接入不要优先使用。

推荐写法:

text
https://your-hengshi-host/app/43900/dashboard/2?agentHost=parent&parentOrigin=https%3A%2F%2Fportal.example.com

parentOrigin 用于安全校验。配置后,iframe 只接受这个 origin 的父页面消息;配置错误时不会自动退回到宽松模式。

接管后的行为边界

父页面接管后,用户看到的是一个 Copilot:

  • iframe 仪表盘不再显示自己的 Copilot 侧边栏
  • 用户点击仪表盘里的智能助理入口时,会打开父页面 Copilot
  • 父页面 Copilot 的 actions 区域可以显示 iframe 仪表盘提供的“智能解读”
  • 图表上的“解读”会把图表上下文发送给父页面 Copilot

对 Agent 来说,iframe 仪表盘不是父页面 DOM 的一部分。Agent 不应该通过父页面的点击、拖拽或路由跳转去操作 iframe 内部内容,而是通过 iframe 代理出来的业务能力读取和修改仪表盘。

调试日志里如果看到 execute_actioninspect_elementread_pathpatch_object 等工具访问 iframe 仪表盘,这是正常行为。它们用于读取仪表盘上下文、查看图表配置和提交 dashboard patch。

跨域和安全要求

跨域接入时请确认:

  • iframe src 指向真实的衡石页面 URL,例如 /app/{appId}/dashboard/{dashboardId}
  • 父页面加载了 hengshi-copilot@<version>.js
  • iframe URL 带上 agentHost=parent
  • iframe URL 带上准确的 parentOrigin
  • 衡石站点允许被你们的门户页面 iframe 嵌入
  • 如果 iframe 使用 sandbox,至少需要允许脚本运行和同源能力,例如 allow-scripts allow-same-origin
  • 登录态、JWT 或 SSO 能让 iframe 页面和父页面 SDK 都正常访问衡石接口

通信安全边界是 origin,而不是页面路径。父页面可以是任意路径,但 origin 必须和 parentOrigin 完全一致。

本地联调 Q&A

Q:本地怎么跑一个 SDK + iframe dashboard 的验证页?

研发本地环境通常可以用下面方式验证:

bash
make production
bash ./nginx.sh
brew services reload nginx

然后访问本地代理地址,例如:

text
http://localhost:8881/

如果父页面和衡石站点分开跑,常见组合是:

text
父页面:http://localhost:8882/
iframe:http://localhost:8881/app/{appId}/dashboard/{dashboardId}?agentHost=parent&parentOrigin=http%3A%2F%2Flocalhost%3A8882

/sdk/ 只是本地测试页路径,不是产品协议要求。真实接入时父页面路径可以由你们自己的系统决定。

Q:为什么 iframe 里没有 Copilot 侧边栏?

当 iframe URL 使用 agentHost=parent,这是预期行为。Copilot 侧边栏由父页面 SDK 统一承接,iframe 内不再重复显示自己的侧边栏。

Q:为什么父页面 Copilot 没有显示“智能解读”?

优先检查这些点:

  • 父页面是否已经加载 hengshi-copilot@<version>.js
  • iframe URL 是否带了 agentHost=parent
  • parentOrigin 是否和父页面 origin 完全一致
  • iframe 页面是否已经加载到仪表盘页,而不是登录页、空白页或错误页
  • 当前用户是否有读取该仪表盘和图表的权限
  • 浏览器控制台是否有 iframe 被 CSP、X-Frame-Options 或登录态拦截的错误

Q:Agent 为什么不能直接用浏览器点击 iframe 内部按钮?

父页面 SDK 场景下,Agent 的浏览器窗口是父页面,不是 iframe 内部页面。直接点击、导航或拖拽只能作用在父页面上。

正确方式是让 iframe 仪表盘通过桥接暴露业务动作和业务对象,Agent 再通过这些能力读取、解读或修改仪表盘。

Q:/api/chat/completions 报 400 或 500,和 iframe bridge 有关吗?

通常不是同一个问题。iframe bridge 负责父页面和 iframe 之间的上下文、动作和消息通信,不会把聊天请求体改成另一种 JSON 格式。

排查顺序建议是:

  • 400 且提示 JSON parse error:检查请求体是否是合法 JSON,content-type 是否是 application/json
  • 401 / 403:检查登录态、JWT、CSRF 和用户权限
  • 本地 nginx 返回 500:先看 nginx error log,再确认 /api 代理到了预期后端,例如 develop 或 rc 环境
  • 后端返回 500:继续看后端服务日志和模型配置

iframe 不适合解决什么问题

  • 不适合深度定制聊天窗口内部 UI
  • 不适合把问答结果拆成多个业务模块嵌入不同位置
  • 不适合只拿后端能力而不复用页面
  • 不适合当成标准图表协议输出能力来使用

如果后续需要这些能力,通常意味着应该改看 JS SDK 集成API 集成

一句话总结

如果只想最快嵌入完整 ChatBI,直接 iframe /copilot

如果父页面已经使用 Copilot JS SDK,同时 iframe 里嵌的是衡石仪表盘,就在 iframe URL 上使用 agentHost=parent,让父页面 Copilot 统一接管 iframe 内的智能助理能力。

衡石分析平台使用手册