ai-error-assistant-mobile 0.0.1

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 (34) hide show
  1. package/README.md +33 -0
  2. package/components/demo/api/index.js +123 -0
  3. package/components/demo/index.js +7 -0
  4. package/components/demo/plugins/cache.js +77 -0
  5. package/components/demo/src/chat-tools.vue +477 -0
  6. package/components/demo/src/chat.vue +618 -0
  7. package/components/demo/src/error-chat.vue +384 -0
  8. package/components/demo/src/main.vue +408 -0
  9. package/components/demo/static/bg-img.png +0 -0
  10. package/components/demo/static/cai-active.png +0 -0
  11. package/components/demo/static/cai.png +0 -0
  12. package/components/demo/static/correct.png +0 -0
  13. package/components/demo/static/delete.png +0 -0
  14. package/components/demo/static/error.png +0 -0
  15. package/components/demo/static/logo.png +0 -0
  16. package/components/demo/static/robot.png +0 -0
  17. package/components/demo/static/send-icon.png +0 -0
  18. package/components/demo/static/zan-active.png +0 -0
  19. package/components/demo/static/zan.png +0 -0
  20. package/components/demo/utils/aes-utils.js +35 -0
  21. package/components/demo/utils/config.js +99 -0
  22. package/components/demo/utils/constants.js +15 -0
  23. package/components/demo/utils/request.js +72 -0
  24. package/components/index.js +16 -0
  25. package/dist/ai-error-assistant-mobile.common.js +14916 -0
  26. package/dist/ai-error-assistant-mobile.common.js.map +1 -0
  27. package/dist/ai-error-assistant-mobile.css +1 -0
  28. package/dist/ai-error-assistant-mobile.umd.js +14935 -0
  29. package/dist/ai-error-assistant-mobile.umd.js.map +1 -0
  30. package/dist/ai-error-assistant-mobile.umd.min.js +18 -0
  31. package/dist/ai-error-assistant-mobile.umd.min.js.map +1 -0
  32. package/dist/demo.html +1 -0
  33. package/dist/img/robot.7ad12cd4.png +0 -0
  34. package/package.json +47 -0
