ai-assistant-plugin

Vue2 AI 助手浮层插件:无 Element UI 依赖,支持主动唤起、多轮对话、部门数据透传
1,125
Install
npm install ai-assistant-plugin
Latest Version:1.0.6
Vue:2
License:MIT
Last Updated:Sep 18, 2026
Links: npm
Maintainer: david.zhang

ai-assistant-plugin

Vue 2 的 AI 助手浮层插件,无 Element UI 依赖,纯 Vue 2 + 原生 CSS。对接周报生成(PMS AIOps)的流式 SSE 接口,支持主动唤起、多轮对话、结果回填。

功能特性

  • 🪟 右下角浮层:非模态,默认 630×560 贴右下角,不遮挡页面操作
  • 🖱️ 拖拽移动:按住头部标题栏拖动
  • 📐 拖拽缩放:右边缘 / 下边缘 / 右下角三个手柄调整宽高
  • 💬 多轮对话:消息气泡,可连续追问
  • ⚡ 结果操作:一键「插入 / 替换 / 复制 / 重新生成」
  • 📌 固定侧边栏:可固定为右侧全高面板
  • 🏢 外部数据透传:唤起时传入 externalData,随请求体带给后端
  • ⌨️ 输入框自适应:随内容撑高,最高 120px,超出滚动

一、安装

已构建为编译产物(dist/),源码不发布,使用方无需额外配置:

npm install ai-assistant-plugin

二、引入并初始化

在项目入口(如 main.js):

import Vue from 'vue'
import AiAssistant from 'ai-assistant-plugin'

Vue.use(AiAssistant, {
  apiPrefix: '/api',   // 宿主代理前缀,默认 '/api'
  token: 'Bearer 你的token',   // 必填。完整凭据,原样作为 Authorization 发出
  title: 'AI 助手'
})

Vue.use 的第二个参数会作为全局默认值保存,之后每次 open(config) 都以 { ...默认值, ...config } 合并。因此这里能配的项和 open(config) 完全一样。

安装后所有组件内均可通过 this.$aiAssistant 访问。

三、主动唤起

this.$aiAssistant.open({
  externalData: { bizType: 'order', bizId: '10086' },
  context: this.name,
  onApply: ({ text, mode }) => {
    this.name = mode === 'replace' ? text : (this.name || '') + text
  }
})

open(config) 参数

字段 类型 默认 说明
title String 'AI 助手' 面板标题
context String '' 上下文(如输入框现有内容),会拼进发给 AI 的消息
baseUrl String — 完整接口地址。给了就整段替换,优先级最高
apiPrefix String '/api' 宿主代理前缀,拼在内置路径前。传 '' 表示不挂前缀
token String 必填 完整凭据(含 Bearer 前缀),原样作为 Authorization 发出,插件不再拼前缀
externalData Object null 外部数据,非空时作为 body.externalData 透传给后端
onApply Function null 「插入 / 替换」的回填回调,参数 { text, mode }

接口地址如何决定

baseUrl 传了   →  就用 baseUrl(整段替换,apiPrefix 不参与)
baseUrl 没传   →  apiPrefix + '/pms-aiops/v1/agent/pms/wr/stream'

实际效果:

配置 实际请求地址
都不传 /api/pms-aiops/v1/agent/pms/wr/stream
apiPrefix: '/gateway' /gateway/pms-aiops/v1/agent/pms/wr/stream
apiPrefix: '' /pms-aiops/v1/agent/pms/wr/stream
baseUrl: 'http://10.0.0.9:8080/x' http://10.0.0.9:8080/x

代理要求:默认地址是相对路径,需要宿主项目为 apiPrefix 配好代理转发到真实服务。以 /api 为例:

devServer: {
  proxy: {
    '/api': {
      target: 'http://真实服务:端口',
      changeOrigin: true,
      pathRewrite: { '^/api': '' }   // 剥掉前缀,转发 /pms-aiops/v1/...
    }
  }
}

代理没配好时的现象:dev server 常把未匹配路由回退成 index.html(200 + HTML)。插件读到 0 个事件,于是静默返回空内容——不报错、也不卡在「生成中」,只是没有回答。遇到这个现象先查代理,不是插件故障。

四、完整 API

成员 类型 说明
$aiAssistant.open(config) 方法 主动唤起,返回组件实例
$aiAssistant.close() 方法 关闭面板(会先中止进行中的请求)
$aiAssistant.isOpen 属性 是否打开中(只读)
$aiAssistant.destroy() 方法 销毁全局实例并移除 DOM

具名导出(不使用 Vue.use 时):

import { AiAssistant, generate } from 'ai-assistant-plugin'
  • AiAssistant —— 组件本体,可单独注册或嵌入页面
  • generate(params) —— 底层 SSE 调用函数,签名 { message, sessionId, baseUrl, apiPrefix, token, externalData, signal, onEvent },返回 Promise<string>(累积的 markdown),onEvent 收到每个原始 SSE 事件对象

五、接口约定

插件向 baseUrl(或 apiPrefix + 内置路径)发起请求:

POST <接口地址>
Content-Type: application/json
Authorization: <token>
Accept: text/event-stream

其中 <token> 就是传入的完整凭据(含 Bearer 前缀),插件原样发出,不做拼接。

请求体:

{
  "input": "用户输入",
  "sessionId": "agent-session-<token 去掉 Bearer 前缀>",
  "externalData": { "bizType": "order" }
}
  • sessionId 默认由 token 拼成('agent-session-' + token 去掉 Bearer 前缀),同一 token 复用同一会话,用于保持多轮上下文
  • externalData 仅当传入非空对象时才出现在请求体里;传 {} 或不传都不会带上该字段

响应为 SSE(text/event-stream),事件按 type 字段区分:

