ai-chat-bot-interface 1.0.1 → 1.0.3

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.0.1",
4
+ "version": "1.0.3",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "description": "A AI chat bot interface. (private)",
package/src/ChatUi.less CHANGED
@@ -27,6 +27,7 @@
27
27
  }
28
28
  &_sug {
29
29
  cursor: pointer;
30
+ font-size: 14px;
30
31
  margin-bottom: 8px;
31
32
  padding: 6px 16px;
32
33
  border-radius: 8px;
@@ -40,7 +41,11 @@
40
41
  &_box {
41
42
  width: 100%;
42
43
  height: 100%;
44
+ font-size: 14px;
43
45
  background-color: @bg-color;
46
+ .btn {
47
+ border: none;
48
+ }
44
49
  }
45
50
 
46
51
  &_wrap {
@@ -127,6 +132,7 @@
127
132
  border-radius: @border-radius;
128
133
 
129
134
  /deep/ .text {
135
+ word-break: break-all;
130
136
  white-space: pre-wrap;
131
137
 
132
138
  a {
@@ -213,5 +219,6 @@
213
219
  color: #1d1c2359;
214
220
  background-color: #2e2e380a;
215
221
  font-size: 12px;
222
+ text-align: center;
216
223
  }
217
224
  }
package/src/ChatUi.vue CHANGED
@@ -4,15 +4,17 @@
4
4
  <div class="cui_header">
5
5
  <div class="title" @click.stop="queryHistoryList">
6
6
  <img class="logo" :src="logo" alt="logo" style="width: 24px; height: 24px;"/>
7
- {{ name }} {{ botId }}
7
+ {{ name }}
8
8
  </div>
9
9
  <div class="btn_group">
10
- <button class="btn">
11
- <clear-icon/>
12
- </button>
13
- <button class="btn">
14
- <close-icon/>
15
- </button>
10
+ <template v-show="false">
11
+ <button class="btn">
12
+ <clear-icon/>
13
+ </button>
14
+ <button class="btn">
15
+ <close-icon/>
16
+ </button>
17
+ </template>
16
18
  </div>
17
19
  </div>
18
20
  <div class="cui_content">
@@ -42,7 +44,8 @@
42
44
  <p class="text" v-html="conv.content"></p>
43
45
  <div v-if="conv.extra.length && !isAnswering">
44
46
  <template v-for="(comp, idx) in conv.extra" :key="idx">
45
- <dishes-list :sku-list="comp.content.skuList" @select="handleCardTap"/>
47
+ <dishes-list v-if="comp.showType === 'card'" :sku-list="comp.skuList" @select="handleCardTap"/>
48
+ <plan-card v-if="comp.showType === 'plan'" @select="handleCardTap({ type: 'match'})" />
46
49
  </template>
47
50
  </div>
48
51
  </div>
@@ -50,23 +53,15 @@
50
53
  </div>
51
54
  <div v-else class="replay role_user">
52
55
  <div class="replay_content">
53
-
54
56
  <div class="name">User_{{ uid }} <!--<span class="time">12:30</span>--></div>
55
57
  <div class="box">
56
58
  <p class="text" v-html="conv.content"></p>
57
- <div v-if="conv.extra.length && !isAnswering">
58
- <template v-for="(comp, idx) in conv.extra" :key="idx">
59
- <dishes-list :sku-list="comp.content.skuList"
60
- @select="handleCardTap"
61
- />
62
- </template>
63
- </div>
64
59
  </div>
65
60
  </div>
66
61
  <img class="avatar" :src="avatar" alt="avatar">
67
62
  </div>
68
63
  </template>
69
- <div ref="endTarget" style="height: 100px;" />
64
+ <div ref="endTarget" style="height: 100px;"/>
70
65
  </div>
71
66
  <div class="cui_operate">
72
67
  <button class="btn" @click.stop="createConv">
@@ -79,7 +74,7 @@
79
74
  </div>
80
75
  </div>
81
76
  </div>
82
- <div class="cui_footer">Powered by Coze</div>
77
+ <div class="cui_footer">Powered by DeepSeek</div>
83
78
  </div>
84
79
  </div>
85
80
 
@@ -95,6 +90,7 @@ import mock from './mock';
95
90
  import {get, post} from './utils/request';
96
91
  import DishesCard from './components/DishesCard.vue';
97
92
  import DishesList from './components/DishesList.vue';
93
+ import PlanCard from './components/PlanCard.vue';
98
94
 
99
95
  const chatOptions = computed(() => {
100
96
  return {
@@ -102,7 +98,7 @@ const chatOptions = computed(() => {
102
98
  Authorization: `Bearer ${props.token}`,
103
99
  'Content-Type': 'application/json',
104
100
  },
105
- }
101
+ };
106
102
  });
107
103
  const conversationId = ref('');
108
104
  const isAnswering = ref(false);
@@ -132,10 +128,13 @@ const props = defineProps({
132
128
  },
133
129
  token: {
134
130
  type: String,
135
- required: true
136
- }
131
+ required: true,
132
+ },
137
133
 
138
134
  });
