mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-23 18:38:12 +00:00
fix(ai-assistant): 优化流式响应期间的 loading 状态显示
- 修改 loading 显示条件,streaming 状态时继续显示 loading icon - SSEClient 添加可选的 onFailed 回调,处理连接失败情况 - 修复 done 事件处理,确保状态正确转为 completed - 解决工具调用期间 loading 动画过早消失的问题
This commit is contained in:
parent
c4f0fb5a3d
commit
8eaba6f364
@ -58,7 +58,7 @@
|
|||||||
<template v-if="response.status === 'error'">
|
<template v-if="response.status === 'error'">
|
||||||
<span class="ai-assistant-output-error">{{ $L('发送失败') }}</span>
|
<span class="ai-assistant-output-error">{{ $L('发送失败') }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="response.rawOutput">
|
<template v-else-if="response.rawOutput && response.status !== 'streaming'">
|
||||||
<Button
|
<Button
|
||||||
v-if="showApplyButton"
|
v-if="showApplyButton"
|
||||||
type="primary"
|
type="primary"
|
||||||
@ -69,9 +69,9 @@
|
|||||||
{{ applyButtonText || $L('应用此内容') }}
|
{{ applyButtonText || $L('应用此内容') }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="!response.rawOutput || response.status === 'streaming'">
|
||||||
<Icon type="ios-loading" class="ai-assistant-output-icon icon-loading"/>
|
<Icon type="ios-loading" class="ai-assistant-output-icon icon-loading"/>
|
||||||
<span v-if="loadingText" class="ai-assistant-output-status">{{ loadingText }}</span>
|
<span v-if="loadingText && !response.rawOutput" class="ai-assistant-output-status">{{ loadingText }}</span>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="ai-assistant-output-meta">
|
<div class="ai-assistant-output-meta">
|
||||||
@ -795,7 +795,7 @@ export default {
|
|||||||
const donePayload = this.parseStreamPayload(event);
|
const donePayload = this.parseStreamPayload(event);
|
||||||
if (donePayload && donePayload.error) {
|
if (donePayload && donePayload.error) {
|
||||||
this.markResponseError(responseEntry, donePayload.error);
|
this.markResponseError(responseEntry, donePayload.error);
|
||||||
} else if (responseEntry && responseEntry.status !== 'error' && responseEntry.rawOutput) {
|
} else if (responseEntry && responseEntry.status !== 'error') {
|
||||||
responseEntry.status = 'completed';
|
responseEntry.status = 'completed';
|
||||||
}
|
}
|
||||||
this.releaseSSEClient(sse);
|
this.releaseSSEClient(sse);
|
||||||
@ -803,6 +803,13 @@ export default {
|
|||||||
this.saveCurrentSession();
|
this.saveCurrentSession();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}, () => {
|
||||||
|
// SSE 连接失败(重试次数用完)时的回调
|
||||||
|
if (responseEntry && responseEntry.status === 'streaming') {
|
||||||
|
responseEntry.status = 'completed';
|
||||||
|
}
|
||||||
|
this.releaseSSEClient(sse);
|
||||||
|
this.saveCurrentSession();
|
||||||
});
|
});
|
||||||
return sse;
|
return sse;
|
||||||
},
|
},
|
||||||
|
|||||||
16
resources/assets/js/utils/index.js
vendored
16
resources/assets/js/utils/index.js
vendored
@ -118,42 +118,44 @@ export class SSEClient {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_onError(type, handler) {
|
_onError(type, handler, onFailed) {
|
||||||
return () => {
|
return () => {
|
||||||
if (window.systemInfo.debug === "yes") {
|
if (window.systemInfo.debug === "yes") {
|
||||||
console.log("SSE retry: " + this.url);
|
console.log("SSE retry: " + this.url);
|
||||||
}
|
}
|
||||||
if (this.es) {
|
if (this.es) {
|
||||||
this._removeAllEvent(type, handler);
|
this._removeAllEvent(type, handler, onFailed);
|
||||||
this.unsunscribe();
|
this.unsunscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.retry > 0) {
|
if (this.retry > 0) {
|
||||||
this.retry--;
|
this.retry--;
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
this.subscribe(type, handler);
|
this.subscribe(type, handler, onFailed);
|
||||||
}, this.options.interval);
|
}, this.options.interval);
|
||||||
|
} else if (typeof onFailed === 'function') {
|
||||||
|
onFailed();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeAllEvent(type, handler) {
|
_removeAllEvent(type, handler, onFailed) {
|
||||||
type = $A.isArray(type) ? type : [type]
|
type = $A.isArray(type) ? type : [type]
|
||||||
this.es.removeEventListener("open", this._onOpen);
|
this.es.removeEventListener("open", this._onOpen);
|
||||||
type.some(item => {
|
type.some(item => {
|
||||||
this.es.removeEventListener(item, this._onMessage(item, handler));
|
this.es.removeEventListener(item, this._onMessage(item, handler));
|
||||||
})
|
})
|
||||||
this.es.removeEventListener("error", this._onError(type, handler));
|
this.es.removeEventListener("error", this._onError(type, handler, onFailed));
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(type, handler) {
|
subscribe(type, handler, onFailed) {
|
||||||
type = $A.isArray(type) ? type : [type]
|
type = $A.isArray(type) ? type : [type]
|
||||||
this.es = new EventSource(this.url);
|
this.es = new EventSource(this.url);
|
||||||
this.es.addEventListener("open", this._onOpen);
|
this.es.addEventListener("open", this._onOpen);
|
||||||
type.some(item => {
|
type.some(item => {
|
||||||
this.es.addEventListener(item, this._onMessage(item, handler));
|
this.es.addEventListener(item, this._onMessage(item, handler));
|
||||||
})
|
})
|
||||||
this.es.addEventListener("error", this._onError(type, handler));
|
this.es.addEventListener("error", this._onError(type, handler, onFailed));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsunscribe() {
|
unsunscribe() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user