@tencentcloud/ai-desk-customer-vue 1.5.6 → 1.5.9

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 (59) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/assets/feedback_dislike_after.svg +1 -1
  3. package/assets/feedback_dislike_before.svg +2 -9
  4. package/assets/feedback_dislike_hover.svg +2 -9
  5. package/assets/feedback_like_after.svg +2 -13
  6. package/assets/feedback_like_before.svg +2 -9
  7. package/assets/feedback_like_hover.svg +2 -9
  8. package/components/CustomerServiceChat/chat-header/index-web.vue +19 -12
  9. package/components/CustomerServiceChat/feedback-modal/index.vue +391 -0
  10. package/components/CustomerServiceChat/index-web.vue +34 -1
  11. package/components/CustomerServiceChat/message-input/message-input-editor-web.vue +0 -1
  12. package/components/CustomerServiceChat/message-input/message-input-quote/index.vue +0 -3
  13. package/components/CustomerServiceChat/message-input-toolbar/index-web.vue +4 -2
  14. package/components/CustomerServiceChat/message-list/bottom-quick-order/index.vue +0 -1
  15. package/components/CustomerServiceChat/message-list/index-web.vue +92 -62
  16. package/components/CustomerServiceChat/message-list/message-elements/feedback-button.vue +96 -251
  17. package/components/CustomerServiceChat/message-list/message-elements/message-bubble-web.vue +51 -16
  18. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-concurrency-limit.vue +0 -2
  19. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-ivr-form/form-branch.vue +0 -1
  20. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-branch/branch-pc.vue +0 -2
  21. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/form-mobile.vue +34 -29
  22. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-form/form-pc.vue +0 -1
  23. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-order.vue +0 -1
  24. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-product-card.vue +0 -1
  25. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-rating/message-rating-star.vue +0 -1
  26. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-stream.vue +0 -1
  27. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-transfer-with-desc.vue +0 -1
  28. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/styles/common.scss +0 -2
  29. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-plugin-layout-web.vue +16 -0
  30. package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-plugin-web.vue +18 -0
  31. package/components/CustomerServiceChat/message-list/message-elements/message-quote/index-web.vue +0 -3
  32. package/components/CustomerServiceChat/message-list/message-elements/message-text.vue +26 -19
  33. package/components/CustomerServiceChat/message-list/message-elements/message-timestamp.vue +0 -1
  34. package/components/CustomerServiceChat/message-list/message-elements/read-status/index.vue +4 -2
  35. package/components/CustomerServiceChat/message-list/scroll-button/index.vue +8 -4
  36. package/components/CustomerServiceChat/message-list/style/web.scss +0 -2
  37. package/components/CustomerServiceChat/message-toolbar-button/index.vue +13 -9
  38. package/components/CustomerServiceChat/message-toolbar-button/toolbar-button-end-human-service.vue +1 -1
  39. package/components/CustomerServiceChat/style/common.scss +4 -0
  40. package/components/CustomerServiceChat/style/web.scss +2 -1
  41. package/components/common/BottomPopup/style/h5.scss +0 -1
  42. package/components/common/Dialog/style/color.scss +0 -1
  43. package/components/common/Toast/index-web.vue +1 -1
  44. package/constant.ts +3 -2
  45. package/locales/en/aidesk.ts +18 -15
  46. package/locales/fil/aidesk.ts +17 -15
  47. package/locales/id/aidesk.ts +17 -15
  48. package/locales/ja/aidesk.ts +17 -15
  49. package/locales/ms/aidesk.ts +17 -15
  50. package/locales/ru/aidesk.ts +17 -15
  51. package/locales/th/aidesk.ts +17 -15
  52. package/locales/vi/aidesk.ts +17 -15
  53. package/locales/zh_cn/aidesk.ts +17 -14
  54. package/locales/zh_tw/aidesk.ts +17 -15
  55. package/package.json +1 -1
  56. package/server.ts +5 -4
  57. package/utils/index.ts +6 -0
  58. package/utils/utils.ts +42 -0
  59. package/assets/customer_avatar.png +0 -0
@@ -15,7 +15,7 @@
15
15
  @onClose="closeDialog"
