@szjy/ai-coms

vue3 ai component
2,471
Install
npm install @szjy/ai-coms
Latest Version:0.1.17
Vue:3
Last Updated:Sep 16, 2026
Links: npm
Maintainer: boycgit

@szjy/ai-coms — Vue3 AI 聊天组件库

一个基于 Vue 3 与 Element Plus 的即插即用 AI 对话组件(SzAiChat)。支持多家大模型流式对话(Spark、Ollama、SiliconFlow、Kimi Moonshot、DashScope、数智建管、Dify OpenAI 兼容等),内置消息面板、Markdown 渲染与高亮、流式增量显示、复制、消息后处理(messagePostRender)与路由链接渲染(routeLinkRender)等常用能力,帮助你在业务系统中快速集成 AI 助手。

当前版本:0.1.8

适用场景

  • 企业 Web 系统内嵌 AI 助手(客服、知识问答、项目辅助)
  • 快速验证多模型 Chat 能力与对比
  • 低侵入集成到现有前端应用(只需安装与注册组件)

亮点

  • 统一组件:提供 SzAiChat 组件与安装器 create,一行注册、开箱即用。
  • 多模型接入:内置多种大模型接入方法与流式解析器,通过 llmName 属性或 ?llmName= 参数轻松切换。
  • 纯端侧语音识别:内置 Whisper 端侧模型与 Web Worker;麦克风与上传入口默认关闭,通过 enableVoiceInput / enableVoiceUpload 显式开启。
  • 体验完善:欢迎页、快捷提问、消息气泡、Markdown 渲染、复制、抽屉模式切换。
  • 消息后处理:通过 messagePostRender 回调在消息渲染完成后自定义处理 DOM,内置 routeLinkRender 支持 #router:xxx# 路由链接渲染。
  • 友好扩展:将流解析、API 调用、渲染拆分,extraConfig 支持供应商级参数透传,方便替换与扩展。

目录结构说明

ai-coms/
├─ index.ts                      # 库入口:导出组件、安装器、自定义渲染器与音频工具
├─ vite.config.mts               # Vite 构建配置(库模式)
├─ package.json                  # 包信息、脚本与依赖
├─ docs/
│  ├─ message-post-render.md     # messagePostRender 与 routeLinkRender 使用教程
│  └─ voice-recognition.md       # 端侧语音识别与音频功能开发指南
├─ scripts/
│  └─ download_model.py          # Whisper 端侧模型一键下载脚本
├─ public/                       # 静态资源(图片、脚本、svg、语音模型)
│  ├─ sounds/                    # Whisper 本地静态大模型目录
│  ├─ images/                    # 组件使用的图片与图标
│  └─ scripts/ai/                # markdown-it 与 highlight.js 静态脚本
├─ packages/
│  ├─ api/ai.ts                  # 多家大模型的流式请求封装(Fetch + SSE/JSON)
│  ├─ common/
│  │  ├─ utils/                  # 通用工具(剪贴板、URL、loader 等)
│  │  └─ custom-render/          # 自定义消息渲染器
│  │     ├─ index.ts             # 出口汇总
│  │     └─ routeLinkRender.ts   # #router:xxx# 路由链接渲染器
│  └─ components/
│     ├─ components.ts           # 组件出口汇总(当前导出 AiChat)
│     ├─ installer.ts            # 全量安装器,循环注册所有导出的组件
│     ├─ contants.ts             # 版本常量、组件名前缀
│     ├─ create.ts               # 可选按需安装器工厂 `create()`
│     ├─ icons/                  # SvgIcon 组件与内置 svg 资源
│     └─ AiChat/
│        ├─ index.ts             # 导出 `SzAiChat`
│        └─ src/
│           ├─ index.vue         # 包裹入口,悬浮按钮与面板开关、依赖脚本加载
│           ├─ components/
│           │  ├─ ChatPanel.vue  # 主聊天面板、输入区、消息列表
│           │  ├─ Previewer.vue  # Markdown 流式渲染、复制、滚动控制
│           │  └─ plugins/markdown.ts # 生成 markdown-it 实例
│           ├─ transform/        # 流解析与模型映射
│           │  └─ index.ts       # LLMTypes、transformStreamValue、splitStream
│           └─ writer.ts         # 桥接 API 与流 Reader,向预览器输出
└─ examples/                     # 运行示例(Vite)
   ├─ main.ts                    # 示例入口,注册 Element Plus 与组件
   ├─ App.vue                    # 示例页面,包含 Tab 与 AiChat 使用
   └─ components/
      ├─ AiChatTab.vue           # 组件使用样例(token/identifier/baseUrl 传参)
      └─ DifyOpenAIChatTab.vue   # Dify OpenAI 兼容 provider 使用样例

