@flexem/chat-box 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +638 -0
  2. package/miniprogram_dist/TEST_CASES.md +256 -0
  3. package/miniprogram_dist/assets/icons/icon-arrow-down.svg +1 -0
  4. package/miniprogram_dist/assets/icons/icon-arrow-up.svg +1 -0
  5. package/miniprogram_dist/assets/icons/icon-avatar-default.svg +1 -0
  6. package/miniprogram_dist/assets/icons/icon-back.svg +1 -0
  7. package/miniprogram_dist/assets/icons/icon-camera.svg +1 -0
  8. package/miniprogram_dist/assets/icons/icon-close.svg +1 -0
  9. package/miniprogram_dist/assets/icons/icon-copy.svg +1 -0
  10. package/miniprogram_dist/assets/icons/icon-delete.svg +1 -0
  11. package/miniprogram_dist/assets/icons/icon-edit-msg.svg +1 -0
  12. package/miniprogram_dist/assets/icons/icon-edit.svg +1 -0
  13. package/miniprogram_dist/assets/icons/icon-file.svg +1 -0
  14. package/miniprogram_dist/assets/icons/icon-image.svg +1 -0
  15. package/miniprogram_dist/assets/icons/icon-keyboard.svg +1 -0
  16. package/miniprogram_dist/assets/icons/icon-menu.svg +1 -0
  17. package/miniprogram_dist/assets/icons/icon-play-voice.svg +1 -0
  18. package/miniprogram_dist/assets/icons/icon-plus.svg +1 -0
  19. package/miniprogram_dist/assets/icons/icon-regenerate.svg +1 -0
  20. package/miniprogram_dist/assets/icons/icon-thinking.svg +1 -0
  21. package/miniprogram_dist/assets/icons/icon-voice.svg +1 -0
  22. package/miniprogram_dist/components/attachment/index.js +169 -0
  23. package/miniprogram_dist/components/attachment/index.json +4 -0
  24. package/miniprogram_dist/components/attachment/index.wxml +40 -0
  25. package/miniprogram_dist/components/attachment/index.wxss +119 -0
  26. package/miniprogram_dist/components/input-bar/index.js +934 -0
  27. package/miniprogram_dist/components/input-bar/index.json +6 -0
  28. package/miniprogram_dist/components/input-bar/index.wxml +132 -0
  29. package/miniprogram_dist/components/input-bar/index.wxss +324 -0
  30. package/miniprogram_dist/components/message/index.js +988 -0
  31. package/miniprogram_dist/components/message/index.json +4 -0
  32. package/miniprogram_dist/components/message/index.wxml +285 -0
  33. package/miniprogram_dist/components/message/index.wxss +575 -0
  34. package/miniprogram_dist/components/sidebar/index.js +506 -0
  35. package/miniprogram_dist/components/sidebar/index.json +4 -0
  36. package/miniprogram_dist/components/sidebar/index.wxml +137 -0
  37. package/miniprogram_dist/components/sidebar/index.wxss +264 -0
  38. package/miniprogram_dist/index.js +1316 -0
  39. package/miniprogram_dist/index.json +8 -0
  40. package/miniprogram_dist/index.wxml +172 -0
  41. package/miniprogram_dist/index.wxss +291 -0
  42. package/miniprogram_dist/package.json +5 -0
  43. package/miniprogram_dist/utils/api.js +474 -0
  44. package/miniprogram_dist/utils/audio.js +860 -0
  45. package/miniprogram_dist/utils/storage.js +168 -0
  46. package/package.json +27 -0
