Skip to content

通过 JS SDK 集成

JS SDK 集成方式需要您在您的 HTML 文件中(或 Vue/React 组件中)引入 AI 助手的 JS 文件,并调用相关 API。这将需要您拥有一定的 JavaScript 开发经验。

获取 Copilot SDK 链接

您可以进入系统内设置->功能配置->AI 助手->控制台页面,点击选项->Copilot SDK打开集成页面指南,在抽屉弹窗中,您将找到用于集成的 SDK 链接,例如

https://develop.hengshi.org/assets/hengshi-copilot@5.3.js

注意

@5.3 是 SDK 的版本号,请确保您使用的 SDK 版本与您的系统版本一致。系统升级时也需要更新。

在其他系统中集成 Copilot SDK

我们提供了在 vue、react、纯 js 等前端框架中集成 Copilot SDK 的示例代码,您可以根据需要进行选择,这要求您需要有一定的前端开发经验。

js
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI助手</title>
    <script type="text/javascript" src="https://develop.hengshi.org/assets/hengshi-copilot@5.3-SNAPSHOT.js" defer></script>
    <style>
        /* 添加样式(如果需要) */
    </style>
</head>
<body>
    <button id="trigger-ai">唤起AI助手</button>
    <div id="copilot-root" style="display: none;"></div>

    <script>
        const copilotConfig = {
            locale: 'zh-CN',
            draggable: {
                enable: true,
                minWidth: 440,
                minHeight: 440,
                position: {
                    x: window.innerWidth - 480,
                    y: 20,
                },
                size: {
                    width: 440,
                    height: window.innerHeight * 0.8,
                },
                onDragStop: onDragStop,
                onResize: onResize,
            },
            userConfig: {
                dataAppId: 130870,
                datasetId: 1,
            },
        };

        let copilotInstance = null;
        const button = document.getElementById('trigger-ai');
        const copilotRoot = document.getElementById('copilot-root');

        button.addEventListener('click', toggleCopilot);

        function onDragStop(event, position) {
            copilotConfig.draggable.position = position;
        }

        function onResize(event, position, size) {
            copilotConfig.draggable.position = position;
            copilotConfig.draggable.size = size;
        }

        function launchCopilot() {
            if (typeof Copilot === 'undefined') {
                (function(fn) {
                    fn(launchCopilot);
                })(requestIdleCallback || setTimeout);
            } else {
                if (!copilotInstance) {
                    copilotInstance = new Copilot(copilotRoot, copilotConfig);
                    copilotRoot.style.display = 'block';
                    button.textContent = '关闭AI助手';
                }
            }
        }

        function destroyCopilot() {
            if (copilotInstance) {
                copilotInstance.destroy();
                copilotInstance = null;
                copilotRoot.style.display = 'none';
                button.textContent = '唤起AI助手';
            }
        }

        function toggleCopilot() {
            if (copilotInstance) {
                destroyCopilot();
            } else {
                launchCopilot();
            }
        }
    </script>
</body>
</html>
jsx
import React, { useState, useEffect } from 'react';

const CopilotComponent = () => {
  const [copilotInstance, setCopilotInstance] = useState(null);
  const [buttonLabel, setButtonLabel] = useState('唤起AI助手');

  const copilotConfig = {
    locale: 'zh-CN',
    draggable: {
      enable: true,
      minWidth: 440,
      minHeight: 440,
      position: {
        x: window.innerWidth - 480,
        y: 20,
      },
      size: {
        width: 440,
        height: window.innerHeight * 0.8,
      },
      onDragStop: onDragStop,
      onResize: onResize,
    },
    userConfig: {
      dataAppId: 130870,
      datasetId: 1,
    },
  };

  useEffect(() => {
    // 加载 SDK
    const script = document.createElement('script');
    script.src = 'https://develop.hengshi.org/assets/hengshi-copilot@5.3-SNAPSHOT.js';
    script.async = true;
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script); // 清理加载的脚本
    };
  }, []);

  function onDragStop(event, position) {
    copilotConfig.draggable.position = position;
  }

  function onResize(event, position, size) {
    copilotConfig.draggable.position = position;
    copilotConfig.draggable.size = size;
  }

  const launchCopilot = () => {
    if (typeof Copilot === 'undefined') {
      (function(fn) {
        fn(launchCopilot);
      })(requestIdleCallback || setTimeout);
    } else {
      if (!copilotInstance) {
        const copilotRoot = document.getElementById('copilot-root');
        const instance = new Copilot(copilotRoot, copilotConfig);
        setCopilotInstance(instance);
        setButtonLabel('关闭AI助手');
      }
    }
  };

  const destroyCopilot = () => {
    if (copilotInstance) {
      copilotInstance.destroy();
      setCopilotInstance(null);
      setButtonLabel('唤起AI助手');
    }
  };

  const toggleCopilot = () => {
    if (copilotInstance) {
      destroyCopilot();
    } else {
      launchCopilot();
    }
  };

  return (
    <div>
      <button onClick={toggleCopilot}>{buttonLabel}</button>
      {copilotInstance && <div id="copilot-root"></div>}
    </div>
  );
};