135
+
136
+ const Emits = defineEmits(['call']);
137
+
139
138
  const endTarget = ref(null);
140
139
  const inputText = ref('');
141
140
  const botInfo = ref({});
@@ -200,16 +199,18 @@ const messageCreate = async () => {
200
199
  );
201
200
  };
202
201
  const chatConv = async (data) => {
203
- console.log('== user send ==');
204
- let txt = '';
205
- if (!(!isAnswering.value && (inputText || data.code))) {
202
+ let isInCode = data.hasOwnProperty('text') && data.hasOwnProperty('code');
203
+ if (!(!isAnswering.value && (inputText.value || isInCode))) {
206
204
  return;
207
205
  }
206
+ const inText = inputText.value;
207
+ console.log('== user send ==', isInCode, data, inText);
208
+ isAnswering.value = true;
208
209
  historyList.value.push({
209
210
  conversation_id: conversationId.value,
210
211
  bot_id: props.botId,
211
212
  role: 'user',
212
- content: data.text ? data.text : inputText.value,
213
+ content: isInCode ? data.text : inText,
213
214
  status: 'ended',
214
215
  extra: [],
215
216
  });
@@ -230,7 +231,7 @@ const chatConv = async (data) => {
230
231
  {
231
232
  'role': 'user',
232
233
  'content_type': 'text',
233
- 'content': data.code ? data.code : inputText.value, // '配餐1600kcal,身高173,体重60kg,生成一天的套餐',
234
+ 'content': isInCode ? data.code : inText, // '配餐1600kcal,身高173,体重60kg,生成一天的套餐',
234
235
  }],
235
236
  }),
236
237
  credentials: 'same-origin', // 默认同源策略
@@ -288,22 +289,25 @@ const chatConv = async (data) => {
288
289
  && strObj.hasOwnProperty('content_type')
289
290
  && strObj.content_type === 'text'
290
291
  && strObj.hasOwnProperty('type')
291
- && strObj.type === 'answer') {
292
- txt += JSON.parse(str).content;
293
- historyList.value[idx].content = handleText(historyList.value[idx].content + JSON.parse(str).content);
292
+ && strObj.type === 'answer'
293
+ && !strObj.hasOwnProperty('created_at')) {
294
+ historyList.value[idx].content = handleText(historyList.value[idx].content + strObj.content);
294
295
  } else if (strObj.hasOwnProperty('type')
295
296
  && strObj.type === 'tool_response') {
296
297
  const extraObj = JSON.parse(strObj.content);
297
- historyList.value[idx].extra.push({
298
- type: strObj.type,
299
- content: extraObj,
300
- });
298
+ if(extraObj.hasOwnProperty('showType')) {
299
+ historyList.value[idx].extra.push({...extraObj});
300
+ }else if(extraObj.hasOwnProperty('response_for_model')){
301
+ const modelObj = JSON.parse(extraObj.response_for_model);
302
+ if(modelObj.hasOwnProperty('showType')) {
303
+ historyList.value[idx].extra.push({...modelObj});
304
+ }
305
+ }
301
306
  }
302
307
  }
303
308
  });
304
309
  }
305
310
  console.log('====', historyList.value);
306
- console.log('== txt ==', txt);
307
311
  };
308
312
 
