@tencentcloud/ai-desk-customer-vue 1.5.11 → 1.6.2

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 (52) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/assets/arrow_down_icon.svg +1 -0
  3. package/assets/arrow_down_icon_white.svg +1 -0
  4. package/assets/audio-blue.svg +4 -0
  5. package/assets/audio_icon_1.svg +3 -0
  6. package/assets/audio_icon_2.svg +3 -0
  7. package/assets/audio_icon_3.svg +3 -0
  8. package/assets/keyboard-icon.svg +9 -0
  9. package/components/CustomerServiceChat/chat-header/index-web.vue +1 -5
  10. package/components/CustomerServiceChat/emoji-config/default-emoji.ts +11 -0
  11. package/components/CustomerServiceChat/emoji-config/index.ts +14 -1
  12. package/components/CustomerServiceChat/index-web.vue +10 -2
  13. package/components/CustomerServiceChat/message-input/index-web.vue +95 -10
  14. package/components/CustomerServiceChat/message-input/message-input-button.vue +5 -0
  15. package/components/CustomerServiceChat/message-input/message-input-editor-web.vue +346 -11
  16. package/components/CustomerServiceChat/message-input-toolbar/emoji-dialog-mobile/emoji-dialog-mobile.vue +26 -46
  17. package/components/CustomerServiceChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue +8 -38
  18. package/components/CustomerServiceChat/message-list/bottom-quick-order/index.vue +1 -0
  19. package/components/CustomerServiceChat/message-list/index-web.vue +13 -0
  20. package/components/CustomerServiceChat/message-list/message-elements/message-audio-web.vue +50 -78
  21. package/components/CustomerServiceChat/message-list/message-elements/message-bubble-web.vue +1 -1
  22. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/marked.ts +5 -3
  23. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-robot-welcome.vue +13 -6
  24. package/components/CustomerServiceChat/message-list/message-elements/message-text.vue +3 -2
  25. package/components/CustomerServiceChat/message-list/scroll-button/index.vue +17 -9
  26. package/components/common/Toast/index-web.ts +16 -3
  27. package/components/common/Toast/index-web.vue +16 -6
  28. package/constant.ts +1 -0
  29. package/locales/en/TUIChat.ts +7 -3
  30. package/locales/en/aidesk.ts +0 -1
  31. package/locales/fil/TUIChat.ts +7 -3
  32. package/locales/fil/aidesk.ts +0 -1
  33. package/locales/id/TUIChat.ts +76 -72
  34. package/locales/id/aidesk.ts +0 -1
  35. package/locales/ja/TUIChat.ts +76 -72
  36. package/locales/ja/aidesk.ts +0 -1
  37. package/locales/ms/TUIChat.ts +76 -72
  38. package/locales/ms/aidesk.ts +0 -1
  39. package/locales/ru/TUIChat.ts +7 -3
  40. package/locales/ru/aidesk.ts +0 -1
  41. package/locales/th/TUIChat.ts +76 -72
  42. package/locales/th/aidesk.ts +0 -1
  43. package/locales/vi/TUIChat.ts +76 -72
  44. package/locales/vi/aidesk.ts +0 -1
  45. package/locales/zh_cn/TUIChat.ts +6 -2
  46. package/locales/zh_cn/aidesk.ts +0 -1
  47. package/locales/zh_tw/TUIChat.ts +6 -2
  48. package/locales/zh_tw/aidesk.ts +0 -1
  49. package/package.json +2 -1
  50. package/server.ts +22 -3
  51. package/assets/double-arrow.svg +0 -1
  52. package/assets/keyboard_icon.png +0 -0
@@ -2,10 +2,12 @@
2
2
  <div
3
3
  :class="[
4
4
  'message-input-editor-container',
5
- isPC && !props.hasInputTool && 'message-input-editor-container-no-inputTool',
5
+ isPC && !props.shouldShowToolbar && 'message-input-editor-container-no-inputTool',
6
6
  isH5 && 'message-input-editor-container-h5',
