npm package: @flexem/chat-box
Description: chat box
Author: songkaige
Latest version: 1.0.12

# @flexem/chat-box

微信小程序 AI 聊天组件，提供完整的聊天界面和功能，支持文本、语音、图片等多种交互方式。

## 功能特性

- ✅ 完整的聊天界面
- ✅ 支持文本、语音输入
- ✅ 支持图片、文件上传
- ✅ 流式输出（SSE）
- ✅ 语音播放（TTS）
- ✅ 会话管理（创建、切换、删除）
- ✅ 消息历史加载
- ✅ 消息编辑、重新生成
- ✅ 自定义导航栏
- ✅ 侧边栏会话列表

## 安装

### 方式一：npm 安装（推荐）

```bash
npm install @flexem/chat-box
```

### 方式二：本地构建

```bash
# 克隆项目
git clone <repository-url>

# 安装依赖
npm install

# 构建组件
npm run build
```

构建后的组件位于 `miniprogram_dist` 目录。

## 快速开始

### 1. 小程序配置

#### 1.1 构建 npm

在小程序开发者工具中：
1. 点击菜单 `工具` -> `构建 npm`
2. 等待构建完成

#### 1.2 配置 app.json

```json
{
  "usingComponents": {
    "chat-box": "@flexem/chat-box/index"
  },
  "permission": {
    "scope.record": {
      "desc": "需要使用您的麦克风进行语音输入"
    }
  },
  "requiredPrivateInfos": [
    "chooseImage",
    "chooseMessageFile"
  ]
}
```

#### 1.3 配置服务器域名

在小程序管理后台配置以下域名（根据实际环境调整）：

**request 合法域名：**
- `https://ids-dev.platform.flexem.net`（IDS 服务）
- `https://chatweb-dev.platform.flexem.net`（AI 聊天服务）
- `https://chatbg.fbox360.com`（线上AI 聊天服务）
- `https://usso.fbox360.com`（线上IDS 服务）
- `https://oss-dev.platform.flexem.net`（线上OSS 服务）
- `https://os.fbox360.com`（线上OSS 服务）
- `https://up-z2.qiniup.com`（七牛云上传）

**uploadFile 合法域名：**
- `https://up-z2.qiniup.com`

**downloadFile 合法域名：**
- `https://blobstorage-dev.platform.flexem.net`（文件下载服务）
- `https://fuf.flexem.net`（线上文件下载服务）

### 2. 页面配置

在需要使用聊天组件的页面 JSON 文件中：

```json
{
  "usingComponents": {
    "chat-box": "@flexem/chat-box/index"
  },
  "navigationStyle": "custom"
}
```

**注意：** 必须设置 `"navigationStyle": "custom"`，因为组件使用自定义导航栏。

### 3. 页面使用

#### 3.1 WXML

```xml
<chat-box
  idsServiceUrl="{{idsServiceUrl}}"
  isToken="{{isToken}}"
  data="{{data}}"
  userInfo="{{userInfo}}"
  speechRecognitionManager="{{speechRecognitionManager}}"
  bind:login="onLogin"
/>
```

#### 3.2 JavaScript

```javascript
const plugin = requirePlugin('WechatSI');
const manager = plugin.getRecordRecognitionManager();

Page({
  data: {
    // IDS 服务地址（必填）
    idsServiceUrl: 'https://ids-dev.platform.flexem.net',

    // 是否为 Token（必填）
    // true: data 是 Token，直接使用
    // false: data 是加密数据，需要组件内部解析
    isToken: false,

    // Token 或加密数据（必填）
    data: '',

    // 用户信息（必填）
    userInfo: {
      name: '用户昵称',
      avatar: 'https://example.com/avatar.jpg'
    },

    // 语音识别管理器（必填，用于语音输入）
    speechRecognitionManager: null
  },

  onLoad() {
    // 初始化语音识别
    if (plugin && manager) {
      this.setData({
        speechRecognitionManager: manager
      });
    }

    // 初始化用户信息
    this.initUserInfo();
  },

  // 初始化用户信息
  initUserInfo() {
    // 从缓存或登录接口获取用户信息
    const data = wx.getStorageSync('data');
    const userInfo = wx.getStorageSync('userInfo');

    if (data && userInfo) {
      this.setData({
        data: data,
        userInfo: {
          name: userInfo.nickName || userInfo.name,
          avatar: userInfo.avatarUrl || userInfo.avatar
        }
      });
    } else {
      // 未登录，跳转到登录页
      this.onLogin();
    }
  },

  // 登录事件
  onLogin() {
    wx.navigateTo({
      url: '/pages/login/index'
    });
  }
});
```

## 组件属性