309
313
  const queryHistoryList = async () => {
@@ -314,16 +318,55 @@ const queryHistoryList = async () => {
314
318
  );
315
319
  if (res.code === 0 && res.data && res.data.length) {
316
320
  historyList.value = [];
321
+ const cardList = [];
317
322
  res.data.forEach(row => {
318
- historyList.value.push({
319
- conversation_id: row.conversation_id,
320
- bot_id: row.bot_id,
321
- role: row.role,
322
- content: row.content,
323
- status: 'ended',
324
- extra: [],
325
- });
323
+ if(row.hasOwnProperty('content_type')) {
324
+ if(row.content_type === 'text') {
325
+ historyList.value.push({
326
+ chat_id: row.chat_id,
327
+ conversation_id: row.conversation_id,
328
+ bot_id: row.bot_id,
329
+ role: row.role,
330
+ content: handleText(row.content),
331
+ status: 'ended',
332
+ extra: [],
333
+ });
334
+ }else if(row.content_type === 'card' && row.role === 'assistant') {
335
+ try {
336
+ const cardObj = JSON.parse(row.content);
337
+ if(cardObj.hasOwnProperty('showType')) {
338
+ cardList.push({
339
+ chat_id: row.chat_id,
340
+ conversation_id: row.conversation_id,
341
+ bot_id: row.bot_id,
342
+ role: row.role,
343
+ extra:[{...cardObj}]
344
+ })
345
+ }else if(cardObj.hasOwnProperty('response_for_model')){
346
+ const modelObj = JSON.parse(cardObj.response_for_model);
347
+ if(modelObj.hasOwnProperty('showType')) {
348
+ cardList.push({
349
+ chat_id: row.chat_id,
350
+ conversation_id: row.conversation_id,
351
+ bot_id: row.bot_id,
352
+ role: row.role,
353
+ extra:[{...modelObj}]
354
+ })
355
+ }
356
+ }
357
+ }catch (e) {
358
+ console.log('== 解析错误 ==');
359
+ }
360
+ }
361
+ }
326
362
  });
363
+ cardList.forEach(card => {
364
+ const idx = historyList.value.findIndex(c => c.chat_id === card.chat_id && c.role === 'assistant');
365
+ if(idx > -1) {
366
+ historyList.value[idx].extra = [...card.extra];
367
+ }
368
+ })
369
+ console.log(historyList.value, cardList);
327
370
  }
328
371
  };
329
372
 
@@ -348,14 +391,19 @@ const handleCardTap = ({type}) => {
348
391
  case 'change':
349
392
  chatConv({code: '換一套菜品', text: '換一套菜品'});
350
393
  break;
394
+ case 'match':
395
+ chatConv({code: '請用以上方案為我配餐', text: '請用以上方案為我配餐'});
396
+ break;
397
+ default:
398
+ Emits('call', { type });
351
399
  }
352
400
  };
353
401
 
354
402
  const scrollToEnd = () => {
355
403
  nextTick(() => {
356
404
  endTarget.value.scrollIntoView();
357
- })
358
- }
405
+ });
406
+ };
359
407
  </script>
360
408
 
361
409
  <style scoped lang="less">
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
  </template>
13
13
  <div class="btn_group">
14
- <div class="btn btn_1" @click.stop="handleBtn('change')">換一套菜品</div>
14
+ <!-- <div class="btn btn_1" @click.stop="handleBtn('change')">換一套菜品</div>-->
15
15
  <div class="btn btn_2" @click.stop="handleBtn('order')">去下單</div>
16
16
  </div>
17
17
  </div>
@@ -69,7 +69,7 @@ const handleBtn = (type) => {
69
69
 
70
70
  &_group {
71
71
  display: grid;
72
- grid-template-columns: 1fr 1fr;
72
+ grid-template-columns: 1fr;
73
73
  grid-column-gap: 10px;
74
74
  margin-top: 20px;
75
75
  }
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div class="btn_group">
3
+ <div class="btn btn_2" @click.stop="handleSel">用該方案配餐</div>
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ const Emits = defineEmits(['select']);
10
+ const handleSel = () => {
11
+ Emits('select', {})
12
+ }
13
+ </script>
14
+
15
+ <style scoped lang="less">
16
+ .btn {
17
+ cursor: pointer;
18
+ width: 100%;
19
+ height: 38px;
20
+ line-height: 38px;
21
+ background-color: #E6F5EB;
22
+ border-radius: 19px;
23
+ text-align: center;
24
+ font-weight: 600;
25
+ font-size: 13px;
26
+ color: #039938;
27
+
28
+ &_2 {
29
+ color: #fff;
30
+ background-color: #039938;
31
+ }
32
+
33
+ &_group {
34
+ display: grid;
35
+ grid-template-columns: 1fr;
36
+ grid-column-gap: 10px;
37
+ margin-top: 20px;
38
+ }
39
+ }
40
+ </style>