@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
@@ -0,0 +1,575 @@
1
+ /* 消息项容器 */
2
+ .message-item {
3
+ display: flex;
4
+ padding: 20rpx 30rpx;
5
+ gap: 20rpx;
6
+ width: 100%;
7
+ box-sizing: border-box;
8
+ overflow: hidden;
9
+ }
10
+
11
+ .user-message {
12
+ flex-direction: row-reverse;
13
+ justify-content: flex-start;
14
+ }
15
+
16
+ .ai-message {
17
+ flex-direction: row;
18
+ }
19
+
20
+ /* 头像 */
21
+ .avatar-container {
22
+ flex-shrink: 0;
23
+ }
24
+
25
+ .avatar {
26
+ width: 72rpx;
27
+ height: 72rpx;
28
+ border-radius: 50%;
29
+ background-color: #f0f0f0;
30
+ }
31
+
32
+ /* 消息内容区域 */
33
+ .message-content {
34
+ max-width: 80%;
35
+ min-width: 0;
36
+ display: flex;
37
+ flex-direction: column;
38
+ overflow: hidden;
39
+ }
40
+
41
+ .user-message .message-content {
42
+ align-items: flex-end;
43
+ }
44
+
45
+ .ai-message .message-content {
46
+ flex: 1;
47
+ align-items: flex-start;
48
+ max-width: calc(100%);
49
+ }
50
+
51
+ /* 消息气泡 */
52
+ .message-bubble {
53
+ padding: 24rpx;
54
+ border-radius: 20rpx;
55
+ word-break: break-word;
56
+ overflow-wrap: break-word;
57
+ max-width: 100%;
58
+ box-sizing: border-box;
59
+ }
60
+
61
+ .user-bubble {
62
+ background-color: #007aff;
63
+ color: #fff;
64
+ border-bottom-right-radius: 8rpx;
65
+ }
66
+
67
+ .ai-bubble {
68
+ background-color: #fff;
69
+ color: #333;
70
+ border-bottom-left-radius: 8rpx;
71
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
72
+ }
73
+
74
+ /* 错误消息样式 */
75
+ .error-bubble {
76
+ background-color: #fff5f5;
77
+ border: 1rpx solid #ffccc7;
78
+ color: #cf1322;
79
+ }
80
+
81
+ .message-text {
82
+ font-size: 32rpx;
83
+ line-height: 1.6;
84
+ }
85
+
86
+ /* 附件 */
87
+ .attachments {
88
+ margin-top: 16rpx;
89
+ }
90
+
91
+ .attachment-image {
92
+ max-width: 100%;
93
+ border-radius: 12rpx;
94
+ margin-top: 8rpx;
95
+ }
96
+
97
+ .attachment-file {
98
+ display: flex;
99
+ align-items: center;
100
+ padding: 16rpx;
101
+ background-color: rgba(255, 255, 255, 0.2);
102
+ border-radius: 8rpx;
103
+ margin-top: 8rpx;
104
+ }
105
+
106
+ .file-icon {
107
+ font-size: 32rpx;
108
+ margin-right: 12rpx;
109
+ }
110
+
111
+ .file-name {
112
+ font-size: 26rpx;
113
+ color: inherit;
114
+ flex: 1;
115
+ overflow: hidden;
116
+ text-overflow: ellipsis;
117
+ white-space: nowrap;
118
+ }
119
+
120
+ /* 思考过程 */
121
+ .thinking-section {
122
+ margin-bottom: 16rpx;
123
+ padding: 16rpx;
124
+ background-color: #f8f9fa;
125
+ border-radius: 12rpx;
126
+ }
127
+
128
+ .thinking-header {
129
+ display: flex;
130
+ align-items: center;
131
+ gap: 8rpx;
132
+ }
133
+
134
+ .thinking-icon {
135
+ width: 32rpx;
136
+ height: 32rpx;
137
+ }
138
+
139
+ .thinking-title {
140
+ font-size: 26rpx;
141
+ color: #666;
142
+ flex: 1;
143
+ }
144
+
145
+ .thinking-toggle {
146
+ font-size: 24rpx;
147
+ color: #007aff;
148
+ }
149
+
150
+ .thinking-content {
151
+ margin-top: 12rpx;
152
+ padding-top: 12rpx;
153
+ border-top: 1rpx solid #eee;
154
+ font-size: 26rpx;
155
+ color: #666;
156
+ line-height: 1.6;
157
+ }
158
+
159
+ /* 正在输入指示器 */
160
+ .typing-indicator {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 8rpx;
164
+ padding: 16rpx 0;
165
+ }
166
+
167
+ .typing-dot {
168
+ width: 12rpx;
169
+ height: 12rpx;
170
+ background-color: #007aff;
171
+ border-radius: 50%;
172
+ animation: typing 1.4s infinite;
173
+ }
174
+
175
+ .typing-dot:nth-child(2) {
176
+ animation-delay: 0.2s;
177
+ }
178
+
179
+ .typing-dot:nth-child(3) {
180
+ animation-delay: 0.4s;
181
+ }
182
+
183
+ @keyframes typing {
184
+ 0%, 60%, 100% {
185
+ transform: translateY(0);
186
+ opacity: 0.4;
187
+ }
188
+ 30% {
189
+ transform: translateY(-8rpx);
190
+ opacity: 1;
191
+ }
192
+ }
193
+
194
+ /* Markdown 样式 */
195
+ .markdown-content {
196
+ font-size: 32rpx;
197
+ line-height: 1.6;
198
+ }
199
+
200
+ .md-bold {
201
+ font-weight: bold;
202
+ }
203
+
204
+ .md-italic {
205
+ font-style: italic;
206
+ }
207
+
208
+ .md-paragraph {
209
+ margin-bottom: 16rpx;
210
+ }
211
+
212
+ .md-paragraph:last-child {
213
+ margin-bottom: 0;
214
+ }
215
+
216
+ /* 标题 */
217
+ .md-heading {
218
+ font-weight: bold;
219
+ margin: 24rpx 0 16rpx;
220
+ }
221
+
222
+ .md-h1 {
223
+ font-size: 40rpx;
224
+ }
225
+
226
+ .md-h2 {
227
+ font-size: 36rpx;
228
+ }
229
+
230
+ .md-h3 {
231
+ font-size: 34rpx;
232
+ }
233
+
234
+ .md-h4, .md-h5, .md-h6 {
235
+ font-size: 32rpx;
236
+ }
237
+
238
+ /* 代码块 */
239
+ .md-code-block {
240
+ margin: 16rpx 0;
241
+ border-radius: 12rpx;
242
+ overflow: hidden;
243
+ background-color: #1e1e1e;
244
+ }
245
+
246
+ .code-header {
247
+ display: flex;
248
+ justify-content: space-between;
249
+ align-items: center;
250
+ padding: 12rpx 20rpx;
251
+ background-color: #2d2d2d;
252
+ }
253
+
254
+ .code-lang {
255
+ font-size: 24rpx;
256
+ color: #999;
257
+ }
258
+
259
+ .code-copy {
260
+ font-size: 24rpx;
261
+ color: #007aff;
262
+ }
263
+
264
+ .code-content {
265
+ padding: 20rpx;
266
+ max-height: none;
267
+ overflow-x: auto;
268
+ }
269
+
270
+ /* 代码内容容器 - 使用纯 CSS overflow 替代 scroll-view,避免内容更新时跳动 */
271
+ .code-content-wrapper {
272
+ padding: 20rpx;
273
+ overflow-x: auto;
274
+ overflow-y: hidden;
275
+ -webkit-overflow-scrolling: touch;
276
+ }
277
+
278
+ .code-text {
279
+ font-family: 'Courier New', monospace;
280
+ font-size: 26rpx;
281
+ color: #d4d4d4;
282
+ white-space: pre;
283
+ word-break: normal;
284
+ display: inline-block;
285
+ min-width: 100%;
286
+ }
287
+
288
+ /* 行内代码 */
289
+ .md-inline-code {
290
+ background-color: #f0f0f0;
291
+ padding: 4rpx 12rpx;
292
+ border-radius: 6rpx;
293
+ font-family: 'Courier New', monospace;
294
+ font-size: 28rpx;
295
+ color: #e83e8c;
296
+ }
297
+
298
+ /* 列表 */
299
+ .md-list {
300
+ margin: 16rpx 0;
301
+ }
302
+
303
+ .md-list-item-wrapper {
304
+ margin-bottom: 8rpx;
305
+ }
306
+
307
+ .md-list-item {
308
+ display: flex;
309
+ margin-bottom: 4rpx;
310
+ }
311
+
312
+ .md-nested-list {
313
+ margin-top: 8rpx;
314
+ }
315
+
316
+ .list-marker {
317
+ width: 32rpx;
318
+ flex-shrink: 0;
319
+ color: #666;
320
+ }
321
+
322
+ .list-text {
323
+ flex: 1;
324
+ }
325
+
326
+ /* 引用 */
327
+ .md-blockquote {
328
+ margin: 16rpx 0;
329
+ padding: 16rpx 20rpx;
330
+ border-left: 6rpx solid #007aff;
331
+ background-color: #f8f9fa;
332
+ color: #666;
333
+ font-style: italic;
334
+ }
335
+
336
+ /* 分隔线 */
337
+ .md-hr {
338
+ margin: 24rpx 0;
339
+ height: 2rpx;
340
+ background-color: #eee;
341
+ }
342
+
343
+ /* 图片 */
344
+ .md-image {
345
+ max-width: 100%;
346
+ border-radius: 12rpx;
347
+ margin: 16rpx 0;
348
+ }
349
+
350
+ /* 行内图片(列表或段落中的图片) */
351
+ .md-inline-image {
352
+ display: block;
353
+ margin: 12rpx 0;
354
+ }
355
+
356
+ /* 链接 */
357
+ .md-link {
358
+ color: #007aff;
359
+ text-decoration: underline;
360
+ word-break: break-all;
361
+ }
362
+
363
+ /* 表格 */
364
+ .md-table-wrapper {
365
+ margin: 16rpx 0;
366
+ width: 100%;
367
+ }
368
+
369
+ .md-table {
370
+ border-collapse: collapse;
371
+ min-width: 100%;
372
+ display: table;
373
+ }
374
+
375
+ .md-table-row {
376
+ display: table-row;
377
+ }
378
+
379
+ .md-table-header {
380
+ background-color: #f5f5f5;
381
+ }
382
+
383
+ .md-table-header .md-table-cell {
384
+ font-weight: bold;
385
+ }
386
+
387
+ .md-table-cell {
388
+ display: table-cell;
389
+ padding: 16rpx 20rpx;
390
+ border: 1rpx solid #e0e0e0;
391
+ font-size: 28rpx;
392
+ min-width: 120rpx;
393
+ white-space: nowrap;
394
+ }
395
+
396
+ .md-table-row:nth-child(even) {
397
+ background-color: #fafafa;
398
+ }
399
+
400
+ /* 消息元信息 */
401
+ .message-meta {
402
+ display: flex;
403
+ align-items: center;
404
+ justify-content: space-between;
405
+ margin-top: 16rpx;
406
+ padding-top: 12rpx;
407
+ border-top: 1rpx solid rgba(0, 0, 0, 0.08);
408
+ gap: 16rpx;
409
+ }
410
+
411
+ .user-bubble .message-meta {
412
+ border-top-color: rgba(255, 255, 255, 0.2);
413
+ }
414
+
415
+ .ai-bubble .message-meta {
416
+ border-top-color: rgba(0, 0, 0, 0.08);
417
+ }
418
+
419
+ .meta-left {
420
+ display: flex;
421
+ align-items: center;
422
+ gap: 12rpx;
423
+ }
424
+
425
+ .meta-right {
426
+ display: flex;
427
+ align-items: center;
428
+ gap: 12rpx;
429
+ }
430
+
431
+ .message-time {
432
+ font-size: 22rpx;
433
+ color: #999;
434
+ }
435
+
436
+ .user-bubble .message-time {
437
+ color: rgba(255, 255, 255, 0.7);
438
+ }
439
+
440
+ .user-bubble .action-btn {
441
+ background-color: rgba(255, 255, 255, 0.2);
442
+ }
443
+
444
+ .user-bubble .action-btn:active {
445
+ background-color: rgba(255, 255, 255, 0.3);
446
+ }
447
+
448
+ /* 操作按钮 */
449
+ .action-btn {
450
+ padding: 8rpx 16rpx;
451
+ border-radius: 8rpx;
452
+ background-color: #f5f5f5;
453
+ }
454
+
455
+ .action-btn:active {
456
+ background-color: #e0e0e0;
457
+ }
458
+
459
+ .action-icon {
460
+ font-size: 24rpx;
461
+ }
462
+
463
+ .action-icon-img {
464
+ width: 40rpx;
465
+ height: 40rpx;
466
+ padding: 8rpx;
467
+ }
468
+
469
+ .user-bubble .action-icon-img {
470
+ filter: brightness(0) invert(1);
471
+ opacity: 0.8;
472
+ }
473
+
474
+ /* 语音播放中动画 */
475
+ .voice-playing {
476
+ display: flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ gap: 4rpx;
480
+ width: 40rpx;
481
+ height: 40rpx;
482
+ padding: 8rpx;
483
+ }
484
+
485
+ .voice-bar {
486
+ width: 6rpx;
487
+ height: 20rpx;
488
+ background-color: #007aff;
489
+ border-radius: 3rpx;
490
+ animation: voice-wave 0.8s ease-in-out infinite;
491
+ }
492
+
493
+ .voice-bar:nth-child(1) {
494
+ animation-delay: 0s;
495
+ }
496
+
497
+ .voice-bar:nth-child(2) {
498
+ animation-delay: 0.2s;
499
+ }
500
+
501
+ .voice-bar:nth-child(3) {
502
+ animation-delay: 0.4s;
503
+ }
504
+
505
+ @keyframes voice-wave {
506
+ 0%, 100% {
507
+ height: 12rpx;
508
+ }
509
+ 50% {
510
+ height: 28rpx;
511
+ }
512
+ }
513
+
514
+ /* 语音合成中状态 */
515
+ .voice-synthesizing {
516
+ display: flex;
517
+ align-items: center;
518
+ gap: 12rpx;
519
+ }
520
+
521
+ .synthesizing-spinner {
522
+ width: 32rpx;
523
+ height: 32rpx;
524
+ border: 4rpx solid #e0e0e0;
525
+ border-top-color: #007aff;
526
+ border-radius: 50%;
527
+ animation: spin 0.8s linear infinite;
528
+ }
529
+
530
+ .synthesizing-text {
531
+ font-size: 24rpx;
532
+ color: #666;
533
+ }
534
+
535
+ @keyframes spin {
536
+ 0% {
537
+ transform: rotate(0deg);
538
+ }
539
+ 100% {
540
+ transform: rotate(360deg);
541
+ }
542
+ }
543
+
544
+ /* 快捷回复 */
545
+ .quick-replies {
546
+ display: flex;
547
+ flex-wrap: wrap;
548
+ gap: 16rpx;
549
+ margin: 20rpx 0;
550
+ }
551
+
552
+ .quick-reply-btn {
553
+ display: inline-flex;
554
+ align-items: center;
555
+ justify-content: center;
556
+ padding: 16rpx 28rpx;
557
+ border-radius: 32rpx;
558
+ font-size: 28rpx;
559
+ font-weight: 500;
560
+ background-color: #e8f4fd;
561
+ color: #1890ff;
562
+ border: 2rpx solid #91d5ff;
563
+ transition: all 0.2s ease;
564
+ }
565
+
566
+ .quick-reply-btn:active {
567
+ background-color: #bae7ff;
568
+ border-color: #69c0ff;
569
+ transform: scale(0.96);
570
+ }
571
+
572
+ .quick-reply-btn.disabled {
573
+ opacity: 0.5;
574
+ pointer-events: none;
575
+ }