模块依赖与调用流向(简化):

graph TD
  A[App 应用] --> B[create() 安装器]
  B --> C[SzAiChat 组件]
  C --> D[ChatPanel]
  D --> E[createAssistantWriterStylized]
  E --> F[LLMTypes.api (packages/api/ai.ts)]
  F --> G[服务端流接口]
  E --> H[splitStream/transformStreamValue]
  H --> I[Previewer 渲染 Markdown]

环境与依赖配置

  • Node.js: 推荐 >= 18(Vite 5 要求)
  • 包管理:pnpm(推荐)/ npm / yarn
  • 框架:Vue 3(Peer/External)、Element Plus
  • 构建:Vite 5,TypeScript 5

运行所需依赖(节选,详见 package.json):

  • 生产依赖:vue@^3.4.21、element-plus@2.7.1、aa-loader@^0.1.5
  • 开发依赖:vite@^5、@vitejs/plugin-vue、@vitejs/plugin-vue-jsx、vite-plugin-dts、vite-plugin-svg-icons、unplugin-icons + @iconify-json/mdi(示例用 ~icons/mdi)、unplugin-vue-components、typescript、vue-tsc、sass/less 等

浏览器兼容:现代浏览器(需支持 ReadableStream/TransformStream 的流式能力;如需更广兼容度请添加 Polyfill)。

推荐工具:

  • VS Code + Volar 扩展(Vue)
  • ESLint/Prettier(建议但当前仓库未内置配置,可按团队规范自加)

安装与项目运行指南

安装依赖:

pnpm install
# 或
npm install

开发模式(示例站点):

pnpm dev
# 访问 http://localhost:8810

构建库:

pnpm build           # 生产构建(ES/UMD,外部化 vue/element-plus)
pnpm build:dev       # 开发模式构建(保留标识符,便于调试)

预览(示例站点打包后预览):

pnpm preview

关于静态依赖:组件运行时会按需加载 public/scripts/ai 下的 markdown-it.min.js 与 highlight.11.11.1.min.js,请确保这些静态文件可被正确访问(Vite 开发与构建后默认可用)。

关于后端代理:多数大模型的请求路径形如 ${location.origin}/spark/...、/moonshot/... 等,需要在网关或本地开发服务器配置反向代理与鉴权,保证浏览器可直接访问同源路径。


快速上手与主要功能

注册并使用组件:

// examples/main.ts(示例)
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import { SzAiChat, create } from '../index'

const app = createApp(App)
const szAIKits = create({ components: [SzAiChat] })
app.use(ElementPlus).use(szAIKits).mount('#app')

在页面中引入:

<template>
  <sz-ai-chat
    :token="token"
    :identifier="identifier"
    :baseUrl="baseUrl"
    :title="'数智AI助理'"
    llmName="szjy"
    :messagePostRender="handleMessagePostRender"
    :extraConfig="{ projectId: 26 }"
  />
  <!-- 右下角悬浮按钮点击后弹出对话面板 -->
  <!-- 可通过 llmName 属性或 ?llmName=szjy 切换默认大模型 -->
  <!-- 支持 standard/spark/ollama3/siliconflow/moonshot/dashscope/szjy/dify-openai -->
  <!-- e.g. http://localhost:8810/?llmName=spark -->
</template>

组件 Props:

属性 类型 默认值 说明
token string '' 大模型 API 的鉴权 token
identifier string '' 项目/租户标识符(数智建管、Dify 等使用)
baseUrl string '' 自定义接口前缀(数智建管、Dify 等使用)
title string '数智AI助理' 对话面板标题
llmName string 'szjy' 大模型名称,对应 LLMTypes 中的 modelName
messagePostRender Function null 消息渲染完成后的回调 (container, textContent) => void
extraConfig Object {} 额外配置参数,透传给供应商 API(如 { projectId }、{ authToken })
enableVoiceInput boolean false 是否显示麦克风语音输入入口
enableVoiceUpload boolean false 是否显示上传音频/视频识别入口