7
- isH5 && !props.hasEmojiTool && props.hasInputTool && 'message-input-editor-container-h5-no-emoji-no-tool',
8
- isH5 && !props.hasEmojiTool && !props.hasInputTool && 'message-input-editor-container-h5-no-emoji',
7
+ isH5 && !props.shouldShowEmoji && props.shouldShowToolbar && 'message-input-editor-container-h5-no-emoji-no-tool',
8
+ isH5 && !props.shouldShowEmoji && !props.shouldShowToolbar && 'message-input-editor-container-h5-no-emoji',
9
+ isH5 && props.shouldShowAudio && 'message-input-editor-container-h5-audio',
10
+ isH5 && isInAudioMode && 'message-input-editor-container-h5-audio-mode',
9
11
  ]"
10
12
  >
11
13
  <div
@@ -14,8 +16,35 @@
14
16
  >
15
17
  {{ muteText }}
16
18
  </div>
19
+ <div v-if="isInAudioMode"
20
+ class="audio-mode no-copy"
21
+ @touchstart="startRecording"
22
+ @touchend="stopRecording"
23
+ @touchcancel="stopRecording"
24
+ @touchmove="handleTouchMove"
25
+ @contextmenu.prevent
26
+ >
27
+ {{ TUITranslateService.t('TUIChat.按住说话') }}
28
+ <div v-if="isRecording" class="record-container">
29
+ <div class="record-tip">
30
+ {{ recordTip }}
31
+ </div>
32
+ <div class="audio-wave-container">
33
+ <div :class="['audio-wave-bubble', recordCancel ? 'audio-wave-bubble-cancel' : '']">
34
+ <div class="audio-wave">
35
+ <div
36
+ v-for="(bar, index) in audioWaveBars"
37
+ :key="index"
38
+ class="wave-bar"
39
+ :style="{ height: bar.height + 'px' }"
40
+ ></div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
17
46
  <div
18
- v-if="!isMuted && enableInput"
47
+ v-if="!isMuted && enableInput && !isInAudioMode"
19
48
  ref="editorDom"
20
49
  class="message-input-editor-area"
21
50
  :contenteditable="isH5"
@@ -30,10 +59,12 @@
30
59
  </template>
31
60
  <script setup lang="ts">
32
61
  import vue from '../../../adapter-vue';
