更新记录

1.0.0(2025-10-29) 下载此版本

用AI对接了大部分DIFY的接口。


平台兼容性

uni-app(4.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
- - - - - - - - - -

Dify Chat 组件

基于 Dify API 的完整聊天组件,采用业务逻辑与 UI 完全解耦的架构设计。

架构设计

三层架构

┌─────────────────────────────────────┐
│       UI 组件层 (Components)         │
│  - index.vue                        │
│  - chat-header.vue                  │
│  - attachment-upload.vue            │
│  - voice-input.vue                  │
│  - history-sidebar.vue              │
│  - message-parser.vue               │
│  - web-search.vue                   │
└────────────┬────────────────────────┘
             │ 使用
             ↓
┌─────────────────────────────────────┐
│    组合式函数层 (Composables)        │
│  - useChat()                        │
│  - useConversation()                │
│  - useFile()                        │
│  - useVoice()                       │
│  - useApp()                         │
└────────────┬────────────────────────┘
             │ 调用
             ↓
┌─────────────────────────────────────┐
│      业务服务层 (Services)           │
│  - chatService                      │
│  - conversationService              │
│  - fileService                      │
│  - voiceService                     │
│  - appService                       │
└────────────┬────────────────────────┘
             │ 调用
             ↓
┌─────────────────────────────────────┐
│         API 层 (API)                │
│  封装所有 11 个 Dify API 接口        │
└─────────────────────────────────────┘

目录结构

components/dify-chat/
├── services/              # 业务服务层
│   ├── api.js            # API 接口封装
│   ├── chat-service.js   # 聊天业务逻辑
│   ├── conversation-service.js  # 会话管理
│   ├── file-service.js   # 文件处理
│   ├── voice-service.js  # 语音处理
│   ├── app-service.js    # 应用配置
│   └── index.js          # 统一导出
├── composables/           # 组合式函数层
│   ├── use-chat.js       # 聊天功能
│   ├── use-conversation.js  # 会话功能
│   ├── use-file.js       # 文件功能
│   ├── use-voice.js      # 语音功能
│   ├── use-app.js        # 应用配置
│   └── index.js          # 统一导出
├── *.vue                  # UI 组件
├── config.js              # 配置文件
└── README.md             # 本文档

API 接口覆盖

已完整集成 Dify API 的全部 11 个接口:

  1. 发送对话消息 - POST /chat-messages
  2. 上传文件 - POST /files/upload
  3. 文件预览 - GET /files/:file_id/preview
  4. 停止响应 - POST /chat-messages/:task_id/stop
  5. 获取会话历史消息 - GET /messages
  6. 获取会话列表 - GET /conversations
  7. 删除会话 - DELETE /conversations/:conversation_id
  8. 语音转文字 - POST /audio-to-text
  9. 文字转语音 - POST /text-to-audio
  10. 获取应用参数 - GET /parameters
  11. 获取应用Meta信息 - GET /meta

使用示例

1. 基础聊天功能

<script setup>
import { useChat } from './composables'

const { 
  messages, 
  isSending, 
  sendMessage, 
  stopMessage 
} = useChat({
  userId: 'user_123',
  onMessageReceived: (chunk) => {
    console.log('收到消息块:', chunk)
  },
  onError: (error) => {
    console.error('发生错误:', error)
  }
})

// 发送消息
async function handleSend() {
  await sendMessage({
    content: '你好,AI助手!',
    files: [],
    inputs: {}
  })
}

// 停止响应
async function handleStop() {
  await stopMessage()
}
</script>

<template>
  <view>
    <!-- 消息列表 -->
    <view v-for="msg in messages" :key="msg.id">
      {{ msg.content }}
    </view>

    <!-- 发送按钮 -->
    <button @click="handleSend" :disabled="isSending">
      {{ isSending ? '发送中...' : '发送' }}
    </button>
  </view>
</template>

2. 会话管理

<script setup>
import { useConversation } from './composables'

const {
  conversations,
  currentConversation,
  isLoading,
  loadConversations,
  createConversation,
  deleteConversation,
  selectConversation
} = useConversation({
  userId: 'user_123',
  autoLoad: true
})

// 创建新会话
function handleCreate() {
  createConversation({ title: '新对话' })
}

// 选择会话
function handleSelect(conversationId) {
  selectConversation(conversationId)
}

// 删除会话
async function handleDelete(conversationId) {
  await deleteConversation(conversationId)
}
</script>

3. 文件上传

<script setup>
import { useFile } from './composables'

const {
  files,
  isUploading,
  uploadProgress,
  chooseAndUpload,
  removeFile
} = useFile({
  userId: 'user_123',
  maxFiles: 5,
  onError: (error) => {
    console.error('上传错误:', error)
  }
})

// 选择并上传文件
async function handleUpload() {
  const results = await chooseAndUpload({
    count: 3,
    type: 'image'
  })
  console.log('上传结果:', results)
}

// 移除文件
function handleRemove(fileId) {
  removeFile(fileId)
}
</script>

4. 语音功能

<script setup>
import { useVoice } from './composables'

const {
  isRecording,
  isTranscribing,
  transcribedText,
  formattedDuration,
  recordAndTranscribe,
  cancelRecording
} = useVoice({
  userId: 'user_123',
  maxDuration: 60000
})

// 录音并转文字
async function handleRecord() {
  const result = await recordAndTranscribe()
  if (result.success) {
    console.log('转录文本:', transcribedText.value)
  }
}

// 取消录音
function handleCancel() {
  cancelRecording()
}
</script>

5. 应用配置

<script setup>
import { useApp } from './composables'

const {
  parameters,
  features,
  openingStatement,
  suggestedQuestions,
  isLoading,
  loadAll,
  refresh
} = useApp({
  userId: 'user_123',
  autoLoad: true
})

// 刷新配置
async function handleRefresh() {
  await refresh()
}

// 检查功能是否启用
console.log('语音转文字:', features.value.speechToText)
console.log('文字转语音:', features.value.textToSpeech)
</script>

6. 完整示例 - 聊天页面

<script setup>
import { ref } from 'vue'
import { useChat, useFile, useVoice, useApp } from './composables'

// 用户ID
const userId = 'user_123'

// 聊天功能
const {
  messages,
  isSending,
  sendMessage,
  stopMessage,
  loadHistory
} = useChat({ userId })

// 文件功能
const {
  files,
  chooseAndUpload,
  buildFileObjects,
  clearFiles
} = useFile({ userId })

// 语音功能
const {
  isRecording,
  transcribedText,
  recordAndTranscribe
} = useVoice({ userId })

// 应用配置
const {
  openingStatement,
  suggestedQuestions,
  features
} = useApp({ userId })

// 输入内容
const inputText = ref('')

// 发送消息
async function handleSend() {
  if (!inputText.value.trim() && files.value.length === 0) return

  await sendMessage({
    content: inputText.value,
    files: buildFileObjects(),
    inputs: {}
  })

  inputText.value = ''
  clearFiles()
}

// 上传文件
async function handleFileUpload() {
  await chooseAndUpload({ count: 5, type: 'all' })
}

// 语音输入
async function handleVoiceInput() {
  const result = await recordAndTranscribe()
  if (result.success) {
    inputText.value = transcribedText.value
  }
}
</script>

<template>
  <view class="chat-page">
    <!-- 开场白 -->
    <view v-if="messages.length === 0" class="opening">
      {{ openingStatement }}
    </view>

    <!-- 消息列表 -->
    <scroll-view class="messages">
      <view v-for="msg in messages" :key="msg.id" 
            :class="['message', msg.role]">
        {{ msg.content }}
      </view>
    </scroll-view>

    <!-- 输入区 -->
    <view class="input-area">
      <!-- 文件列表 -->
      <view v-if="files.length > 0" class="files">
        <view v-for="file in files" :key="file.id">
          {{ file.name }}
        </view>
      </view>

      <!-- 输入框 -->
      <input v-model="inputText" placeholder="请输入消息..." />

      <!-- 按钮组 -->
      <view class="buttons">
        <button @click="handleFileUpload">上传文件</button>
        <button @click="handleVoiceInput" :disabled="isRecording">
          {{ isRecording ? '录音中...' : '语音输入' }}
        </button>
        <button @click="handleSend" :disabled="isSending">
          {{ isSending ? '发送中...' : '发送' }}
        </button>
      </view>
    </view>
  </view>
</template>

直接使用 Service 层

如果需要更底层的控制,可以直接使用 Service 层:

import { chatService, fileService } from './services'

// 直接调用服务
const result = await chatService.sendMessageStreaming({
  query: '你好',
  user: 'user_123',
  conversation_id: 'conv_123',
  onChunk: (chunk) => {
    console.log('消息块:', chunk)
  }
})

API 配置

在使用前需要配置 API 地址和授权信息:

import { API } from './services'

API.setApiConfig({
  baseUrl: '',
  authorization: '',
  timeout: 30000
})

特性

  • 完全解耦:业务逻辑与 UI 完全分离
  • 响应式:基于 Vue 3 Composition API
  • 类型安全:完整的参数验证
  • 错误处理:统一的错误处理机制
  • 缓存机制:智能缓存提升性能
  • 流式支持:完整的流式消息处理
  • 文件管理:完善的文件上传下载
  • 语音功能:录音、转文字、播放
  • 会话管理:完整的会话生命周期
  • 配置灵活:丰富的配置选项

注意事项

  1. 用户标识:所有接口都需要传入 userId,确保在应用内唯一
  2. 会话ID:流式消息第一次调用不需要 conversation_id,后续会自动返回
  3. 文件上传:先上传文件获取 file_id,再在发送消息时引用
  4. 语音格式:支持 mp3, m4a, wav, webm 等格式,最大 15MB
  5. 错误处理:建议所有调用都添加错误处理回调

许可

MIT License

隐私、权限声明

1. 本插件需要申请的系统权限列表:

录音权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。