@@ -0,0 +1,618 @@
1
+ <template>
2
+ <div class="chat-contain" ref="chatContainer">
3
+ <error-chat :question-stem="analyExercise" :businessSource="businessSource" @on-init="errorChatInit"/>
4
+ <div v-for="(list, index) in messageData" :key="index"
5
+ :class="{'user-list': list.type === 'user'}"
6
+ class="message">
7
+ <div v-if="list.type === 'user' && avatarUrl" class="robot">
8
+ <img :src="avatarUrl" alt="" style="width: 48px; height: 48px; border-radius: 50%;">
9
+ </div>
10
+ <div v-if="list.type === 'user' && avatarUrl===''" class="robot user">user</div>
11
+ <div :class="{'user-info': list.type === 'user'}" class="robot-message">
12
+ <div v-html="list.message"></div>
13
+ <div v-if="list.type === 'robot' && list.links.length > 0 && showFile" class="link">
14
+ <div v-if="!list.allIdWithStart">
15
+ <div class="link-title">参考文件</div>
16
+ <div class="link-content">
17
+ <template v-for="item in list.links">
18
+ <template v-if="!item.title.startsWith(chatMajorId)">
19
+ <div class="links">
20
+ <span>{{ `《${item.title}》` }} 共
21
+ <span style="font-weight: bold">
22
+ {{ item.fileDTOS.length }}
23
+ </span>
24
+ 处引用
25
+ </span>
26
+ </div>
27
+ <div
28
+ v-for="(pdf, index) in item.fileDTOS"
29
+ class="link-part-container"
30
+ :key="index"
31
+ >
32
+ <span class="link-list-part">
33
+ {{ pdf.matchContent }}
34
+ </span>
35
+ <!-- <span-->
36
+ <!-- class="link-list-button"-->
37
+ <!-- @click="seeDetail(pdf, item.documentUrl)"-->
38
+ <!-- >-->
39
+ <!-- 点击查看-->
40
+ <!-- </span>-->
41
+ </div>
42
+ </template>
43
+ </template>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <div v-if="list.type === 'robot' && list.connectUrl.length > 0" class="link">
48
+ <div class="link-title">相关链接</div>
49
+ <div class="link-content">
50
+ <template v-for="item in list.connectUrl">
51
+ <div class="links">
52
+ <a :href="item.iaUrl" target="_blank">
53
+ <span>{{ item.iaUrlName }}</span>
54
+ </a>
55
+ </div>
56
+ </template>
57
+ </div>
58
+ </div>
59
+ <div v-if="list.type === 'robot' && finish && list.followUps && list.followUps.length > 0">
60
+ <div class="link-title">智能追问</div>
61
+ <div class="link-content">
62
+ <div class="hot-list"
63
+ v-for="(list, index) in list.followUps"
64
+ :key="index"
65
+ @click="selectModule(list)">
66
+ {{ list }}
67
+ <i class="el-icon-arrow-right go-icon"></i>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ <chat-tools v-if="list.type === 'robot'"
72
+ :chatId="chatId"
73
+ :detail-data="list"
74
+ :sending="list.sending"
75
+ :is-last="index === messageData.length - 1"
76
+ @on-reanswer="(list) => reanswer(list, index)"
77
+ @on-stop-chat="onStopChat"/>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </template>
82
+ <script>
83
+ import {errorList} from '../utils/config';
84
+ import ChatTools from './chat-tools.vue';
85
+ import ErrorChat from './error-chat.vue';
86
+ import {marked} from 'marked';
87
+ import {chartClear, sendMessageEventSource, getAutoQuestioning, pdfUrlBase} from "../api";
88
+
89
+ const controller = new AbortController();
90
+ const signal = controller.signal;
91
+
92
+ export default {
93
+ name: 'Chat',
94
+ components: {
95
+ ErrorChat,
96
+ ChatTools
97
+ },
98
+ props: {
99
+ analyExercise: {},
100
+ keyWord: {
101
+ type: String,
102
+ default: '',
103
+ },
104
+ businessSource: {
105
+ type: String,
106
+ default: ''
107
+ },
108
+ resId: {
109
+ type: String,
110
+ default: '',
111
+ },
112
+ xtId: {
113
+ type: String,
114
+ default: '',
115
+ },
116
+ showMoreQA: {
117
+ type: Boolean,
118
+ default: false,
119
+ },
120
+ showFile: {
121
+ type: Boolean,
122
+ default: false,
123
+ },
124
+ avatarUrl: {
125
+ type: String,
126
+ default: '',
127
+ },
128
+ },
129
+ data() {
130
+ return {
131
+ popover: false,
132
+ input: '',
133
+ errors: [],
134
+ errorList: errorList,
135
+ cacheKeyWord: '', // 由于外部需要快速清掉 keyword 但是存在重新发送请求的情况,因此需要一个混存记录
136
+ messageData: [],
137
+ chatId: '', // 对话id
138
+ chatMajorId: '',
139
+ finish: false,
140
+ }
141
+ },
142
+ computed: {
143
+ canSubmit() {
144
+ return this.errors.length === 0 && this.input === "";
145
+ },
146
+ },
147
+ watch: {
148
+ keyWord: {
149
+ handler() {
150
+ if (this.keyWord) {
151
+ this.cacheKeyWord = this.keyWord;
152
+ this.postMessage();
153
+ }
154
+ },
155
+ immediate: true
156
+ }
157
+ },
158
+ methods: {
159
+ cancelPopover() {
160
+ this.popover = false;
161
+ },
162
+ openPopover() {
163
+ this.popover = true;
164
+ },
165
+ scrollToBottom() {
166
+ this.$refs.chatContainer.scrollTop = this.$refs.chatContainer.scrollHeight;
167
+ },
168
+ async postMessage(list, commonKey, parentMsgId) {
169
+ let reanswerParams = {};
170
+ this.finish = false;
171
+ if (list) {
172
+ list.sending = true;
173
+ reanswerParams = {
174
+ reStatus: 1,
175
+ parentMsgId: list.parentMsgId,
176
+ msgId: list.msgId,
177
+ content: this.messageData[list.index - 1].message,
178
+ }
179
+ this.messageData[list.index].message = '';
180
+ this.messageData[list.index].cacheMessage = '';
181
+ this.makeAutoMessage();
182
+ }
183
+ const params = {
184
+ messageList: [
185
+ {
186
+ content: this.keyWord || this.cacheKeyWord,
187
+ resId: this.resId,
188
+ chatId: this.chatId || undefined,
189
+ commonKey: commonKey || false,
190
+ parentMsgId: parentMsgId || undefined,
191
+ xtId: this.analyExercise.busId,
192
+ ...reanswerParams,
193
+ }
194
+ ]
195
+ };
196
+ // list 存在说明是重新生成
197
+ if (!list && !commonKey) {
198
+ const userWord = this.keyWord || this.cacheKeyWord;
199
+ this.messageData.push({type: 'user', message: userWord.replace(/\n/g, '<br>')});
200
+ setTimeout(() => {
201
+ this.messageData.push(
202
+ {
203
+ type: 'robot',
204
+ message: '',
205
+ cacheMessage: '',
206
+ zan: false,
207
+ cai: false,
208
+ stop: false,
209
+ finish: false,
210
+ sending: true,
211
+ links: [],
212
+ connectUrl: [],
213
+ reAnswerCount: 0
214
+ }
215
+ )
216
+ this.makeAutoMessage();
217
+ });
218
+ }
219
+ await sendMessageEventSource(params, signal, res => {
220
+ this.makeMessageLine(res, list);
221
+ });
222
+ },
223
+ makeAutoMessage() {
224
+ const cacheMessage = [];
225
+ for (let i = 0; i < this.messageData.length; i++) {
226
+ const current = this.messageData[i];
227
+ cacheMessage.push({
228
+ role: current.type === 'robot' ? 'assistant' : 'user',
229
+ content: current.message || '正在思考中。',
230
+ });
231
+ }
232
+ if (this.showMoreQA) {
233
+ this.makeAutoQuestioning(cacheMessage);
234
+ }
235
+ },
236
+ makeMessageLine(res, list) {
237
+ const {content, status, chatId, msgId, parentMsgId, reference, commonKey, connectUrl} = JSON.parse(res.data);
238
+ let index = list ? list.index : this.messageData.length - 1;
239
+ const currentList = this.messageData[index];
240
+ let allIdWithStart = true;
241
+ // 结束标识
242
+ if (status === 2 || status === 1) {
243
+ if (commonKey) {
244
+ currentList.sending = true;
245
+ this.postMessage(list, commonKey, parentMsgId);
246
+ return;
247
+ }
248
+ currentList.finish = true;
249
+ if (reference) {
250
+ currentList.links = JSON.parse(reference);
251
+ currentList.links.map((item) => {
252
+ if (!item.title.startsWith(this.chatMajorId)) {
253
+ allIdWithStart = false;
254
+ }
255
+ });
256
+ }
257
+ if (connectUrl) {
258
+ currentList.connectUrl = JSON.parse(connectUrl);
259
+ }
260
+ currentList.allIdWithStart = allIdWithStart;
261
+ this.cacheKeyWord = '';
262
+ this.finish = true;
263
+ this.$emit('on-message-finish', chatId);
264
+ return;
265
+ }
266
+ currentList.cacheMessage += content;
267
+ currentList.cacheMessage = currentList.cacheMessage.replace('```json{', '```json\n{');
268
+ currentList.message = marked.parse(currentList.cacheMessage);
269
+ currentList.msgId = msgId;
270
+ currentList.parentMsgId = parentMsgId;
271
+ currentList.chatId = chatId;
272
+
273
+ setTimeout(() => {
274
+ if (!list) this.scrollToBottom();
275
+ }, 100);
276
+ // 防止出现调用基础模型前导致停止回答id错误
277
+ setTimeout(() => currentList.sending = false, 500);
278
+ },
279
+ async makeAutoQuestioning(messages) {
280
+ // 首次不触发
281
+ if (messages.length <= 2) return;
282
+ const autoRes = await getAutoQuestioning(this.chatMajorId, messages);
283
+ const {
284
+ message: {
285
+ content: {followUps},
286
+ },
287
+ } = autoRes;
288
+ this.messageData[this.messageData.length - 1].followUps = [];
289
+ this.messageData[this.messageData.length - 1].followUps =
290
+ followUps.length > 3 ? followUps.splice(0, 3) : followUps;
291
+ },
292
+ onStopChat(list) {
293
+ this.$emit('on-message-finish', list.chatId)
294
+ },
295
+ selectModule(message) {
296
+ this.cacheKeyWord = message;
297
+ this.postMessage();
298
+ },
299
+ async clearChat() {
300
+ if (this.messageData.length < 1) {
301
+ this.$message.warning('当前对话为最新对话');
302
+ return;
303
+ }
304
+ await chartClear(this.chatId);
305
+ this.messageData = []
306
+ this.$message.success('对话清除成功!');
307
+ },
308
+ reanswer(list, index) {
309
+ list.index = index;
310
+ list.stop = false;
311
+ list.finish = false;
312
+ list.links = [];
313
+ list.connectUrl = [];
314
+ this.postMessage(list);
315
+ this.$emit('on-reanser');
316
+ },
317
+ errorChatInit(list, chatId) {
318
+ if (list && list[0].contents) {
319
+ const {chatMajorId} = list[0];
320
+ this.chatMajorId = chatMajorId && chatMajorId.toString();
321
+ const cacheArray = [];
322
+ list[0].contents.reverse().map((list) => {
323
+ let allIdWithStart = true;
324
+ if (this.chatMajorId && list.references) {
325
+ list.references.map((item) => {
326
+ if (!item.title.startsWith(this.chatMajorId)) {
327
+ allIdWithStart = false;
328
+ }
329
+ });
330
+ }
331
+ const obj = {
332
+ type: list.role === 'assistant' ? 'robot' : 'user',
333
+ message: list.role === 'assistant' ? marked.parse(list.content || '') : list.content.replace(/\n/g, '<br>'),
334
+ zan: list.type === 1,
335
+ cai: list.type === 2,
336
+ stop: list.status === 1,
337
+ finish: true,
338
+ links: list.references || [],
339
+ connectUrl: list.connectUrls || [],
340
+ reAnswerCount: 0,
341
+ msgId: list.contentId,
342
+ parentMsgId: list.parentMsgId,
343
+ allIdWithStart
344
+ };
345
+ cacheArray.push(obj);
346
+ })
347
+ this.messageData = cacheArray;
348
+ this.chatId = chatId;
349
+ } else {
350
+ this.messageData = [];
351
+ }
352
+ },
353
+ seeDetail(pdfInfo, url) {
354
+ console.log(1234);
355
+ const {pageIndex} = pdfInfo;
356
+ const baseUrl = `${pdfUrlBase}/#/pdf-view?documentUrl=${encodeURIComponent(url)}&pageIndex=${pageIndex}`;
357
+ window.open(baseUrl, '_blank');
358
+ },
359
+ },
360
+ }
361
+ </script>
362
+ <style lang="scss" scoped>
363
+ .chat-contain {
364
+ height: 100%;
365
+ overflow-y: auto;
366
+ -webkit-overflow-scrolling: touch;
367
+ padding: 0.75rem;
368
+ box-sizing: border-box;
369
+ scroll-behavior: smooth;
370
+ touch-action: manipulation;
371
+ -webkit-touch-callout: none;
372
+ -webkit-user-select: none;
373
+ user-select: none;
374
+
375
+ .message-loading {
376
+ display: flex;
377
+ justify-content: center;
378
+ align-items: center;
379
+ padding: 0.5rem 0;
380
+ }
381
+ }
382
+
383
+ .message {
384
+ display: flex;
385
+ gap: 0.75rem;
386
+ max-width: 100%;
387
+ margin-bottom: 1rem;
388
+ margin-left: 0;
389
+ margin-right: auto;
390
+ position: relative;
391
+ padding: 0.625rem;
392
+
393
+ &.user-list {
394
+ flex-direction: row-reverse;
395
+ margin-left: auto;
396
+ margin-right: 0;
397
+ margin-top: 1rem;
398
+ padding: 0.75rem;
399
+
400
+ .robot-message {
401
+ background: linear-gradient(90deg, rgb(130, 136, 220) 0%, rgb(48, 90, 220) 100%);
402
+ color: white;
403
+ border-radius: 1rem 0.25rem 1rem 1rem;
404
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
405
+ max-width: 90%;
406
+ }
407
+ }
408
+
409
+ &:not(.user-list) {
410
+ .robot-message {
411
+ background: white;
412
+ color: #333;
413
+ border-radius: 0.25rem 1rem 1rem 1rem;
414
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
415
+ min-width: 120px;
416
+ max-width: 85%;
417
+ padding: 0.75rem;
418
+ }
419
+ }
420
+ }
421
+
422
+ .robot {
423
+ width: 2.5rem;
424
+ height: 2.5rem;
425
+ margin: 0;
426
+ flex-shrink: 0;
427
+
428
+ &.user {
429
+ background: linear-gradient(90deg, rgb(0, 144, 240) 0%, rgb(144, 48, 240) 100%);
430
+ border-radius: 50%;
431
+ display: flex;
432
+ align-items: center;
433
+ justify-content: center;
434
+ font-size: 0.875rem;
435
+ color: #fff;
436
+ box-shadow: 2px 2px 4px rgba(0, 3, 6, 0.16);
437
+ }
438
+
439
+ img {
440
+ width: 100%;
441
+ height: 100%;
442
+ object-fit: cover;
443
+ border-radius: 50%;
444
+ }
445
+
446
+ .robot-image-div {
447
+ width: 100%;
448
+ height: 100%;
449
+ background: url('../static/robot.png') no-repeat center center;
450
+ background-size: cover;
451
+ border-radius: 50%;
452
+ }
453
+ }
454
+
455
+ .robot-message {
456
+ padding: 0.75rem;
457
+ box-sizing: border-box;
458
+ font-size: 0.9375rem;
459
+ line-height: 1.5;
460
+ overflow-wrap: break-word;
461
+ word-wrap: break-word;
462
+ word-break: break-word;
463
+ white-space: pre-wrap;
464
+ flex-grow: 0;
465
+ flex-shrink: 1;
466
+
467
+ &.user-info {
468
+ background: linear-gradient(90deg, rgb(130, 136, 220) 0%, rgb(48, 90, 220) 100%);
469
+ color: #fff;
470
+ border-radius: 1rem 0.25rem 1rem 1rem;
471
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
472
+ }
473
+
474
+ :deep(p) {
475
+ margin: 0.5rem 0;
476
+ line-height: 1.6;
477
+ font-size: 0.9375rem;
478
+ }
479
+
480
+ :deep(pre) {
481
+ background: #f5f5f5;
482
+ padding: 0.75rem;
483
+ border-radius: 0.25rem;
484
+ overflow-x: auto;
485
+ margin: 0.5rem 0;
486
+ font-size: 0.875rem;
487
+ }
488
+
489
+ :deep(code) {
490
+ font-family: monospace;
491
+ background: #f5f5f5;
492
+ padding: 0.125rem 0.25rem;
493
+ border-radius: 0.25rem;
494
+ font-size: 0.875rem;
495
+ }
496
+
497
+ :deep(a) {
498
+ color: #6050f0;
499
+ text-decoration: none;
500
+ font-size: 0.9375rem;
501
+
502
+ &:hover {
503
+ text-decoration: underline;
504
+ }
505
+ }
506
+
507
+ .link {
508
+ margin-top: 0.75rem;
509
+ font-size: 0.9375rem;
510
+
511
+ .link-title {
512
+ font-weight: 600;
513
+ margin-bottom: 0.5rem;
514
+ color: #333;
515
+ }
516
+
517
+ .link-content {
518
+ .links {
519
+ margin-bottom: 0.5rem;
520
+ font-size: 0.875rem;
521
+ }
522
+
523
+ .link-part-container {
524
+ display: flex;
525
+ justify-content: space-between;
526
+ align-items: center;
527
+ margin-bottom: 0.5rem;
528
+ font-size: 0.875rem;
529
+
530
+ .link-list-part {
531
+ flex: 1;
532
+ margin-right: 0.5rem;
533
+ }
534
+
535
+ .link-list-button {
536
+ color: #6050f0;
537
+ cursor: pointer;
538
+ white-space: nowrap;
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+ .hot-list {
545
+ display: flex;
546
+ align-items: center;
547
+ justify-content: space-between;
548
+ padding: 0.5rem;
549
+ margin-bottom: 0.5rem;
550
+ background: #f5f5f5;
551
+ border-radius: 0.25rem;
552
+ cursor: pointer;
553
+ font-size: 0.875rem;
554
+
555
+ .go-icon {
556
+ color: #999;
557
+ }
558
+ }
559
+ }
560
+
561
+ @media screen and (max-width: 320px) {
562
+ .chat-contain {
563
+ padding: 0.5rem;
564
+ }
565
+
566
+ .message {
567
+ gap: 0.5rem;
568
+ padding: 0.5rem;
569
+
570
+ &.user-list {
571
+ padding: 0.5rem;
572
+ }
573
+ }
574
+
575
+ .robot {
576
+ width: 2rem;
577
+ height: 2rem;
578
+ }
579
+
580
+ .robot-message {
581
+ padding: 0.5rem;
582
+ font-size: 0.875rem;
583
+
584
+ :deep(p) {
585
+ font-size: 0.875rem;
586
+ }
587
+ }
588
+ }
589
+
590
+ @media screen and (min-width: 768px) {
591
+ .chat-contain {
592
+ padding: 1rem;
593
+ }
594
+
595
+ .message {
596
+ gap: 1rem;
597
+ padding: 0.75rem;
598
+
599
+ &.user-list {
600
+ padding: 1rem;
601
+ }
602
+ }
603
+
604
+ .robot {
605
+ width: 3rem;
606
+ height: 3rem;
607
+ }
608
+
609
+ .robot-message {
610
+ padding: 1rem;
611
+ font-size: 1rem;
612
+
613
+ :deep(p) {
614
+ font-size: 1rem;
615
+ }
616
+ }
617
+ }
618
+ </style>