export default CopilotComponent;
vue
<template>
  <div>
    <button @click="toggleCopilot">{{ buttonLabel }}</button>
    <div id="copilot-root" v-if="copilotInstance"></div>
  </div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';

export default {
  setup() {
    const copilotInstance = ref(null);
    const buttonLabel = ref('唤起AI助手');

    const copilotConfig = {
      locale: 'zh-CN',
      draggable: {
        enable: true,
        minWidth: 440,
        minHeight: 440,
        position: {
          x: window.innerWidth - 480,
          y: 20,
        },
        size: {
          width: 440,
          height: window.innerHeight * 0.8,
        },
        onDragStop: onDragStop,
        onResize: onResize,
      },
      userConfig: {
        dataAppId: 130870,
        datasetId: 1,
      },
    };

    function onDragStop(event, position) {
      copilotConfig.draggable.position = position;
    }

    function onResize(event, position, size) {
      copilotConfig.draggable.position = position;
      copilotConfig.draggable.size = size;
    }

    function launchCopilot() {
      if (typeof Copilot === 'undefined') {
        (function(fn) {
          fn(launchCopilot);
        })(requestIdleCallback || setTimeout);
      } else {
        if (!copilotInstance.value) {
          copilotInstance.value = new Copilot(document.getElementById('copilot-root'), copilotConfig);
          buttonLabel.value = '关闭AI助手';
        }
      }
    }

    function destroyCopilot() {
      if (copilotInstance.value) {
        copilotInstance.value.destroy();
        copilotInstance.value = null;
        buttonLabel.value = '唤起AI助手';
      }
    }

    function toggleCopilot() {
      if (copilotInstance.value) {
        destroyCopilot();
      } else {
        launchCopilot();
      }
    }

    return {
      copilotInstance,
      buttonLabel,
      toggleCopilot,
    };
  },
};
</script>

<style>
/* 添加样式(如果需要) */
</style>

登录认证

集成 SDK 时,您可能需要进行登录认证。我们提供两种方式:

  1. SSO 单点登录:如果您的系统已与衡石系统集成,无需额外登录。
  2. JWT 认证:通过以下代码使用 JWT 进行登录认证:
js
fetch('https://develop.hengshi.org/api/auth/login-info?activeAuth=jwt-param&jwtParam=您的 JWT 参数')
  .then(response => {
    // 登录成功,继续使用 SDK
  })
  .catch(error => {
    // 登录失败,处理错误
  });

提示

确保您已经在 '设置->组织管理->认证方式->JWT 请求参数' 中配置了 JWT。

请将 '您的 JWT 参数' 替换为实际的 JWT 参数。

在衡石系统内的仪表盘里集成 Copilot

在衡石系统中调用 Copilot 方式与上述 HTML 方式是类似的。

首先,在全局 JS 文件中通过代码加载 Copilot SDK:

js
// 1. 保持 copilot sdk 与系统的 store 数据同步
window.__INITIAL_STATE__ = window._hs_store_.getState();
// 2. 引入 copilot sdk 代码
var script = document.createElement('script');
script.src = 'https://develop.hengshi.org/assets/hengshi-copilot@5.3-SNAPSHOT.js';
script.async = true;
script.onload = function() {
  // 3. 重置 sdk base url
  window.__hs_sdk_base_url__ = undefined;
  // 4. 创建 sdk 容器
  var copilotRoot = document.createElement('div');
  copilotRoot.id = 'copilot-root';
  copilotRoot.style.width = '100%';
  copilotRoot.style.height = '100%';
  copilotRoot.style.position = 'fixed';
  copilotRoot.style.inset = '0';
  copilotRoot.style.zIndex = '9999';
  copilotRoot.style.pointerEvents = 'none';
  document.body.appendChild(copilotRoot);
  // 5. 赋值给自定义 sandbox 变量以便自定义 js 能使用
  window.myJS = window.myJS || {};
  window.myJS.innerWidth = window.innerWidth;
  window.myJS.innerHeight = window.innerHeight;
  window.myJS.Copilot = Copilot;
  window.myJS.CopilotRoot = copilotRoot;
};
document.body.appendChild(script);