33
- import {
62
+ import TUIChatEngine, {
34
63
  TUIStore,
35
64
  StoreName,
36
65
  IMessageModel,
66
+ TUIChatService,
67
+ TUITranslateService,
37
68
  } from '@tencentcloud/chat-uikit-engine';
38
69
  import { Editor, JSONContent } from '@tiptap/core';
39
70
  import Document from '@tiptap/extension-document';
@@ -46,6 +77,14 @@ import { ITipTapEditorContent } from '../../../interface';
46
77
  import { parseTextToRenderArray } from '../emoji-config';
47
78
  import { isH5, isPC } from '../../../utils/env';
48
79
  import DraftManager from '../utils/conversationDraft';
80
+ import {
81
+ Toast,
82
+ TOAST_TYPE,
83
+ } from '../../common/Toast/index-web';
84
+ import Recorder from "js-audio-recorder";
85
+ import { isEnabledMessageReadReceiptGlobal } from '../../../utils/utils';
86
+ import Log from '../../../utils/logger';
87
+ import state from '../../../utils/state.js';
49
88
  const { toRefs, ref, onMounted, watch, onUnmounted } = vue;
50
89
 
51
90
  const props = defineProps({
@@ -77,14 +116,22 @@ const props = defineProps({
77
116
  type: Boolean,
78
117
  default: true,
79
118
  },
80
- hasEmojiTool: {
119
+ isInAudioMode:{
120
+ type: Boolean,
121
+ default: false,
122
+ },
123
+ shouldShowEmoji: {
81
124
  type: Boolean,
82
125
  default: true,
83
126
  },
84
- hasInputTool: {
127
+ shouldShowToolbar: {
85
128
  type: Boolean,
86
129
  default: true,
87
- }
130
+ },
131
+ shouldShowAudio: {
132
+ type: Boolean,
133
+ default: false,
134
+ },
88
135
  });
89
136
 
90
137
  const emits = defineEmits(['sendMessage', 'onTyping', 'blurToolAndEmojiH5', 'isInputNotEmpty']);
@@ -97,6 +144,18 @@ const currentQuoteMessage = ref<{ message: IMessageModel; type: string }>();
97
144
  const editorDom = ref();
98
145
  let editor: Editor | null = null;
99
146
  const fileMap = new Map<string, any>();
147
+ const recorder = ref();
148
+ const recordTime = ref(0);
149
+ const isInAudioMode = ref(props.isInAudioMode);
150
+ const isRecording = ref(false);
151
+ let startRecordY = 0;
152
+ const recordCancel = ref(false);
153
+ const recordTip = ref(TUITranslateService.t('TUIChat.松开发送'));
154
+ let recordTimer: any = null;
155
+ const audioWaveBars = ref(Array(24).fill({ height: 6 }));
156
+ let audioWaveAnimation = -1;
157
+ let pressStartTime: any = null;
158
+ const hasMicPermission = ref(false);
100
159
 
101
160
  function onCurrentConversationIDUpdated(conversationID: string) {
102
161
  if (currentConversationID.value !== conversationID) {
@@ -134,6 +193,13 @@ function focusEditor() {
134
193
  }
135
194
  }
136
195
 
196
+ watch(
197
+ () => [props.isInAudioMode],
198
+ (newValue) => {
199
+ isInAudioMode.value = newValue[0];
200
+ }
201
+ );
202
+
137
203
  onMounted(() => {
138
204
  editor = isPC
139
205
  ? new Editor({
@@ -209,6 +275,15 @@ onMounted(() => {
209
275
  TUIStore.watch(StoreName.CHAT, {
210
276
  quoteMessage: onQuoteMessageUpdated,
211
277
  });
278
+
279
+ document.addEventListener('visibilitychange', handleVisibilityChange);
280
+
281
+ recorder.value = new Recorder({
282
+ sampleBits: 16,
283
+ sampleRate: 44100,
284
+ numChannels: 1,
285
+ compiling: false,
286
+ });
212
287
  });
213
288
 
214
289
  onUnmounted(() => {
@@ -222,6 +297,8 @@ onUnmounted(() => {
222
297
 
223
298
  // clear map store
224
299
  fileMap.clear();
300
+ initRecorder();
301
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
225
302
  });
226
303
 
227
304
  function handleEnter(e: any) {
@@ -250,9 +327,12 @@ function handleH5Blur() {
250
327
  isH5 && (isEditorBlur.value = true);
251
328
  }
252
329
 
253
- async function handleH5Focus() {
330
+ async function handleH5Focus(e: any) {
254
331
  emits('blurToolAndEmojiH5');
255
332
  isH5 && (isEditorBlur.value = false);
333
+ if (e.target) {
334
+ e.target.scrollIntoView({ behavior: 'smooth', block: 'center' });
335
+ }
256
336
  }
257
337
 
258
338
  function handlePCFileDrop(e: any) {
@@ -619,7 +699,9 @@ function resetEditor() {
619
699
  editor?.commands?.clearContent(true);
620
700
  isEditorBlur.value = true;
621
701
  isEditorEmpty.value = true;
622
- isH5 && (editorDom.value.innerHTML = '');
702
+ if (!isInAudioMode.value) {
703
+ isH5 && (editorDom.value.innerHTML = '');
704
+ }
623
705
  }
624
706
 
625
707
  function getEditorHTML(): string {
@@ -712,7 +794,167 @@ watch(
712
794
  deep: true,
713
795
  },
714
796
  );
797
+ async function initRecorder() {
798
+ clearInterval(recordTimer);
799
+ recordTimer = null;
800
+ recordTime.value = 0;
801
+ await recorder.value.stop();
802
+ isRecording.value = false;
803
+ recordTip.value = TUITranslateService.t("TUIChat.松开发送");
804
+ cancelAnimationFrame(audioWaveAnimation);
805
+ }
806
+
807
+ watch(
808
+ recordTime,
809
+ (newVal: number) => {
810
+ if(newVal >= 50 && newVal < 60) {
811
+ let tip = '';
812
+ const currentLanguage = state.get('currentLanguage');
813
+ if (currentLanguage === 'zh' || currentLanguage === 'zh_tw' || currentLanguage === 'ja') {
814
+ tip = `${10 - newVal}${TUITranslateService.t('TUIChat.录音结束提醒')}`
815
+ } else {
816
+ tip = `${TUITranslateService.t('TUIChat.录音结束提醒')} ${10 - newVal}s`
817
+ }
818
+ recordTip.value = tip;
819
+ } else if (newVal >= 60) {
820
+ stopRecording();
821
+ }
822
+ }
823
+ );
824
+
825
+ const startRecording = async(e) => {
826
+ if (isRecording.value) {
827
+ return;
828
+ }
829
+ isRecording.value = true;
830
+ pressStartTime = new Date();
831
+ recordCancel.value = false;
832
+ Recorder.getPermission().then(() => {
833
+ hasMicPermission.value = true;
834
+ if (!isRecording.value) {
835
+ return;
836
+ }
837
+ if (recordTimer !== null) {
838
+ initRecorder();
839
+ }
840
+ // 提前获取音频流,避免开始录音时启动过长
841
+ recorder.value.start().then(() => {
842
+ if (!isRecording.value) {
843
+ return;
844
+ }
845
+ updateRecordWave();
846
+ startRecordY = getRecordY(e);
847
+ recordTimer = setInterval(() => {
848
+ recordTime.value = recordTime.value + 1;
849
+ }, 1000);
850
+ }, (error) => {
851
+ Log.e(`Error in recording ${error.name} : ${error.message}`);
852
+ let toastMessage = `${error.name} : ${error.message}`;
853
+ Toast({
854
+ message:toastMessage,
855
+ type: TOAST_TYPE.ERROR,
856
+ duration: 2000,
857
+ });
858
+ initRecorder();
859
+ });
860
+ }, (error) => {
861
+ initRecorder();
862
+ Toast({
863
+ message:TUITranslateService.t("TUIChat.请检查麦克风访问权限"),
864
+ type: TOAST_TYPE.ERROR,
865
+ duration: 2000,
866
+ });
867
+ Log.w(`Error in mic permission ${error.name} : ${error.message}`);
868
+ });
869
+ e.preventDefault();
870
+ };
871
+
872
+ const stopRecording = async () => {
873
+ const duration = recordTime.value;
874
+ initRecorder();
875
+ const pressDuration = Date.now() - pressStartTime;
876
+ if (pressDuration < 1000 && hasMicPermission.value) {
877
+ // 按压时间过短,还没开始录音就结束
878
+ Toast({
879
+ message: TUITranslateService.t("TUIChat.按压时间过短,请按压超过1秒"),
880
+ type: TOAST_TYPE.ERROR,
881
+ duration: 3000,
882
+ });
883
+ } else if (!recordCancel.value && duration) {
884
+ // 已经录音 && 没有取消录音
885
+ if (duration <= 60) {
886
+ let wavBlob = recorder.value.getWAVBlob();
887
+ let tempFilePath = new File([wavBlob], `ai_desk_customer_vue_${Date.now()}.wav`, { type: "wav" });
888
+ (tempFilePath as any).duration = duration * 1000;
889
+ if (tempFilePath && duration <= 60) {
890
+ try {
891
+ TUIChatService.sendAudioMessage({
892
+ to: currentConversationID.value.replace(TUIChatEngine.TYPES.CONV_C2C, ''),
893
+ conversationType: TUIChatEngine.TYPES.CONV_C2C,
894
+ payload: { file: tempFilePath },
895
+ needReadReceipt: isEnabledMessageReadReceiptGlobal(),
896
+ });
897
+ } catch (error) {
898
+ const message = `${TUITranslateService.t("TUIChat.发送失败")}: ${error}`;
899
+ Toast({
900
+ message,
901
+ type: TOAST_TYPE.ERROR,
902
+ duration: 2000,
903
+ });
904
+ }
905
+ }
906
+ }
907
+ }
908
+ };
909
+
910
+ const getRecordY = (e) => {
911
+ return e.type.includes('touch') ? e.touches[0].clientY : e.clientY;
912
+ }
913
+
914
+ const handleTouchMove = (e) => {
915
+ if (!isRecording.value) return;
916
+ let currentRecordY = getRecordY(e);
917
+ let deltaY = Math.abs(currentRecordY - startRecordY);
918
+ if (recordTime.value <= 50) {
919
+ if (deltaY > 40) {
920
+ recordCancel.value = true;
921
+ recordTip.value = TUITranslateService.t("TUIChat.松手取消");
922
+ } else {
923
+ recordCancel.value = false;
924
+ recordTip.value = TUITranslateService.t("TUIChat.松开发送");
925
+ }
926
+ }
927
+ }
928
+
929
+ const updateRecordWave = () => {
930
+ if (!isRecording.value) return;
931
+ const dataArray = recorder.value.getRecordAnalyseData();
932
+ const chunkSize = Math.floor(dataArray.length / 24);
933
+ const newBars = [{height: 0}];
934
+ const SILENCE_THRESHOLD = 129;
935
+ for (let i = 0; i < 24; i++) {
936
+ const chunk = dataArray.slice(i * chunkSize, (i + 1) * chunkSize);
937
+ const avg = chunk.reduce((sum, val) => sum + Math.abs(val), 0) / chunkSize; // 使用绝对值确保正值
938
+ let height;
939
+ if (avg < SILENCE_THRESHOLD) {
940
+ // 静音时固定为5px
941
+ height = 5;
942
+ } else {
943
+ // 动态映射:静音(5px) ~ 最大音量(60px)
944
+ const normalized = Math.min(avg / 255, 1); // 限制到[0,1]范围
945
+ height = 5 + normalized * 55; // 5 + (0~1)*55 => 5~60px
946
+ }
947
+ newBars.push({ height });
948
+ }
949
+ audioWaveBars.value = newBars;
950
+ audioWaveAnimation = requestAnimationFrame(updateRecordWave);
951
+ }
715
952
 
953
+ const handleVisibilityChange = () => {
954
+ if (document.visibilityState === 'hidden') {
955
+ initRecorder();
956
+ }
957
+ }
716
958
  defineExpose({
717
959
  getEditorContent,
718
960
  addEmoji,
@@ -721,6 +963,8 @@ defineExpose({
721
963
  getEditorHTML,
722
964
  insertEditorContent,
723
965
  blur,
966
+ startRecording,
967
+ stopRecording
724
968
  });
725
969
  </script>
726
970
 
@@ -822,6 +1066,12 @@ defineExpose({
822
1066
  .message-input-editor-container-h5-no-emoji-no-tool {
823
1067
  border-radius: 10px;
824
1068
  }
1069
+ .message-input-editor-container-h5-audio {
1070
+ margin: 10px 0 0 5px;
1071
+ }
1072
+ .message-input-editor-container-h5-audio-mode {
1073
+ padding: 0;
1074
+ }
825
1075
  </style>
826
1076
  <style lang="scss">
827
1077
  /* stylelint-disable-next-line selector-class-pattern */
@@ -915,7 +1165,92 @@ defineExpose({
915
1165
  pointer-events: none;
916
1166
  }
917
1167
  }
918
-
1168
+ .audio-mode {
1169
+ text-align: center;
1170
+ font-size: 14px;
1171
+ color: rgb(0,0,0);
1172
+ padding: 8px 0 8px 10px !important;
1173
+ }
1174
+ .no-copy {
1175
+ user-select: none; /* 标准属性 */
1176
+ -webkit-user-select: none; /* Safari/Chrome */
1177
+ -moz-user-select: none; /* Firefox */
1178
+ -ms-user-select: none; /* IE10+ */
1179
+ }
1180
+ .record-container{
1181
+ height: 30vh;
1182
+ width: 100vw;
1183
+ position:fixed;
1184
+ overflow: hidden;
1185
+ right: 0;
1186
+ bottom: 0;
1187
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 64.35%);
1188
+ display: flex;
1189
+ flex-direction: column;
1190
+ justify-content: flex-end;
1191
+ .audio-wave-container {
1192
+ box-sizing: border-box;
1193
+ width: 100vw;
1194
+ margin-bottom: 10px;
1195
+ display: flex;
1196
+ .audio-wave-bubble {
1197
+ background: #006AF6;
1198
+ margin: 0 10px;
1199
+ height: 34px;
1200
+ border-radius: 10px;
1201
+ width: 100%;
1202
+ display: flex;
1203
+ justify-content: center;
1204
+ align-items: center;
1205
+ }
1206
+ .audio-wave-bubble-cancel {
1207
+ background: #FF002F;
1208
+ }
1209
+ .audio-wave {
1210
+ color: white;
1211
+ display: flex;
1212
+ gap: 4px;
1213
+ .wave-bar {
1214
+ width: 3px;
1215
+ background: white;
1216
+ border-radius: 6px;
1217
+ transition: height 0.1s ease-out;
1218
+ margin-top: auto;
1219
+ margin-bottom: auto;
1220
+ transform-origin: center bottom;
1221
+ }
1222
+ }
1223
+ }
1224
+ .icon-container{
1225
+ position: absolute;
1226
+ bottom: -190%;
1227
+ left: -80%;
1228
+ width: 950px;
1229
+ height: 950px;
1230
+ border-radius: 50%;
1231
+ background: linear-gradient(180deg, #E8EDF3 -1.18%, #FBFBFB 4.94%);
1232
+ box-shadow: 0px -7.5px 5px 0px rgba(218, 224, 232, 0.15);
1233
+ }
1234
+ .record-tip{
1235
+ color:#656A72;
1236
+ font-size: 12px;
1237
+ margin-bottom: 12px;
1238
+ }
1239
+ .audio-record-icon{
1240
+ position:absolute;
1241
+ bottom:50px;
1242
+ left: 50%;
1243
+ transform: translateX(-50%);
1244
+ z-index:2;
1245
+ }
1246
+ .audio-close-icon {
1247
+ position:absolute;
1248
+ bottom:160px;
1249
+ left: 50%;
1250
+ transform: translateX(-50%);
1251
+ z-index:2;
1252
+ }
1253
+ }
919
1254
  .message-input-mute {
920
1255
  color: #721c24;
921
1256
  background-color: #f8d7da;
@@ -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(){
@@ -17,9 +17,8 @@
17
17
  @click="select(childrenItem, childrenIndex)"
18
18
  >
19
19
  <img
20
- v-if="currentTabItem.type === EMOJI_TYPE.BASIC"
21
20
  class="emoji"
22
- :src="currentTabItem.url + BASIC_EMOJI_URL_MAPPING[childrenItem]"
21
+ :src="BASIC_EMOJI_URL + BASIC_EMOJI_URL_MAPPING[childrenItem]"
23
22
  >
24
23
  <!-- <img-->
25
24
  <!-- v-else-if="currentTabItem.type === EMOJI_TYPE.BIG"-->
@@ -76,9 +75,6 @@ import {
76
75
  SendMessageParams,
77
76
  TUITranslateService
78
77
  } from '@tencentcloud/chat-uikit-engine';
79
- import Icon from '../../../common/Icon.vue';
80
- import faceIcon from '../../../../assets/face.svg';
81
- import { EMOJI_TYPE } from '.././../../../constant';
82
78
  import { isPC, isH5 } from '../../../../utils/env';
83
79
  import { IEmojiGroupList, IEmojiGroup } from '../../../../interface';
84
80
  import { isEnabledMessageReadReceiptGlobal } from '../../../../utils/utils';
@@ -86,22 +82,23 @@ import {
86
82
  EMOJI_GROUP_LIST,
87
83
  BASIC_EMOJI_URL_MAPPING,
88
84
  convertKeyToEmojiName,
85
+ BASIC_EMOJI_URL,
86
+ filterEmojisInNonChineseEnv,
89
87
  } from '../../emoji-config';
90
88
  const { ref, onMounted, onUnmounted } = vue;
91
89
 
92
90
  const emits = defineEmits(['insertEmoji', 'onClose', 'sendMessage']);
93
- const currentTabIndex = ref<number>(0);
94
91
  const currentConversation = ref();
95
92
  const emojiPickerDialog = ref();
96
93
  const emojiPickerListRef = ref();
97
- const list = ref<IEmojiGroupList>(initEmojiList());
98
- const currentTabItem = ref<IEmojiGroup>(list?.value[0]);
94
+ const list = ref<IEmojiGroupList>(EMOJI_GROUP_LIST);
99
95
  const currentEmojiList = ref<string[]>(list?.value[0]?.list);
100
96
 
101
97
  onMounted(() => {
102
98
  TUIStore.watch(StoreName.CONV, {
103
99
  currentConversation: onCurrentConversationUpdate,
104
100
  });
101
+ currentEmojiList.value = filterEmojisInNonChineseEnv(list.value[0].list);
105
102
  });
106
103
 
107
104
  onUnmounted(() => {
@@ -110,35 +107,13 @@ onUnmounted(() => {
110
107
  });
111
108
  });
112
109
 
113
- const toggleEmojiTab = (index: number) => {
114
- currentTabIndex.value = index;
115
- currentTabItem.value = list?.value[index];
116
- currentEmojiList.value = list?.value[index]?.list;
117
- // web & h5 side scroll to top
118
- emojiPickerListRef?.value && (emojiPickerListRef.value.scrollTop = 0);
119
-
120
- };
121
-
122
110
  const select = (item: any, index: number) => {
123
111
  const options: any = {
124
112
  emoji: { key: item, name: convertKeyToEmojiName(item) },
125
- type: currentTabItem?.value?.type,
113
+ type: 'basic',
126
114
  };
127
- switch (currentTabItem?.value?.type) {
128
- case EMOJI_TYPE.BASIC:
129
- options.url = currentTabItem?.value?.url + BASIC_EMOJI_URL_MAPPING[item];
130
- emits('insertEmoji', options);
131
-
132
- break;
133
- case EMOJI_TYPE.BIG:
134
- sendFaceMessage(index, currentTabItem.value);
135
- break;
136
- case EMOJI_TYPE.CUSTOM:
137
- sendFaceMessage(index, currentTabItem.value);
138
- break;
139
- default:
140
- break;
141
- }
115
+ options.url = BASIC_EMOJI_URL + BASIC_EMOJI_URL_MAPPING[item];
116
+ emits('insertEmoji', options);
142
117
  isPC && emits('onClose');
143
118
  };
144
119
 
@@ -159,16 +134,11 @@ const sendFaceMessage = (index: number, listItem: IEmojiGroup) => {
159
134
 
160
135
  function sendMessage() {
161
136
  emits('sendMessage');
162
-
163
137
  }
164
138
 
165
139
  function onCurrentConversationUpdate(conversation: IConversationModel) {
166
140
  currentConversation.value = conversation;
167
141
  }
168
-
169
- function initEmojiList() {
170
- return EMOJI_GROUP_LIST;
171
- }
172
142
  </script>
173
143
 
174
144
  <style lang="scss" scoped src="./style/index.scss"></style>
@@ -91,6 +91,7 @@ const closeOrder = () => {
91
91
  .bottom-quick-order-line {
92
92
  display: flex;
93
93
  align-items: flex-end;
94
+ width: min-content;
94
95
  }
95
96
  .bottom-quick-order-container {
96
97
  display: flex;