主要功能:

  • 悬浮入口与关闭:右下角按钮打开对话,悬浮关闭按钮隐藏组件。
  • 欢迎页与快捷提问:无对话时显示欢迎与常见问题,点击自动填充发送。
  • 流式对话:使用 Fetch Response.body + Reader,配合 TransformStream 分割,逐字输出。
  • Markdown 渲染与代码高亮:外链 markdown-it 与 highlight.js,支持标题/列表/链接/代码块。
  • 复制消息:一键复制渲染后的文本内容。
  • 抽屉模式:点击图标切换为右侧抽屉铺满高的会话模式。

核心流程(发送到渲染):

sequenceDiagram
  participant U as 用户
  participant P as ChatPanel
  participant W as createAssistantWriterStylized
  participant A as API 调用 (packages/api/ai.ts)
  participant T as splitStream/transform
  participant R as Previewer

  U->>P: 输入问题并提交
  P->>W: 调用并传入 LLM 类型与参数
  W->>A: 发起 Fetch (stream: true)
  A-->>W: 返回 Response.body ReadableStream
  W->>T: TextDecoderStream + splitStream 按行/JSON 解析
  T-->>R: Reader.read() 增量输出片段
  R-->>U: Markdown 渲染、滚动到底部、完成复制

API 接口文档(前端调用封装)

文件:packages/api/ai.ts(基于浏览器 fetch,返回 Promise<Response>,调用处继续基于 Response.body 进行流式读取)

公共说明:所有接口均使用 POST,默认 stream: true,对于需要鉴权的接口通过 Authorization: Bearer <token> 头传递。所有函数签名统一为 (text, token, identifier, baseUrl, extraConfig),未使用的参数可留空。

函数名 说明 请求路径 认证 主要参数 备注
createDifyOpenAIStylized(text, token, identifier, baseUrl, extraConfig) Dify(OpenAI 兼容) ${ensureFullURL(baseUrl)}/v1/chat/completions Bearer(authToken) text, token, identifier, baseUrl, extraConfig 请求体含 inputs.token、inputs.projectCode,extraConfig.authToken 为 Dify 应用密钥,extraConfig.projectId 可选
createOllama3Stylized(text) 本地 Ollama3 http://localhost:11434/api/chat 否 text 模型固定 llama3
createSparkStylized(text, token) 科大讯飞 Spark ${location.origin}/spark/v1/chat/completions Bearer text, token SSE data: JSON 行,模型 generalv4.0Ultra
createSiliconFlowStylized(text, token) SiliconFlow ${location.origin}/siliconflow/v1/chat/completions Bearer text, token 兼容 OpenAI 接口格式
createKimiMoonshotStylized(text, token) Moonshot ${location.origin}/moonshot/v1/chat/completions Bearer text, token 提供 system 提示
createDashScopeStylized(text, token) 通义千问 ${location.origin}/dashscope/compatible-mode/v1/chat/completions Bearer text, token 兼容 OpenAI 路径
createSZJYStylized(text, token, identifier, baseUrl) 数智建管 ${ensureFullURL(baseUrl)}/support/${identifier}/a Bearer text, token, identifier, baseUrl 业务网关需配置

大模型映射(LLMTypes,packages/components/AiChat/src/transform/index.ts):

modelName label api
standard 模拟数据模型 null(本地模拟,不发起请求)
spark Spark 星火大模型 createSparkStylized
ollama3 Ollama 3 大模型 createOllama3Stylized
siliconflow SiliconFlow 硅基流动大模型 createSiliconFlowStylized
moonshot Kimi Moonshot 月之暗面大模型 createKimiMoonshotStylized
dashscope 通义千问大模型 createDashScopeStylized
szjy 数智建管大模型 createSZJYStylized
dify-openai Dify (OpenAI 兼容) createDifyOpenAIStylized

流解析器(packages/components/AiChat/src/transform/index.ts):

  • splitStream('\n') 将 ReadableStream<string> 按行切分,兼容 SSE data: 与直接 JSON 片段。
  • transformStreamValue 针对各模型对单行数据进行解析,统一返回 { content, done };dify-openai、siliconflow、moonshot、dashscope、szjy 均复用 spark 的 OpenAI 兼容解析逻辑。

在组件中,createAssistantWriterStylized 会把 Response.body 管道化为可读 reader,再交给 Previewer 逐步渲染。


