@tencentcloud/ai-desk-customer-vue 1.5.2 → 1.5.4
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.
- package/CHANGELOG.md +18 -0
- package/README.md +316 -71
- package/assets/language_arrow_down.svg +3 -0
- package/assets/language_check.svg +3 -0
- package/components/CustomerServiceChat/chat-header/index-web.vue +215 -13
- package/components/CustomerServiceChat/emoji-config/index.ts +3 -2
- package/components/CustomerServiceChat/index-web.vue +87 -25
- package/components/CustomerServiceChat/message-input/index-web.vue +9 -2
- package/components/CustomerServiceChat/message-input/message-input-editor-web.vue +11 -0
- package/components/CustomerServiceChat/message-input/message-input-quote/index.vue +31 -6
- package/components/CustomerServiceChat/message-input-toolbar/file-upload/index.vue +14 -4
- package/components/CustomerServiceChat/message-input-toolbar/image-upload/index.vue +19 -16
- package/components/CustomerServiceChat/message-input-toolbar/index-web.vue +4 -4
- package/components/CustomerServiceChat/message-input-toolbar/video-upload/index.vue +10 -3
- package/components/CustomerServiceChat/message-list/index-web.vue +27 -14
- package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-desk.vue +6 -1
- package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-branch/branch-pc.vue +20 -13
- package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-multi-branch/index.vue +1 -0
- package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-robot-welcome.vue +73 -29
- package/components/CustomerServiceChat/message-list/message-elements/message-desk/message-desk-elements/message-transfer-with-desc.vue +51 -0
- package/components/CustomerServiceChat/message-list/message-elements/message-quote/index-web.vue +18 -9
- package/components/CustomerServiceChat/message-toolbar-button/index.vue +13 -2
- package/components/CustomerServiceChat/style/web.scss +2 -0
- package/components/CustomerServiceChat/utils/sendMessage.ts +5 -0
- package/constant.ts +21 -1
- package/interface.ts +16 -3
- package/locales/en/TUIChat.ts +2 -1
- package/locales/en/aidesk.ts +4 -4
- package/locales/en/index.ts +2 -2
- package/locales/en/time.ts +2 -2
- package/locales/fil/TUIChat.ts +1 -0
- package/locales/fil/index.ts +2 -2
- package/locales/fil/time.ts +2 -2
- package/locales/id/TUIChat.ts +161 -160
- package/locales/id/index.ts +2 -2
- package/locales/id/time.ts +2 -2
- package/locales/ja/TUIChat.ts +162 -161
- package/locales/ja/index.ts +2 -2
- package/locales/ja/time.ts +2 -2
- package/locales/ms/TUIChat.ts +162 -161
- package/locales/ms/index.ts +2 -2
- package/locales/ms/time.ts +2 -2
- package/locales/ru/TUIChat.ts +155 -154
- package/locales/ru/index.ts +2 -2
- package/locales/ru/time.ts +2 -2
- package/locales/th/TUIChat.ts +162 -161
- package/locales/th/index.ts +2 -2
- package/locales/th/time.ts +2 -2
- package/locales/vi/TUIChat.ts +153 -152
- package/locales/vi/index.ts +2 -2
- package/locales/vi/time.ts +2 -2
- package/locales/zh_cn/TUIChat.ts +1 -0
- package/locales/zh_cn/aidesk.ts +1 -1
- package/locales/zh_cn/index.ts +2 -2
- package/locales/zh_cn/time.ts +2 -2
- package/locales/zh_tw/TUIChat.ts +1 -0
- package/locales/zh_tw/aidesk.ts +1 -1
- package/locales/zh_tw/index.ts +2 -2
- package/locales/zh_tw/time.ts +2 -2
- package/package.json +5 -6
- package/server.ts +63 -10
- package/utils/index.ts +6 -13
- package/utils/utils.ts +96 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ToolbarItemContainer
|
|
3
|
-
:iconFile="isH5?fileIconH5:fileIcon"
|
|
4
|
-
:title="TUITranslateService.t('文件')"
|
|
3
|
+
:iconFile="isH5 ? fileIconH5 : fileIcon"
|
|
4
|
+
:title="props.title || TUITranslateService.t('文件')"
|
|
5
5
|
iconWidth='20px'
|
|
6
6
|
iconHeight='20px'
|
|
7
7
|
:needDialog="false"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<div :class="['file-upload', !isPC && 'file-upload-h5']">
|
|
11
11
|
<input
|
|
12
12
|
ref="inputRef"
|
|
13
|
-
:title="TUITranslateService.t('文件')"
|
|
13
|
+
:title="props.title || TUITranslateService.t('文件')"
|
|
14
14
|
type="file"
|
|
15
15
|
data-type="file"
|
|
16
16
|
accept="*"
|
|
@@ -39,6 +39,12 @@ import Log from '../../../../utils/logger';
|
|
|
39
39
|
import { Toast, TOAST_TYPE } from '../../../common/Toast/index-web';
|
|
40
40
|
const { ref } = vue;
|
|
41
41
|
|
|
42
|
+
const props = defineProps({
|
|
43
|
+
title: {
|
|
44
|
+
type: String,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
42
48
|
const inputRef = ref();
|
|
43
49
|
const currentConversation = ref<IConversationModel>();
|
|
44
50
|
|
|
@@ -56,11 +62,15 @@ const sendFileMessage = (e: any) => {
|
|
|
56
62
|
if (e?.target?.files?.length <= 0) {
|
|
57
63
|
return;
|
|
58
64
|
}
|
|
65
|
+
const file = e.target.files[0];
|
|
66
|
+
if (!file || !file.size) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
59
69
|
const options = {
|
|
60
70
|
to: getTo(currentConversation?.value),
|
|
61
71
|
conversationType: currentConversation?.value?.type,
|
|
62
72
|
payload: {
|
|
63
|
-
file: e
|
|
73
|
+
file: e.target,
|
|
64
74
|
},
|
|
65
75
|
needReadReceipt: isEnabledMessageReadReceiptGlobal(),
|
|
66
76
|
} as SendMessageParams;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
>
|
|
14
14
|
<input
|
|
15
15
|
ref="inputRef"
|
|
16
|
-
:title="TUITranslateService.t('图片')"
|
|
16
|
+
:title="props.title || TUITranslateService.t('图片')"
|
|
17
17
|
type="file"
|
|
18
18
|
accept="image/gif,image/jpeg,image/jpg,image/png,image/bmp,image/webp,video/mov,video/mp4"
|
|
19
19
|
@change="sendImageInWeb"
|
|
@@ -31,7 +31,6 @@ import {
|
|
|
31
31
|
SendMessageOptions,
|
|
32
32
|
TUITranslateService
|
|
33
33
|
} from '@tencentcloud/chat-uikit-engine';
|
|
34
|
-
import { TUIGlobal } from '@tencentcloud/universal-api';
|
|
35
34
|
import vue from '../../../../adapter-vue';
|
|
36
35
|
import { isPC, isH5 } from '../../../../utils/env';
|
|
37
36
|
import ToolbarItemContainer from '../toolbar-item-container/index.vue';
|
|
@@ -50,9 +49,12 @@ const props = defineProps({
|
|
|
50
49
|
type: String,
|
|
51
50
|
default: 'album',
|
|
52
51
|
},
|
|
53
|
-
isH5ToolShow:{
|
|
54
|
-
type:Boolean,
|
|
55
|
-
default:false,
|
|
52
|
+
isH5ToolShow: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
default: false,
|
|
55
|
+
},
|
|
56
|
+
title: {
|
|
57
|
+
type: String,
|
|
56
58
|
}
|
|
57
59
|
});
|
|
58
60
|
|
|
@@ -61,11 +63,11 @@ const currentConversation = ref<IConversationModel>();
|
|
|
61
63
|
const IMAGE_TOOLBAR_SHOW_MAP = {
|
|
62
64
|
web_album: {
|
|
63
65
|
icon: imageIcon,
|
|
64
|
-
title: TUITranslateService.t("图片"),
|
|
66
|
+
title: props.title || TUITranslateService.t("图片"),
|
|
65
67
|
},
|
|
66
68
|
uni_album: {
|
|
67
69
|
icon: imageUniIcon,
|
|
68
|
-
title: TUITranslateService.t("图片"),
|
|
70
|
+
title: props.title || TUITranslateService.t("图片"),
|
|
69
71
|
}
|
|
70
72
|
};
|
|
71
73
|
|
|
@@ -95,15 +97,16 @@ const sendImageInWeb = (e: any) => {
|
|
|
95
97
|
return;
|
|
96
98
|
}
|
|
97
99
|
const file = e.target.files[0];
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
if (!file || !file.size) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (file.type.startsWith('image/')) {
|
|
104
|
+
// 处理图片文件
|
|
105
|
+
sendImageMessage(e.target);
|
|
106
|
+
} else if (file.type.startsWith('video/')) {
|
|
107
|
+
// 处理视频文件
|
|
108
|
+
sendVideoMessage(e.target);
|
|
109
|
+
}
|
|
107
110
|
|
|
108
111
|
e.target.value = '';
|
|
109
112
|
};
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
:isH5EmojiShow="isH5EmojiShow"
|
|
41
41
|
@sendMessage="sendMessage"
|
|
42
42
|
/>
|
|
43
|
-
<ImageUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.IMAGE && item.isEnabled === 1" imageSourceType="album" :isH5ToolShow="isH5ToolShow"/>
|
|
44
|
-
<FileUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.FILE && item.isEnabled === 1" :isH5ToolShow="isH5ToolShow"/>
|
|
45
|
-
<VideoUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.VIDEO && item.isEnabled === 1" videoSourceType="album" :isH5ToolShow="isH5ToolShow"/>
|
|
46
|
-
<RatingTool v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.RATING && item.isEnabled === 1 && isInHumanService" :isH5ToolShow="isH5ToolShow"/>
|
|
43
|
+
<ImageUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.IMAGE && item.isEnabled === 1" imageSourceType="album" :isH5ToolShow="isH5ToolShow" :title="item.title"/>
|
|
44
|
+
<FileUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.FILE && item.isEnabled === 1" :isH5ToolShow="isH5ToolShow" :title="item.title"/>
|
|
45
|
+
<VideoUpload v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.VIDEO && item.isEnabled === 1" videoSourceType="album" :isH5ToolShow="isH5ToolShow" :title="item.title"/>
|
|
46
|
+
<RatingTool v-else-if="item.presetId === INPUT_TOOLBAR_TYPE.RATING && item.isEnabled === 1 && isInHumanService" :isH5ToolShow="isH5ToolShow" :title="item.title"/>
|
|
47
47
|
<UserDefineTool
|
|
48
48
|
v-else-if="item.isEnabled === 1 && item.isPreset === 0 && item.presetId !== INPUT_TOOLBAR_TYPE.EMOJI"
|
|
49
49
|
:isH5ToolShow="isH5ToolShow"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<div :class="['video-upload', !isPC && 'video-upload-h5']">
|
|
11
11
|
<input
|
|
12
12
|
ref="inputRef"
|
|
13
|
-
:title="TUITranslateService.t('视频')"
|
|
13
|
+
:title="props.title || TUITranslateService.t('视频')"
|
|
14
14
|
type="file"
|
|
15
15
|
data-type="video"
|
|
16
16
|
accept="video/*"
|
|
@@ -47,6 +47,9 @@ const props = defineProps({
|
|
|
47
47
|
type: String,
|
|
48
48
|
default: 'album',
|
|
49
49
|
},
|
|
50
|
+
title: {
|
|
51
|
+
type: String,
|
|
52
|
+
},
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
const inputRef = ref();
|
|
@@ -63,7 +66,7 @@ const handleIcon = (): string => {
|
|
|
63
66
|
};
|
|
64
67
|
|
|
65
68
|
const handleTitle = (): string => {
|
|
66
|
-
return TUITranslateService.t('视频');
|
|
69
|
+
return props.title || TUITranslateService.t('视频');
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
const onIconClick = () => {
|
|
@@ -74,7 +77,11 @@ const sendVideoInWeb = (e: any) => {
|
|
|
74
77
|
if (e?.target?.files?.length <= 0) {
|
|
75
78
|
return;
|
|
76
79
|
}
|
|
77
|
-
|
|
80
|
+
const file = e?.target?.files[0];
|
|
81
|
+
if (!file || !file.size) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
sendVideoMessage(e.target);
|
|
78
85
|
e.target.value = '';
|
|
79
86
|
};
|
|
80
87
|
|
|
@@ -227,7 +227,7 @@ import {
|
|
|
227
227
|
deepCopy,
|
|
228
228
|
isNonEmptyObject,
|
|
229
229
|
} from '../../../utils/utils';
|
|
230
|
-
import { isMessageInvisible, isThinkingMessage, isThinkingMessageOverTime, JSONToObject } from '../../../utils/index';
|
|
230
|
+
import { isMessageInvisible, isThinkingMessage, isThinkingMessageOverTime, JSONToObject, isTransferMessageWithoutDesc } from '../../../utils/index';
|
|
231
231
|
import { isCustomerConversation } from '../../../index';
|
|
232
232
|
import { CUSTOM_MESSAGE_SRC } from '../../../constant';
|
|
233
233
|
import { QuickOrderModel } from '../../../interface';
|
|
@@ -352,21 +352,31 @@ onUnmounted(() => {
|
|
|
352
352
|
|
|
353
353
|
function onNewMessageList(list: IMessageModel[]) {
|
|
354
354
|
list.forEach((message:IMessageModel) => {
|
|
355
|
-
if (message
|
|
356
|
-
const data = JSONToObject(message
|
|
357
|
-
if (data
|
|
358
|
-
if (data
|
|
359
|
-
if (data.content.content === '
|
|
360
|
-
TUIStore.update(StoreName.CUSTOM, "isInHumanService", true);
|
|
361
|
-
} else if (data.content.content === 'outSeat') {
|
|
355
|
+
if (message.type === TUIChatEngine.TYPES.MSG_CUSTOM) {
|
|
356
|
+
const data = JSONToObject(message.payload.data);
|
|
357
|
+
if (data) {
|
|
358
|
+
if (data.src === CUSTOM_MESSAGE_SRC.BOT_STATUS) {
|
|
359
|
+
if (data.content.content === 'inBot') {
|
|
362
360
|
TUIStore.update(StoreName.CUSTOM, "isInHumanService", false);
|
|
363
361
|
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
362
|
+
} else if (data.src === CUSTOM_MESSAGE_SRC.SEAT_STATUS) {
|
|
363
|
+
if (data.content.command === "updateSeatStatus") {
|
|
364
|
+
if (data.content.content === 'inSeat') {
|
|
365
|
+
TUIStore.update(StoreName.CUSTOM, "isInHumanService", true);
|
|
366
|
+
} else if (data.content.content === 'outSeat') {
|
|
367
|
+
TUIStore.update(StoreName.CUSTOM, "isInHumanService", false);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
} else if (data.src === CUSTOM_MESSAGE_SRC.TYPING_STATE) {
|
|
371
|
+
if (data.typingStatus === 1) {
|
|
372
|
+
TUIStore.update(StoreName.CUSTOM, 'isTyping', true);
|
|
373
|
+
} else {
|
|
374
|
+
TUIStore.update(StoreName.CUSTOM, 'isTyping', false);
|
|
375
|
+
}
|
|
376
|
+
} else if (data.src === CUSTOM_MESSAGE_SRC.NO_SEAT_ONLINE || data.src === CUSTOM_MESSAGE_SRC.TIMEOUT || data.src === CUSTOM_MESSAGE_SRC.END) {
|
|
377
|
+
TUIStore.update(StoreName.CUSTOM, "isInSession", false);
|
|
378
|
+
} else if (data.src === CUSTOM_MESSAGE_SRC.SESSION_RESTARTED) {
|
|
379
|
+
TUIStore.update(StoreName.CUSTOM, "isInSession", true);
|
|
370
380
|
}
|
|
371
381
|
}
|
|
372
382
|
}
|
|
@@ -391,6 +401,9 @@ async function onMessageListUpdated(list: IMessageModel[]) {
|
|
|
391
401
|
if (isThinkingMessage(message)) {
|
|
392
402
|
return isThinkingMessageOverTime(message);
|
|
393
403
|
}
|
|
404
|
+
if (isTransferMessageWithoutDesc(message)) {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
394
407
|
return !message.isDeleted && !isMessageInvisible(message as any);
|
|
395
408
|
});
|
|
396
409
|
|
|
@@ -71,7 +71,10 @@
|
|
|
71
71
|
<div v-if="payload.src === CUSTOM_MESSAGE_SRC.ORDER">
|
|
72
72
|
<MessageOrder :payload="payload" />
|
|
73
73
|
</div>
|
|
74
|
-
|
|
74
|
+
<div v-if="payload.src === CUSTOM_MESSAGE_SRC.TRANSFER_TO_HUMAN || payload.src === CUSTOM_MESSAGE_SRC.TRANSFER_TO_TASK_FLOW">
|
|
75
|
+
<MessageTransferWithDesc :payload="payload" />
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
75
78
|
</div>
|
|
76
79
|
</template>
|
|
77
80
|
<script lang="ts">
|
|
@@ -91,6 +94,7 @@ import MessageMultiBranch from './message-multi-branch/index.vue';
|
|
|
91
94
|
import MessageMultiForm from './message-multi-form/index.vue';
|
|
92
95
|
import MessageConcurrencyLimit from "./message-concurrency-limit.vue";
|
|
93
96
|
import MessageOrder from './message-order.vue';
|
|
97
|
+
import MessageTransferWithDesc from './message-transfer-with-desc.vue';
|
|
94
98
|
import {
|
|
95
99
|
IMessageModel,
|
|
96
100
|
TUIChatService,
|
|
@@ -112,6 +116,7 @@ export default {
|
|
|
112
116
|
MessageRating,
|
|
113
117
|
MessageConcurrencyLimit,
|
|
114
118
|
MessageOrder,
|
|
119
|
+
MessageTransferWithDesc
|
|
115
120
|
},
|
|
116
121
|
props: {
|
|
117
122
|
message: {
|
|
@@ -23,10 +23,12 @@ import vue from '../../../../../../../adapter-vue';
|
|
|
23
23
|
import { TUITranslateService } from '@tencentcloud/chat-uikit-engine';
|
|
24
24
|
import { customerServicePayloadType } from '../../../../../../../interface';
|
|
25
25
|
import { isPC } from '../../../../../../../utils/env'
|
|
26
|
+
import { openSafeUrl } from '../../../../../../../utils/utils';
|
|
26
27
|
const { ref } = vue;
|
|
27
28
|
interface branchItem {
|
|
28
29
|
content: string;
|
|
29
30
|
desc: string;
|
|
31
|
+
url?: string;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
interface Props {
|
|
@@ -47,20 +49,25 @@ export default {
|
|
|
47
49
|
if (!branch.content) {
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
if (branch.url) {
|
|
53
|
+
openSafeUrl(branch.url);
|
|
54
|
+
} else {
|
|
55
|
+
let cloudCustomData;
|
|
56
|
+
if (props.payload.optionType === 0) {
|
|
57
|
+
cloudCustomData = '';
|
|
58
|
+
canSelect.value = false;
|
|
59
|
+
} else if (props.payload.optionType === 1) {
|
|
60
|
+
cloudCustomData = JSON.stringify({
|
|
61
|
+
BranchOptionInfo: {
|
|
62
|
+
taskID: props.payload.taskInfo?.taskID,
|
|
63
|
+
nodeID: props.payload.taskInfo?.nodeID,
|
|
64
|
+
env: props.payload.taskInfo?.env,
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
emit('input-click', branch, cloudCustomData);
|
|
62
69
|
}
|
|
63
|
-
|
|
70
|
+
|
|
64
71
|
};
|
|
65
72
|
|
|
66
73
|
return {
|
|
@@ -17,13 +17,18 @@
|
|
|
17
17
|
<Icon :src="iconRefresh" />
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
|
-
<div
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
<div class="welcome-items-container">
|
|
21
|
+
<div
|
|
22
|
+
v-for="(item, index) in showList"
|
|
23
|
+
:key="index"
|
|
24
|
+
class="welcome-item"
|
|
25
|
+
@click="handleContentListItemClick(item)"
|
|
26
|
+
>
|
|
27
|
+
<div class="item-content">{{ item.content }}</div>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="welcome-item welcome-item-hidden">
|
|
30
|
+
{{ longestContent }}
|
|
31
|
+
</div>
|
|
27
32
|
</div>
|
|
28
33
|
</div>
|
|
29
34
|
</template>
|
|
@@ -37,7 +42,7 @@ import Icon from './customer-icon.vue';
|
|
|
37
42
|
import iconQuestion from '../../../../../../assets/icon_question.png';
|
|
38
43
|
import iconRefresh from '../../../../../../assets/icon_refresh.png';
|
|
39
44
|
import { customerServicePayloadType } from '../../../../../../interface';
|
|
40
|
-
const { reactive, toRefs } = vue;
|
|
45
|
+
const { reactive, toRefs, computed } = vue;
|
|
41
46
|
|
|
42
47
|
interface Props {
|
|
43
48
|
payload: customerServicePayloadType;
|
|
@@ -56,7 +61,7 @@ export default {
|
|
|
56
61
|
props: {
|
|
57
62
|
payload: {
|
|
58
63
|
type: Object as () => customerServicePayloadType,
|
|
59
|
-
default: () => ({ content: { title: '', items: [] }
|
|
64
|
+
default: () => ({ content: { title: '', items: [] }}),
|
|
60
65
|
},
|
|
61
66
|
},
|
|
62
67
|
emits: ['sendMessage'],
|
|
@@ -86,6 +91,19 @@ export default {
|
|
|
86
91
|
);
|
|
87
92
|
data.pageNumber += 1;
|
|
88
93
|
};
|
|
94
|
+
|
|
95
|
+
const longestContent = computed(() => {
|
|
96
|
+
if (!data.list) {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
let longestContent = '';
|
|
100
|
+
data.list.forEach((item) => {
|
|
101
|
+
if (item.content.length > longestContent.length) {
|
|
102
|
+
longestContent = item.content;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return longestContent;
|
|
106
|
+
});
|
|
89
107
|
|
|
90
108
|
return {
|
|
91
109
|
...toRefs(data),
|
|
@@ -96,6 +114,7 @@ export default {
|
|
|
96
114
|
changeBranchList,
|
|
97
115
|
iconQuestion,
|
|
98
116
|
iconRefresh,
|
|
117
|
+
longestContent
|
|
99
118
|
};
|
|
100
119
|
},
|
|
101
120
|
};
|
|
@@ -104,6 +123,9 @@ export default {
|
|
|
104
123
|
<style lang="scss">
|
|
105
124
|
.welcome-card {
|
|
106
125
|
max-width: 400px;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
align-items: center;
|
|
107
129
|
|
|
108
130
|
.welcome-title {
|
|
109
131
|
display: flex;
|
|
@@ -111,6 +133,7 @@ export default {
|
|
|
111
133
|
margin-bottom: 10px;
|
|
112
134
|
justify-content: space-between;
|
|
113
135
|
align-items: center;
|
|
136
|
+
width: 100%;
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
.welcome-title-left-container {
|
|
@@ -151,28 +174,49 @@ export default {
|
|
|
151
174
|
cursor: pointer;
|
|
152
175
|
}
|
|
153
176
|
|
|
154
|
-
.welcome-
|
|
155
|
-
|
|
177
|
+
.welcome-items-container {
|
|
178
|
+
width: 100%;
|
|
156
179
|
display: flex;
|
|
157
|
-
|
|
180
|
+
flex-direction: column;
|
|
158
181
|
align-items: center;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
.welcome-item {
|
|
183
|
+
width: 100%;
|
|
184
|
+
padding: 6px 10px;
|
|
185
|
+
display: flex;
|
|
186
|
+
justify-content: center;
|
|
187
|
+
align-items: center;
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
background-color: #ffffff;
|
|
190
|
+
margin-bottom: 10px;
|
|
191
|
+
border:1px solid #adcfff;
|
|
192
|
+
border-radius: 20px;
|
|
193
|
+
font-weight: 500;
|
|
194
|
+
color: #1c66e5;
|
|
195
|
+
gap: 10px;
|
|
196
|
+
box-sizing: border-box;
|
|
197
|
+
.item-content {
|
|
198
|
+
text-align: center;
|
|
199
|
+
overflow-wrap: break-word;
|
|
200
|
+
word-break: normal;
|
|
201
|
+
width: 100%;
|
|
202
|
+
padding: 0 10px;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.welcome-item:hover {
|
|
207
|
+
background: #f2f7ff;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.welcome-item:last-child {
|
|
211
|
+
margin-bottom: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.welcome-item-hidden {
|
|
215
|
+
visibility: hidden;
|
|
216
|
+
padding: 0;
|
|
217
|
+
margin: 0;
|
|
218
|
+
height: 0;
|
|
219
|
+
}
|
|
176
220
|
}
|
|
177
221
|
}
|
|
178
222
|
</style>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="['text', isPC && 'text-select']">
|
|
3
|
+
{{ props.payload.description }}
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import vue from '../../../../../../adapter-vue';
|
|
9
|
+
import { customerServicePayloadType } from '../../../../../../interface';
|
|
10
|
+
import { isPC } from '../../../../../../utils/env';
|
|
11
|
+
const { computed } = vue;
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
payload: customerServicePayloadType;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
props: {
|
|
19
|
+
payload: {
|
|
20
|
+
type: Object as () => customerServicePayloadType,
|
|
21
|
+
default: () => ({}),
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
setup(props: Props) {
|
|
25
|
+
const payload = computed<customerServicePayloadType>(() => {
|
|
26
|
+
return props.payload;
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
props,
|
|
30
|
+
isPC,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
</script>
|
|
35
|
+
<style lang="scss" scoped>
|
|
36
|
+
.text-select {
|
|
37
|
+
-webkit-user-select: text;
|
|
38
|
+
-moz-user-select: text;
|
|
39
|
+
-ms-user-select: text;
|
|
40
|
+
user-select: text;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.text {
|
|
44
|
+
white-space: pre-wrap;
|
|
45
|
+
font-size: 14px;
|
|
46
|
+
text-size-adjust: none;
|
|
47
|
+
font-family: PingFangSC-Regular;
|
|
48
|
+
overflow-wrap: break-word;
|
|
49
|
+
word-break: normal;
|
|
50
|
+
}
|
|
51
|
+
</style>
|
package/components/CustomerServiceChat/message-list/message-elements/message-quote/index-web.vue
CHANGED
|
@@ -14,18 +14,18 @@
|
|
|
14
14
|
|
|
15
15
|
<div
|
|
16
16
|
v-if="isMessageRevoked"
|
|
17
|
-
class="revoked-text"
|
|
17
|
+
:class="isPC ? 'revoked-text' : ''"
|
|
18
18
|
>
|
|
19
19
|
{{ TUITranslateService.t("TUIChat.引用内容已撤回") }}
|
|
20
20
|
</div>
|
|
21
21
|
<div v-else>
|
|
22
22
|
<div v-if="isH5" class="mobile-quote-sender">
|
|
23
|
-
{{
|
|
23
|
+
{{ quoteMessageSender }}
|
|
24
24
|
</div>
|
|
25
25
|
<div
|
|
26
26
|
class="max-double-line"
|
|
27
27
|
>
|
|
28
|
-
{{ isPC ?
|
|
28
|
+
{{ isPC ? quoteMessageSender + ": "+ transformTextWithKeysToEmojiNames(messageQuoteText) : transformTextWithKeysToEmojiNames(messageQuoteText)}}
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
@@ -77,6 +77,7 @@ let selfAddValue = 0;
|
|
|
77
77
|
const messageQuoteText = ref<string>('');
|
|
78
78
|
const hasQuoteContent = ref(false);
|
|
79
79
|
const messageQuoteContent = ref<IQuoteContent>({} as IQuoteContent);
|
|
80
|
+
const quoteMessageSender = ref<string>('');
|
|
80
81
|
|
|
81
82
|
const isMessageRevoked = computed<boolean>(() => {
|
|
82
83
|
try {
|
|
@@ -110,6 +111,7 @@ onMounted(() => {
|
|
|
110
111
|
function performQuoteContent(params: IQuoteContent) {
|
|
111
112
|
let messageKey: string = '';
|
|
112
113
|
let quoteContent: string = '';
|
|
114
|
+
const quoteMessage = getQuoteMessage(params.messageID);
|
|
113
115
|
switch (params.messageType) {
|
|
114
116
|
case MessageQuoteTypeEnum.TYPE_TEXT:
|
|
115
117
|
messageKey = '[文本]';
|
|
@@ -145,18 +147,25 @@ function performQuoteContent(params: IQuoteContent) {
|
|
|
145
147
|
messageKey = '[消息]';
|
|
146
148
|
break;
|
|
147
149
|
}
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
params.messageType
|
|
151
|
-
)
|
|
152
|
-
) {
|
|
150
|
+
if (params.messageType === MessageQuoteTypeEnum.TYPE_CUSTOM ||
|
|
151
|
+
params.messageType === MessageQuoteTypeEnum.TYPE_TEXT ||
|
|
152
|
+
params.messageType === MessageQuoteTypeEnum.TYPE_MERGER) {
|
|
153
153
|
quoteContent = params.messageAbstract;
|
|
154
154
|
}
|
|
155
|
+
quoteMessageSender.value = !quoteMessage ? messageQuoteContent.value.messageSender : (quoteMessage.nick || quoteMessage.from);
|
|
155
156
|
return quoteContent
|
|
156
157
|
? quoteContent
|
|
157
158
|
: TUITranslateService.t(`TUIChat.${messageKey}`);
|
|
158
159
|
}
|
|
159
160
|
|
|
161
|
+
function getQuoteMessage(messageID: string) {
|
|
162
|
+
const currentMessageList = TUIStore.getData(StoreName.CHAT, 'messageList');
|
|
163
|
+
let quoteMessage = currentMessageList.find(
|
|
164
|
+
message => message.ID === messageID,
|
|
165
|
+
);
|
|
166
|
+
return quoteMessage;
|
|
167
|
+
}
|
|
168
|
+
|
|
160
169
|
async function scrollToOriginalMessage() {
|
|
161
170
|
if (isMessageRevoked.value) {
|
|
162
171
|
return;
|
|
@@ -164,7 +173,7 @@ async function scrollToOriginalMessage() {
|
|
|
164
173
|
const originMessageID = messageQuoteContent.value?.messageID;
|
|
165
174
|
const currentMessageList = TUIStore.getData(StoreName.CHAT, 'messageList');
|
|
166
175
|
const isOriginalMessageInScreen = currentMessageList.some(
|
|
167
|
-
|
|
176
|
+
message => message.ID === originMessageID,
|
|
168
177
|
);
|
|
169
178
|
if (originMessageID && isOriginalMessageInScreen) {
|
|
170
179
|
try {
|