ai-chat-bot-interface 1.3.2 → 1.4.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.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-chat-bot-interface",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"description": "A AI chat bot interface. (private)",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"bot"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"v-viewer": "^3.0.21",
|
|
20
21
|
"vue": "^3.5.13"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
package/src/App.vue
CHANGED
package/src/ChatUi.vue
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
</p>
|
|
76
76
|
</template>
|
|
77
77
|
<template v-if="conv.content">
|
|
78
|
-
<
|
|
78
|
+
<assistant-replay :content="conv.content" />
|
|
79
79
|
<template v-if="!isAnswering">
|
|
80
80
|
<div v-if="conv.extra.length">
|
|
81
81
|
<template v-for="(comp, idx) in conv.extra" :key="idx">
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
<plan-card
|
|
96
96
|
v-if="comp.showType === 'plan'"
|
|
97
97
|
:info="comp"
|
|
98
|
+
:def-msg="finalDefMsg"
|
|
98
99
|
@select="handleCardTap({ type: 'match' }, comp)"
|
|
99
100
|
/>
|
|
100
101
|
</template>
|
|
@@ -163,6 +164,7 @@ import LoadingIcon2 from './components/icons/loadingIcon2.vue';
|
|
|
163
164
|
import ImgeList from './components/imgeList.vue';
|
|
164
165
|
import ThinkingIcon from './components/icons/ThinkingIcon.vue';
|
|
165
166
|
import OkIcon from './components/icons/OkIcon.vue';
|
|
167
|
+
import AssistantReplay from './components/assistantReplay/assistantReplay.vue';
|
|
166
168
|
|
|
167
169
|
const chatOptions = computed(() => {
|
|
168
170
|
return {
|
|
@@ -180,6 +182,8 @@ const msgObj = {
|
|
|
180
182
|
placeholder: '發消息⋯',
|
|
181
183
|
fileText: '請根據我上傳的體檢報告為我生成飲食方案',
|
|
182
184
|
uploadingTips: '文件正在上傳,請稍候...',
|
|
185
|
+
matchText: '請用以上方案為我配餐',
|
|
186
|
+
matchContent: '請用以上方案為我配餐',
|
|
183
187
|
};
|
|
184
188
|
|
|
185
189
|
const props = defineProps({
|
|
@@ -583,13 +587,14 @@ const queryBotInfo = async () => {
|
|
|
583
587
|
};
|
|
584
588
|
|
|
585
589
|
const handleText = (str) => {
|
|
590
|
+
return str;
|
|
586
591
|
// console.log(str);
|
|
587
|
-
let txt = '';
|
|
588
|
-
|
|
589
|
-
return str.replaceAll(
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
);
|
|
592
|
+
// let txt = '';
|
|
593
|
+
//
|
|
594
|
+
// return str.replaceAll(
|
|
595
|
+
// /\[([^\]]+)\]\((https?:\/\/[^)]+)\)/gi,
|
|
596
|
+
// '<a href="$2" target="_blank">[$1]</a>',
|
|
597
|
+
// );
|
|
593
598
|
};
|
|
594
599
|
const handleBack = () => {
|
|
595
600
|
Emits('call', { type: 'back' });
|
|
@@ -613,7 +618,10 @@ const handleCardTap = ({ type }, info) => {
|
|
|
613
618
|
break;
|
|
614
619
|
case 'match':
|
|
615
620
|
chatConv([
|
|
616
|
-
{
|
|
621
|
+
{
|
|
622
|
+
content: finalDefMsg.value.matchContent,
|
|
623
|
+
text: finalDefMsg.value.matchText,
|
|
624
|
+
},
|
|
617
625
|
]);
|
|
618
626
|
break;
|
|
619
627
|
default:
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<p class="text">
|
|
3
|
+
<template v-for="(item, idx) in msgList" :key="idx">
|
|
4
|
+
<template v-if="item.type === 'text'">{{ item.content }}</template>
|
|
5
|
+
<template v-if="item.type === 'link'">
|
|
6
|
+
<a class="link" @click.stop="previewImg(item)">{{ item.content }}</a>
|
|
7
|
+
</template>
|
|
8
|
+
</template>
|
|
9
|
+
</p>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, ref } from 'vue';
|
|
14
|
+
import { api as viewerApi } from 'v-viewer';
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
content: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: '',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const images = ref([]);
|
|
24
|
+
const msgList = computed(() => {
|
|
25
|
+
const regEx = /\[([^\]]+)]\((https?:\/\/[^)]+)\)/gi;
|
|
26
|
+
const matches = [...props.content.matchAll(regEx)];
|
|
27
|
+
let remaining = props.content;
|
|
28
|
+
let pointer = 0;
|
|
29
|
+
const result = [];
|
|
30
|
+
if (matches.length) {
|
|
31
|
+
matches.forEach((match, index) => {
|
|
32
|
+
result.push({
|
|
33
|
+
type: 'text',
|
|
34
|
+
content: match.input.slice(pointer, match.index).replace(regEx, ''),
|
|
35
|
+
});
|
|
36
|
+
result.push({
|
|
37
|
+
type: 'link',
|
|
38
|
+
string: match[0],
|
|
39
|
+
...JSON.parse(match[0].replace(regEx, '{"content":"[$1]","url":"$2"}')),
|
|
40
|
+
});
|
|
41
|
+
remaining = match.input.slice(match.index).replace(match[0], '');
|
|
42
|
+
pointer = match.index;
|
|
43
|
+
});
|
|
44
|
+
if (remaining.length) {
|
|
45
|
+
result.push({
|
|
46
|
+
type: 'text',
|
|
47
|
+
content: remaining,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
result.push({
|
|
52
|
+
type: 'text',
|
|
53
|
+
content: remaining,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const previewImg = ({ url }) => {
|
|
60
|
+
images.value = [url];
|
|
61
|
+
viewerApi({
|
|
62
|
+
images: images.value,
|
|
63
|
+
options: {
|
|
64
|
+
navbar: false,
|
|
65
|
+
toolbar: {
|
|
66
|
+
flipHorizontal: false,
|
|
67
|
+
flipVertical: false,
|
|
68
|
+
next: false,
|
|
69
|
+
prev: false,
|
|
70
|
+
play: false,
|
|
71
|
+
reset: true,
|
|
72
|
+
oneToOne: true,
|
|
73
|
+
rotateLeft: true,
|
|
74
|
+
rotateRight: true,
|
|
75
|
+
zoomIn: true,
|
|
76
|
+
zoomOut: true,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style scoped lang="less">
|
|
84
|
+
.text {
|
|
85
|
+
word-break: break-all;
|
|
86
|
+
white-space: pre-wrap;
|
|
87
|
+
margin: 0;
|
|
88
|
+
}
|
|
89
|
+
.link {
|
|
90
|
+
color: #039938;
|
|
91
|
+
}
|
|
92
|
+
</style>
|