@tencentcloud/ai-desk-customer-vue 1.4.0 → 1.5.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 (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/assets/feedback_dialog_close.svg +3 -0
  3. package/assets/feedback_dislike_after.svg +3 -0
  4. package/assets/feedback_dislike_before.svg +10 -0
  5. package/assets/feedback_dislike_hover.svg +10 -0
  6. package/assets/feedback_like_after.svg +14 -0
  7. package/assets/feedback_like_before.svg +10 -0
  8. package/assets/feedback_like_hover.svg +10 -0
  9. package/assets/green_check.svg +4 -0
  10. package/components/CustomerServiceChat/index-web.vue +18 -0
  11. package/components/CustomerServiceChat/message-input/message-input-editor-web.vue +1 -0
  12. package/components/CustomerServiceChat/message-input/message-input-quote/index.vue +29 -20
  13. package/components/CustomerServiceChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue +35 -35
  14. package/components/CustomerServiceChat/message-input-toolbar/index-web.vue +1 -1
  15. package/components/CustomerServiceChat/message-list/index-web.vue +5 -0
  16. package/components/CustomerServiceChat/message-list/message-elements/feedback-button.vue +369 -0
  17. package/components/CustomerServiceChat/message-list/message-elements/message-bubble-web.vue +30 -11
  18. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/marked.ts +17 -10
  19. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-branch.vue +13 -5
  20. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-concurrency-limit.vue +1 -1
  21. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-desk.vue +8 -6
  22. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-ivr-form/form-branch.vue +117 -0
  23. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/{message-single-form → message-ivr-form}/form-input.vue +65 -111
  24. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/{message-single-form → message-ivr-form}/index.vue +7 -2
  25. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-branch/branch-pc.vue +5 -3
  26. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-branch/index.vue +3 -1
  27. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/component-mobile/input-mobile.vue +1 -0
  28. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/component-mobile/label-mobile.vue +4 -2
  29. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/component-pc/label-pc.vue +5 -3
  30. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/form-mobile.vue +17 -5
  31. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/form-pc.vue +21 -1
  32. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-order.vue +2 -1
  33. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-product-card.vue +2 -1
  34. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-rating/message-rating-number.vue +9 -13
  35. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-rating/message-rating-star.vue +11 -18
  36. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-robot-welcome.vue +1 -0
  37. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-stream.vue +14 -10
  38. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-timeout-warning.vue +29 -0
  39. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/styles/common.scss +1 -0
  40. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-plugin-web.vue +22 -2
  41. package/components/CustomerServiceChat/message-list/message-elements/message-quote/index-web.vue +6 -24
  42. package/components/CustomerServiceChat/message-list/message-elements/message-text.vue +0 -9
  43. package/components/CustomerServiceChat/message-list/message-elements/read-status/index.vue +31 -20
  44. package/components/CustomerServiceChat/message-list/message-elements/simple-message-list/index.vue +2 -1
  45. package/components/common/Toast/index-web.vue +4 -2
  46. package/constant.ts +11 -1
  47. package/locales/en/aidesk.ts +28 -16
  48. package/locales/fil/aidesk.ts +28 -16
  49. package/locales/id/aidesk.ts +28 -16
  50. package/locales/ja/aidesk.ts +28 -16
  51. package/locales/ms/aidesk.ts +28 -16
  52. package/locales/ru/aidesk.ts +28 -16
  53. package/locales/th/aidesk.ts +28 -16
  54. package/locales/vi/aidesk.ts +28 -16
  55. package/locales/zh_cn/aidesk.ts +28 -16
  56. package/locales/zh_tw/aidesk.ts +28 -16
  57. package/package.json +1 -1
  58. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-single-form/form-branch.vue +0 -68
@@ -0,0 +1,369 @@
1
+ <template>
2
+ <div>
3
+ <div class="feedback-container">
4
+ <div
5
+ class="feedback-like"
6
+ @mouseenter="isFeedbackLikeHover = true"
7
+ @mouseleave="isFeedbackLikeHover = false"
8
+ @click="feedbackLikeClick"
9
+ >
10
+ <Icon :file="feedbackLikeIcon" width="16px" height="16px"/>
11
+ <div
12
+ class="tooltip"
13
+ >
14
+ {{ TUITranslateService.t("AIDesk.满意") }}
15
+ <div class="tooltip-arrow"></div>
16
+ </div>
17
+ </div>
18
+ <span class="divider"></span>
19
+ <div
20
+ class="feedback-dislike"
21
+ @mouseenter="isFeedbackDislikeHover = true"
22
+ @mouseleave="isFeedbackDislikeHover = false"
23
+ @click="feedbackDislikeClick"
24
+ >
25
+ <Icon :file="feedbackDislikeIcon" width="16px" height="16px" @click="dislickClick"/>
26
+ <div
27
+ class="tooltip"
28
+ >
29
+ {{ TUITranslateService.t("AIDesk.不满意") }}
30
+ <div class="tooltip-arrow"></div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ <div v-if="showDialog" class="feedback-dialog">
35
+ <div class="feedback-dialog-main">
36
+ <div class="feedback-dialog-header">
37
+ <div class="dialog-header-content">
38
+ <Icon :file="GreenCheck" width="24px" height="24px"/>
39
+ <span class="dialog-header-title">
40
+ {{ TUITranslateService.t("AIDesk.感谢您的反馈,我们会持续优化改进") }}
41
+ </span>
42
+ </div>
43
+ <Icon :file="DialogCloseIcon" width="24px" height="24px" @click="closeDialog"/>
44
+ </div>
45
+
46
+ <div class="dialog-select">
47
+ <span class="dialog-session-title">
48
+ {{ TUITranslateService.t("AIDesk.您遇到了哪方面的问题") }}
49
+ </span>
50
+ <div class="dialog-button-list">
51
+ <div class="dialog-button-row" v-for="(item) in feedbackButton">
52
+ <div :class="['dialog-button',item.isSelected ? 'dialog-button-selected': '']" @click="dialogButtonClick(item)">
53
+ {{ TUITranslateService.t(`AIDesk.${item.text}`) }}
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+
59
+ <div class="dialog-other">
60
+ <span class="dialog-session-title">
61
+ {{ TUITranslateService.t("AIDesk.其他反馈内容") }}
62
+ </span>
63
+ <textarea type="text" :placeholder="TUITranslateService.t('AIDesk.请输入内容')" v-model="feedbackText" class="dialog-other-input"/>
64
+ </div>
65
+ <div class="dialog-foot">
66
+ <div class="dialog-submit" @click="submitBadFeeback">
67
+ {{ TUITranslateService.t("AIDesk.提交") }}
68
+ </div>
69
+ <div class="dialog-cancel" @click="closeDialog">
70
+ {{ TUITranslateService.t("AIDesk.取消") }}
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </template>
77
+ <script lang="ts">
78
+ import vue from '../../../../adapter-vue';
79
+ import Icon from '../../../common/Icon.vue';
80
+ import { TUITranslateService } from '@tencentcloud/chat-uikit-engine';
81
+ import FeedbackLikeBefore from '../../../../assets/feedback_like_before.svg';
82
+ import FeedbackLikeAfter from '../../../../assets/feedback_like_after.svg';
83
+ import FeedbackLikeHover from '../../../../assets/feedback_like_hover.svg';
84
+ import FeedbackDislikeBefore from '../../../../assets/feedback_dislike_before.svg';
85
+ import FeedbackDislikeAfter from '../../../../assets/feedback_dislike_after.svg';
86
+ import FeedbackDislikeHover from '../../../../assets/feedback_dislike_hover.svg';
87
+ import GreenCheck from '../../../../assets/green_check.svg';
88
+ import DialogCloseIcon from '../../../../assets/feedback_dialog_close.svg';
89
+ const { ref,computed } = vue;
90
+
91
+ export default {
92
+ components:{
93
+ Icon
94
+ },
95
+ setup(){
96
+ const isFeedbackLikeHover = ref(false);
97
+ const isFeedbackLikeClick = ref(false);
98
+ const isFeedbackDislikeHover = ref(false);
99
+ const isFeedbackDislikeClick = ref(false);
100
+ const showDialog = ref(false);
101
+ const feedbackText = ref('');
102
+ const feedbackButton = ref([
103
+ { id:'nonResponsiveAnswer', text: '答非所问', isSelected: false },
104
+ { id:'unmatchedContentRetrieval', text: '未匹配相关内容', isSelected: false },
105
+ { id:'incorrectInfoAnswer', text: '信息错误', isSelected: false },
106
+ { id:'contextMisunderstandingQuery', text: '上下文理解错误', isSelected: false },
107
+ { id:'nonStandardFormatAnswer', text: '格式不规范', isSelected: false },
108
+ { id:'incompleteContentRetrieval', text: '内容不完整', isSelected: false },
109
+ ]);
110
+ const feedbackReply = {
111
+ isSupport:1, //1:点赞。0:点踩
112
+ nonResponsiveAnswer:0, // 是否答非所问
113
+ incorrectInfoAnswer:0, // 是否信息错误
114
+ nonStandardFormatAnswer:0, // 是否信息不规范
115
+ incompleteContentRetrieval:0, // 是否回答不完整
116
+ unmatchedContentRetrieval:0, // 是否信息不匹配
117
+ contextMisunderstandingQuery:0, //是否上下文理解错误
118
+ feedbackText:"" //文字反馈
119
+ };
120
+ const feedbackLikeIcon = computed(() => {
121
+ if (isFeedbackLikeClick.value) {
122
+ return FeedbackLikeAfter;
123
+ } else if (isFeedbackLikeHover.value) {
124
+ return FeedbackLikeHover;
125
+ } else {
126
+ return FeedbackLikeBefore;
127
+ }
128
+ });
129
+ const feedbackLikeClick = () => {
130
+ isFeedbackLikeClick.value = !isFeedbackLikeClick.value;
131
+ if(isFeedbackLikeClick.value){
132
+ isFeedbackDislikeClick.value = false;
133
+ feedbackReply.isSupport = 1;
134
+ }
135
+ resetFeedback();
136
+ }
137
+ const feedbackDislikeIcon = computed(() => {
138
+ if (isFeedbackDislikeClick.value) {
139
+ return FeedbackDislikeAfter;
140
+ } else if (isFeedbackDislikeHover.value) {
141
+ return FeedbackDislikeHover;
142
+ } else {
143
+ return FeedbackDislikeBefore;
144
+ }
145
+ });
146
+ const dialogButtonClick = (item) => {
147
+ item.isSelected = !item.isSelected;
148
+ }
149
+ const feedbackDislikeClick = () => {
150
+ isFeedbackDislikeClick.value = true;
151
+ if(isFeedbackDislikeClick.value){
152
+ isFeedbackLikeClick.value = false;
153
+ }
154
+ }
155
+ const dislickClick = () => {
156
+ showDialog.value = true;
157
+ }
158
+ const closeDialog = () => {
159
+ isFeedbackDislikeClick.value = false;
160
+ showDialog.value = false;
161
+ resetFeedback();
162
+ }
163
+ const resetFeedback = () => {
164
+ feedbackButton.value.forEach(item => {
165
+ item.isSelected = false;
166
+ });
167
+ feedbackText.value = "";
168
+ }
169
+ const submitBadFeeback = () => {
170
+ feedbackReply.isSupport = 0;
171
+ feedbackButton.value.forEach(item => {
172
+ feedbackReply[item.id] = item.isSelected ? 1 : 0;
173
+ feedbackReply.feedbackText = feedbackText.value;
174
+ });
175
+ }
176
+
177
+ return {
178
+ feedbackLikeIcon,
179
+ isFeedbackLikeHover,
180
+ feedbackLikeClick,
181
+ isFeedbackDislikeHover,
182
+ feedbackDislikeIcon,
183
+ feedbackDislikeClick,
184
+ GreenCheck,
185
+ DialogCloseIcon,
186
+ feedbackButton,
187
+ showDialog,
188
+ closeDialog,
189
+ dislickClick,
190
+ feedbackText,
191
+ dialogButtonClick,
192
+ TUITranslateService,
193
+ submitBadFeeback
194
+ };
195
+ }
196
+ }
197
+ </script>
198
+ <style lang="scss">
199
+ .feedback-container {
200
+ display: flex;
201
+ flex-direction: row !important;
202
+ padding: 4px 10px;
203
+ align-items: center;
204
+ gap: 10px;
205
+ border-radius: 8px;
206
+ border: 1px solid var(---G61, #DBE1EB);
207
+ .feedback-like, .feedback-dislike {
208
+ position: relative;
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ cursor: pointer;
213
+ &:hover .tooltip {
214
+ display: block;
215
+ }
216
+ }
217
+ .divider {
218
+ width: 1px;
219
+ height: 14px;
220
+ background-color: rgba(0,0,0,0.05);
221
+ }
222
+ }
223
+ .feedback-dialog {
224
+ position: fixed;
225
+ top: 0;
226
+ left: 0;
227
+ right: 0;
228
+ bottom: 0;
229
+ background: rgba(13, 17, 26, 0.4);
230
+ z-index: 1000;
231
+ display: flex;
232
+ justify-content: center;
233
+ align-items: center;
234
+ font-family: PingFangSC-Regular;
235
+ &-main {
236
+ width: 418px;
237
+ min-height: 442px;
238
+ background: white;
239
+ border-radius: 16px;
240
+ padding: 30px;
241
+ overflow: hidden;
242
+
243
+ .feedback-dialog-header {
244
+ display: flex;
245
+ justify-content: space-between;
246
+ .dialog-header-content {
247
+ display: flex;
248
+ gap: 8px;
249
+ align-items: center;
250
+ .dialog-header-title {
251
+ font-weight: 600;
252
+
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ .dialog-session-title {
259
+ color: #4F586B;
260
+ font-size: 14px;
261
+ }
262
+ .dialog-select {
263
+ margin-top: 30px;
264
+ .dialog-button-list {
265
+ display: flex;
266
+ flex-wrap: wrap;
267
+ justify-content: center;
268
+ align-items: center;
269
+ gap: 8px;
270
+ margin-top: 10px;
271
+ .dialog-button-row {
272
+ flex: 0 0 49%;
273
+ .dialog-button {
274
+ border-radius: 8px;
275
+ border: 1px solid #E4E8EE;
276
+ background: #F9FAFC;
277
+ padding: 10px 16px;
278
+ display: flex;
279
+ justify-content: center;
280
+ font-size: 12px;
281
+ color: #0f1014;
282
+ cursor: pointer;
283
+ text-align: center;
284
+ align-items: center;
285
+ &-selected {
286
+ border-radius: 8px;
287
+ border: 1px solid #1C66E5;
288
+ background: rgba(28, 102, 229, 0.10);
289
+ color: #0052d9;
290
+ }
291
+ }
292
+ }
293
+
294
+ }
295
+ }
296
+ .dialog-other {
297
+ margin: 20px 0 10px 0;
298
+ display: flex;
299
+ flex-direction: column;
300
+ gap: 10px;
301
+ .dialog-other-input {
302
+ border-radius: 12px;
303
+ border: 1px solid #E4E8EE;
304
+ background: #F9FAFC;
305
+ height: 102px;
306
+ padding: 10px 16px;
307
+ display: flex;
308
+ align-items: flex-start;
309
+ align-self: stretch;
310
+ resize: none;
311
+ &::placeholder {
312
+ color: #929CB2;
313
+ font-size: 14px;
314
+ }
315
+ }
316
+ }
317
+ .dialog-foot {
318
+ width: 100%;
319
+ display: flex;
320
+ margin-top: 30px;
321
+ gap: 10px;
322
+ justify-content: center;
323
+ .dialog-submit {
324
+ padding: 9px 33px;
325
+ border-radius: 20px;
326
+ background: #1C66E5;
327
+ font-weight: 600;
328
+ color: #fff;
329
+ cursor: pointer;
330
+ }
331
+ .dialog-cancel {
332
+ padding: 9px 33px;
333
+ border-radius: 20px;
334
+ border: 1px solid #1C66E5;
335
+ font-weight: 600;
336
+ color: #1C66E5;
337
+ cursor: pointer;
338
+ }
339
+ }
340
+
341
+ .tooltip {
342
+ position: absolute;
343
+ z-index: 100;
344
+ font-size: 14px;
345
+ bottom: calc(100% + 13px);
346
+ left: 50%;
347
+ transform: translateX(-50%);
348
+ background: #fff;
349
+ color: #000;
350
+ padding: 8px 16px;
351
+ border-radius: 6px;
352
+ box-shadow: var(--shadow-md-offsetx-1, 0px) var(--shadow-md-offsety-1, 8px) var(--shadow-md-blur-1, 12px) var(--shadow-md-spread-1, -8px) var(--shadow-md-color-1, rgba(0, 0, 0, 0.05)), var(--shadow-md-offsetx-2, 0px) var(--shadow-md-offsety-2, 8px) var(--shadow-md-blur-2, 24px) var(--shadow-md-spread-2, -4px) var(--shadow-md-color-2, rgba(0, 0, 0, 0.10));
353
+ text-align: center;
354
+ display: none;
355
+ white-space: nowrap;
356
+
357
+ &-arrow {
358
+ position: absolute;
359
+ bottom: -8px;
360
+ left: 50%;
361
+ transform: translateX(-50%);
362
+ width: 0;
363
+ height: 0;
364
+ border-left: 8px solid transparent;
365
+ border-right: 8px solid transparent;
366
+ border-top: 8px solid #fff;
367
+ }
368
+ }
369
+ </style>
@@ -12,7 +12,7 @@
12
12
  :class="[message.flow === 'in' ? '' : 'reverse']"
13
13
  >
14
14
  <Avatar
15
- v-if="isPC && showAvatar === 1"
15
+ v-if="showAvatar === 1"
16
16
  useSkeletonAnimation
17
17
  :url="avatarUrl"
18
18
  />
@@ -21,7 +21,7 @@
21
21
  @click.stop
22
22
  >
23
23
  <div
24
- v-if="isPC && showNickName === 1"
24
+ v-if="showNickName === 1"
25
25
  class="message-body-nick-name"
26
26
  >
27
27
  {{ nickName }}
@@ -107,8 +107,13 @@
107
107
  <ReadStatus
108
108
  class="message-label align-self-bottom"
109
109
  :message="shallowCopyMessage(message)"
110
+ @setStatus="setStatus"
111
+ :prevStatus="prevStatus"
110
112
  />
111
113
  </div>
114
+ <!-- <div class="message-bubble-feedback-button">
115
+ <FeedbackButton v-if="isFromRobot(message.cloudCustomData)"/>
116
+ </div> -->
112
117
  </main>
113
118
  </div>
114
119
  <!-- message extra area -->
@@ -143,6 +148,8 @@ import { isPC,isH5 } from '../../../../utils/env';
143
148
  import { JSONToObject } from '../../../../utils/index';
144
149
  import state from '../../../../utils/state.js';
145
150
  import { CUSTOM_MESSAGE_SRC } from '../../../../constant';
151
+ import FeedbackButton from './feedback-button.vue';
152
+ import { ReadState } from '../../../../constant';
146
153
  const { computed, toRefs } = vue;
147
154
 
148
155
  interface IProps {
@@ -192,7 +199,7 @@ const {
192
199
  staffNickName,
193
200
  userNickName,
194
201
  } = state.get('avatarNickName');
195
-
202
+ let prevStatus = ReadState.Unread;
196
203
  const isDisplayUnplayMark = computed<boolean>(() => {
197
204
  return (
198
205
  message.value.flow === 'in'
@@ -313,6 +320,10 @@ function blinkMessage(messageID: string) {
313
320
  function scrollTo(scrollHeight: number) {
314
321
  emits('scrollTo', scrollHeight);
315
322
  }
323
+
324
+ function setStatus(status: ReadState) {
325
+ prevStatus = status;
326
+ }
316
327
  </script>
317
328
 
318
329
  <style lang="scss" scoped>
@@ -324,7 +335,7 @@ function scrollTo(scrollHeight: number) {
324
335
  }
325
336
 
326
337
  .message-bubble {
327
- padding: 10px 15px;
338
+ padding: 10px 5px;
328
339
  display: flex;
329
340
  flex-direction: row;
330
341
  user-select: none;
@@ -407,12 +418,12 @@ function scrollTo(scrollHeight: number) {
407
418
  flex-direction: column;
408
419
  min-width: 0;
409
420
  box-sizing: border-box;
410
- padding: 16px;
421
+ padding: 8px 16px;
411
422
  font-size: 14px;
412
423
  color: #000;
413
424
  letter-spacing: 0;
414
- word-wrap: break-word;
415
- word-break: break-all;
425
+ overflow-wrap: break-word;
426
+ word-break: normal;
416
427
  position: relative;
417
428
 
418
429
  .content-main {
@@ -445,7 +456,7 @@ function scrollTo(scrollHeight: number) {
445
456
 
446
457
  .content-in {
447
458
  background: #f3f4f7;
448
- border-radius: 0 10px 10px;
459
+ border-radius: 0 8px 8px;
449
460
  }
450
461
 
451
462
  .body-mobile {
@@ -454,7 +465,7 @@ function scrollTo(scrollHeight: number) {
454
465
 
455
466
  .multi-branch-message {
456
467
  background-color: transparent;
457
- border-radius: 0 10px 10px;
468
+ border-radius: 0 8px 8px;
458
469
  padding: 0px;
459
470
  }
460
471
 
@@ -469,7 +480,7 @@ function scrollTo(scrollHeight: number) {
469
480
  .content-out {
470
481
  background: linear-gradient(26deg, #1C66E5 2.07%, #03C8FD 152.75%);
471
482
  color:#fff;
472
- border-radius: 10px 0 10px 10px;
483
+ border-radius: 8px 0 8px 8px;
473
484
  }
474
485
 
475
486
  .content-no-padding {
@@ -501,7 +512,10 @@ function scrollTo(scrollHeight: number) {
501
512
  .blink-content {
502
513
  @keyframes reference-blink {
503
514
  50% {
504
- background-color: #ff9c19;
515
+ // 消息气泡的底色是渐变色,实际是 background-image,background-image 优先级高于 background-color
516
+ // 所以这里如果设置 background-color,动画将不会生效
517
+ // 闪烁时背景不渐变
518
+ background: linear-gradient(90deg, #ff9c19, #ff9c19);
505
519
  }
506
520
  }
507
521
 
@@ -551,6 +565,11 @@ function scrollTo(scrollHeight: number) {
551
565
  align-self: flex-end;
552
566
  }
553
567
  }
568
+ .message-bubble-feedback-button {
569
+ display: flex;
570
+ flex-direction: row;
571
+ margin-top: 8px;
572
+ }
554
573
  }
555
574
  }
556
575
 
@@ -1,4 +1,5 @@
1
1
  import {Marked} from 'marked';
2
+ import Log from '../../../../../../utils/logger';
2
3
 
3
4
  export const marked = new Marked(
4
5
  {mangle: false, headerIds: false},
@@ -7,19 +8,25 @@ export const marked = new Marked(
7
8
  image(this: any, href: string | null, title: string | null, text: string) {
8
9
  const safeHref = encodeURIComponent(href || '');
9
10
  return `<div
10
- class="image-container"
11
- onclick="onMarkdownImageClicked('${safeHref}')"
12
- style="cursor:pointer;" >
13
- <img src="${href}" alt="${text}" onload="onMarkdownImageLoad()"/>
14
- </div>
15
- `;
11
+ class="image-container"
12
+ onclick="onMarkdownImageClicked('${safeHref}')"
13
+ style="cursor:pointer;" >
14
+ <img src="${href}" alt="${text}" onload="onMarkdownImageLoad()"/>
15
+ </div>
16
+ `;
16
17
  },
17
18
  link(this: any, href: string | null, title: string | null, text: string) {
18
- // a 标签 href 如果异常(包含非 ASCII 字符),则当成普通文本处理
19
- if (href && /[^\x00-\x7F]/g.test(href)) {
20
- return text;
19
+ if (href) {
20
+ // 匹配以 http:// https:// 开头,所有 URL 主体字符,遇到第一个非主体字符(如中文括号、空格、表情符号等)时停止
21
+ let ret = href.replace(/https?:\/\/[\w\-./?=&:#]+(?=[^\w\-./?=&:#]|$)/g, (matchedUrl) => {
22
+ return `<a target="_blank" rel="noreferrer noopenner" class="message-marked_link" href="${matchedUrl || ''}" title="${title}">${matchedUrl}</a>`;
23
+ });
24
+ if (ret === href) {
25
+ Log.w(`Unable to extract url, href:${href}`);
26
+ }
27
+ return ret;
21
28
  }
22
- return `<a target="_blank" rel="noreferrer noopenner" class="message-marked_link" href="${href || ''}" title="${title}">${text}</a>`;
29
+ return text;
23
30
  },
24
31
  },
25
32
  },
@@ -5,7 +5,9 @@
5
5
  :class="['branch-body',isPC ? 'branch-bubble':'branch-bubble-h5']"
6
6
  >
7
7
  <Icon :src="iconQuestion" class="branch-title-icon"/>
8
- {{ content.header || content.title }}
8
+ <div class="branch-title-text">
9
+ {{ content.header || content.title }}
10
+ </div>
9
11
  </div>
10
12
  <div
11
13
  v-for="(item, index) in content.items"
@@ -91,14 +93,15 @@ export default {
91
93
  display: flex;
92
94
  min-width: 0;
93
95
  box-sizing: border-box;
94
- padding: 12px 14px;
96
+ padding: 8px 16px;
95
97
  font-size: 14px;
96
98
  color: #000;
97
99
  letter-spacing: 0;
98
- word-wrap: break-word;
99
- word-break: break-all;
100
+ overflow-wrap: break-word;
101
+ word-break: normal;
100
102
  position: relative;
101
-
103
+ width: 100%;
104
+ max-width: fit-content;
102
105
  .branch-main {
103
106
  box-sizing: border-box;
104
107
  display: flex;
@@ -124,6 +127,7 @@ export default {
124
127
  .branch-item {
125
128
  color: #1c66e5;
126
129
  cursor: pointer;
130
+ display: inline-block;
127
131
  }
128
132
  .warning-item {
129
133
  color: #ff9800;
@@ -145,4 +149,8 @@ export default {
145
149
  align-items: flex-start !important;
146
150
  margin-top: 2px;
147
151
  }
152
+ .branch-title-text {
153
+ display: inline-block;
154
+ min-width: 0;
155
+ }
148
156
  </style>
@@ -26,7 +26,7 @@ import {TUITranslateService} from "@tencentcloud/chat-uikit-engine";
26
26
  text-size-adjust: none;
27
27
  font-family: PingFangSC-Regular;
28
28
  overflow-wrap: break-word;
29
- word-break: break-all;
29
+ word-break: normal;
30
30
  }
31
31
 
32
32
  .text:lang(en) {
@@ -82,7 +82,7 @@ import { JSONToObject } from '../../../../../../utils/index';
82
82
  import { isEnabledMessageReadReceiptGlobal } from '../../../../../../utils/utils';
83
83
  import { CUSTOM_MESSAGE_SRC } from '../../../../../../constant';
84
84
  import MessageBranch from './message-branch.vue';
85
- import MessageForm from './message-single-form/index.vue';
85
+ import MessageForm from './message-ivr-form/index.vue';
86
86
  import MessageIMRobotWelcome from './message-robot-welcome.vue';
87
87
  import MessageProductCard from './message-product-card.vue';
88
88
  import MessageRichText from './message-rich-text.vue';
@@ -119,20 +119,22 @@ export default {
119
119
  default: () => ({}),
120
120
  },
121
121
  },
122
- emits: ['showFormPopup', 'heightChanged'],
122
+ emits: ['showFormPopup', 'heightChanged', 'messageSent'],
123
123
  setup(props: Props, { emit }) {
124
124
  const payload = computed<customerServicePayloadType>(() => {
125
125
  return props.message && JSONToObject(props.message?.payload?.data);
126
126
  });
127
- const sendTextMessage = (payload: TextMessagePayload, cloudCustomData?: string) => {
128
- TUIChatService.sendTextMessage({
127
+ const sendTextMessage = async (payload: TextMessagePayload, cloudCustomData?: string) => {
128
+ await TUIChatService.sendTextMessage({
129
129
  payload,
130
130
  cloudCustomData: cloudCustomData || '',
131
131
  needReadReceipt: isEnabledMessageReadReceiptGlobal()
132
132
  });
133
+ emit('messageSent');
133
134
  };
134
- const sendCustomMessage = (payload: CustomMessagePayload) => {
135
- TUIChatService.sendCustomMessage({ payload });
135
+ const sendCustomMessage = async (payload: CustomMessagePayload) => {
136
+ await TUIChatService.sendCustomMessage({ payload });
137
+ emit('messageSent');
136
138
  };
137
139
  const handleShowFormPopup = (data: boolean) => {
138
140
  emit('showFormPopup', data);