140140 <!-- 回答 -->
141141 <AnswerContent
142142 :application =" applicationDetails "
143- :loading =" loading "
143+ :loading =" currentChatGenerating "
144144 v-model :chat-record =" chatList [index ]"
145145 :type =" type "
146146 :send-message =" sendMessage "
202202 :validate =" validate "
203203 :chat-management =" ChatManagement "
204204 v-model :chat-id =" chartOpenId "
205- v-model :loading =" loading "
205+ :loading =" currentChatGenerating "
206206 v-model :show-user-input =" showUserInput "
207207 v-else-if =" type !== ' log' && type !== ' share' "
208208 >
@@ -310,6 +310,7 @@ const props = withDefaults(
310310)
311311const emit = defineEmits ([
312312 ' refresh' ,
313+ ' openChat' ,
313314 ' scroll' ,
314315 ' openExecutionDetail' ,
315316 ' openParagraph' ,
@@ -346,6 +347,12 @@ const loading = ref(false)
346347const inputValue = ref <string >(' ' )
347348const chartOpenId = ref <string >(' ' )
348349const chatList = ref <any []>([])
350+ // 当前正在查看的会话是否有在途消息(还在吐字)。
351+ // 用它驱动"停止回答"按钮、输入禁用、发送拦截, 替代组件级全局 loading,
352+ // 这样后台其它会话的流式不会把当前会话的输入栏按住。
353+ const currentChatGenerating = computed (() =>
354+ chatList .value .some ((c ) => c && c .write_ed === false && c .is_stop !== true ),
355+ )
349356const form_data = ref <any >({})
350357const api_form_data = ref <any >({})
351358const userFormRef = ref <InstanceType <typeof UserForm >>()
@@ -531,7 +538,7 @@ function sendMessage(val: string, other_params_data?: any, chat?: chatType): Pro
531538
532539 showUserInput .value = false
533540
534- if (! loading .value && props .applicationDetails ?.name ) {
541+ if (! currentChatGenerating .value && props .applicationDetails ?.name ) {
535542 handleDebounceClick (val , other_params_data , chat )
536543 return true
537544 }
@@ -551,7 +558,7 @@ function sendMessage(val: string, other_params_data?: any, chat?: chatType): Pro
551558 }
552559 } else {
553560 showUserInput .value = false
554- if (! loading .value && props .applicationDetails ?.name ) {
561+ if (! currentChatGenerating .value && props .applicationDetails ?.name ) {
555562 handleDebounceClick (val , other_params_data , chat )
556563 return Promise .resolve (true )
557564 }
@@ -656,6 +663,16 @@ const errorWrite = (chat: any, message?: string) => {
656663 ChatManagement .close (chat .id )
657664}
658665
666+ // 停止"当前正在查看的会话"里在途的消息。
667+ // 只动 chatList(当前会话), 不会波及后台其它正在跑的会话。
668+ const stopGenerating = () => {
669+ chatList .value .forEach ((c ) => {
670+ if (c && c .write_ed === false && c .is_stop !== true ) {
671+ ChatManagement .stop (c .id )
672+ }
673+ })
674+ }
675+
659676// 保存上传文件列表
660677
661678function chatMessage(chat ? : any , problem ? : string , re_chat ? : boolean , other_params_data ? : any ) {
@@ -731,6 +748,11 @@ function chatMessage(chat?: any, problem?: string, re_chat?: boolean, other_para
731748 } else if (response .status === 461 ) {
732749 return Promise .reject (t (' aiChat.tip.errorLimitMessage' ))
733750 } else {
751+ // 新建会话: 此刻后端已执行 set_chat 建好 Chat 行(在产出流之前),
752+ // 通知父级把新会话加入历史列表, 这样长回答流式期间切走也能切回来继续看
753+ if (props .chatId === ' new' ) {
754+ emit (' openChat' , chartOpenId .value )
755+ }
734756 nextTick (() => {
735757 // 将滚动条滚动到最下面
736758 scrollDiv .value .setScrollTop (getMaxHeight ())
@@ -907,11 +929,13 @@ onMounted(() => {
907929 checkAll .value = multipleSelectionChat .value .length === chatList .value .length
908930 emit (' update:selection' , true )
909931 })
932+ bus .on (' chat:stop' , stopGenerating )
910933})
911934
912935onBeforeUnmount (() => {
913936 window .sendMessage = null
914937 window .chatUserProfile = null
938+ bus .off (' chat:stop' , stopGenerating )
915939})
916940
917941function setScrollBottom() {
0 commit comments