16
16
  title=""
17
17
  >
18
- <div style="height:100%;overflow-y: auto;">
18
+ <div style="height:100%;">
19
19
  <div class="dialog-title">
20
20
  <div class="dialog-title-tip">
21
21
  {{ props.payload.content.tip }}
@@ -24,28 +24,30 @@
24
24
  <Icon :src="iconClose" width="16px" height="16px"/>
25
25
  </div>
26
26
  </div>
27
- <div
28
- v-for="(item, index) in props.payload.content.inputVariables"
29
- :key="index"
30
- >
31
- <div v-if="item.formType == 0 && props.payload.nodeStatus == 0">
32
- <InputMobile :placeholder="item.placeholder" :variableValue="item.variableValue" :name="item.name" :isRequired="item.isRequired" @input-change="handleInputChange" :validator="item.isRequired == 1 && isValid(item.name)"/>
33
- </div>
34
- <div v-else-if="item.formType == 1 && props.payload.nodeStatus == 0">
35
- <RadioMobile :chooseItemList="item.chooseItemList" :name="item.name" :isRequired="item.isRequired" @input-change="handleInputChange" :validator="item.isRequired == 1 && isValid(item.name)"/>
36
- </div>
37
- <div v-else class="variable-value-container-mobile">
38
- <div class="variable-value-label-mobile">
39
- {{ item.name }}
27
+ <div class="dialog-show-content">
28
+ <div
29
+ v-for="(item, index) in props.payload.content.inputVariables"
30
+ :key="index"
31
+ >
32
+ <div v-if="item.formType == 0 && props.payload.nodeStatus == 0">
33
+ <InputMobile :placeholder="item.placeholder" :variableValue="item.variableValue" :name="item.name" :isRequired="item.isRequired" @input-change="handleInputChange" :validator="item.isRequired == 1 && isValid(item.name)"/>
40
34
  </div>
41
- <div class="variable-value">
42
- {{ item.variableValue == '' || item.variableValue == null ? mapValue[item.name] : item.variableValue}}
35
+ <div v-else-if="item.formType == 1 && props.payload.nodeStatus == 0">
36
+ <RadioMobile :chooseItemList="item.chooseItemList" :name="item.name" :isRequired="item.isRequired" @input-change="handleInputChange" :validator="item.isRequired == 1 && isValid(item.name)"/>
37
+ </div>
38
+ <div v-else class="variable-value-container-mobile">
39
+ <div class="variable-value-label-mobile">
40
+ {{ item.name }}
41
+ </div>
42
+ <div class="variable-value">
43
+ {{ item.variableValue == '' || item.variableValue == null ? mapValue[item.name] : item.variableValue}}
44
+ </div>
43
45
  </div>
44
46
  </div>
45
- </div>
46
- <div class="button-container" v-if="props.payload.nodeStatus === 0">
47
- <div class="button" @click="handleSendForm">
48
- {{ TUITranslateService.t("AIDesk.提交") }}
47
+ <div class="button-container" v-if="props.payload.nodeStatus === 0">
48
+ <div class="button" @click="handleSendForm">
49
+ {{ TUITranslateService.t("AIDesk.提交") }}
50
+ </div>
49
51
  </div>
50
52
  </div>
51
53
  </div>
@@ -75,7 +77,7 @@ import RadioMobile from './component-mobile/radios-mobile.vue';
75
77
  import LabelMobile from './component-mobile/label-mobile.vue';
76
78
  import FormPopup from './component-mobile/form-popup.vue';
77
79
  import { CUSTOM_MESSAGE_SRC } from '../../../../../../../constant';
78
- import {TUITranslateService} from '@tencentcloud/chat-uikit-engine';
80
+ import { TUITranslateService } from '@tencentcloud/chat-uikit-engine';
79
81
  const { ref, onMounted } = vue;
80
82
  interface Props {
81
83
  payload: customerServicePayloadType;
@@ -163,6 +165,7 @@ export default {
163
165
  };
164
166
  emit('sendMessage', submitData);
165
167
  isSubmit.value = false;
168
+ closeDialog();
166
169
  };
