@tencentcloud/ai-desk-customer-vue 1.6.0 → 1.6.3

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 (40) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/assets/arrow_down_icon.svg +1 -0
  3. package/assets/arrow_down_icon_white.svg +1 -0
  4. package/components/CustomerServiceChat/chat-header/index-web.vue +1 -5
  5. package/components/CustomerServiceChat/customer-queue-page/index.vue +138 -0
  6. package/components/CustomerServiceChat/emoji-config/default-emoji.ts +11 -0
  7. package/components/CustomerServiceChat/emoji-config/index.ts +14 -1
  8. package/components/CustomerServiceChat/index-web.vue +29 -7
  9. package/components/CustomerServiceChat/message-input/index-web.vue +38 -0
  10. package/components/CustomerServiceChat/message-input/message-input-button.vue +5 -0
  11. package/components/CustomerServiceChat/message-input/message-input-editor-web.vue +13 -9
  12. package/components/CustomerServiceChat/message-input-toolbar/emoji-dialog-mobile/emoji-dialog-mobile.vue +26 -46
  13. package/components/CustomerServiceChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue +8 -38
  14. package/components/CustomerServiceChat/message-list/bottom-quick-order/index.vue +1 -0
  15. package/components/CustomerServiceChat/message-list/index-web.vue +7 -1
  16. package/components/CustomerServiceChat/message-list/message-elements/message-bubble-web.vue +33 -15
  17. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/marked.ts +7 -6
  18. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-stream.vue +1 -0
  19. package/components/CustomerServiceChat/message-list/scroll-button/index.vue +17 -9
  20. package/locales/en/TUIChat.ts +1 -1
  21. package/locales/en/aidesk.ts +4 -1
  22. package/locales/fil/TUIChat.ts +1 -1
  23. package/locales/fil/aidesk.ts +4 -1
  24. package/locales/id/TUIChat.ts +1 -1
  25. package/locales/id/aidesk.ts +4 -1
  26. package/locales/ja/TUIChat.ts +1 -1
  27. package/locales/ja/aidesk.ts +4 -1
  28. package/locales/ms/TUIChat.ts +1 -1
  29. package/locales/ms/aidesk.ts +4 -1
  30. package/locales/ru/TUIChat.ts +1 -1
  31. package/locales/ru/aidesk.ts +4 -1
  32. package/locales/th/TUIChat.ts +1 -1
  33. package/locales/th/aidesk.ts +4 -1
  34. package/locales/vi/TUIChat.ts +1 -1
  35. package/locales/vi/aidesk.ts +4 -1
  36. package/locales/zh_cn/aidesk.ts +4 -1
  37. package/locales/zh_tw/aidesk.ts +4 -1
  38. package/package.json +1 -1
  39. package/utils/utils.ts +1 -1
  40. package/assets/double-arrow.svg +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 1.6.3 @2025.11.13
2
+
3
+ ### Features
4
+ - 转人工排队阶段支持展示排队信息,提升用户体验。
5
+ - 转人工成功后支持展示人工客服的昵称和头像。
6
+ - 优化 markdown 图片尺寸。
7
+
8
+ ### Fixed
9
+ - 没有消息时显示查看更多。
10
+ - 流式消息的字体跟主字体不一致的问题。
11
+
12
+ ## 1.6.2 @2025.10.30
13
+
14
+ ### Features
15
+ - 优化发送语音的产品体验。
16
+ - 优化 scroll-button 等组件样式。
17
+ - emoji 表情适配海外。
18
+ - 完善 markdown 解析。
19
+
1
20
  ## 1.6.0 @2025.10.21
2
21
 
