dify-message-component
Dify Message Component
企业级 Vue 3 智能对话组件,深度整合 Dify API,提供流式对话、来源溯源、Markdown 渲染等能力。
特性
- 流式对话体验 — 基于 SSE 实现逐字渲染的实时交互
- 来源可追溯 — 集成 Dify Citations & Attributions,支持行内引用角标、来源详情面板
- 丰富内容渲染 — Markdown、代码高亮(highlight.js)、ECharts 图表
- 安全防护 — DOMPurify XSS 清洗、外链安全属性、输入过滤
- 主题切换 — 支持 Light / Dark 双主题,CSS 变量化
- 响应式设计 — 移动端、平板、桌面端自适应
- TypeScript 全类型覆盖 — 完整的类型定义与推断
- Vue Plugin 模式 — 支持全局注册或按需引入
技术栈
| 技术 | 版本 | 说明 |
|---|---|---|
| Vue 3 | 3.4+ | Composition API + <script setup> |
| TypeScript | 5.x | 严格模式 |
| Pinia | 2.x | 状态管理 |
| Vite | 5.x | 构建工具 |
| marked | 12+ | Markdown 解析 |
| highlight.js | 11+ | 代码高亮 |
| DOMPurify | 3+ | XSS 清洗 |
| ECharts | 5+ | 数据可视化 |
快速开始
安装
npm install dify-message-component
npm install vue pinia echarts
vue、pinia、echarts 为 peer dependencies,请在宿主项目中安装。
全局注册(Plugin 模式)
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import DifyMessagePlugin from 'dify-message-component';
import 'dify-message-component/style.css';
const app = createApp(App);
app.use(createPinia());
app.use(DifyMessagePlugin, {
apiBase: '/api/v1',
apiKey: 'your-dify-api-key'
});
app.mount('#app');
按需引入
<template>
<ChatContainer
dify-api-key="your-api-key"
dify-api-base="/api/v1"
theme="light"
@send="onSend"
@stream-end="onStreamEnd"
@error="onError"
/>
</template>
<script setup lang="ts">
import { ChatContainer } from 'dify-message-component';
import 'dify-message-component/style.css';
</script>
工厂函数
import { createChatComponent } from 'dify-message-component';
app.use(createChatComponent({
apiBase: '/api/v1',
apiKey: 'your-dify-api-key',
theme: 'dark'
}));
开发预览
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 构建组件库
npm run build
# 生成类型声明
npm run build:types
# 类型检查
npm run type-check
# 发布前打包校验
npm run pack:check
执行 npm run dev 后,浏览器会打开一个开发预览页面,包含模拟对话数据的完整组件演示。
组件 API
ChatContainer
主容器组件,提供完整的对话功能。
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
difyApiKey |
string |
— | Dify API Key(必填) |
difyApiBase |
string |
'/api/v1' |
Dify API 基础路径 |
conversationId |
string |
— | 会话 ID(可选,若无则新建) |
theme |
'light' | 'dark' |
'light' |
主题模式 |
user |
string |
— | 业务用户标识 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
send |
{ message: ChatMessage } |
消息发送时触发 |
streamStart |
{ messageId: string } |
流式开始时触发 |
streamEnd |
{ citations: Citation[] } |
流式结束时触发 |
error |
{ error: string } |
异常时触发 |
SourcePanel
来源溯源面板(Drawer)。
Props
| 属性 | 类型 | 说明 |
|---|---|---|
visible |
boolean |
面板可见性(v-model) |
citations |
Citation[] |
引用列表 |
Composables
| 名称 | 返回值 | 说明 |
|---|---|---|
useChat(config) |
{ sendMessage, stopStream, clearMessages, regenerateMessage, sendFeedback, error } |
对话编排逻辑 |
useSSE(config) |
{ streamChat, abortSSE, isConnected } |
SSE 连接管理 |
useMarkdown() |
{ render, getEChartsBlocks, clearEChartsBlocks } |
Markdown 渲染 |
useCitation() |
{ activeCitationId, highlightCitation, clearHighlight, scrollToCitation } |
引用交互 |
useECharts() |
{ renderChart, renderAllCharts, resizeAll, disposeAll } |
ECharts 管理 |
类型定义
interface ChatMessage {
id: string;
messageId?: string;
role: 'user' | 'assistant';
content: string;
status: 'pending' | 'streaming' | 'completed' | 'error';
citations: Citation[];
conversationId: string;
createdAt: number;
errorInfo?: string;
}
interface Citation {
id: string;
index: number;
source: string;
url?: string;
snippet?: string;
documentId?: string;
metadata?: {
page?: number;
author?: string;
date?: string;
};
}
项目结构
src/
├── api/ # Dify API 封装
│ └── dify.ts
├── assets/styles/ # 样式系统
│ ├── variables.scss # CSS 变量
│ ├── chat.scss # 组件样式
│ ├── markdown.scss # Markdown 样式
│ └── index.scss # 样式入口
├── components/ # Vue 组件
│ ├── ChatContainer.vue
│ ├── ChatHeader.vue
│ ├── ChatInput.vue
│ ├── MessageList.vue
│ ├── UserMessage.vue
│ ├── AssistantMessage.vue
│ ├── MarkdownRenderer.vue
│ ├── CitationInline.vue
│ ├── SourcePanel.vue
│ └── TypingIndicator.vue
├── composables/ # 组合式函数
│ ├── useChat.ts
│ ├── useSSE.ts
│ ├── useMarkdown.ts
│ ├── useCitation.ts
│ └── useECharts.ts
├── stores/ # Pinia Store
│ └── chat.ts
├── types/ # 类型定义
│ └── chat.ts
├── utils/ # 工具函数
│ ├── sseParser.ts
│ └── citationParser.ts
└── index.ts # 组件库入口
异常降级策略
| 场景 | 降级方案 |
|---|---|
| SSE 连接失败 | 自动降级为阻断模式(blocking) |
| Markdown 解析异常 | 降级为 <pre> 纯文本 |
| ECharts 渲染失败 | 回退为 JSON 文本 |
| 无引用返回 | 隐藏引用区域 |
Dify 后端配置
- 使用 Dify 1.7.0+ 版本
- 知识检索节点开启"返回引用来源"
- LLM 提示词中要求使用
[^index^]格式标注引用
License
MIT
Related Packages
@linto-ai/transcript-ui-plugin-chat
Chat panel plugin for @linto-ai/transcript-ui — talk with an LLM assistant about...
5,748
59
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.0.0 | ^3.4.0 | MIT |