167
170
  const handleInputChange = ({name,value}) => {
168
171
  mapValue.value[name] = value;
@@ -197,10 +200,6 @@ export default {
197
200
  <style lang="scss">
198
201
  @import "../styles/common.scss";
199
202
 
200
- .form-mobile-container {
201
- font-family: PingFangSC-Regular;
202
- }
203
-
204
203
  .edit-profile-container {
205
204
  @extend .container;
206
205
  font-size: 14px;
@@ -311,7 +310,6 @@ export default {
311
310
  display:flex;
312
311
  flex-direction: column;
313
312
  justify-content: center;
314
- font-family: PingFangSC-Regular;
315
313
  .form-button {
316
314
  display:flex;
317
315
  justify-content: center;
@@ -374,6 +372,12 @@ export default {
374
372
  color: rgba(153,153,153,1);
375
373
  }
376
374
  }
375
+
376
+ .dialog-show-content {
377
+ overflow-y: auto;
378
+ max-height: 68vh;
379
+ }
380
+
377
381
  .variable-value-container-mobile {
378
382
  padding: 16px;
379
383
  display: flex;
@@ -399,15 +403,16 @@ export default {
399
403
  .button-container {
400
404
  display: flex;
401
405
  justify-content: center;
402
- margin: 15px;
406
+ padding: 20px;
403
407
  .button {
404
408
  display: flex;
405
409
  justify-content: center;
406
- width: 87px;
407
- padding: 6px 10px;
410
+ width: 100%;
411
+ padding: 9px 33px;
408
412
  background-color: #1c66e5;
409
413
  color: white;
410
414
  border-radius: 20px;
415
+ font-weight: 500;
411
416
  }
412
417
  }
413
418
  </style>
@@ -151,7 +151,6 @@ export default {
151
151
  </script>
152
152
  <style lang="scss">
153
153
  .form-pc-container {
154
- font-family: PingFangSC-Regular;
155
154
  max-width: 350px;
156
155
  }
157
156
  .title-container {
@@ -56,7 +56,6 @@ export default {
56
56
  min-width: 200px;
57
57
  max-width: 400px;
58
58
  color: #000;
59
- font-family: PingFangSC-Regular;
60
59
 
61
60
  .order-guide {
62
61
  font-size: 14px;
@@ -103,7 +103,6 @@ export default {
103
103
  min-width: 100%;
104
104
  max-width: 400px;
105
105
  margin-top: 2px;
106
- font-family: PingFangSC-Regular;
107
106
  display: flex;
108
107
  flex-direction: column;
109
108
  .product-card-main {
@@ -207,7 +207,6 @@ export default {
207
207
  }
208
208
 
209
209
  .message-rating-star {
210
- font-family: PingFangSC-Regular;
211
210
  text-align: center;
212
211
  display: flex;
213
212
  flex-flow: column wrap;
@@ -151,7 +151,6 @@ const closeImage = () => {
151
151
  word-break: normal;
152
152
  white-space: normal;
153
153
  font-size: 14px;
154
- font-family: PingFangSC-Regular;
155
154
  user-select: text;
156
155
  }
157
156
 
@@ -39,7 +39,6 @@ export default {
39
39
  white-space: pre-wrap;
40
40
  font-size: 14px;
41
41
  text-size-adjust: none;
42
- font-family: PingFangSC-Regular;
43
42
  overflow-wrap: break-word;
44
43
  word-break: normal;
45
44
  }
@@ -109,7 +109,6 @@
109
109
  .title-name {
110
110
  font-size: 18px;
111
111
  font-weight: 500;
112
- font-family: PingFangSC-Medium;
113
112
  }
114
113
  }
115
114
  }
@@ -124,7 +123,6 @@
124
123
  justify-content: flex-start;
125
124
  margin: 0;
126
125
  padding: 0;
127
- font-family: PingFangSC-Regular;
128
126
  user-select: text;
129
127
 
130
128
  .message-marked_code-container {
@@ -22,7 +22,11 @@
22
22
  :content="messageModel.getMessageContent()"
23
23
  :blinkMessageIDList="props.blinkMessageIDList"
24
24
  :classNameList="props.bubbleClassNameList"
25
+ :enableFeedback="props.enableFeedback"
26
+ :enableAINote="props.enableAINote"
25
27
  @resendMessage="resendMessage(messageModel)"
28
+ @like="onLike"
29
+ @dislike="onDislike"
26
30
  >
27
31
  <!-- web message-bubble is a named slot, content area slotName is messageElement -->
28
32
  <template #messageElement>
@@ -45,6 +49,8 @@ interface IProps {
45
49
  showStyle: string;
46
50
  bubbleClassNameList?: string[];
47
51
  blinkMessageIDList?: string[];
52
+ enableFeedback: number;
53
+ enableAINote: number;
48
54
  }
49
55
 
50
56
  const props = withDefaults(defineProps<IProps>(), {
@@ -52,12 +58,16 @@ const props = withDefaults(defineProps<IProps>(), {
52
58
  showStyle: '',
53
59
  bubbleClassNameList: () => [] as string[],
54
60
  blinkMessageIDList: () => [] as string[],
61
+ enableFeedback: 0,
62
+ enableAINote: 1,
55
63
  });
56
64
 
57
65
  const emits = defineEmits([
58
66
  'resendMessage',
59
67
  'handleToggleMessageItem',
60
68
  'handleH5LongPress',
69
+ 'like',
70
+ 'dislike',
61
71
  ]);
62
72
  const messageModel = computed(() =>
63
73
  TUIStore.getMessageModel(props.message?.ID),
@@ -77,6 +87,12 @@ const handleToggleMessageItem = (
77
87
  const handleH5LongPress = (e: any, message: IMessageModel, type: string) => {
78
88
  emits('handleH5LongPress', e, message, type);
79
89
  };
90
+ const onLike = (messageInfo: Object) => {
91
+ emits('like', messageInfo);
92
+ };
93
+ const onDislike = (messageInfo: Object) => {
94
+ emits('dislike', messageInfo);
95
+ };
80
96
  </script>
81
97
 
82
98
  <style lang="scss" scoped>
@@ -9,6 +9,10 @@
9
9
  @resendMessage="resendMessage"
10
10
  @handleToggleMessageItem="handleToggleMessageItem"
11
11
  @handleH5LongPress="handleH5LongPress"
12
+ :enableFeedback="props.enableFeedback"
13
+ :enableAINote="props.enableAINote"
14
+ @like="onLike"
15
+ @dislike="onDislike"
12
16
  >
13
17
  <template #messageBubble>
14
18
  <MessageCustomerService
@@ -43,11 +47,15 @@ const { computed } = vue;
43
47
  interface IProps {
44
48
  message: IMessageModel;
45
49
  blinkMessageIDList?: string[];
50
+ enableFeedback: number;
51
+ enableAINote: number;
46
52
  }
47
53
 
48
54
  const props = withDefaults(defineProps<IProps>(), {
49
55
  message: () => ({} as IMessageModel),
50
56
  blinkMessageIDList: () => [] as string[],
57
+ enableFeedback: 0,
58
+ enableAINote: 1,
51
59
  });
52
60
 
53
61
  const emits = defineEmits([
@@ -56,6 +64,8 @@ const emits = defineEmits([
56
64
  'handleH5LongPress',
57
65
  'heightChanged',
58
66
  'messageSent',
67
+ 'like',
68
+ 'dislike',
59
69
  ]);
60
70
  const messageModel = computed(() => TUIStore.getMessageModel(props.message.ID));
61
71
 
@@ -101,6 +111,14 @@ const onHeightChanged = () => {
101
111
  const onMessageSent = () => {
102
112
  emits('messageSent');
103
113
  };
114
+
115
+ function onLike(messageInfo: Object) {
116
+ emits('like', messageInfo);
117
+ };
118
+
119
+ function onDislike(messageInfo: Object) {
120
+ emits('dislike', messageInfo);
121
+ };
104
122
  </script>
105
123
 
106
124
  <style lang="scss" scoped>
@@ -256,13 +256,10 @@ async function scrollToOriginalMessage() {
256
256
  }
257
257
 
258
258
  .mobile-quote-sender{
259
- font-family: PingFangSC-Regular;
260
259
  font-size: 10px;
261
-
262
260
  }
263
261
 
264
262
  .max-double-line {
265
- font-family: PingFangSC-Regular;
266
263
  font-size: 14px;
267
264
  overflow-wrap: break-word;
268
265
  word-break: normal;
@@ -1,11 +1,15 @@
1
1
  <template>
2
2
  <div :class="['message-text-container', isPC && 'text-select']">
3
3
  <span
4
- v-for="(item, index) in data.text"
4
+ v-for="(item, index) in textMessageData.text"
5
5
  :key="index"
6
- >
6
+ >
7
+ <span v-if="item.name === 'text' && enableURLDetection === 1"
8
+ class="text"
9
+ v-html="item.text"
10
+ ></span>
7
11
  <span
8
- v-if="item.name === 'text'"
12
+ v-else-if="item.name === 'text'"
9
13
  class="text"
10
14
  >{{ item.text }}</span>
11
15
  <img
@@ -25,17 +29,23 @@ import {
25
29
  CUSTOM_BASIC_EMOJI_URL_MAPPING,
26
30
  } from '../../emoji-config';
27
31
  import { isPC } from '../../../../utils/env';
28
- const { watchEffect, ref } = vue;
32
+ import state from '../../../../utils/state.js';
33
+ const {ref, computed } = vue;
29
34
  interface IProps {
30
35
  content: Record<string, any>;
36
+ flow: string;
31
37
  }
32
38
  const props = withDefaults(defineProps<IProps>(), {
33
39
  content: () => ({}),
40
+ flow: 'in',
41
+ });
42
+ const enableURLDetection = ref(state.get('enableURLDetection'));
43
+ const linkColor = computed(() => {
44
+ return props.flow === 'out' && isPC ? '#fff' : '#0052d9';
34
45
  });
35
- const data = ref();
36
- watchEffect(() => {
37
- data.value = props.content;
38
- data.value.text?.forEach(
46
+ const textMessageData = computed(() => {
47
+ const contentCopy = JSON.parse(JSON.stringify(props.content));
48
+ contentCopy.text?.forEach(
39
49
  (item: {
40
50
  name: string;
41
51
  text?: string;
@@ -45,24 +55,22 @@ watchEffect(() => {
45
55
  }) => {
46
56
  if (item.name === 'img' && item?.type === 'custom') {
47
57
  if (!CUSTOM_BASIC_EMOJI_URL) {
48
- console.warn(
49
- 'CUSTOM_BASIC_EMOJI_URL is required for custom emoji, please check your CUSTOM_BASIC_EMOJI_URL.',
50
- );
51
- } else if (
52
- !item.emojiKey
53
- || !CUSTOM_BASIC_EMOJI_URL_MAPPING[item.emojiKey]
54
- ) {
55
- console.warn(
56
- 'emojiKey is required for custom emoji, please check your emojiKey.',
57
- );
58
+ console.warn('CUSTOM_BASIC_EMOJI_URL is required for custom emoji, please check your CUSTOM_BASIC_EMOJI_URL.');
59
+ } else if (!item.emojiKey || !CUSTOM_BASIC_EMOJI_URL_MAPPING[item.emojiKey]) {
60
+ console.warn('emojiKey is required for custom emoji, please check your emojiKey.');
58
61
  } else {
59
62
  item.src
60
63
  = CUSTOM_BASIC_EMOJI_URL
61
64
  + CUSTOM_BASIC_EMOJI_URL_MAPPING[item.emojiKey];
62
65
  }
66
+ } else if (item.name === 'text' && enableURLDetection.value) {
67
+ item.text = item.text.replace(/https?:\/\/[\w\-./?=&:#]+(?=[^\w\-./?=&:#]|$)/g, (url) => {
68
+ return `<a href="${url}" target="_blank" rel="noopener noreferrer" class="message-text-link" style="color: ${linkColor.value}; text-decoration: underline;">${url}</a>`;
69
+ }) || '';
63
70
  }
64
71
  },
65
72
  );
73
+ return contentCopy;
66
74
  });
67
75
  </script>
68
76
  <style lang="scss" scoped>
@@ -87,7 +95,6 @@ watchEffect(() => {
87
95
  white-space: pre-wrap;
88
96
  font-size: 14px;
89
97
  text-size-adjust: none;
90
- font-family: PingFangSC-Regular;
91
98
  overflow-wrap: break-word;
92
99
  word-break: normal;
93
100
  }
@@ -64,7 +64,6 @@ watch(
64
64
  @import "../../style/common";
65
65
 
66
66
  .message-timestamp {
67
- font-family: PingFangSC-Regular;
68
67
  margin: 10px auto;
69
68
  color: #999;
70
69
  font-size: 12px;
@@ -62,8 +62,10 @@ onUnmounted(() => {
62
62
  });
63
63
  });
64
64
 
65
- const onInHumanServiceUpdate = (value: boolean) => {
66
- isInHumanService.value = value;
65
+ const onInHumanServiceUpdate = (data: {conversationID: string, value: boolean}) => {
66
+ if (data && data.conversationID === props.message.conversationID) {
67
+ isInHumanService.value = data.value;
68
+ }
67
69
  };
68
70
 
69
71
  const isShowReadStatus = computed<boolean>(() => {
@@ -33,6 +33,7 @@ import { JSONToObject } from '../../../../utils';
33
33
 
34
34
  interface IEmits {
35
35
  (key: 'scrollToLatestMessage'): void;
36
+ (key: 'scrollNearToBottom'): void;
36
37
  }
37
38
  const emits = defineEmits<IEmits>();
38
39
 
@@ -89,11 +90,11 @@ function isTypingMessage(message: IMessageModel): boolean {
89
90
 
90
91
  function onMessageListUpdated(newMessageList: IMessageModel[]) {
91
92
  messageList.value = newMessageList || [];
92
- const lastMessage = messageList.value?.[messageList.value?.length - 1];
93
+ const lastMessage = messageList.value[messageList.value.length - 1];
93
94
  isExistLastMessage.value = !!(
94
95
  // 过滤在线消息
95
96
  // @ts-ignore
96
- lastMessage && !lastMessage?._message._onlineOnlyFlag && lastMessage?.time < currentLastMessageTime?.value
97
+ lastMessage && !lastMessage._onlineOnlyFlag && lastMessage.time < currentLastMessageTime.value
97
98
  );
98
99
  }
99
100
 
@@ -108,7 +109,7 @@ function onNewMessageList(newMessageList: IMessageModel[]) {
108
109
  && !isTypingMessage(message)
109
110
  // 过滤在线消息
110
111
  // @ts-ignore
111
- && !message._message._onlineOnlyFlag
112
+ && !message._onlineOnlyFlag
112
113
  ) {
113
114
  newMessageCount.value += 1;
114
115
  }
@@ -147,6 +148,10 @@ async function judgeScrollOverOneScreen(e: Event) {
147
148
  isScrollOverOneScreen.value = true;
148
149
  return;
149
150
  }
151
+ if (scrollHeight - scrollTop < height + 20) {
152
+ // 滚动接近底部,通知 message-list
153
+ emits('scrollNearToBottom');
154
+ }
150
155
  isScrollOverOneScreen.value = false;
151
156
  } catch (error) {
152
157
  isScrollOverOneScreen.value = false;
@@ -205,7 +210,6 @@ defineExpose({
205
210
  -webkit-tap-highlight-color: transparent;
206
211
 
207
212
  &-text {
208
- font-family: PingFangSC-Regular, system-ui;
209
213
  font-size: 10px;
210
214
  color: #147aff;
211
215
  margin-left: 3px;
@@ -20,7 +20,6 @@
20
20
  background-color: rgba(255, 149, 0, 0.1);
21
21
  color: #ff8c39;
22
22
  line-height: 18px;
23
- font-family: PingFangSC-Regular;
24
23
  font-style: normal;
25
24
  font-weight: 400;
26
25
  text-align: justify;
@@ -76,7 +75,6 @@
76
75
  cursor: pointer;
77
76
 
78
77
  &-text {
79
- font-family: PingFangSC-Regular;
80
78
  font-weight: 400;
81
79
  font-size: 10px;
82
80
  color: #147aff;
@@ -3,7 +3,7 @@
3
3
  <template v-for="(item, index) in props.toolbarButtonList">
4
4
  <ToolbarButtonHumanService v-if="item.presetId === TOOLBAR_BUTTON_TYPE.HUMAN_SERVICE && shouldRender(item) && !isInHumanService" :title="item.title" :icon="item.icon"/>
5
5
  <ToolbarButtonServiceRating v-else-if="item.presetId === TOOLBAR_BUTTON_TYPE.SERVICE_RATING && shouldRender(item) && isInHumanService" :title="item.title" :icon="item.icon"/>
6
- <ToolbarButtonEndHumanService v-else-if="item.presetId === TOOLBAR_BUTTON_TYPE.END_HUMAN_SERVICE && shouldRender(item) && ((item.displayFlag === 1 && isInSession) || isInHumanService)" :title="item.title" :icon="item.icon"/>
6
+ <ToolbarButtonEndHumanService v-else-if="item.presetId === TOOLBAR_BUTTON_TYPE.END_HUMAN_SERVICE && shouldRender(item) && ((item.displayFlag === 1 && canEndConversation) || isInHumanService)" :title="item.title" :icon="item.icon"/>
7
7
  <div v-else-if="shouldRender(item) && !item.presetId" :key="index"
8
8
  :class="['toolbar-button', isH5 ? 'toolbar-button-h5' : '']" @click="onClick(item, index)">
9
9
  <Icon v-if="item.icon" class="toolbar-button-icon" :file="item.icon" width="18px" height="18px"/>
@@ -39,7 +39,7 @@ const props = withDefaults(defineProps<IProps>(), {});
39
39
 
40
40
  const isInHumanService = ref(false);
41
41
  const currentConversation = ref<IConversationModel>();
42
- const isInSession = ref(true);
42
+ const canEndConversation = ref(false);
43
43
 
44
44
  onMounted(() => {
45
45
  TUIStore.watch(StoreName.CONV, {
@@ -47,7 +47,7 @@ onMounted(() => {
47
47
  });
48
48
  TUIStore.watch(StoreName.CUSTOM, {
49
49
  isInHumanService: onInHumanServiceUpdate,
50
- isInSession: onInSessionUpdate
50
+ canEndConversation: onCanEndConversationUpdate
51
51
  });
52
52
  });
53
53
 
@@ -57,7 +57,7 @@ onUnmounted(() => {
57
57
  });
58
58
  TUIStore.unwatch(StoreName.CUSTOM, {
59
59
  isInHumanService: onInHumanServiceUpdate,
60
- isInSession: onInSessionUpdate
60
+ canEndConversation: onCanEndConversationUpdate
61
61
  });
62
62
  });
63
63
 
@@ -65,12 +65,16 @@ const onCurrentConversationUpdate = (conversation: IConversationModel) => {
65
65
  currentConversation.value = conversation;
66
66
  }
67
67
 
68
- const onInHumanServiceUpdate = (value: boolean) => {
69
- isInHumanService.value = value;
68
+ const onInHumanServiceUpdate = (data: {conversationID: string, value: boolean}) => {
69
+ if (data && data.conversationID === currentConversation.value.conversationID) {
70
+ isInHumanService.value = data.value;
71
+ }
70
72
  };
71
73
 
72
- const onInSessionUpdate = (value: boolean) => {
73
- isInSession.value = value;
74
+ const onCanEndConversationUpdate = (data: {conversationID: string, value: boolean}) => {
75
+ if (data && data.conversationID === currentConversation.value.conversationID) {
76
+ canEndConversation.value = data.value;
77
+ }
74
78
  }
75
79
 
76
80
  function onClick(item:ToolbarButtonModel, index: number) {
@@ -115,6 +119,7 @@ function shouldRender(item: ToolbarButtonModel) {
115
119
  overflow-x: auto; /* 允许横向滚动 */
116
120
  scrollbar-width: none; /* Firefox 隐藏滚动条 */
117
121
  -ms-overflow-style: none; /* IE/Edge 隐藏滚动条 */
122
+ min-height: 28px;
118
123
  &::-webkit-scrollbar {
119
124
  display: none; /* Chrome 隐藏滚动条 */
120
125
  }
@@ -150,6 +155,5 @@ function shouldRender(item: ToolbarButtonModel) {
150
155
  text-overflow: ellipsis;
151
156
  max-width: 100px;
152
157
  overflow: hidden;
153
- font-family: PingFangSC-Regular;
154
158
  }
155
159
  </style>
@@ -48,7 +48,7 @@ const onClick = () => {
48
48
  payload: {
49
49
  data: JSON.stringify({
50
50
  customerServicePlugin: 0,
51
- src: CUSTOM_MESSAGE_SRC.USER_END_SESSION,
51
+ src: CUSTOM_MESSAGE_SRC.USER_END_CONVERSATION,
52
52
  }),
53
53
  },
54
54
  needReadReceipt: isEnabledMessageReadReceiptGlobal(),
@@ -57,3 +57,7 @@ input:focus, input:active, textarea:focus, textarea:active {
57
57
  z-index: 9999;
58
58
  max-height: calc(100% - 50px);
59
59
  }
60
+
61
+ pre, button, input, select, textarea {
62
+ font-family: inherit;
63
+ }
@@ -7,6 +7,7 @@
7
7
  display: flex;
8
8
  flex-direction: column;
9
9
  position: relative;
10
+ font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', '微软雅黑', 'Segoe UI', 'Noto Sans CJK SC', 'Noto Sans CJK TC', 'Noto Sans CJK JP', 'Noto Sans CJK KR', 'Roboto', 'Helvetica Neue', 'MIUI', Arial, sans-serif;
10
11
 
11
12
  &-default {
12
13
  width: 100%;
@@ -45,4 +46,4 @@
45
46
  height: 160px;
46
47
  display: flex;
47
48
  }
48
- }
49
+ }
@@ -34,7 +34,6 @@
34
34
  font-size: 16px;
35
35
 
36
36
  .header-close {
37
- font-family: PingFangSC-Regular;
38
37
  font-weight: 400;
39
38
  color: #006eff;
40
39
  font-size: 18px;
@@ -10,7 +10,6 @@
10
10
  }
11
11
 
12
12
  &-title {
13
- font-family: PingFangSC-Medium;
14
13
  font-weight: 500;
15
14
  color: #333;
16
15
  }
@@ -129,6 +129,7 @@ const handleStyle = (type?: string) => {
129
129
  width: fit-content;
130
130
  overflow-wrap: break-word;
131
131
  word-break: normal;
132
+ font-size: 14px;
132
133
  }
133
134
  }
134
135
 
@@ -144,7 +145,6 @@ const handleStyle = (type?: string) => {
144
145
  padding: 10px 15px;
145
146
 
146
147
  span {
147
- font-family: PingFangSC-Regular;
148
148
  font-weight: 400;
149
149
  font-size: 14px;
150
150
  letter-spacing: 0;
package/constant.ts CHANGED
@@ -25,7 +25,7 @@ export const CUSTOM_MESSAGE_SRC = {
25
25
  USER_SATISFACTION: '24',
26
26
  BOT_STATUS: '25',
27
27
  SEAT_STATUS: '26',
28
- USER_END_SESSION: '27',
28
+ USER_END_CONVERSATION: '27',
29
29
  ORDER:'28',
30
30
  ROBOT_MSG: '29',
31
31
  RICH_TEXT: '30',
@@ -37,7 +37,8 @@ export const CUSTOM_MESSAGE_SRC = {
37
37
  CONCURRENCY_LIMIT: '36',
38
38
  TIMEOUT_WARNING: '37',
39
39
  TRANSFER_TO_HUMAN: '39',
40
- SESSION_RESTARTED: '40',
40
+ GET_FEEDBACK_MENU: '42',
41
+ SEND_FEEDBACK: '43',
41
42
  };
42
43
 
43
44
  // im message extra type