配置与扩展

  • 切换默认模型:使用 llmName 属性,或在地址栏加上 ?llmName=<name>(支持:standard、spark、ollama3、siliconflow、moonshot、dashscope、szjy、dify-openai)。
  • 供应商参数透传:通过 extraConfig 传入供应商级配置(如 Dify 的 authToken、projectId)。
  • 消息后处理:通过 messagePostRender 回调在消息渲染完成后自定义处理 DOM(详见下节)。
  • 自定义图标:SvgIcon 支持传入绝对路径或 /images/svg/*.svg,颜色通过滤镜近似实现。
  • 组件前缀:packages/components/contants.ts 中 COMP_PREFIX = 'Sz',通过 create({ componentPrefix }) 可定制。
  • 版本常量:VERSION 注入自 package.json,在 Vite 中以 __PKG_VERSION__ 注入。

消息后处理与路由链接渲染

组件提供 messagePostRender 回调,在每条 AI 消息流式输出完成、DOM 更新后触发一次,可用于自定义处理渲染后的内容(高亮关键词、埋点、插入自定义元素等)。

// 函数签名
messagePostRender?: (container: HTMLElement, textContent: string) => void

库内置了 routeLinkRender(从 @szjy/ai-coms 导出),可将 AI 输出中的 #router:xxx# 标记自动渲染为可点击的路由链接:

<template>
  <sz-ai-chat :token="token" :messagePostRender="handleMessagePostRender" />
</template>

<script setup lang="ts">
import { routeLinkRender } from '@szjy/ai-coms'
import { useRouter } from 'vue-router'

const router = useRouter()

const handleMessagePostRender = (container: HTMLElement, textContent: string) => {
  routeLinkRender(container, textContent, {
    onRouteClick: (routeName, queryParams) => {
      const routeData = router.resolve({ name: routeName, query: queryParams })
      window.open(routeData.href, '_blank')
    },
    // 可选:自定义链接样式(会与默认样式合并)
    linkStyle: { color: '#536fec', fontWeight: 'bold', textDecoration: 'underline' }
  })
}
</script>

支持的标记格式:

格式 说明
#router:routeName# 简单路由,只有路由名
#router:routeName?a=1&b=2# 带查询参数的路由,? 后解析为 queryParams 对象

完整教程见 docs/message-post-render.md。


szjy-ui fence:AI 结构化输出渲染为可交互组件(驱动 BIM 沙盘等外部页面)

AI 响应中的 ```szjy-ui fence 块(JSON)会渲染为可交互组件(内置 list 容器 / button),用户点击触发动作(内置 postMessage),把 actionParams 原样作为消息体发送到目标窗口——典型场景为 BIM 沙盘构件定位(BIM_SANDBOX 协议,详见《BIM沙盘外部通信文档》)。

<template>
  <!-- 聊天与沙盘同窗口:target 默认 self 即可 -->
  <sz-ai-chat llmName="dify-openai" ... />

  <!-- 宿主页嵌沙盘 iframe:指定目标窗口与真实源 -->
  <sz-ai-chat
    :customUi="{ postMessage: { target: () => sandboxIframe.contentWindow, targetOrigin: 'http://172.17.102.17:5174' } }"
  />
</template>
```szjy-ui
{
  "title": "构件列表",
  "type": "list",
  "gap": 12,
  "items": [
    { "type": "button", "props": { "type": "primary", "content": "查看构件1" },
      "action": "postMessage",
      "actionParams": { "type": "BIM_SANDBOX", "action": "locateComponent", "payload": { "wbsCode": "CHKSLDY-SD-001" } } }
  ]
}
```

特性:流式中 JSON 未完整时降级为代码块、完成后自动切换;回执反馈(成功/失败就地展示,未就绪自动重试);组件/动作均注册表模式,宿主可用 registerSzjyUiComponent / registerSzjyUiAction 扩展。

配套 Mock 模式(不调真实后端):llmName="standard" + :mockResponse="文本" 即可流式输出自定义响应(内置样例 DEFAULT_MOCK_RESPONSE),examples 第 4 个 tab「BIM 沙盘 Mock 联调」提供完整联调环境(mock 编辑 + 沙盘 iframe + 协议消息日志)。

完整文档见 docs/szjy-ui-fence.md。


项目维护规范

  • 代码风格:
    • 建议接入 ESLint + Prettier(当前仓库未内置,推荐团队按规范落地)。
    • TypeScript 严格模式,避免 any;函数与导出接口显式类型标注。
  • 分支管理:
    • main/release 稳定分支;feat/*、fix/*、chore/*、docs/* 分支用于日常迭代。
  • 提交规范:
    • 使用 Conventional Commits(如 feat: ...、fix: ...、docs: ...)。
    • 已内置版本发布脚本:pnpm release(npx commit-and-tag-version)。
  • CI/CD:
    • 建议在 CI 中执行 pnpm i && pnpm build && vue-tsc --noEmit 校验类型与构建产物。
  • 代码审核:
    • 所有 PR 需通过代码评审与预览构建,确保可回滚、可追踪。

常见问题与故障排查(FAQ)

  1. 无法渲染 Markdown 或高亮无效
  • 可能原因:public/scripts/ai/markdown-it.min.js 或 highlight.11.11.1.min.js 未能被加载。
  • 解决:确认构建后静态资源是否在同路径;开发模式下检查网络请求是否 200;必要时调整 base 或静态资源路径。
  1. 流式输出不显示或中断
  • 可能原因:后端未按行输出 data: 或 JSON 片段;跨域/CORS 拦截;代理未配置。
  • 解决:
    • 确认后端开启 stream: true 并按行刷写;
    • 开发环境配置本地域名反向代理到真实 API;
    • 浏览器控制台查看网络流(Fetch/XHR)与 JS 报错。
  1. 请求 401/403 或鉴权失败
  • 可能原因:未正确传入 token、identifier、baseUrl;网关校验不通过。
  • 解决:
    • 在 <sz-ai-chat> 传入合法 token、identifier,并确认 baseUrl 为网关前缀;
    • 检查服务端对 Authorization: Bearer <token> 的解析逻辑。
  1. 图标不显示或颜色不生效
  • 可能原因:SvgIcon 传入的是外链/多色 SVG;过滤器无法覆盖填充色。
  • 解决:优先使用单色 SVG,或在设计时约定可控样式;必要时改为内联 SVG 方案。
  1. 生产打包后 vue/element-plus 重复打包
  • 可能原因:未将其外部化。
  • 解决:本库构建已在 vite.config.mts 配置 external,作为使用方请在你的应用构建中确保仅引用一次依赖。
  1. 使用 Dify(OpenAI 兼容)报鉴权错误或提示缺少 authToken
  • 可能原因:未通过 extraConfig.authToken 传入 Dify 应用密钥(app-xxx),此时会回退到内网默认值并在控制台报错。
  • 解决:在 <sz-ai-chat> 传入 :extraConfig="{ authToken: 'app-xxx', projectId: 26 }",并确认 baseUrl 指向 Dify 实例地址。
  1. #router:xxx# 链接未渲染或点击无跳转
  • 可能原因:未绑定 messagePostRender,或未在 routeLinkRender 的 onRouteClick 中实现跳转逻辑。
  • 解决:参考「消息后处理与路由链接渲染」一节绑定回调;# 为分隔符,路由名与参数不能包含 #。

参考资料与延伸阅读

  • Vite 官方文档:https://vitejs.dev/
  • Vue 3 官方文档:https://vuejs.org/
  • Element Plus:https://element-plus.org/
  • Streams API(ReadableStream/TransformStream):https://developer.mozilla.org/docs/Web/API/Streams_API
  • markdown-it:https://markdown-it.github.io/
  • highlight.js:https://highlightjs.org/
  • OpenAI 风格 Chat Completions 接口模式(兼容生态):https://platform.openai.com/docs/api-reference/chat
  • Ollama 本地模型:https://ollama.com/
  • Moonshot API:https://platform.moonshot.cn/
  • DashScope(通义千问):https://dashscope.aliyun.com/
  • SiliconFlow:https://docs.siliconflow.cn/
  • Dify(OpenAI 兼容接口):https://docs.dify.ai/
  • 科大讯飞 Spark(参考其服务端/网关说明)

如有问题或建议,欢迎提交 Issue/PR 共同完善组件能力与生态。

Related Packages

@szjy/excel-form

vue3 excel form component

1,002

Version History

Version Released Vue License
0.1.17 ^3.4.21
0.1.16 ^3.4.21
0.1.15 ^3.4.21
0.1.14 ^3.4.21
0.1.13 ^3.4.21