@flexem/chat-box 1.0.9 → 1.0.10

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.
@@ -80,7 +80,7 @@ Component({
80
80
  data: {
81
81
  inputValue: '', // 输入内容
82
82
  inputHeight: 50, // 输入框高度
83
- maxInputHeight: 200, // 最大输入框高度(5行)
83
+ maxInputHeight: 210, // 最大输入框高度(5行 × 42rpx)
84
84
  isVoiceMode: false, // 是否语音模式
85
85
  isRecording: false, // 是否正在录音
86
86
  isRecognizing: false, // 是否正在识别
@@ -92,7 +92,8 @@ Component({
92
92
  textareaFocus: false, // textarea 是否聚焦
93
93
  recognizedText: '', // 语音识别的中间结果
94
94
  recordStartTime: 0, // 录音开始时间
95
- voiceStartY: 0 // 录音开始时的 Y 坐标
95
+ voiceStartY: 0, // 录音开始时的 Y 坐标
96
+ placeholderStyle: '' // placeholder 样式(Android 需要特殊处理垂直居中)
96
97
  },
97
98
 
98
99
  observers: {
@@ -125,6 +126,16 @@ Component({
125
126
  if (this.properties.defaultValue) {
126
127
  this.setData({ inputValue: this.properties.defaultValue });
127
128
  }
129
+
130
+ // 检测平台,Android 需要特殊处理 textarea placeholder 垂直居中
131
+ const systemInfo = wx.getSystemInfoSync();
132
+ const isAndroid = systemInfo.platform === 'android';
133
+ if (isAndroid) {
134
+ // Android 上 textarea 的 placeholder 不会垂直居中,需要通过 padding-top 调整
135
+ this.setData({
136
+ placeholderStyle: 'padding-top: 15rpx;'
137
+ });
138
+ }
128
139
  },
129
140
  detached() {
130
141
  if (this.data.isRecording) {
@@ -282,10 +293,11 @@ Component({
282
293
  * 输入框行数变化
283
294
  */
284
295
  onLineChange(e) {
285
- const lineHeight = 35;
286
- const baseHeight = 50; // 单行基准高度
296
+ const lineHeight = 42; // 基于 font-size: 30rpx, line-height: 1.4
297
+ const baseHeight = 50; // 单行基准高度(和语音按钮内容高度一致)
287
298
  const lines = Math.min(e.detail.lineCount, 5);
288
- const newHeight = lineHeight * lines;
299
+ // 单行时使用基准高度,多行时使用行高计算
300
+ const newHeight = lines <= 1 ? baseHeight : lineHeight * lines;
289
301
  this.setData({
290
302
  inputHeight: newHeight
291
303
  });
@@ -48,6 +48,7 @@
48
48
  class="text-input"
49
49
  placeholder="{{placeholder}}"
50
50
  placeholder-class="text-input-placeholder"
51
+ placeholder-style="{{placeholderStyle}}"
51
52
  value="{{inputValue}}"
52
53
  focus="{{textareaFocus}}"
53
54
  bindinput="onInput"
@@ -52,10 +52,10 @@
52
52
 
53
53
  .attachment-remove {
54
54
  position: absolute;
55
- top: -12rpx;
56
- right: -12rpx;
57
- width: 36rpx;
58
- height: 36rpx;
55
+ top: -14rpx;
56
+ right: -14rpx;
57
+ width: 40rpx;
58
+ height: 40rpx;
59
59
  background-color: rgba(0, 0, 0, 0.6);
60
60
  border-radius: 50%;
61
61
  display: flex;
@@ -65,8 +65,9 @@
65
65
 
66
66
  .attachment-remove text {
67
67
  color: #fff;
68
- font-size: 24rpx;
68
+ font-size: 32rpx;
69
69
  line-height: 1;
70
+ margin-top: -6rpx;
70
71
  }
71
72
 
72
73
  .attachment-progress {
@@ -115,19 +116,20 @@
115
116
  background-color: #fff;
116
117
  border-radius: 16rpx;
117
118
  border: 1rpx solid #E0E0E0;
118
- padding: 0rpx 24rpx 0rpx 24rpx;
119
- min-height: 82rpx;
119
+ padding: 0 24rpx;
120
+ min-height: 92rpx;
120
121
  box-sizing: border-box;
121
122
  display: flex;
122
123
  align-items: center;
124
+ overflow: hidden;
123
125
  }
124
126
 
125
127
  .text-input {
126
128
  width: 100%;
127
129
  font-size: 30rpx;
128
130
  line-height: 1.4;
129
- min-height: 40rpx;
130
131
  color: #333;
132
+ min-height: 50rpx;
131
133
  }
132
134
 
133
135
  .text-input-placeholder {
@@ -137,15 +139,16 @@
137
139
  /* 语音按钮 */
138
140
  .voice-btn {
139
141
  flex: 1;
140
- height: 82rpx;
141
- padding: 16rpx 24rpx;
142
+ height: 92rpx;
143
+ padding: 32rpx 24rpx;
142
144
  display: flex;
143
145
  align-items: center;
144
146
  justify-content: center;
145
147
  background-color: #fff;
146
148
  border-radius: 16rpx;
147
149
  border: 1rpx solid #E0E0E0;
148
- font-size: 28rpx;
150
+ font-size: 30rpx;
151
+ font-weight: bold;
149
152
  color: #333;
150
153
  transition: all 0.2s;
151
154
  box-sizing: border-box;
@@ -52,7 +52,11 @@ Component({
52
52
  searchKeyword: '', // 搜索关键词
53
53
  // 胶囊按钮位置
54
54
  menuButtonTop: 0,
55
- menuButtonHeight: 0
55
+ menuButtonHeight: 0,
56
+ // 重命名模态框
57
+ showRenameModal: false,
58
+ renameValue: '',
59
+ renamingSession: null
56
60
  },
57
61
 
58
62
  lifetimes: {
@@ -272,8 +276,13 @@ Component({
272
276
  * 选择会话
273
277
  */
274
278
  onSelectSession(e) {
275
- if (this.data.isEditMode) return;
276
279
  const session = e.currentTarget.dataset.session;
280
+
281
+ // 如果在编辑模式,先退出编辑模式
282
+ if (this.data.isEditMode) {
283
+ this.setData({ isEditMode: false });
284
+ }
285
+
277
286
  this.triggerEvent('select', { session });
278
287
  this.onClose();
279
288
  },
@@ -331,45 +340,89 @@ Component({
331
340
  },
332
341
 
333
342
  /**
334
- * 重命名对话
343
+ * 重命名对话 - 显示自定义模态框
335
344
  */
336
345
  onRename(e) {
337
346
  const session = e.currentTarget.dataset.session;
347
+ this.setData({
348
+ showRenameModal: true,
349
+ renameValue: session.title || '',
350
+ renamingSession: session
351
+ });
352
+ },
338
353
 
339
- wx.showModal({
340
- title: '重命名',
341
- editable: true,
342
- placeholderText: '请输入新标题',
343
- content: session.title,
344
- success: async (res) => {
345
- if (res.confirm && res.content && res.content.trim()) {
346
- try {
347
- await api.renameChatSession(
348
- this.properties.baseUrl,
349
- this.properties.token,
350
- session.id,
351
- res.content.trim()
352
- );
353
-
354
- // 更新本地数据
355
- this.updateSessionTitle(session.id, res.content.trim());
354
+ /**
355
+ * 重命名输入变化
356
+ */
357
+ onRenameInput(e) {
358
+ this.setData({
359
+ renameValue: e.detail.value
360
+ });
361
+ },
356
362
 
357
- wx.showToast({
358
- title: '重命名成功',
359
- icon: 'success'
360
- });
361
- } catch (error) {
362
- console.error('重命名失败', error);
363
- wx.showToast({
364
- title: error.message || '重命名失败',
365
- icon: 'none'
366
- });
367
- }
368
- }
369
- }
363
+ /**
364
+ * 取消重命名
365
+ */
366
+ onRenameCancel() {
367
+ this.setData({
368
+ showRenameModal: false,
369
+ renameValue: '',
370
+ renamingSession: null
370
371
  });
371
372
  },
372
373
 
374
+ /**
375
+ * 确认重命名
376
+ */
377
+ async onRenameConfirm() {
378
+ const { renameValue, renamingSession } = this.data;
379
+
380
+ if (!renameValue || !renameValue.trim()) {
381
+ wx.showToast({
382
+ title: '请输入标题',
383
+ icon: 'none'
384
+ });
385
+ return;
386
+ }
387
+
388
+ try {
389
+ await api.renameChatSession(
390
+ this.properties.baseUrl,
391
+ this.properties.token,
392
+ renamingSession.id,
393
+ renameValue.trim()
394
+ );
395
+
396
+ // 更新本地数据
397
+ this.updateSessionTitle(renamingSession.id, renameValue.trim());
398
+
399
+ // 关闭模态框
400
+ this.setData({
401
+ showRenameModal: false,
402
+ renameValue: '',
403
+ renamingSession: null
404
+ });
405
+
406
+ wx.showToast({
407
+ title: '重命名成功',
408
+ icon: 'success'
409
+ });
410
+ } catch (error) {
411
+ console.error('重命名失败', error);
412
+ wx.showToast({
413
+ title: error.message || '重命名失败',
414
+ icon: 'none'
415
+ });
416
+ }
417
+ },
418
+
419
+ /**
420
+ * 阻止模态框点击冒泡
421
+ */
422
+ preventModalBubble() {
423
+ // 空函数,阻止事件冒泡
424
+ },
425
+
373
426
  /**
374
427
  * 更新会话标题
375
428
  */
@@ -134,4 +134,32 @@
134
134
  </view>
135
135
  </view>
136
136
  </view>
137
+
138
+ <!-- 重命名模态框 -->
139
+ <view wx:if="{{showRenameModal}}" class="rename-modal-overlay" catchtap="onRenameCancel">
140
+ <view class="rename-modal" catchtap="preventModalBubble">
141
+ <view class="rename-modal-header">
142
+ <text class="rename-modal-title">重命名</text>
143
+ </view>
144
+ <view class="rename-modal-body">
145
+ <input
146
+ class="rename-input"
147
+ value="{{renameValue}}"
148
+ placeholder="请输入新标题"
149
+ focus="{{showRenameModal}}"
150
+ bindinput="onRenameInput"
151
+ bindconfirm="onRenameConfirm"
152
+ maxlength="50"
153
+ />
154
+ </view>
155
+ <view class="rename-modal-footer">
156
+ <view class="rename-modal-btn rename-cancel-btn" bindtap="onRenameCancel">
157
+ <text>取消</text>
158
+ </view>
159
+ <view class="rename-modal-btn rename-confirm-btn" bindtap="onRenameConfirm">
160
+ <text>确定</text>
161
+ </view>
162
+ </view>
163
+ </view>
164
+ </view>
137
165
  </view>
@@ -260,3 +260,77 @@
260
260
  color: #333;
261
261
  font-weight: bold;
262
262
  }
263
+
264
+ /* 重命名模态框 */
265
+ .rename-modal-overlay {
266
+ position: fixed;
267
+ top: 0;
268
+ left: 0;
269
+ right: 0;
270
+ bottom: 0;
271
+ background-color: rgba(0, 0, 0, 0.5);
272
+ display: flex;
273
+ align-items: center;
274
+ justify-content: center;
275
+ z-index: 9999;
276
+ }
277
+
278
+ .rename-modal {
279
+ width: 80%;
280
+ max-width: 560rpx;
281
+ background-color: #fff;
282
+ border-radius: 24rpx;
283
+ overflow: hidden;
284
+ }
285
+
286
+ .rename-modal-header {
287
+ padding: 32rpx;
288
+ text-align: center;
289
+ }
290
+
291
+ .rename-modal-title {
292
+ font-size: 34rpx;
293
+ font-weight: 500;
294
+ color: #333;
295
+ }
296
+
297
+ .rename-modal-body {
298
+ padding: 0 32rpx 32rpx;
299
+ }
300
+
301
+ .rename-input {
302
+ width: 100%;
303
+ height: 80rpx;
304
+ padding: 0 24rpx;
305
+ background-color: #f5f5f5;
306
+ border-radius: 12rpx;
307
+ font-size: 30rpx;
308
+ box-sizing: border-box;
309
+ }
310
+
311
+ .rename-modal-footer {
312
+ display: flex;
313
+ border-top: 1rpx solid #eee;
314
+ }
315
+
316
+ .rename-modal-btn {
317
+ flex: 1;
318
+ display: flex;
319
+ align-items: center;
320
+ justify-content: center;
321
+ padding: 28rpx;
322
+ font-size: 32rpx;
323
+ }
324
+
325
+ .rename-modal-btn:active {
326
+ background-color: #f5f5f5;
327
+ }
328
+
329
+ .rename-cancel-btn {
330
+ color: #666;
331
+ border-right: 1rpx solid #eee;
332
+ }
333
+
334
+ .rename-confirm-btn {
335
+ color: #007aff;
336
+ }
@@ -399,6 +399,12 @@ Component({
399
399
  return;
400
400
  }
401
401
 
402
+ // 停止语音播放
403
+ if (this.data.playingMessageId) {
404
+ audio.stop();
405
+ this.setData({ playingMessageId: null, synthesizingMessageId: null });
406
+ }
407
+
402
408
  this.setData({ showSidebar: true });
403
409
  // 刷新对话列表
404
410
  const sidebar = this.selectComponent('#sidebar');
@@ -761,11 +767,24 @@ Component({
761
767
  };
762
768
 
763
769
  const messages = [...this.data.messages, userMessage];
764
- this.setData({ messages });
765
- this.scrollToBottom();
766
-
767
- // 发送请求
768
- this.sendChatRequest(content, attachments, isVoice);
770
+ this.setData({ messages }, () => {
771
+ // 使用 nextTick 确保 DOM 已更新
772
+ wx.nextTick(() => {
773
+ // 如果有图片附件,延迟一下让图片开始加载
774
+ const hasImages = attachments && attachments.some(att => att.type === 'image');
775
+ if (hasImages) {
776
+ setTimeout(() => {
777
+ this.scrollToBottom(true);
778
+ // 发送请求
779
+ this.sendChatRequest(content, attachments, isVoice);
780
+ }, 150);
781
+ } else {
782
+ this.scrollToBottom();
783
+ // 发送请求
784
+ this.sendChatRequest(content, attachments, isVoice);
785
+ }
786
+ });
787
+ });
769
788
  },
770
789
 
771
790
  /**
@@ -1007,7 +1026,10 @@ Component({
1007
1026
  streamingMessage: null,
1008
1027
  isStreaming: false,
1009
1028
  playingMessageId: null,
1010
- synthesizingMessageId: null
1029
+ synthesizingMessageId: null
1030
+ }, () => {
1031
+ // 停止生成后滚动到底部
1032
+ this.scrollToBottom(true);
1011
1033
  });
1012
1034
  } else {
1013
1035
  this.setData({
@@ -1091,10 +1113,16 @@ Component({
1091
1113
  isVoice: message.isVoice
1092
1114
  };
1093
1115
 
1094
- this.setData({ messages: [...messages, userMessage] });
1095
-
1096
- // 重新发送该用户消息
1097
- this.sendChatRequest(message.content, message.attachments, message.isVoice);
1116
+ // 重置用户滚动状态,确保重新生成时能自动滚动
1117
+ this.setData({
1118
+ messages: [...messages, userMessage],
1119
+ userScrolledUp: false
1120
+ }, () => {
1121
+ // 先滚动到底部,再发送请求
1122
+ this.scrollToBottom(true);
1123
+ // 重新发送该用户消息
1124
+ this.sendChatRequest(message.content, message.attachments, message.isVoice);
1125
+ });
1098
1126
  },
1099
1127
 
1100
1128
  /**
@@ -1401,7 +1429,7 @@ Component({
1401
1429
  */
1402
1430
  scrollToBottom(force = false) {
1403
1431
  const now = Date.now();
1404
- const throttleInterval = 200; // 200ms 节流
1432
+ const throttleInterval = 100; // 100ms 节流(更快响应)
1405
1433
 
1406
1434
  // 流式输出时,如果用户手动向上滚动了,不自动滚动(除非强制)
1407
1435
  if (!force && this.data.isStreaming && this.data.userScrolledUp) {
@@ -1422,12 +1450,25 @@ Component({
1422
1450
  }
1423
1451
  }
1424
1452
 
1425
- // 使用计数器确保每次都能触发滚动
1426
- const counter = this.data.scrollCounter + 1;
1453
+ // 设置自动滚动标志,防止 onScroll 误判为用户手动滚动
1454
+ this.isAutoScrolling = true;
1455
+
1456
+ // 先清空 scrollToMessage,再设置为目标值,确保触发滚动
1457
+ // 因为 scroll-into-view 值不变时不会重新触发滚动
1427
1458
  this.setData({
1428
- scrollToMessage: 'scroll-bottom',
1429
- scrollCounter: counter,
1459
+ scrollToMessage: '',
1430
1460
  lastScrollTime: now
1461
+ }, () => {
1462
+ // 在下一个 tick 设置目标值
1463
+ wx.nextTick(() => {
1464
+ this.setData({
1465
+ scrollToMessage: 'scroll-bottom'
1466
+ });
1467
+ // 延迟清除自动滚动标志,等待滚动动画完成
1468
+ setTimeout(() => {
1469
+ this.isAutoScrolling = false;
1470
+ }, 300);
1471
+ });
1431
1472
  });
1432
1473
  },
1433
1474
 
@@ -1450,6 +1491,11 @@ Component({
1450
1491
  return;
1451
1492
  }
1452
1493
 
1494
+ // 如果是自动滚动触发的,忽略
1495
+ if (this.isAutoScrolling) {
1496
+ return;
1497
+ }
1498
+
1453
1499
  const { deltaY } = e.detail;
1454
1500
 
1455
1501
  // deltaY > 0 表示向上滚动(手指向下滑)
@@ -87,7 +87,7 @@
87
87
  <!-- 消息列表区域 -->
88
88
  <scroll-view
89
89
  class="message-list"
90
- style="margin-top: {{navBarHeight}}px; padding-bottom: {{keyboardHeight > 0 ? (keyboardHeight + inputBarHeight + 40) : (55 + safeAreaBottom + attachmentHeight + inputBarHeight)}}px;"
90
+ style="margin-top: {{navBarHeight}}px; padding-bottom: {{keyboardHeight > 0 ? (keyboardHeight + inputBarHeight + 62) : (83 + safeAreaBottom + attachmentHeight + inputBarHeight)}}px;"
91
91
  scroll-y="true"
92
92
  scroll-into-view="{{scrollToMessage}}"
93
93
  enhanced="true"
@@ -104,6 +104,13 @@
104
104
 
105
105
  <!-- 消息列表 -->
106
106
  <view class="message-wrapper">
107
+ <!-- 空状态 -->
108
+ <view wx:if="{{messages.length === 0 && !streamingMessage}}" class="empty-state">
109
+ <view class="empty-icon"></view>
110
+ <text class="empty-text">开始新对话</text>
111
+ <text class="empty-hint">输入问题或按住说话</text>
112
+ </view>
113
+
107
114
  <block wx:for="{{messages}}" wx:key="id">
108
115
  <message-item
109
116
  id="msg-{{item.id}}"
@@ -136,13 +143,6 @@
136
143
  />
137
144
  </view>
138
145
 
139
- <!-- 空状态 -->
140
- <view wx:if="{{messages.length === 0 && !streamingMessage}}" class="empty-state">
141
- <view class="empty-icon"></view>
142
- <text class="empty-text">开始新对话</text>
143
- <text class="empty-hint">输入问题或按住说话</text>
144
- </view>
145
-
146
146
  <!-- 底部占位 -->
147
147
  <view class="scroll-bottom-spacer" id="scroll-bottom"></view>
148
148
  </scroll-view>
@@ -218,7 +218,7 @@
218
218
  }
219
219
 
220
220
  .message-wrapper {
221
- padding-bottom: 40rpx;
221
+ padding-bottom: 10rpx;
222
222
  /* 设置最小高度为100%+额外空间,确保能够滚动 */
223
223
  min-height: calc(100%);
224
224
  }
@@ -241,6 +241,7 @@
241
241
  flex-direction: column;
242
242
  align-items: center;
243
243
  justify-content: center;
244
+ min-height: 100%; /* 占满整个 message-wrapper */
244
245
  padding: 100rpx 0;
245
246
  }
246
247
 
@@ -262,7 +263,7 @@
262
263
 
263
264
  /* 底部占位 */
264
265
  .scroll-bottom-spacer {
265
- height: 20rpx;
266
+ height: 0rpx;
266
267
  }
267
268
 
268
269
  /* 底部区域 */
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@flexem/chat-box",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "main": "index.js"
5
5
  }
@@ -11,6 +11,7 @@ let currentPlayingId = null;
11
11
  let onPlayStateChange = null;
12
12
  let currentSegmentPlayer = null; // 当前正在播放的片段播放器(用于分段播放)
13
13
  let currentPlayState = null; // 当前的 playState 对象引用(用于停止时标记)
14
+ let pendingStopCallback = false; // 是否有待处理的 stop 回调(用于区分 onEnded 是 stop 触发还是正常播放完毕)
14
15
 
15
16
  // 流式播放队列相关
16
17
  let streamingId = null; // 当前流式播放的消息 ID
@@ -55,6 +56,10 @@ function initAudioPlayer() {
55
56
 
56
57
  innerAudioContext.onStop(() => {
57
58
  console.log('音频停止');
59
+ // 清除待处理的 stop 回调标志
60
+ pendingStopCallback = false;
61
+ // 如果 playText 正在用 segmentPlayer 管理播放,不要干扰
62
+ if (currentPlayState) return;
58
63
  if (onPlayStateChange) {
59
64
  onPlayStateChange({ playing: false, id: currentPlayingId });
60
65
  }
@@ -64,11 +69,31 @@ function initAudioPlayer() {
64
69
 
65
70
  innerAudioContext.onEnded(() => {
66
71
  console.log('音频播放结束');
72
+
73
+ // 如果这个 onEnded 是由 stop() 触发的(而非正常播放完毕),不要进入流式播放分支
74
+ // 否则会错误地将其当作新流式播放的"音频段播放完毕",导致状态混乱
75
+ if (pendingStopCallback) {
76
+ console.log('onEnded 由 stop() 触发,忽略流式播放处理');
77
+ pendingStopCallback = false;
78
+ // 按停止逻辑处理
79
+ if (!currentPlayState) {
80
+ if (onPlayStateChange) {
81
+ onPlayStateChange({ playing: false, id: currentPlayingId });
82
+ }
83
+ }
84
+ currentPlayingId = null;
85
+ return;
86
+ }
87
+
67
88
  // 流式模式下,播放完当前段后继续播放队列中的下一段
68
89
  if (isStreamingMode && streamingId) {
69
90
  isPlayingAudio = false;
70
91
  playNextAudio();
71
92
  } else {
93
+ // 如果 playText 正在用 segmentPlayer 管理播放,不要干扰
94
+ // 否则 innerAudioContext.stop() 触发的异步 onEnded 会把 currentPlayingId 置空,
95
+ // 导致 tryPlayNext 的 currentPlayingId !== playState.id 判断失败,音频不播放
96
+ if (currentPlayState) return;
72
97
  if (onPlayStateChange) {
73
98
  onPlayStateChange({ playing: false, id: currentPlayingId });
74
99
  }
@@ -155,6 +180,8 @@ function stop() {
155
180
 
156
181
  // 停止全局播放器
157
182
  if (innerAudioContext) {
183
+ // 标记有待处理的 stop 回调,防止异步 onEnded 被错误地当作新流式播放的"音频段播放完毕"
184
+ pendingStopCallback = true;
158
185
  innerAudioContext.stop();
159
186
  }
160
187
  currentPlayingId = null;
@@ -622,6 +649,9 @@ function startStreamingPlay(id) {
622
649
  stopStreamingPlay();
623
650
  }
624
651
 
652
+ // 清除待处理的 stop 回调标志,确保新的流式播放不受之前 stop() 的影响
653
+ pendingStopCallback = false;
654
+
625
655
  streamingId = id;
626
656
  textQueue = [];
627
657
  audioQueue = [];
@@ -816,6 +846,7 @@ function playNextAudio() {
816
846
  console.log('流式播放全部完成');
817
847
  const id = streamingId;
818
848
  stopStreamingPlay();
849
+ currentPlayingId = null;
819
850
  if (onPlayStateChange) {
820
851
  onPlayStateChange({ playing: false, id: id });
821
852
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexem/chat-box",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "chat box",
5
5
  "main": "miniprogram_dist/index.js",
6
6
  "miniprogram": "miniprogram_dist",