| 属性名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| idsServiceUrl | String | 是 | - | IDS 服务地址，用于获取 serviceUrls 配置 |
| data | String | 是 | - | Token 或加密数据（根据 isToken 决定） |
| isToken | Boolean | 否 | true | true: data 是 Token 直接使用；false: data 是加密数据需解析 |
| userInfo | Object | 是 | `{name:'', avatar:''}` | 用户信息对象 |
| speechRecognitionManager | Object | 否 | null | 语音识别管理器（边录边识别） |

### data 参数说明

组件支持两种传参方式：

**方式一：直接传 Token（默认）**
```javascript
// isToken 默认为 true，data 直接作为 Token 使用
data: 'your-access-token',
isToken: true  // 可省略
```

**方式二：传加密数据（由组件内部解析）**
```javascript
// isToken 为 false 时，组件会调用 IDS 接口解析 data 获取 Token
data: 'encrypted-data-string',
isToken: false
```

### userInfo 对象结构

```javascript
{
  name: '用户昵称',      // 用户名称（必填）
  avatar: 'https://...' // 用户头像 URL（选填）
}
```

## 组件事件

| 事件名 | 说明 | 回调参数 |
|--------|------|----------|
| bind:back | 点击返回按钮时触发 | - |
| bind:login | 需要登录时触发（Token 失效或未登录） | - |

## 主程序依赖

### 1. 后端服务

组件需要对接以下后端服务：

#### 1.1 IDS 服务（认证服务）

**接口：** `GET /api/aiChatWeb/serviceUrls`

**说明：** 获取其他服务的 URL 配置

**请求头：**
```
X-Access-Token: Bearer {userToken}
```

**返回示例：**
```json
{
  "aiChatUrl": "https://chatweb-dev.platform.flexem.net",
  "ossServiceUrl": "https://oss-dev.platform.flexem.net",
  "blobStorageDownloadServiceUrl": "https://blobstorage-dev.platform.flexem.net"
}
```

#### 1.2 AI Chat 服务

主要接口：

- `GET /app/sessions/paging` - 获取会话列表
- `POST /app/sessions` - 创建新会话
- `DELETE /app/sessions/{id}` - 删除会话
- `GET /app/chat-histories/mine` - 获取聊天历史
- `POST /app/api/chatstream` - 发送消息（SSE 流式）
- `POST /app/sessions/title` - 更新会话标题

#### 1.3 OSS 服务

- `POST /api/app/externalStorage/tickets` - 获取七牛上传 Token
- `POST /app/tempFile/parse` - 解析文件内容

### 2. 微信同声传译插件（可选）

如需使用语音功能，需要在 `app.json` 中引入插件：

```json
{
  "plugins": {
    "WechatSI": {
      "version": "0.3.5",
      "provider": "wx069ba97219f66d99"
    }
  }
}
```

在小程序管理后台添加插件：
1. 进入小程序管理后台
2. 设置 -> 第三方设置 -> 插件管理
3. 添加插件：微信同声传译（wx069ba97219f66d99）

### 3. 权限配置

在 `app.json` 中配置必要权限：

```json
{
  "permission": {
    "scope.record": {
      "desc": "需要使用您的麦克风进行语音输入"
    }
  },
  "requiredPrivateInfos": [
    "chooseImage",
    "chooseMessageFile"
  ]
}
```

## 注意事项

### 1. 导航栏

- 组件使用自定义导航栏，页面必须设置 `"navigationStyle": "custom"`
- 组件会自动适配不同机型的状态栏和胶囊按钮位置

### 2. Token / 数据管理

- Token 失效时会触发 `bind:login` 事件
- 建议在主程序中统一管理 Token 的刷新和存储
- 支持两种传参方式：
  - `isToken: true` - data 直接作为 Token 使用
  - `isToken: false` - data 是加密数据，组件会调用 IDS 接口解析

### 3. 语音功能

- 使用微信同声传译插件需要在小程序后台添加插件
- `speechRecognitionManager` 用于边录边识别（实时显示识别结果）
- 组件内置 TTS 功能用于 AI 回复的语音播放

### 4. 文件上传

- 组件支持图片和文件上传
- 图片会自动识别并解析内容（OCR）
- 文件上传使用七牛云存储
- 需要配置七牛云上传域名白名单

### 5. 网络请求

- 所有 API 请求都需要在小程序后台配置域名白名单
- 支持 SSE 流式传输（使用 `enableChunked: true`）
- 请求失败会自动重试或提示用户

### 6. 样式适配

- 组件使用 rpx 单位，自动适配不同屏幕尺寸
- 支持深色模式（根据系统设置自动切换）
- 键盘弹出时自动调整布局

### 7. 性能优化

- 消息列表使用虚拟滚动，支持大量历史消息
- 图片懒加载，减少内存占用
- 流式输出时节流滚动，提升性能

## 完整示例

查看 `examples` 目录获取完整的示例代码。

## API 文档

详细的 API 文档请参考：[API.md](./API.md)

## 更新日志

### v1.0.0 (2024-01-23)