然后,您可以在仪表盘中使用控件按钮来唤起 Copilot,在按钮控件的设置中添加点击事件,执行相应的 JS 代码。

js
if (!myJS) {
  throw new Error('hengshi copilot sdk not loaded yet');
}
if (!myJS.copilotConfig) {
  var stylesheet = `html.hengshi-copilot-sdk, html.hengshi-copilot-sdk body {width:100% !important; height: 100% !important;}
    html.hengshi-copilot-sdk body.hst {background: transparent;}
    .react-draggable {pointer-events: all;}`;
  myJS.copilotConfig = {
    locale: 'zh-CN',
    stylesheet: stylesheet,
    closable: true, // 设置对话框可关闭
    draggable: { // 设置对话框拖动功能,不需要拖动功能可以设置为 false 或不设置
      enable: true,
      minWidth: 440,
      minHeight: 440,
      position: {
        x: myJS.innerWidth - 480,
        y: 20,
      },
      size: {
        width: 440,
        height: myJS.innerHeight * 0.8,
      },
      // 设定记住拖动的位置和大小
      onDragStop: onDragStop,
      onResize: onResize,
    },
    // 设置对话数据来源
    userConfig: {
      dataAppId: 354, // 数据包 id
      datasetId: 26, // 数据集 id
    },
  };
}
function onDragStop(event, position) {
  myJS.copilotConfig.draggable.position = position;
}
function onResize(event, position, size) {
  myJS.copilotConfig.draggable.position = position;
  myJS.copilotConfig.draggable.size = size;
}
function launchCopilot() {
  if (typeof myJS.Copilot === 'undefined') {
    (function (fn) {
      fn(launchCopilot);
    })(requestIdleCallback || setTimeout);
  } else {
    myJS.copilot = new myJS.Copilot(myJS.CopilotRoot, myJS.copilotConfig);
  }
}
if (myJS.copilot) {
  myJS.copilot.destroy();
  myJS.copilot = null;
} else {
  launchCopilot();
}

Copilot 配置项

您可以根据需要调整配置项:

ts
// Copilot 配置定义
interface ICopilotConfig {
  userConfig: {
    appId: number;
    chartId?: number;
    dataAppId: number;
    datasetId?: number;
  };
  closable?: boolean;
  draggable?: boolean | {
    enable: boolean;
    minWidth: number;
    minHeight: number;
    bounds: 'window' | 'parent';
    position: {
      x: number;
      y: number;
    };
    size: {
      width: number;
      height: number;
    };
  };
  locale?: string;
  stylesheet?: string;
  className?: string;
  style?: React.CSSProperties;
  bodyClassName?: string;
  bodyStyle?: React.CSSProperties;
  header?: string | React.ReactElement;
  systemMsg?: string;
  parser?: {
    selectText: string;
    onSelect: (chart: any) => void;
  };
  chartTheme?: string | Theme;
}
interface Theme {
  base?: string | number;
  background?: string;
  color?: string;
  fontSize?: number;
  fontFamily?: any;
  fontWeight?: string;
  textAlign?: string;
  borderColor?: string;
  borderWidth?: number;
  borderStyle?: string;
  borderRadius?: number;
  boxShadow?: string;
  chartBackground?: string;
  chartPadding?: number;
  schema?: string[];
  mapTheme?: string;
}

