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.3.2",
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
@@ -5,8 +5,8 @@ import ChatUi from './ChatUi.vue';
5
5
  <template>
6
6
  <div style="width: 100vw; height: 100vh">
7
7
  <chat-ui
8
- bot-id="000"
9
- token="pat_8888"
8
+ bot-id="555"
9
+ token="pat_88888"
10
10
  uid="262598"
11
11
  :def-msg="{ placeholder: '发消息...' }"
12
12
  :show-header="true"
package/src/ChatUi.vue CHANGED
@@ -75,7 +75,7 @@
75
75
  </p>
76
76
  </template>
77
77
  <template v-if="conv.content">
78
- <p class="text" v-html="conv.content"></p>
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
- /\[([^\]]+)\]\((https?:\/\/[^)]+)\)/gi,
591
- '<a href="$2" target="_blank">[$1]</a>',
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
- { content: '請用以上方案為我配餐', text: '請用以上方案為我配餐' },
621
+ {
622
+ content: finalDefMsg.value.matchContent,
623
+ text: finalDefMsg.value.matchText,
624
+ },
617
625
  ]);
618
626
  break;
619
627
  default:
@@ -46,6 +46,10 @@ const props = defineProps({
46
46
  type: Object,
47
47
  required: true,
48
48
  },
49
+ defMsg: {
50
+ type: Object,
51
+ required: true,
52
+ },
49
53
  });
50
54
  const Emits = defineEmits(['select']);
51
55
  const handleSel = () => {
@@ -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>
package/src/main.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createApp } from 'vue';
2
2
  import './style.css';
3
3
  import App from './App.vue';
4
+ import 'viewerjs/dist/viewer.css';
4
5
 
5
6
  createApp(App).mount('#app');