事件 type 说明
THINKING_BLOCK_START 模型开始思考
TEXT_BLOCK_DELTA 正式回答增量,取 delta 字段累积
AGENT_END 终止事件,收到即结束本次请求
其它(TOOL_CALL_* / TOOL_RESULT_* / AGENT_RESULT) 会透传给 onEvent,内置 UI 当前不展示

插件读到流关闭(done)或收到 AGENT_END 都会收尾并主动释放连接。这一点是必要的——服务端发完 AGENT_END 后通常不会主动断流,只等断流会导致界面一直卡在「生成中」。

六、回填说明(onApply)

用户点击「插入」或「替换」时触发 onApply({ text, mode }):

onApply: ({ text, mode }) => {
  if (mode === 'replace') {
    this.value = text
  } else {
    // 简化示例:追加到末尾;实际项目可结合 selectionStart/End 插到光标处
    this.value = (this.value || '') + text
  }
}
  • mode === 'replace':整体替换
  • mode === 'insert':插入

七、交互说明

操作 方式
移动面板 按住头部标题栏拖动
调整宽度 / 高度 / 宽高 拖拽右边缘 / 下边缘 / 右下角手柄
固定侧边栏 点头部固定图标
关闭 点头部 × ,或按 Esc
发送消息 输入框按 Enter(Shift+Enter 换行)
停止生成 生成中点击红色停止按钮
重新生成 回答下方的 ↻ 按钮

八、目录结构

ai-assistant-plugin/
├── src/
│   ├── index.js                  # 入口(install + $aiAssistant API)
│   ├── components/
│   │   └── AiAssistant.vue       # 核心浮层组件
│   └── services/
│       └── chat.js               # SSE 接口调用
├── dist/                         # 构建产物(发布用)
│   ├── ai-assistant.common.js    # main 指向
│   ├── ai-assistant.umd.js
│   └── ai-assistant.umd.min.js
├── package.json
└── README.md

九、开发与发布

npm run build    # 改完源码必须重新构建——私仓消费的是 dist,不是 src
npm publish      # 升级 package.json 的 version 后发布

⚠️ 产物必须保持在 ES2019 以内(别破坏 webpack 4 兼容)

使用方里有 webpack 4 的项目,而 webpack 4 依赖的 acorn 最高只支持 ES2019。产物里一旦出现 ?.(可选链)或 ??(空值合并)这类 ES2020 语法,使用方构建直接失败。

这个坑很隐蔽——源码干净、本机编译成功、产物自己跑也没事,只有使用方会炸。已经踩过三次,来源各不相同:

来源 表现 对应措施
依赖 marked v18 自带 31 处 ?.、4 处 ?? transpileDependencies: ['marked'] 交给 babel 转译
构建链缺 babel 本工程 devDependencies 缺 @vue/cli-plugin-babel,导致上一条是空转,依赖原样进产物 已补装该依赖
压缩器 terser 把 x == null ? a : x 优化成 x ?? a,在压缩阶段二次引入 terserOptions.ecma: 2019 锁住

所以下面三样都不要动:

  • 不要改 .browserslistrc——它压到 Chrome 79 / FF 73 / Safari 13 / Edge 79(最后一批还不支持 ?. 的版本),是逼 babel 转译 ES2020 语法的开关
  • 不要拿掉或调高 vue.config.js 里的 terserOptions.ecma,也不要去掉 transpileDependencies
  • 不要删 babel.config.js,删了 babel 就完全不参与构建

另外别在 src/ 里直接写 ?. / ??。现在有 babel 兜底不会出错,但每处可选链展开成三元都很啰嗦,会白白撑大产物(当前 153KB 里相当一部分就是转译 marked 的代价)。

改完必须自检——这是唯一可靠的验收方式,三个产物都要通过:

node -e "
const acorn=require('./node_modules/acorn'), fs=require('fs');
for (const f of ['dist/ai-assistant.common.js','dist/ai-assistant.umd.js','dist/ai-assistant.umd.min.js']) {
  try { acorn.parse(fs.readFileSync(f,'utf8'),{ecmaVersion:2019,sourceType:'script',allowReturnOutsideFunction:true}); console.log(f,'OK'); }
  catch(e){ console.log(f,'FAIL',e.message); }
}"

babel.config.js 里的 useBuiltIns: false 是有意为之:库不该自带 polyfill(既撑大体积——实测从 367KB 降到 153KB,又会污染使用方的运行环境)。它不影响语法降级,语法目标仍由 .browserslistrc 控制。代价是老浏览器缺失的运行时 API 需由使用方自行 polyfill(如 marked 用到的 Array.prototype.at())。

注意

  • token:源码不内置任何凭据(避免敏感信息随包发布),token 为必填项。未传时 generate 会直接抛错「缺少 token」,错误会显示在对话面板上。请由接入方从自身的登录态/环境变量读取后传入,不要硬编码进仓库。
  • peerDependency:仅 vue@^2.6.0,不依赖 Element UI。
  • 运行时依赖:marked,用于渲染回答中的 markdown。

Related Packages

tax-ai

AI assistant component library for Vue 3

4,109
@assistant-ui/vue

Vue bindings for assistant-ui

1,101 12,692
@huyooo/ai-chat-frontend-vue

AI Chat Frontend - Vue components with adapter pattern

12,303
punine-design

一个基于 Vue 3 的 AI 聊天插件,通过Langchain.js、DeepSeek API Key快速构建自定义...

3,987
@eyzenai/vue

The Eyzen chat for Vue 3 and Nuxt.

172

Version History

Version Released Vue License
1.0.6 ^2.6.0 MIT
1.0.5 ^2.6.0 MIT
1.0.4 ^2.6.0 MIT
1.0.3 ^2.6.0 MIT
1.0.2 ^2.6.0 MIT