3
22
  ### Features
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#444444"><path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#ffffff"><path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z"/></svg>
@@ -160,11 +160,7 @@ function setCurrentConversationName() {
160
160
  if (props.headerConfig && props.headerConfig.title) {
161
161
  currentConversationName.value = props.headerConfig.title;
162
162
  } else {
163
- if (isH5) {
164
- currentConversationName.value = TUITranslateService.t('AIDesk.Hi,我是') + currentConversation.value.getShowName();
165
- } else {
166
- currentConversationName.value = currentConversation.value.getShowName() || '';
167
- }
163
+ currentConversationName.value = currentConversation.value.getShowName() || '';
168
164
  }
169
165
  }
170
166
 
@@ -0,0 +1,138 @@
1
+ <template>
2
+ <div class="customer-queue">
3
+ <div class="customer-queue-header">
4
+ {{ TUITranslateService.t("AIDesk.排队等待中") }}...
5
+ </div>
6
+ <div class="customer-queue-info">
7
+ {{ TUITranslateService.t("AIDesk.排队等待话术") }}
8
+ </div>
9
+ <div class="customer-queue-container">
10
+ <div class="customer-queue-content-title">
11
+ {{ TUITranslateService.t("AIDesk.当前前方排队人数") }}
12
+ </div>
13
+ <div class="customer-queue-content-number">
14
+ {{ props.queueNumber }}
15
+ </div>
16
+ </div>
17
+ <div class="customer-queue-end-button">
18
+ <div :class="['customer-queue-end-button-content', isClicked ? 'button-clicked' : '']" @click="endQueuing">
19
+ {{ TUITranslateService.t("AIDesk.结束排队") }}
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </template>
24
+ <script lang="ts" setup>
25
+ import vue from '../../../adapter-vue';
26
+ const { ref, onMounted, onUnmounted } = vue;
27
+ import { IConversationModel, StoreName, TUIChatService, TUIStore, TUITranslateService } from '@tencentcloud/chat-uikit-engine';
28
+ import { CUSTOM_MESSAGE_SRC } from '../../../constant';
29
+ import { getTo, isEnabledMessageReadReceiptGlobal } from '../../../utils/utils';
30
+ const currentConversation = ref<IConversationModel>();
31
+ const isClicked = ref(false);
32
+ const props = defineProps({
33
+ queueNumber: {
34
+ type: Number,
35
+ default: 0
36
+ },
37
+ });
38
+ onMounted(() => {
39
+ TUIStore.watch(StoreName.CONV, {
40
+ currentConversation: onCurrentConversationUpdate,
41
+ });
42
+ });
43
+
44
+ onUnmounted(() => {
45
+ TUIStore.unwatch(StoreName.CONV, {
46
+ currentConversation: onCurrentConversationUpdate,
47
+ });
48
+ });
49
+
50
+ const onCurrentConversationUpdate = (conversation: IConversationModel) => {
51
+ currentConversation.value = conversation;
52
+ };
53
+
54
+ const endQueuing = () => {
55
+ if (isClicked.value) {
56
+ return;
57
+ }
58
+ isClicked.value = true;
59
+ TUIChatService.sendCustomMessage({
60
+ to: getTo(currentConversation.value),
61
+ conversationType: currentConversation.value.type,
62
+ payload: {
63
+ data: JSON.stringify({
64
+ customerServicePlugin: 0,
65
+ src: CUSTOM_MESSAGE_SRC.USER_END_CONVERSATION,
66
+ }),
67
+ },
68
+ needReadReceipt: isEnabledMessageReadReceiptGlobal(),
69
+ },{ onlineUserOnly:true });
70
+ }
71
+ </script>
72
+ <style lang="scss">
73
+ .customer-queue {
74
+ width: 100%;
75
+ height: 100%;
76
+ max-width: 100%;
77
+ overflow: hidden;
78
+ box-sizing: border-box;
79
+ display: flex;
80
+ flex-direction: column;
81
+ }
82
+ .customer-queue-header {
83
+ height: 52px;
84
+ background-color: #1C66E5;
85
+ color: white;
86
+ line-height: 52px;
87
+ padding-left: 20px;
88
+ }
89
+ .customer-queue-info {
90
+ padding: 20px;
91
+ color: #666;
92
+ }
93
+ .customer-queue-container {
94
+ flex: 1;
95
+ display: flex;
96
+ flex-direction: column;
97
+ align-items: center;
98
+ justify-content: center;
99
+ color: #1C66E5;
100
+ }
101
+
102
+ .customer-queue-content-title {
103
+ font-size: 20px;
104
+ margin-bottom: 10px;
105
+ }
106
+
107
+ .customer-queue-content-number {
108
+ font-size: 40px;
109
+ font-weight: bold;
110
+ }
111
+ .customer-queue-end-button {
112
+ color: white;
113
+ padding: 8px 23px;
114
+ border-radius: 10px;
115
+ }
116
+ .customer-queue-end-button {
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ margin-bottom: 20px;
121
+ &-content {
122
+ background: #1c66e5;
123
+ color: white;
124
+ padding: 8px 23px;
125
+ border-radius: 10px;
126
+ width: fit-content;
127
+ min-width: 70px;
128
+ cursor: pointer;
129
+ display: flex;
130
+ justify-content: center;
131
+ }
132
+ }
133
+ .button-clicked {
134
+ cursor: default;
135
+ background: #cccccc;
136
+ color: #666666;
137
+ }
138
+ </style>
@@ -80,6 +80,17 @@ export const DEFAULT_BASIC_EMOJI_URL_MAPPING: Record<string, string> = {
80
80
  '[TUIEmoji_Like]': 'emoji_61@2x.png',
81
81
  };