// 创建 Copilot 配置对象
const copilotConfig: ICopilotConfig = {
  userConfig: {
    // appId 和 datasetId 或 chartId 必须提供其中之一
    // 示例:appId: 130870, datasetId: 1 // 数据包 id + 数据集 id
    // 或者
    // appId: 130870, chartId: 1 // 应用 id + 图表 id
  },
  closable: true, // 可选,是否显示关闭按钮,默认为 false
  draggable: {
    enable: false,
    minWidth: 400,
    minHeight: 400,
    bounds: 'window',
    position: {
      x: window.innerWidth - 480,
      y: 20,
    },
    size: {
      width: 440,
      height: window.innerHeight * 0.8,
    },
  },
  locale: 'zh-CN', // 可选,语言设置,默认为中文简体
  stylesheet: '', // 可选,自定义 CSS 样式
  className: '', // 可选,自定义类名
  style: {}, // 可选,自定义样式
  bodyClassName: '', // 可选,对话框内容容器的类名
  bodyStyle: {}, // 可选,对话框内容容器的样式
  header: '', // 可选,标题内额外内容
  systemMsg: '欢迎使用智能分析助手', // 可选,欢迎语,默认值
  parser: {
    selectText: '选择图表', // 按钮文案
    onSelect: (chart) => {
      // 点击按钮时触发的事件,chart 参数需要根据实际使用场景定义类型
      console.log('图表选择事件', chart);
    },
  },
  chartTheme: 'HAWAII_SEA', // 可选,图表主题,参考仪表盘主题
};

自定义 AI 助手样式

如果您想自定义 AI 助手的样式,可以通过以下 CSS 代码实现:

css
/* 示例: 使用 css 批量自定义皮肤样式 */
*, ::before, ::after {
  --brand: #4CAF50; // 这是系统整体的品牌色
}
/* 设置 AI 助手对话框根元素样式 */
.hengshi-copilot-sdk .hst-copilot {
  position: fixed;
  // z-index: 1; // 按需设定
  top: 10vh;
  right: 50px;
  width: 440px;
  height: 80vh;
  border-width: 1px;
}
/* 设置 AI 助手 标题 元素样式 */
.hengshi-copilot-sdk .hst-copilot-header {
  color: #fff;
  background-color: darkslategray;
}
/* 设置 AI 助手 对话区域 元素样式 */
.hengshi-copilot-sdk .hst-copilot-conversations {
  border-color: #aaa;
  background-color: darkslategray;
  height: calc(100% - 50px);
}
/* 设置 AI 助手 消息 元素样式 */
.hengshi-copilot-sdk .hst-copilot-msg,
/* 设置 AI 助手 消息下方 ICON 操作 元素样式 */
.hengshi-copilot-sdk .hst-copilot-msg > .hs-relative > *,
/* 设置 AI 助手 辅助信息 元素样式 */
.hengshi-copilot-sdk .hst-copilot-mark {
  color: #fff;
}
.hengshi-copilot-sdk .hst-copilot-mark .hs-bg-\[color\:var\(--hs-bg-lighter\)\] {
  background-color: transparent;
}
/* 设置 AI 助手 消息下方 ICON 操作 hover 时 元素背景样式 */
.hengshi-copilot-sdk .hover\:hs-bg-\[\#eee\]:hover {
  --tw-bg-opacity: .2;
}
/* 设置 AI 助手 AI 消息气泡 元素样式 */
.hengshi-copilot-sdk .hst-copilot-msg-bot .hst-copilot-msg-inner,
/* 设置 AI 助手 用户消息气泡 元素样式 */
.hengshi-copilot-sdk .hst-copilot-msg-user .hst-copilot-msg-inner {
  border-color: darkgray;
  background-color: darkgray;
}
/* 设置 AI 助手推荐问题的问题气泡背景色 */
.hengshi-copilot-sdk .hst-copilot-msg-inner .hst-copilot-msg-inner {
  background-color: slategray !important;
}
/* 设置 AI 助手 输入内容区域 元素样式 */
.hengshi-copilot-sdk .hst-copilot-prompt {
  color: #fff;
  background-color: darkslategray;
}
/* 设置 AI 助手 输入框 元素样式 */
.hengshi-copilot-sdk .hst-copilot-prompt textarea {
  color: #fff;
  border-color: darkgray !important;
}
.hengshi-copilot-sdk .hst-copilot-prompt .hs-from-\[\#f1f1f1\],
.hengshi-copilot-sdk .hst-copilot-prompt .hs-to-\[\#f1f1f1\] {
  --tw-gradient-to: darkslategray;
}

将上述 css 作为字符串传递在 Copilot 配置中的 stylesheet 即可:

ts
// 创建 Copilot 配置对象
const copilotConfig: ICopilotConfig = {
  ...
  stylesheet: css, 
  ...
};

衡石分析平台使用手册