3434 <template v-if =" message .role === ' assistant' " >
3535 <ChatAnswer :message =" message" >
3636 <template #footer >
37- <el-button text type =" primary" @click =" clickAnalysis(message.record?.id)" >{{
38- t('chat.data_analysis')
39- }}</el-button >
40- {{ message.record?.analysis }}
37+ <div style =" padding : 0 22px ; display : flex ; justify-content : flex-end " >
38+ <el-button text type =" primary" @click =" clickAnalysis(message.record?.id)" >
39+ {{ t('chat.data_analysis') }}
40+ </el-button >
41+ <el-button text type =" primary" @click =" clickPredict(message.record?.id)" >
42+ {{ t('chat.data_predict') }}
43+ </el-button >
44+ </div >
45+ <div class =" analysis-container" >
46+ <MdComponent
47+ v-if =" message.record?.analysis || isAnalysisTyping"
48+ :message =" message.record?.analysis"
49+ />
50+ </div >
4151 </template >
4252 </ChatAnswer >
4353 </template >
@@ -90,6 +100,7 @@ import { Chat, chatApi, ChatInfo, type ChatMessage, ChatRecord, questionApi } fr
90100import ChatList from ' ./ChatList.vue'
91101import ChatRow from ' ./ChatRow.vue'
92102import ChatAnswer from ' ./ChatAnswer.vue'
103+ import MdComponent from ' ./component/MdComponent.vue'
93104import { useI18n } from ' vue-i18n'
94105import { find } from ' lodash-es'
95106
@@ -115,6 +126,7 @@ const currentChatId = ref<number | undefined>()
115126const currentChat = ref <ChatInfo >(new ChatInfo ())
116127const isTyping = ref <boolean >(false )
117128const isAnalysisTyping = ref <boolean >(false )
129+ const isPredictTyping = ref <boolean >(false )
118130
119131const computedMessages = computed <Array <ChatMessage >>(() => {
120132 const welcome: ChatMessage = {
@@ -306,6 +318,16 @@ const sendMessage = async () => {
306318 throw err
307319 }
308320
321+ if (data .code && data .code !== 200 ) {
322+ ElMessage ({
323+ message: data .msg ,
324+ type: ' error' ,
325+ showClose: true ,
326+ })
327+ isTyping .value = false
328+ return
329+ }
330+
309331 switch (data .type ) {
310332 case ' id' :
311333 currentChat .value .records [currentChat .value .records .length - 1 ].id = data .id
@@ -412,14 +434,22 @@ async function clickAnalysis(id?: number) {
412434 throw err
413435 }
414436
437+ if (data .code && data .code !== 200 ) {
438+ ElMessage ({
439+ message: data .msg ,
440+ type: ' error' ,
441+ showClose: true ,
442+ })
443+ isAnalysisTyping .value = false
444+ return
445+ }
446+
415447 switch (data .type ) {
416448 case ' info' :
417449 console .log (data .msg )
418450 break
419451 case ' error' :
420- currentRecord .error = data .content
421- isAnalysisTyping .value = false
422- break
452+ throw Error (data .content )
423453 case ' analysis-result' :
424454 analysis_answer += data .content
425455 currentChat .value .records [_index ].analysis = analysis_answer
@@ -432,15 +462,107 @@ async function clickAnalysis(id?: number) {
432462 }
433463 }
434464 } catch (error ) {
435- if (! currentRecord .error ) {
436- currentRecord .error = ' '
465+ console .error (' Error:' , error )
466+ ElMessage ({
467+ message: error + ' ' ,
468+ type: ' error' ,
469+ showClose: true ,
470+ })
471+ isAnalysisTyping .value = false
472+ }
473+ }
474+
475+ async function clickPredict(id ? : number ) {
476+ let _index = - 1
477+ const currentRecord = find (currentChat .value .records , (value , index ) => {
478+ if (id === value .id ) {
479+ _index = index
480+ return true
437481 }
438- if (currentRecord .error .trim ().length !== 0 ) {
439- currentRecord .error = currentRecord .error + ' \n '
482+ return false
483+ })
484+ if (currentRecord == undefined ) {
485+ return
486+ }
487+ currentChat .value .records [_index ].predict = ' '
488+
489+ try {
490+ const response = await chatApi .predict (id )
491+ const reader = response .body .getReader ()
492+ const decoder = new TextDecoder ()
493+
494+ let predict_answer = ' '
495+
496+ while (true ) {
497+ const { done, value } = await reader .read ()
498+ if (done ) {
499+ isPredictTyping .value = false
500+ break
501+ }
502+
503+ const chunk = decoder .decode (value )
504+
505+ let _list = [chunk ]
506+
507+ const lines = chunk .trim ().split (' }\n\n {' )
508+ if (lines .length > 1 ) {
509+ _list = []
510+ for (let line of lines ) {
511+ if (! line .trim ().startsWith (' {' )) {
512+ line = ' {' + line .trim ()
513+ }
514+ if (! line .trim ().endsWith (' }' )) {
515+ line = line .trim () + ' }'
516+ }
517+ _list .push (line )
518+ }
519+ }
520+
521+ console .log (_list )
522+
523+ for (const str of _list ) {
524+ let data
525+ try {
526+ data = JSON .parse (str )
527+ } catch (err ) {
528+ console .error (' JSON string:' , str )
529+ throw err
530+ }
531+
532+ if (data .code && data .code !== 200 ) {
533+ ElMessage ({
534+ message: data .msg ,
535+ type: ' error' ,
536+ showClose: true ,
537+ })
538+ return
539+ }
540+
541+ switch (data .type ) {
542+ case ' info' :
543+ console .log (data .msg )
544+ break
545+ case ' error' :
546+ throw Error (data .content )
547+ case ' predict-result' :
548+ predict_answer += data .content
549+ currentChat .value .records [_index ].predict = predict_answer
550+ break
551+ case ' predict_finish' :
552+ isPredictTyping .value = false
553+ break
554+ }
555+ await nextTick ()
556+ }
440557 }
441- currentRecord . error = currentRecord . error + ' Error: ' + error
558+ } catch ( error ) {
442559 console .error (' Error:' , error )
443- isAnalysisTyping .value = false
560+ ElMessage ({
561+ message: error + ' ' ,
562+ type: ' error' ,
563+ showClose: true ,
564+ })
565+ isPredictTyping .value = false
444566 }
445567}
446568
@@ -522,4 +644,11 @@ const handleCtrlEnter = (e: KeyboardEvent) => {
522644 min-width : 0 ;
523645 }
524646}
647+
648+ .analysis-container {
649+ color : var (--ed-text-color-primary );
650+ font-size : 12px ;
651+ line-height : 1.7692307692 ;
652+ padding : 16px 22px ;
653+ }
525654 </style >
0 commit comments