|
@@ -1,15 +1,12 @@
|
|
|
<template>
|
|
|
<div class="steps-display-container">
|
|
|
<div v-if="parsedContent" class="steps-content">
|
|
|
- <button>删除</button>
|
|
|
-
|
|
|
<h2 class="steps-title">{{ parsedContent.title }}</h2>
|
|
|
<!-- <p class="steps-id">计划ID: {{ parsedContent.planId }}</p> -->
|
|
|
<el-steps
|
|
|
:active="activeStep"
|
|
|
finish-status="success"
|
|
|
class="custom-steps"
|
|
|
- :space="60"
|
|
|
direction="vertical"
|
|
|
>
|
|
|
<el-step
|
|
@@ -45,14 +42,20 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #description>
|
|
|
- <div :class="['step-description', { 'collapsed': collapsedSteps[index] }]">
|
|
|
+ <div :class="['step-description',{ 'collapsed': collapsedSteps[index] }]">
|
|
|
<div class="step-content">
|
|
|
- {{ step.stepRequirement }}
|
|
|
- <div>22312312</div>
|
|
|
- <div>22312312</div>
|
|
|
- <div>22312312</div>
|
|
|
- <div>22312312</div>
|
|
|
-
|
|
|
+ {{ step.description }}
|
|
|
+ <div v-if="response?.agentExecutionSequence[index]?.thinkActSteps" >
|
|
|
+ <div v-for="item,i in response.agentExecutionSequence[index]?.thinkActSteps" >
|
|
|
+ <div v-if="item?.toolParameters?.action !=='get_text'">
|
|
|
+ <div v-if="item?.toolName === 'browser_use' ">{{ item.actionResult?.output}}</div>
|
|
|
+ <div v-if="item?.toolName === 'terminate'" v-html="formatMessage(item.thinkOutput)"></div>
|
|
|
+ <div class="timestamp ">{{ moment(item?.actEndTime).format('MM-DD HH:mm:ss') }}</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -104,6 +107,9 @@
|
|
|
import { ref, computed, onMounted, watch, onBeforeUnmount } from 'vue'
|
|
|
import { ChatDotRound, Check, Loading, ArrowDown, ArrowUp } from '@element-plus/icons-vue'
|
|
|
import { deleteExecutor, executePlanByTemplateId, executorDetail } from '@/api/advance'
|
|
|
+import moment from 'moment'
|
|
|
+import { formatMessage } from '../utils/ai-service'
|
|
|
+
|
|
|
|
|
|
// 定义props
|
|
|
const props = defineProps({
|
|
@@ -130,25 +136,55 @@ const planId = ref('')
|
|
|
const currentStepIndex = ref()
|
|
|
const response = ref()
|
|
|
const handleExecute = async () => {
|
|
|
- const res = await executorDetail(planId)
|
|
|
+ const res = await executorDetail(planId.value)
|
|
|
response.value = res
|
|
|
- if (!res.completed) handleExecute()
|
|
|
- else deleteExecutor(planId)
|
|
|
+ response.value?.agentExecutionSequence.forEach(sequence => {
|
|
|
+ if (sequence.thinkActSteps) {
|
|
|
+ sequence.thinkActSteps.forEach(step => {
|
|
|
+ // 转换actionResult
|
|
|
+ if (step.actionResult && typeof step.actionResult === 'string') {
|
|
|
+ step.actionResult = JSON.parse(step.actionResult);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换toolParametersJSON
|
|
|
+ if (step.toolParameters && typeof step.toolParameters === 'string') {
|
|
|
+ step.toolParameters = JSON.parse(step.toolParameters);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.currentStepIndex) {
|
|
|
+ if (currentStepIndex.value !== res.currentStepIndex) {
|
|
|
+ collapsedSteps.value[currentStepIndex.value] = !collapsedSteps.value[currentStepIndex.value]
|
|
|
+ collapsedSteps.value[res.currentStepIndex] = false
|
|
|
+ activeStep.value++
|
|
|
+ }
|
|
|
+ currentStepIndex.value = res.currentStepIndex
|
|
|
+ }
|
|
|
+ if (!res.completed) setTimeout(() => {
|
|
|
+ handleExecute()
|
|
|
+ }, 2000);
|
|
|
+ else {
|
|
|
+ activeStep.value++
|
|
|
+ deleteExecutor(planId.value)
|
|
|
+ }
|
|
|
}
|
|
|
// 解析内容
|
|
|
const parsedContent = computed(() => {
|
|
|
try {
|
|
|
if (typeof props.content === 'string') {
|
|
|
const obj = JSON.parse(props.content)
|
|
|
- console.log(obj);
|
|
|
- obj.steps = obj.steps.map(_ => ({ ..._, stepRequirement: _.stepRequirement.split(' ')[1] }))
|
|
|
- planTemplateId.value = obj.planTemplateId
|
|
|
+ obj.steps = obj.steps.map(_ => ({ ..._, description: _.description.split(' ')[1] }))
|
|
|
+ planTemplateId.value = obj.planId
|
|
|
currentStepIndex.value = 0
|
|
|
- setTimeout(() => {
|
|
|
- executePlanByTemplateId({ planTemplateId: planTemplateId.value }).then(res => {
|
|
|
- planId.value = res.planId
|
|
|
- })
|
|
|
- }, 1000);
|
|
|
+ // setTimeout(() => {
|
|
|
+ // executePlanByTemplateId({ planTemplateId: planTemplateId.value }).then(res => {
|
|
|
+ // planId.value = res.planId
|
|
|
+ // setTimeout(() => {
|
|
|
+ // handleExecute()
|
|
|
+ // }, 2000);
|
|
|
+ // })
|
|
|
+ // }, 1000);
|
|
|
return obj
|
|
|
} else {
|
|
|
return props.content
|
|
@@ -169,118 +205,22 @@ watch(() => parsedContent.value, (newContent) => {
|
|
|
|
|
|
// 切换步骤折叠状态
|
|
|
const toggleCollapse = (index) => {
|
|
|
- collapsedSteps.value[index] = !collapsedSteps.value[index]
|
|
|
-}
|
|
|
-
|
|
|
-// 获取步骤类型
|
|
|
-const getStepType = (requirement) => {
|
|
|
- if (requirement.includes('[BROWSER_AGENT]')) {
|
|
|
- return 'BROWSER_AGENT'
|
|
|
- } else if (requirement.includes('[DEFAULT_AGENT]')) {
|
|
|
- return 'DEFAULT_AGENT'
|
|
|
- } else {
|
|
|
- return 'UNKNOWN'
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 开始进度条动画
|
|
|
-const startProgressAnimation = () => {
|
|
|
- // 重置进度
|
|
|
- stepProgress.value = 0
|
|
|
-
|
|
|
- // 清除之前的定时器
|
|
|
- if (progressTimer) {
|
|
|
- clearInterval(progressTimer)
|
|
|
- }
|
|
|
-
|
|
|
- // 创建新的定时器,模拟进度增长
|
|
|
- progressTimer = setInterval(() => {
|
|
|
- if (stepProgress.value < 100) {
|
|
|
- // 使用非线性增长,开始快,接近100%时变慢
|
|
|
- const increment = Math.max(1, 5 * Math.pow(1 - stepProgress.value / 100, 1.5))
|
|
|
- stepProgress.value = Math.min(100, stepProgress.value + increment)
|
|
|
- } else {
|
|
|
- clearInterval(progressTimer)
|
|
|
- }
|
|
|
- }, 200) // 每200毫秒更新一次进度,更加流畅
|
|
|
-}
|
|
|
-
|
|
|
-// 上一步
|
|
|
-const prevStep = () => {
|
|
|
- if (activeStep.value > 0) {
|
|
|
- // 折叠当前步骤,展开上一步骤
|
|
|
- if (collapsedSteps.value[activeStep.value - 1]) {
|
|
|
- collapsedSteps.value[activeStep.value - 1] = false
|
|
|
- }
|
|
|
- if (!collapsedSteps.value[activeStep.value]) {
|
|
|
- collapsedSteps.value[activeStep.value] = true
|
|
|
- }
|
|
|
-
|
|
|
- activeStep.value--
|
|
|
- emit('step-change', activeStep.value)
|
|
|
- startProgressAnimation()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 下一步
|
|
|
-const nextStep = () => {
|
|
|
- if (parsedContent.value && activeStep.value < parsedContent.value.steps.length) {
|
|
|
- // 折叠当前步骤,展开下一步骤
|
|
|
- if (!collapsedSteps.value[activeStep.value]) {
|
|
|
- collapsedSteps.value[activeStep.value] = true
|
|
|
- }
|
|
|
- if (activeStep.value + 1 < parsedContent.value.steps.length && collapsedSteps.value[activeStep.value + 1]) {
|
|
|
- collapsedSteps.value[activeStep.value + 1] = false
|
|
|
- }
|
|
|
+ console.log(index);
|
|
|
|
|
|
- activeStep.value++
|
|
|
- emit('step-change', activeStep.value)
|
|
|
- if (activeStep.value < parsedContent.value.steps.length) {
|
|
|
- startProgressAnimation()
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 完成所有步骤
|
|
|
-const completeAll = () => {
|
|
|
- if (parsedContent.value) {
|
|
|
- activeStep.value = parsedContent.value.steps.length
|
|
|
- emit('complete')
|
|
|
- // 清除进度条定时器
|
|
|
- if (progressTimer) {
|
|
|
- clearInterval(progressTimer)
|
|
|
- }
|
|
|
- }
|
|
|
+ collapsedSteps.value[index] = !collapsedSteps.value[index]
|
|
|
}
|
|
|
|
|
|
-// 监听content变化,重置步骤
|
|
|
watch(() => props.content, () => {
|
|
|
- activeStep.value = props.initialStep
|
|
|
- // 重置进度条
|
|
|
- stepProgress.value = 0
|
|
|
- if (progressTimer) {
|
|
|
- clearInterval(progressTimer)
|
|
|
- }
|
|
|
- // 如果有初始步骤,开始进度动画
|
|
|
- if (activeStep.value > 0 && activeStep.value < parsedContent.value?.steps.length) {
|
|
|
- startProgressAnimation()
|
|
|
- }
|
|
|
+
|
|
|
}, { deep: true })
|
|
|
|
|
|
// 组件挂载时初始化
|
|
|
onMounted(() => {
|
|
|
if (activeStep.value > 0 && parsedContent.value) {
|
|
|
emit('step-change', activeStep.value)
|
|
|
- startProgressAnimation()
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-// 组件卸载时清理定时器
|
|
|
-onBeforeUnmount(() => {
|
|
|
- if (progressTimer) {
|
|
|
- clearInterval(progressTimer)
|
|
|
- }
|
|
|
-})
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -288,6 +228,7 @@ onBeforeUnmount(() => {
|
|
|
padding: 20px;
|
|
|
background-color: #fff;
|
|
|
border-radius: 8px;
|
|
|
+
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
@@ -332,7 +273,13 @@ onBeforeUnmount(() => {
|
|
|
:deep(.el-step__icon) {
|
|
|
background-color: #f5f7fa;
|
|
|
}
|
|
|
-
|
|
|
+.timestamp {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 6px;
|
|
|
+}
|
|
|
:deep(.el-step.is-success .el-step__icon) {
|
|
|
background-color: #67c23a;
|
|
|
color: white;
|
|
@@ -362,13 +309,13 @@ onBeforeUnmount(() => {
|
|
|
/* 步骤描述 */
|
|
|
.step-description {
|
|
|
transition: all 0.3s ease;
|
|
|
+ transform-origin: top center;
|
|
|
overflow: hidden;
|
|
|
- max-height: 500px;
|
|
|
}
|
|
|
|
|
|
-.step-description.collapsed {
|
|
|
- max-height: 30px;
|
|
|
- overflow: hidden;
|
|
|
+.collapsed {
|
|
|
+ height: 0;
|
|
|
+ /* overflow: hidden; */
|
|
|
}
|
|
|
|
|
|
/* 步骤内容 */
|