- 🎉 首次发布
- ✅ 完整的聊天界面
- ✅ 支持文本、语音、图片输入
- ✅ 流式输出和语音播放
- ✅ 会话管理功能

## 许可证

MIT License

## 技术支持

如有问题，请联系：songkaige

---

**注意：** 本组件依赖 Flexem 平台的后端服务，使用前请确保已正确配置相关服务地址和权限。

---

## 简化使用指南（快速上手）

以下是最简化的接入步骤，照抄即可使用。

### Step 1: 安装组件

```bash
npm install @flexem/chat-box
```

然后在微信开发者工具中点击 `工具` -> `构建 npm`。

### Step 2: 配置 app.json

在你的小程序 `app.json` 中添加以下配置：

```json
{
  "plugins": {
    "WechatSI": {
      "version": "0.3.6",
      "provider": "wx069ba97219f66d99"
    }
  },
  "permission": {
    "scope.record": {
      "desc": "用于语音识别功能"
    }
  },
  "requiredPrivateInfos": [
    "chooseImage",
    "chooseMessageFile"
  ]
}
```

### Step 3: 创建聊天页面

#### chat.json

```json
{
  "usingComponents": {
    "chat-box": "@flexem/chat-box"
  },
  "navigationStyle": "custom",
  "navigationBarTitleText": ""
}
```

#### chat.wxml

```xml
<chat-box
  idsServiceUrl="{{idsServiceUrl}}"
  isToken="{{isToken}}"
  data="{{data}}"
  userInfo="{{userInfo}}"
  speechRecognitionManager="{{speechRecognitionManager}}"
  bind:login="onNeedLogin"
/>
```

#### chat.js (或 chat.ts)

```javascript
const plugin = requirePlugin('WechatSI');
const manager = plugin.getRecordRecognitionManager();

Page({
  data: {
    speechRecognitionManager: null,
    idsServiceUrl: 'https://ids-dev.platform.flexem.net',
    isToken: false,  // false 表示 data 是加密数据，需要解析
    data: '',        // Token 或加密数据
    userInfo: {
      name: '',
      avatar: ''
    }
  },

  onLoad() {
    // 初始化语音识别
    if (plugin && manager) {
      this.setData({
        speechRecognitionManager: manager
      });
    }

    // 加载用户认证信息
    this.loadUserAuth();
  },

  onShow() {
    // 每次页面显示时检查登录状态
    this.loadUserAuth();
  },

  /**
   * 加载用户认证信息
   */
  loadUserAuth() {
    const data = wx.getStorageSync('data') || '';
    const userInfo = wx.getStorageSync('userInfo') || { name: '', avatar: '' };

    if (data) {
      this.setData({
        data: data,
        userInfo: userInfo
      });
    }
  },

  /**
   * 需要登录时的回调
   */
  onNeedLogin() {
    wx.showModal({
      title: '提示',
      content: '请先登录后再使用聊天功能',
      confirmText: '去登录',
      success: (res) => {
        if (res.confirm) {
          wx.navigateTo({
            url: '/pages/login/login'
          });
        }
      }
    });
  }
});
```

### Step 4: 配置服务器域名

在微信小程序管理后台 -> 开发管理 -> 开发设置 -> 服务器域名，添加：

**request 合法域名：**
```
https://ids-dev.platform.flexem.net
https://oss-dev.platform.flexem.net
https://up-z2.qiniup.com
```

**uploadFile 合法域名：**
```
https://up-z2.qiniup.com
```

**downloadFile 合法域名：**
```
https://blobstorage-dev.platform.flexem.net
```

### Step 5: 添加微信同声传译插件

1. 登录微信小程序管理后台
2. 设置 -> 第三方设置 -> 插件管理 -> 添加插件
3. 搜索 `wx069ba97219f66d99` 或 `微信同声传译`
4. 点击添加

### 必须提供的参数

| 参数 | 说明 | 示例 |
|------|------|------|
| idsServiceUrl | IDS 认证服务地址 | `https://ids-dev.platform.flexem.net` |
| data | Token 或加密数据 | 从登录接口获取 |
| isToken | data 类型标识 | `true`（data 是 Token）或 `false`（data 是加密数据） |
| userInfo | 用户信息对象 | `{ name: '用户昵称', avatar: '头像URL' }` |
| speechRecognitionManager | 语音识别管理器 | 通过 `plugin.getRecordRecognitionManager()` 获取 |

### 必须监听的事件

| 事件 | 说明 |
|------|------|
| bind:login | Token 失效或未登录时触发，需要跳转到登录页 |

### 完成

按照以上步骤配置完成后，即可正常使用聊天组件。用户登录后将数据存储到本地：

```javascript
// 登录成功后存储数据
wx.setStorageSync('data', response.token);  // 或加密数据
wx.setStorageSync('userInfo', {
  name: response.userName,
  avatar: response.avatarUrl
});
```

然后跳转到聊天页面即可开始使用。