工作流动画效果

This commit is contained in:
rjb
2026-01-19 17:52:29 +08:00
parent 6674060f2f
commit e4aa6cdb79
12 changed files with 2835 additions and 102 deletions

View File

@@ -143,7 +143,7 @@
</template>
<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import { ref, computed, watch, nextTick, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import {
UserFilled,
@@ -170,10 +170,15 @@ const props = defineProps<{
nodeTestResult?: any
}>()
const emit = defineEmits<{
'execution-status': [status: any]
}>()
const messages = ref<Message[]>([])
const inputMessage = ref('')
const loading = ref(false)
const messagesContainer = ref<HTMLElement>()
let pollingInterval: any = null
// 发送消息
const handleSendMessage = async () => {
@@ -208,8 +213,16 @@ const handleSendMessage = async () => {
// 轮询执行状态
const checkStatus = async () => {
try {
const statusResponse = await api.get(`/api/v1/executions/${execution.id}`)
const exec = statusResponse.data
// 获取详细执行状态(包含节点执行信息)
const statusResponse = await api.get(`/api/v1/executions/${execution.id}/status`)
const status = statusResponse.data
// 将执行状态传递给父组件,用于显示工作流动画
emit('execution-status', status)
// 获取执行详情(用于提取输出结果)
const execResponse = await api.get(`/api/v1/executions/${execution.id}`)
const exec = execResponse.data
if (exec.status === 'completed') {
// 提取Agent回复
@@ -244,6 +257,16 @@ const handleSendMessage = async () => {
loading.value = false
scrollToBottom()
// 延迟清除执行状态,让用户能看到最终的执行结果
setTimeout(() => {
emit('execution-status', null)
}, 3000) // 3秒后清除
if (pollingInterval) {
clearInterval(pollingInterval)
pollingInterval = null
}
} else if (exec.status === 'failed') {
messages.value.push({
role: 'agent',
@@ -252,9 +275,19 @@ const handleSendMessage = async () => {
})
loading.value = false
scrollToBottom()
// 延迟清除执行状态,让用户能看到失败节点的状态
setTimeout(() => {
emit('execution-status', null)
}, 5000) // 5秒后清除
if (pollingInterval) {
clearInterval(pollingInterval)
pollingInterval = null
}
} else {
// 继续轮询
setTimeout(checkStatus, 1000)
// 继续轮询pending 或 running 状态)
// 不需要做任何操作,等待下次轮询
}
} catch (error: any) {
messages.value.push({
@@ -264,11 +297,21 @@ const handleSendMessage = async () => {
})
loading.value = false
scrollToBottom()
// 清除执行状态
emit('execution-status', null)
if (pollingInterval) {
clearInterval(pollingInterval)
pollingInterval = null
}
}
}
// 开始轮询
setTimeout(checkStatus, 1000)
// 使用 setInterval 进行轮询每500毫秒检查一次更频繁能捕获快速执行的节点
pollingInterval = setInterval(checkStatus, 500)
// 立即执行一次
checkStatus()
} catch (error: any) {
console.error('发送消息失败:', error)
@@ -292,6 +335,13 @@ const handlePresetQuestion = (question: string) => {
// 清空对话
const handleClearChat = () => {
messages.value = []
// 清除执行状态
emit('execution-status', null)
// 清除轮询
if (pollingInterval) {
clearInterval(pollingInterval)
pollingInterval = null
}
}
// 滚动到底部
@@ -341,6 +391,16 @@ const handleCloseNodeTest = () => {
watch(messages, () => {
scrollToBottom()
}, { deep: true })
// 组件卸载时清理轮询
onUnmounted(() => {
if (pollingInterval) {
clearInterval(pollingInterval)
pollingInterval = null
}
// 清除执行状态
emit('execution-status', null)
})
</script>
<style scoped>