82
82
 
83
+ export const EXCLUDED_EMOJI_LIST = [
84
+ '[TUIEmoji_Pig]',
85
+ '[TUIEmoji_Rich]',
86
+ '[TUIEmoji_Fortune]',
87
+ '[TUIEmoji_857]',
88
+ '[TUIEmoji_666]',
89
+ '[TUIEmoji_Prohibit]',
90
+ '[TUIEmoji_Convinced]',
91
+ '[TUIEmoji_Knife]',
92
+ ];
93
+
83
94
  export const BIG_EMOJI_GROUP_LIST: IEmojiGroupList = [
84
95
  {
85
96
  emojiGroupID: 1,
@@ -1,6 +1,6 @@
1
1
  import { TUITranslateService } from '@tencentcloud/chat-uikit-engine';
2
2
  import { CUSTOM_BASIC_EMOJI_URL, CUSTOM_BIG_EMOJI_URL, CUSTOM_BASIC_EMOJI_URL_MAPPING, CUSTOM_BIG_EMOJI_GROUP_LIST } from './custom-emoji';
3
- import { DEFAULT_BASIC_EMOJI_URL, BIG_EMOJI_GROUP_LIST, DEFAULT_BASIC_EMOJI_URL_MAPPING, BASIC_EMOJI_NAME_TO_KEY_MAPPING, DEFAULT_BIG_EMOJI_URL } from './default-emoji';
3
+ import { DEFAULT_BASIC_EMOJI_URL, BIG_EMOJI_GROUP_LIST, DEFAULT_BASIC_EMOJI_URL_MAPPING, BASIC_EMOJI_NAME_TO_KEY_MAPPING, DEFAULT_BIG_EMOJI_URL, EXCLUDED_EMOJI_LIST } from './default-emoji';
4
4
  import { default as emojiCNLocales } from './locales/zh_cn';
5
5
  import { default as emojiENLocales } from './locales/en';
6
6
  import { IEmojiGroupList } from '../../../interface';
@@ -126,6 +126,17 @@ const parseTextToRenderArray = (text: string): Array<{ type: 'text' | 'image'; c
126
126
  return result;
127
127
  };
128
128
 
129
+ const filterEmojisInNonChineseEnv = (list: string[]) => {
130
+ const language = state.get('currentLanguage') || 'zh';
131
+ if (!(language === 'zh' || language === 'zh_tw')) {
132
+ return list.filter((item) => {
133
+ return !EXCLUDED_EMOJI_LIST.includes(item);
134
+ });
135
+ } else {
136
+ return list;
137
+ }
138
+ }
139
+
129
140
  export {
130
141
  EMOJI_GROUP_LIST,
131
142
  CUSTOM_BIG_EMOJI_URL,
@@ -138,4 +149,6 @@ export {
138
149
  transformTextWithKeysToEmojiNames,
139
150
  transformTextWithEmojiNamesToKeys,
140
151
  emojiConfig,
152
+ BASIC_EMOJI_URL,
153
+ filterEmojisInNonChineseEnv,
141
154
  };
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div :class="['tui-chat', !isPC && 'tui-chat-h5']" :key="currentLanguage">
3
3
  <div
4
- v-if="currentConversationID"
4
+ v-if="currentConversationID && (!props.showQueuePage || queueNumber < 0 || queueNumber === undefined)"
5
5
  :class="['tui-chat', !isPC && 'tui-chat-h5']"
6
6
  >
7
7
  <ChatHeader
@@ -94,6 +94,9 @@
94
94
  @close="() => { showFeedbackModal = false }"
95
95
  />
96
96
  </div>
97
+ <div v-if="props.showQueuePage && queueNumber >= 0" :class="['tui-chat', !isPC && 'tui-chat-h5']">
98
+ <CustomerQueuePage :queueNumber="queueNumber"/>
99
+ </div>
97
100
  </div>
98
101
  </template>
99
102
  <script lang="ts" setup>
@@ -122,6 +125,7 @@ import state from '../../utils/state.js';
122
125
  import { switchReadStatus,isNonEmptyObject } from '../../utils/utils';
123
126
  import { getCountryForTimezone } from 'countries-and-timezones';
124
127
  import FeedbackModal from './feedback-modal/index.vue';
128
+ import CustomerQueuePage from './customer-queue-page/index.vue';
125
129
  const { ref, onMounted, onUnmounted, computed } = vue;
126
130
 
127
131
  interface IProps {
@@ -134,12 +138,13 @@ interface IProps {
134
138
  toolbarButtonList?: ToolbarButtonModel[];
135
139
  showAvatar?: number;
136
140
  robotAvatar?: string;
137
- staffAvatar?: string;
141
+ memberAvatar?: string;
138
142
  userAvatar?: string;
139
143
  showNickName?: number;
140
144
  robotNickName?: string;
141
- staffNickName?: string;
145
+ memberNickName?: string;
142
146
  userNickName?: string;
147
+ enableUnifiedMemberProfile?: number;
143
148
  inputToolbarList?: InputToolbarModel[];
144
149
  showReadStatus?: number;
145
150
  showTyping?: number;
@@ -151,6 +156,7 @@ interface IProps {
151
156
  enableURLDetection?: number;
152
157
  headerConfig?: IHeaderConfig;
153
158
  enableSendingAudio?: number;
159
+ showQueuePage?: number;
154
160
  }
155
161
 
156
162
  const emits = defineEmits(['closeChat']);
@@ -170,6 +176,7 @@ const currentLanguage = ref('');
170
176
  const languageForShowList = ref<Array<string>>([]);
171
177
  const feedbackModalRef = ref();
172
178
  const showFeedbackModal = ref(false);
179
+ const queueNumber = ref(-1);
173
180
  let timezone = '';
174
181
  let countryID = '';
175
182
  const props = withDefaults(defineProps<IProps>(), {
@@ -182,12 +189,13 @@ const props = withDefaults(defineProps<IProps>(), {
182
189
  showReadStatus: 1,
183
190
  showAvatar: 1,
184
191
  robotAvatar: '',
185
- staffAvatar: '',
192
+ memberAvatar: '',
186
193
  userAvatar: '',
187
194
  showNickName: 0,
188
195
  robotNickName: '',
189
- staffNickName: '',
196
+ memberNickName: '',
190
197
  userNickName: '',
198
+ enableUnifiedMemberProfile: 1,
191
199
  showTyping: 0,
192
200
  enableMultilingual: 0,
193
201
  enableFeedback: 0,
@@ -195,6 +203,7 @@ const props = withDefaults(defineProps<IProps>(), {
195
203
  langList: () => [],
196
204
  enableURLDetection: 0,
197
205
  enableSendingAudio: 0,
206
+ showQueuePage: 0,
198
207
  });
199
208
 
200
209
  const loginCustomerUIKit = () => {
@@ -290,11 +299,12 @@ const setAvatarNickName = () => {
290
299
  showAvatar: props.showAvatar,
291
300
  showNickName: props.showNickName,
292
301
  userAvatar: props.userAvatar,
293
- staffAvatar: props.staffAvatar,
302
+ memberAvatar: props.memberAvatar,
294
303
  robotAvatar: props.robotAvatar,
295
304
  userNickName: props.userNickName,
296
- staffNickName: props.staffNickName,
305
+ memberNickName: props.memberNickName,
297
306
  robotNickName: props.robotNickName,
307
+ enableUnifiedMemberProfile: props.enableUnifiedMemberProfile,
298
308
  });
299
309
  }
300
310
 
@@ -346,6 +356,9 @@ onMounted(() => {
346
356
  TUIStore.watch(StoreName.CHAT, {
347
357
  quoteMessage: onQuoteMessageUpdated,
348
358
  });
359
+ TUIStore.watch(StoreName.CUSTOM, {
360
+ isQueuing: onIsQueuingUpdate,
361
+ });
349
362
  });
350
363
 
351
364
  onUnmounted(() => {
@@ -358,6 +371,9 @@ onUnmounted(() => {
358
371
  TUIStore.unwatch(StoreName.CHAT, {
359
372
  quoteMessage: onQuoteMessageUpdated,
360
373
  });
374
+ TUIStore.unwatch(StoreName.CUSTOM, {
375
+ isQueuing: onIsQueuingUpdate,
376
+ });
361
377
  });
362
378
 
363
379
  const isInputToolbarShow = computed<boolean>(() => {
@@ -501,6 +517,12 @@ function onDislike(messageInfo: Object) {
501
517
  showFeedbackModal.value = true;
502
518
  feedbackModalRef.value.onDislike(messageInfo);
503
519
  }
520
+
521
+ function onIsQueuingUpdate(data: {conversationID: string, value: number}) {
522
+ if (data && data.conversationID === currentConversationID.value) {
523
+ queueNumber.value = data.value;
524
+ }
525
+ }
504
526
  </script>
505
527
 
506
528
  <style scoped lang="scss" src="./style/index.scss">
@@ -69,6 +69,7 @@ import audioIcon from '../../../assets/audio-blue.svg';
69
69
  import keyboardIcon from '../../../assets/keyboard-icon.svg';
70
70
  import { INPUT_TOOLBAR_TYPE } from '../../../constant';
71
71
  import { onUnmounted } from 'vue';
72
+ import Log from '../../../utils/logger';
72
73
  const { ref, onMounted, onBeforeUnmount, computed } = vue;
73
74
 
74
75
  const props = defineProps({
@@ -111,23 +112,33 @@ const showSendButton = ref(false);
111
112
  const isInHumanService = ref(false);
112
113
  let quoteMessageCloudCustomData:string = '';
113
114
  const isInAudioMode = ref(false);
115
+ let hasAudioStream = false;
116
+ let audioStream = null;
114
117
 
115
118
  onMounted(() => {
116
119
  // document.addEventListener('click', handleClick);
117
120
  TUIStore.watch(StoreName.CUSTOM, {
118
121
  isInHumanService: onInHumanServiceUpdate,
119
122
  });
123
+ document.addEventListener('visibilitychange', handleVisibilityChange);
120
124
  });
121
125
 
122
126
  onUnmounted(() => {
123
127
  TUIStore.unwatch(StoreName.CUSTOM, {
124
128
  isInHumanService: onInHumanServiceUpdate,
125
129
  });
130
+ stopAudioStream();
131
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
126
132
  });
127
133
 
128
134
  const onInHumanServiceUpdate = (data: {conversationID: string, value: boolean}) => {
129
135
  if (data && data.conversationID === currentConversation.value.conversationID) {
130
136
  isInHumanService.value = data.value;
137
+ if (!isInHumanService.value) {
138
+ isInAudioMode.value = false;
139
+ placeholder.value = TUITranslateService.t('TUIChat.请输入消息');
140
+ stopAudioStream();
141
+ }
131
142
  }
132
143
  };
133
144
 
@@ -203,9 +214,28 @@ const toolShow = () => {
203
214
  const blurToolAndEmojiH5 = () =>{
204
215
  emit('blurToolAndEmojiH5');
205
216
  }
217
+ const getAudioStream = async () => {
218
+ try {
219
+ stopAudioStream();
220
+ audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
221
+ hasAudioStream = true;
222
+ } catch (err) {
223
+ Log.e('Error accessing audio stream:', err);
224
+ }
225
+ }
226
+ const stopAudioStream = () => {
227
+ if (audioStream) {
228
+ audioStream.getTracks().forEach(track => track.stop());
229
+ audioStream = null;
230
+ hasAudioStream = false;
231
+ }
232
+ }
206
233
 
207
234
  const audioShow = () => {
208
235
  isInAudioMode.value = !isInAudioMode.value;
236
+ if (isInAudioMode.value && !hasAudioStream) {
237
+ getAudioStream();
238
+ }
209
239
  placeholder.value = isInAudioMode.value ? TUITranslateService.t('TUIChat.按住说话') : TUITranslateService.t('TUIChat.请输入消息');
210
240
  emit('blurToolAndEmojiH5');
211
241
  }
@@ -228,6 +258,14 @@ const shouldShowAudio = computed(() => {
228
258
  return isH5 && isInHumanService.value && (props.enableSendingAudio === 1 || (props.inputToolbarList !== undefined && props.inputToolbarList.some(item => item.presetId === INPUT_TOOLBAR_TYPE.AUDIO && item.isEnabled === 1)));
229
259
  });
230
260
 
261
+ const handleVisibilityChange = () => {
262
+ if (document.visibilityState === 'hidden') {
263
+ stopAudioStream();
264
+ } else if (document.visibilityState === 'visible' && isInAudioMode.value) {
265
+ getAudioStream();
266
+ }
267
+ }
268
+
231
269
  defineExpose({
232
270
  insertEmoji,
233
271
  reEdit,
@@ -89,6 +89,11 @@ const sendMessage = () => {
89
89
  &:hover {
90
90
  .message-input-button-hover {
91
91
  display: flex;
92
+ width: max-content;
93
+ max-width: 60vw;
94
+ overflow: hidden;
95
+ word-break: break-word;
96
+ white-space: normal;
92
97
  }
93
98
  }
94
99
  }
@@ -155,6 +155,7 @@ let recordTimer: any = null;
155
155
  const audioWaveBars = ref(Array(24).fill({ height: 6 }));
156
156
  let audioWaveAnimation = -1;
157
157
  let pressStartTime: any = null;
158
+ const hasMicPermission = ref(false);
158
159
 
159
160
  function onCurrentConversationIDUpdated(conversationID: string) {
160
161
  if (currentConversationID.value !== conversationID) {
@@ -795,9 +796,11 @@ watch(
795
796
  );
796
797
  async function initRecorder() {
797
798
  clearInterval(recordTimer);
798
- recordTimer = undefined;
799
+ recordTimer = null;
799
800
  recordTime.value = 0;
800
801
  await recorder.value.stop();
802
+ isRecording.value = false;
803
+ recordTip.value = TUITranslateService.t("TUIChat.松开发送");
801
804
  cancelAnimationFrame(audioWaveAnimation);
802
805
  }
803
806
 
@@ -826,14 +829,19 @@ const startRecording = async(e) => {
826
829
  isRecording.value = true;
827
830
  pressStartTime = new Date();
828
831
  recordCancel.value = false;
829
- Recorder.getPermission().then(async() => {
832
+ Recorder.getPermission().then(() => {
833
+ hasMicPermission.value = true;
830
834
  if (!isRecording.value) {
831
835
  return;
832
836
  }
833
- if (recordTimer !== undefined) {
837
+ if (recordTimer !== null) {
834
838
  initRecorder();
835
839
  }
840
+ // 提前获取音频流,避免开始录音时启动过长
836
841
  recorder.value.start().then(() => {
842
+ if (!isRecording.value) {
843
+ return;
844
+ }
837
845
  updateRecordWave();
838
846
  startRecordY = getRecordY(e);
839
847
  recordTimer = setInterval(() => {
@@ -841,7 +849,6 @@ const startRecording = async(e) => {
841
849
  }, 1000);
842
850
  }, (error) => {
843
851
  Log.e(`Error in recording ${error.name} : ${error.message}`);
844
- isRecording.value = false;
845
852
  let toastMessage = `${error.name} : ${error.message}`;
846
853
  Toast({
847
854
  message:toastMessage,
@@ -851,7 +858,6 @@ const startRecording = async(e) => {
851
858
  initRecorder();
852
859
  });
853
860
  }, (error) => {
854
- isRecording.value = false;
855
861
  initRecorder();
856
862
  Toast({
857
863
  message:TUITranslateService.t("TUIChat.请检查麦克风访问权限"),
@@ -864,11 +870,10 @@ const startRecording = async(e) => {
864
870
  };
865
871
 
866
872
  const stopRecording = async () => {
867
- isRecording.value = false;
868
873
  const duration = recordTime.value;
869
874
  initRecorder();
870
875
  const pressDuration = Date.now() - pressStartTime;
871
- if (pressDuration < 1000) {
876
+ if (pressDuration < 1000 && hasMicPermission.value) {
872
877
  // 按压时间过短,还没开始录音就结束
873
878
  Toast({
874
879
  message: TUITranslateService.t("TUIChat.按压时间过短,请按压超过1秒"),
@@ -1179,8 +1184,7 @@ defineExpose({
1179
1184
  overflow: hidden;
1180
1185
  right: 0;
1181
1186
  bottom: 0;
1182
- background: linear-gradient(180deg, #FFF 0%, #FFF 64.35%);
1183
- background: linear-gradient(180deg, color(display-p3 1 1 1 / 0.00) 0%, color(display-p3 1 1 1) 64.35%);
1187
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 64.35%);
1184
1188
  display: flex;
1185
1189
  flex-direction: column;
1186
1190
  justify-content: flex-end;
@@ -1,60 +1,54 @@
1
1
  <template>
2
-
3
- <div class="emojiDialog">
4
- <ul ref="emojiPickerListRef" class="emojiDialogList">
5
- <li
6
- v-for="(childrenItem, childrenIndex) in currentEmojiList"
7
- :key="childrenIndex"
8
- class="emojiDialogList-item"
9
- @click="select(childrenItem, childrenIndex)"
10
- >
11
- <img
12
- v-if="currentTabItem.type === EMOJI_TYPE.BASIC"
13
- class="emoji"
14
- :src="currentTabItem.url + BASIC_EMOJI_URL_MAPPING[childrenItem]"
15
- >
16
- </li>
17
- </ul>
18
- <div class="sendButtonContainer">
19
- <div class="sendButton" @click="sendMessage">
20
- {{ TUITranslateService.t("发送") }}
21
- </div>
22
- </div>
2
+ <div class="emojiDialog">
3
+ <ul ref="emojiPickerListRef" class="emojiDialogList">
4
+ <li
5
+ v-for="(childrenItem, childrenIndex) in currentEmojiList"
6
+ :key="childrenIndex"
7
+ class="emojiDialogList-item"
8
+ @click="select(childrenItem, childrenIndex)"
9
+ >
10
+ <img
11
+ class="emoji"
12
+ :src="BASIC_EMOJI_URL + BASIC_EMOJI_URL_MAPPING[childrenItem]"
13
+ >
14
+ </li>
15
+ </ul>
16
+ <div class="sendButtonContainer">
17
+ <div class="sendButton" @click="sendMessage">
18
+ {{ TUITranslateService.t("发送") }}
19
+ </div>
23
20
  </div>
24
-
21
+ </div>
25
22
  </template>
26
23
  <script lang="ts" setup>
27
24
  import vue from '../../../../adapter-vue';
28
- import { IEmojiGroupList, IEmojiGroup } from '../../../../interface';
25
+ import { IEmojiGroupList } from '../../../../interface';
29
26
  const { ref, onMounted, onUnmounted } = vue;
30
27
  import {
31
- TUIChatService,
32
28
  TUIStore,
33
29
  StoreName,
34
30
  IConversationModel,
35
31
  TUITranslateService,
36
- SendMessageParams,
37
32
  } from '@tencentcloud/chat-uikit-engine';
38
33
  import {
39
34
  EMOJI_GROUP_LIST,
40
35
  BASIC_EMOJI_URL_MAPPING,
41
36
  convertKeyToEmojiName,
37
+ BASIC_EMOJI_URL,
38
+ filterEmojisInNonChineseEnv,
42
39
  } from '../../emoji-config';
43
- import { EMOJI_TYPE } from '.././../../../constant';
44
- import { isPC, } from '../../../../utils/env';
45
40
 
46
41
  const emits = defineEmits(['insertEmoji', 'onClose', 'sendMessage']);
47
42
  const list = ref<IEmojiGroupList>(initEmojiList());
48
43
  const currentConversation = ref();
49
44
  const emojiPickerListRef = ref();
50
- const currentTabIndex = ref<number>(0);
51
45
  const currentEmojiList = ref<string[]>(list?.value[0]?.list);
52
- const currentTabItem = ref<IEmojiGroup>(list?.value[0]);
53
46
 
54
47
  onMounted(() => {
55
48
  TUIStore.watch(StoreName.CONV, {
56
49
  currentConversation: onCurrentConversationUpdate,
57
50
  });
51
+ currentEmojiList.value = filterEmojisInNonChineseEnv(list.value[0].list);
58
52
  });
59
53
 
60
54
  onUnmounted(() => {
@@ -66,24 +60,10 @@ onUnmounted(() => {
66
60
  const select = (item: any, index: number) => {
67
61
  const options: any = {
68
62
  emoji: { key: item, name: convertKeyToEmojiName(item) },
69
- type: currentTabItem?.value?.type,
63
+ type: 'basic',
64
+ url : BASIC_EMOJI_URL + BASIC_EMOJI_URL_MAPPING[item],
70
65
  };
71
- switch (currentTabItem?.value?.type) {
72
- case EMOJI_TYPE.BASIC:
73
- options.url = currentTabItem?.value?.url + BASIC_EMOJI_URL_MAPPING[item];
74
- emits('insertEmoji', options);
75
-
76
- break;
77
- case EMOJI_TYPE.BIG:
78
- // sendFaceMessage(index, currentTabItem.value);
79
- break;
80
- case EMOJI_TYPE.CUSTOM:
81
- // sendFaceMessage(index, currentTabItem.value);
82
- break;
83
- default:
84
- break;
85
- }
86
- isPC && emits('onClose');
66
+ emits('insertEmoji', options);
87
67
  };
88
68
 
89
69
  function sendMessage(){