package/README.md ADDED
@@ -0,0 +1,638 @@
1
+ # @flexem/chat-box
2
+
3
+ 微信小程序 AI 聊天组件,提供完整的聊天界面和功能,支持文本、语音、图片等多种交互方式。
4
+
5
+ ## 功能特性
6
+
7
+ - ✅ 完整的聊天界面
8
+ - ✅ 支持文本、语音输入
9
+ - ✅ 支持图片、文件上传
10
+ - ✅ 流式输出(SSE)
11
+ - ✅ 语音播放(TTS)
12
+ - ✅ 会话管理(创建、切换、删除)
13
+ - ✅ 消息历史加载
14
+ - ✅ 消息编辑、重新生成
15
+ - ✅ 自定义导航栏
16
+ - ✅ 侧边栏会话列表
17
+
18
+ ## 安装
19
+
20
+ ### 方式一:npm 安装(推荐)
21
+
22
+ ```bash
23
+ npm install @flexem/chat-box
24
+ ```
25
+
26
+ ### 方式二:本地构建
27
+
28
+ ```bash
29
+ # 克隆项目
30
+ git clone <repository-url>
31
+
32
+ # 安装依赖
33
+ npm install
34
+
35
+ # 构建组件
36
+ npm run build
37
+ ```
38
+
39
+ 构建后的组件位于 `miniprogram_dist` 目录。
40
+
41
+ ## 快速开始
42
+
43
+ ### 1. 小程序配置
44
+
45
+ #### 1.1 构建 npm
46
+
47
+ 在小程序开发者工具中:
48
+ 1. 点击菜单 `工具` -> `构建 npm`
49
+ 2. 等待构建完成
50
+
51
+ #### 1.2 配置 app.json
52
+
53
+ ```json
54
+ {
55
+ "usingComponents": {
56
+ "chat-box": "@flexem/chat-box/index"
57
+ },
58
+ "permission": {
59
+ "scope.record": {
60
+ "desc": "需要使用您的麦克风进行语音输入"
61
+ }
62
+ },
63
+ "requiredPrivateInfos": [
64
+ "chooseImage",
65
+ "chooseMessageFile"
66
+ ]
67
+ }
68
+ ```
69
+
70
+ #### 1.3 配置服务器域名
71
+
72
+ 在小程序管理后台配置以下域名(根据实际环境调整):
73
+
74
+ **request 合法域名:**
75
+ - `https://ids-dev.platform.flexem.net`(IDS 服务)
76
+ - `https://chatweb-dev.platform.flexem.net`(AI 聊天服务)
77
+ - `https://oss-dev.platform.flexem.net`(OSS 服务)
78
+ - `https://up-z2.qiniup.com`(七牛云上传)
79
+
80
+ **uploadFile 合法域名:**
81
+ - `https://up-z2.qiniup.com`
82
+
83
+ **downloadFile 合法域名:**
84
+ - `https://blobstorage-dev.platform.flexem.net`(文件下载服务)
85
+
86
+ ### 2. 页面配置
87
+
88
+ 在需要使用聊天组件的页面 JSON 文件中:
89
+
90
+ ```json
91
+ {
92
+ "usingComponents": {
93
+ "chat-box": "@flexem/chat-box/index"
94
+ },
95
+ "navigationStyle": "custom"
96
+ }
97
+ ```
98
+
99
+ **注意:** 必须设置 `"navigationStyle": "custom"`,因为组件使用自定义导航栏。
100
+
101
+ ### 3. 页面使用
102
+
103
+ #### 3.1 WXML
104
+
105
+ ```xml
106
+ <chat-box
107
+ idsServiceUrl="{{idsServiceUrl}}"
108
+ userToken="{{userToken}}"
109
+ userInfo="{{userInfo}}"
110
+ voiceToText="{{voiceToText}}"
111
+ speechRecognitionManager="{{speechRecognitionManager}}"
112
+ textToVoice="{{textToVoice}}"
113
+ bind:back="onBack"
114
+ bind:login="onLogin"
115
+ />
116
+ ```
117
+
118
+ #### 3.2 JavaScript
119
+
120
+ ```javascript
121
+ Page({
122
+ data: {
123
+ // IDS 服务地址(必填)
124
+ idsServiceUrl: 'https://ids-dev.platform.flexem.net',
125
+
126
+ // 用户 Token(必填)
127
+ userToken: '',
128
+
129
+ // 用户信息(必填)
130
+ userInfo: {
131
+ name: '用户昵称',
132
+ avatar: 'https://example.com/avatar.jpg'
133
+ },
134
+
135
+ // 语音转文字函数(可选)
136
+ voiceToText: null,
137
+
138
+ // 语音识别管理器(可选)
139
+ speechRecognitionManager: null,
140
+
141
+ // 文字转语音函数(可选)
142
+ textToVoice: null
143
+ },
144
+
145
+ onLoad() {
146
+ // 初始化用户信息和 Token
147
+ this.initUserInfo();
148
+
149
+ // 初始化语音功能(可选)
150
+ this.initVoiceFeatures();
151
+ },
152
+
153
+ // 初始化用户信息
154
+ initUserInfo() {
155
+ // 从缓存或登录接口获取用户信息
156
+ const userInfo = wx.getStorageSync('userInfo');
157
+ const userToken = wx.getStorageSync('userToken');
158
+
159
+ if (userInfo && userToken) {
160
+ this.setData({
161
+ userInfo: {
162
+ name: userInfo.nickName || userInfo.name,
163
+ avatar: userInfo.avatarUrl || userInfo.avatar
164
+ },
165
+ userToken: userToken
166
+ });
167
+ } else {
168
+ // 未登录,跳转到登录页
169
+ this.onLogin();
170
+ }
171
+ },
172
+
173
+ // 初始化语音功能(可选)
174
+ initVoiceFeatures() {
175
+ // 1. 引入微信同声传译插件(边录边识别)
176
+ const plugin = requirePlugin('WechatSI');
177
+ const manager = plugin.getRecordRecognitionManager();
178
+
179
+ this.setData({
180
+ speechRecognitionManager: manager
181
+ });
182
+
183
+ // 2. 设置语音转文字函数(长按录音后识别)
184
+ this.setData({
185
+ voiceToText: (options) => {
186
+ plugin.textToSpeech({
187
+ lang: 'zh_CN',
188
+ tts: true,
189
+ content: options.content,
190
+ success: (res) => {
191
+ if (options.success) {
192
+ options.success(res);
193
+ }
194
+ },
195
+ fail: (err) => {
196
+ if (options.fail) {
197
+ options.fail(err);
198
+ }
199
+ }
200
+ });
201
+ }
202
+ });
203
+
204
+ // 3. 设置文字转语音函数(可选,不传则使用内置)
205
+ this.setData({
206
+ textToVoice: (options) => {
207
+ plugin.textToSpeech({
208
+ lang: 'zh_CN',
209
+ tts: true,
210
+ content: options.content,
211
+ success: (res) => {
212
+ if (options.success) {
213
+ options.success({ src: res.filename });
214
+ }
215
+ },
216
+ fail: (err) => {
217
+ if (options.fail) {
218
+ options.fail(err);
219
+ }
220
+ }
221
+ });
222
+ }
223
+ });
224
+ },
225
+
226
+ // 返回事件
227
+ onBack() {
228
+ wx.navigateBack({
229
+ fail: () => {
230
+ wx.switchTab({
231
+ url: '/pages/index/index'
232
+ });
233
+ }
234
+ });
235
+ },
236
+
237
+ // 登录事件
238
+ onLogin() {
239
+ wx.navigateTo({
240
+ url: '/pages/login/index'
241
+ });
242
+ }
243
+ });
244
+ ```
245
+
246
+ ## 组件属性
247
+
248
+ | 属性名 | 类型 | 必填 | 默认值 | 说明 |
249
+ |--------|------|------|--------|------|
250
+ | idsServiceUrl | String | 是 | - | IDS 服务地址,用于获取 serviceUrls 配置 |
251
+ | userToken | String | 是 | - | 用户认证 Token |
252
+ | userInfo | Object | 是 | `{name:'', avatar:''}` | 用户信息对象 |
253
+ | voiceToText | Function | 否 | null | 语音转文字函数(长按录音后识别) |
254
+ | speechRecognitionManager | Object | 否 | null | 语音识别管理器(边录边识别) |
255
+ | textToVoice | Function | 否 | null | 文字转语音函数,不传则使用内置 TTS |
256
+
257
+ ### userInfo 对象结构
258
+
259
+ ```javascript
260
+ {
261
+ name: '用户昵称', // 用户名称
262
+ avatar: 'https://...' // 用户头像 URL
263
+ }
264
+ ```
265
+
266
+ ### voiceToText 函数签名
267
+
268
+ ```javascript
269
+ function voiceToText(options) {
270
+ // options: {
271
+ // content: '要转换的文本',
272
+ // success: (res) => { /* res.src: 音频文件路径 */ },
273
+ // fail: (err) => { /* 错误处理 */ }
274
+ // }
275
+ }
276
+ ```
277
+
278
+ ### textToVoice 函数签名
279
+
280
+ ```javascript
281
+ function textToVoice(options) {
282
+ // options: {
283
+ // content: '要播放的文本',
284
+ // success: (res) => { /* res.src: 音频文件路径 */ },
285
+ // fail: (err) => { /* 错误处理 */ }
286
+ // }
287
+ }
288
+ ```
289
+
290
+ ## 组件事件
291
+
292
+ | 事件名 | 说明 | 回调参数 |
293
+ |--------|------|----------|
294
+ | bind:back | 点击返回按钮时触发 | - |
295
+ | bind:login | 需要登录时触发(Token 失效或未登录) | - |
296
+
297
+ ## 主程序依赖
298
+
299
+ ### 1. 后端服务
300
+
301
+ 组件需要对接以下后端服务:
302
+
303
+ #### 1.1 IDS 服务(认证服务)
304
+
305
+ **接口:** `GET /api/aiChatWeb/serviceUrls`
306
+
307
+ **说明:** 获取其他服务的 URL 配置
308
+
309
+ **请求头:**
310
+ ```
311
+ X-Access-Token: Bearer {userToken}
312
+ ```
313
+
314
+ **返回示例:**
315
+ ```json
316
+ {
317
+ "aiChatUrl": "https://chatweb-dev.platform.flexem.net",
318
+ "ossServiceUrl": "https://oss-dev.platform.flexem.net",
319
+ "blobStorageDownloadServiceUrl": "https://blobstorage-dev.platform.flexem.net"
320
+ }
321
+ ```
322
+
323
+ #### 1.2 AI Chat 服务
324
+
325
+ 主要接口:
326
+
327
+ - `GET /app/sessions/paging` - 获取会话列表
328
+ - `POST /app/sessions` - 创建新会话
329
+ - `DELETE /app/sessions/{id}` - 删除会话
330
+ - `GET /app/chat-histories/mine` - 获取聊天历史
331
+ - `POST /app/api/chatstream` - 发送消息(SSE 流式)
332
+ - `POST /app/sessions/title` - 更新会话标题
333
+
334
+ #### 1.3 OSS 服务
335
+
336
+ - `POST /api/app/externalStorage/tickets` - 获取七牛上传 Token
337
+ - `POST /app/tempFile/parse` - 解析文件内容
338
+
339
+ ### 2. 微信同声传译插件(可选)
340
+
341
+ 如需使用语音功能,需要在 `app.json` 中引入插件:
342
+
343
+ ```json
344
+ {
345
+ "plugins": {
346
+ "WechatSI": {
347
+ "version": "0.3.5",
348
+ "provider": "wx069ba97219f66d99"
349
+ }
350
+ }
351
+ }
352
+ ```
353
+
354
+ 在小程序管理后台添加插件:
355
+ 1. 进入小程序管理后台
356
+ 2. 设置 -> 第三方设置 -> 插件管理
357
+ 3. 添加插件:微信同声传译(wx069ba97219f66d99)
358
+
359
+ ### 3. 权限配置
360
+
361
+ 在 `app.json` 中配置必要权限:
362
+
363
+ ```json
364
+ {
365
+ "permission": {
366
+ "scope.record": {
367
+ "desc": "需要使用您的麦克风进行语音输入"
368
+ }
369
+ },
370
+ "requiredPrivateInfos": [
371
+ "chooseImage",
372
+ "chooseMessageFile"
373
+ ]
374
+ }
375
+ ```
376
+
377
+ ## 注意事项
378
+
379
+ ### 1. 导航栏
380
+
381
+ - 组件使用自定义导航栏,页面必须设置 `"navigationStyle": "custom"`
382
+ - 组件会自动适配不同机型的状态栏和胶囊按钮位置
383
+
384
+ ### 2. Token 管理
385
+
386
+ - Token 失效时会触发 `bind:login` 事件
387
+ - 建议在主程序中统一管理 Token 的刷新和存储
388
+ - Token 格式:`Bearer {token}`
389
+
390
+ ### 3. 语音功能
391
+
392
+ - 语音功能为可选功能,不传相关参数则不显示语音按钮
393
+ - 使用微信同声传译插件需要在小程序后台添加插件
394
+ - `speechRecognitionManager` 用于边录边识别(实时显示)
395
+ - `voiceToText` 用于录音完成后识别
396
+ - `textToVoice` 用于 AI 回复的语音播放
397
+
398
+ ### 4. 文件上传
399
+
400
+ - 组件支持图片和文件上传
401
+ - 图片会自动识别并解析内容(OCR)
402
+ - 文件上传使用七牛云存储
403
+ - 需要配置七牛云上传域名白名单
404
+
405
+ ### 5. 网络请求
406
+
407
+ - 所有 API 请求都需要在小程序后台配置域名白名单
408
+ - 支持 SSE 流式传输(使用 `enableChunked: true`)
409
+ - 请求失败会自动重试或提示用户
410
+
411
+ ### 6. 样式适配
412
+
413
+ - 组件使用 rpx 单位,自动适配不同屏幕尺寸
414
+ - 支持深色模式(根据系统设置自动切换)
415
+ - 键盘弹出时自动调整布局
416
+
417
+ ### 7. 性能优化
418
+
419
+ - 消息列表使用虚拟滚动,支持大量历史消息
420
+ - 图片懒加载,减少内存占用
421
+ - 流式输出时节流滚动,提升性能
422
+
423
+ ## 完整示例
424
+
425
+ 查看 `examples` 目录获取完整的示例代码。
426
+
427
+ ## API 文档
428
+
429
+ 详细的 API 文档请参考:[API.md](./API.md)
430
+
431
+ ## 更新日志
432
+
433
+ ### v1.0.0 (2024-01-23)
434
+
435
+ - 🎉 首次发布
436
+ - ✅ 完整的聊天界面
437
+ - ✅ 支持文本、语音、图片输入
438
+ - ✅ 流式输出和语音播放
439
+ - ✅ 会话管理功能
440
+
441
+ ## 许可证
442
+
443
+ MIT License
444
+
445
+ ## 技术支持
446
+
447
+ 如有问题,请联系:songkaige
448
+
449
+ ---
450
+
451
+ **注意:** 本组件依赖 Flexem 平台的后端服务,使用前请确保已正确配置相关服务地址和权限。
452
+
453
+ ---
454
+
455
+ ## 简化使用指南(快速上手)
456
+
457
+ 以下是最简化的接入步骤,照抄即可使用。
458
+
459
+ ### Step 1: 安装组件
460
+
461
+ ```bash
462
+ npm install @flexem/chat-box
463
+ ```
464
+
465
+ 然后在微信开发者工具中点击 `工具` -> `构建 npm`。
466
+
467
+ ### Step 2: 配置 app.json
468
+
469
+ 在你的小程序 `app.json` 中添加以下配置:
470
+
471
+ ```json
472
+ {
473
+ "plugins": {
474
+ "WechatSI": {
475
+ "version": "0.3.6",
476
+ "provider": "wx069ba97219f66d99"
477
+ }
478
+ },
479
+ "permission": {
480
+ "scope.record": {
481
+ "desc": "用于语音识别功能"
482
+ }
483
+ },
484
+ "requiredPrivateInfos": [
485
+ "chooseImage",
486
+ "chooseMessageFile"
487
+ ]
488
+ }
489
+ ```
490
+
491
+ ### Step 3: 创建聊天页面
492
+
493
+ #### chat.json
494
+
495
+ ```json
496
+ {
497
+ "usingComponents": {
498
+ "chat-box": "@flexem/chat-box"
499
+ },
500
+ "navigationStyle": "custom",
501
+ "navigationBarTitleText": ""
502
+ }
503
+ ```
504
+
505
+ #### chat.wxml
506
+
507
+ ```xml
508
+ <chat-box
509
+ idsServiceUrl="{{idsServiceUrl}}"
510
+ userToken="{{userToken}}"
511
+ userInfo="{{userInfo}}"
512
+ speechRecognitionManager="{{speechRecognitionManager}}"
513
+ bind:login="onNeedLogin"
514
+ />
515
+ ```
516
+
517
+ #### chat.js (或 chat.ts)
518
+
519
+ ```javascript
520
+ const plugin = requirePlugin('WechatSI');
521
+ const manager = plugin.getRecordRecognitionManager();
522
+
523
+ Page({
524
+ data: {
525
+ speechRecognitionManager: null,
526
+ idsServiceUrl: 'https://ids-dev.platform.flexem.net',
527
+ userToken: '',
528
+ userInfo: {
529
+ name: ''
530
+ }
531
+ },
532
+
533
+ onLoad() {
534
+ // 初始化语音识别
535
+ if (plugin && manager) {
536
+ this.setData({
537
+ speechRecognitionManager: manager
538
+ });
539
+ }
540
+
541
+ // 加载用户认证信息
542
+ this.loadUserAuth();
543
+ },
544
+
545
+ onShow() {
546
+ // 每次页面显示时检查登录状态
547
+ this.loadUserAuth();
548
+ },
549
+
550
+ /**
551
+ * 加载用户认证信息
552
+ */
553
+ loadUserAuth() {
554
+ const token = wx.getStorageSync('userToken') || '';
555
+ const userInfo = wx.getStorageSync('userInfo') || { name: '' };
556
+
557
+ if (token) {
558
+ this.setData({
559
+ userToken: token,
560
+ userInfo: userInfo
561
+ });
562
+ }
563
+ },
564
+
565
+ /**
566
+ * 需要登录时的回调
567
+ */
568
+ onNeedLogin() {
569
+ wx.showModal({
570
+ title: '提示',
571
+ content: '请先登录后再使用聊天功能',
572
+ confirmText: '去登录',
573
+ success: (res) => {
574
+ if (res.confirm) {
575
+ wx.navigateTo({
576
+ url: '/pages/login/login'
577
+ });
578
+ }
579
+ }
580
+ });
581
+ }
582
+ });
583
+ ```
584
+
585
+ ### Step 4: 配置服务器域名
586
+
587
+ 在微信小程序管理后台 -> 开发管理 -> 开发设置 -> 服务器域名,添加:
588
+
589
+ **request 合法域名:**
590
+ ```
591
+ https://ids-dev.platform.flexem.net
592
+ https://oss-dev.platform.flexem.net
593
+ https://up-z2.qiniup.com
594
+ ```
595
+
596
+ **uploadFile 合法域名:**
597
+ ```
598
+ https://up-z2.qiniup.com
599
+ ```
600
+
601
+ **downloadFile 合法域名:**
602
+ ```
603
+ https://blobstorage-dev.platform.flexem.net
604
+ ```
605
+
606
+ ### Step 5: 添加微信同声传译插件
607
+
608
+ 1. 登录微信小程序管理后台
609
+ 2. 设置 -> 第三方设置 -> 插件管理 -> 添加插件
610
+ 3. 搜索 `wx069ba97219f66d99` 或 `微信同声传译`
611
+ 4. 点击添加
612
+
613
+ ### 必须提供的参数
614
+
615
+ | 参数 | 说明 | 示例 |
616
+ |------|------|------|
617
+ | idsServiceUrl | IDS 认证服务地址 | `https://ids-dev.platform.flexem.net` |
618
+ | userToken | 用户登录后的 Token | 从登录接口获取,存储在 `wx.setStorageSync('userToken', token)` |
619
+ | userInfo | 用户信息对象 | `{ name: '用户昵称' }` |
620
+ | speechRecognitionManager | 语音识别管理器 | 通过 `plugin.getRecordRecognitionManager()` 获取 |
621
+
622
+ ### 必须监听的事件
623
+
624
+ | 事件 | 说明 |
625
+ |------|------|
626
+ | bind:login | Token 失效或未登录时触发,需要跳转到登录页 |
627
+
628
+ ### 完成
629
+
630
+ 按照以上步骤配置完成后,即可正常使用聊天组件。用户登录后将 Token 存储到本地:
631
+
632
+ ```javascript
633
+ // 登录成功后
634
+ wx.setStorageSync('userToken', response.token);
635
+ wx.setStorageSync('userInfo', { name: response.userName });
636
+ ```
637
+
638
+ 然后跳转到聊天页面即可开始使用。