feat:冗余代码清理
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { pick } from 'lodash'
|
||||
|
||||
import { ElMessage } from 'element-plus'
|
||||
import api from '@/api/index.ts'
|
||||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { agentMapDuty } from '@/layout/components/config.ts'
|
||||
import { type Agent, useAgentsStore } from '@/stores'
|
||||
@@ -39,82 +37,41 @@ const handleFileSelect = (event: Event) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 在validateApiConfig函数中添加更详细的日志
|
||||
// 验证API配置:三个字段必须同时存在或同时不存在
|
||||
const validateApiConfig = (agent: any) => {
|
||||
const hasApiUrl = 'apiUrl' in agent
|
||||
const hasApiKey = 'apiKey' in agent
|
||||
const hasApiModel = 'apiModel' in agent
|
||||
|
||||
// 三个字段必须同时存在或同时不存在
|
||||
if (hasApiUrl !== hasApiKey || hasApiKey !== hasApiModel) {
|
||||
console.error('❌ API配置不完整:', {
|
||||
agentName: agent.Name,
|
||||
missingFields: {
|
||||
apiUrl: !hasApiUrl,
|
||||
apiKey: !hasApiKey,
|
||||
apiModel: !hasApiModel
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
if (hasApiUrl && hasApiKey && hasApiModel) {
|
||||
console.log('✅ API配置完整,将使用自定义API配置:', {
|
||||
apiUrl: agent.apiUrl,
|
||||
apiKey: agent.apiKey ? '***' + agent.apiKey.slice(-4) : '未设置',
|
||||
apiModel: agent.apiModel
|
||||
})
|
||||
} else {
|
||||
console.log('ℹ️ 未设置API配置,将使用默认URL配置')
|
||||
}
|
||||
|
||||
return true
|
||||
return hasApiUrl === hasApiKey && hasApiKey === hasApiModel
|
||||
}
|
||||
|
||||
const readFileContent = (file: File) => {
|
||||
console.log('📁 开始读取文件:', file.name, '大小:', file.size, '类型:', file.type)
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = e => {
|
||||
try {
|
||||
console.log('📄 文件读取完成,开始解析JSON')
|
||||
const content = e.target?.result as string
|
||||
const jsonData = JSON.parse(content)
|
||||
|
||||
console.log('🔍 解析的JSON数据:', jsonData)
|
||||
console.log(
|
||||
'📊 数据类型:',
|
||||
Array.isArray(jsonData) ? '数组' : '对象',
|
||||
'长度:',
|
||||
Array.isArray(jsonData) ? jsonData.length : 'N/A'
|
||||
)
|
||||
|
||||
if (!Array.isArray(jsonData)) {
|
||||
console.error('❌ JSON格式错误: 必须为数组格式')
|
||||
ElMessage.error('JSON格式错误: 必须为数组格式')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('🔍 开始验证智能体数据...')
|
||||
const validAgents = jsonData.filter((agent, index) => {
|
||||
console.log(`🔍 验证第${index + 1}个智能体:`, agent.Name || '未命名')
|
||||
const validAgents = jsonData.filter((agent) => {
|
||||
// 验证必需字段
|
||||
if (!agent.Name || typeof agent.Name !== 'string') {
|
||||
console.error(`❌ 智能体${index + 1}缺少Name字段或格式错误`)
|
||||
return false
|
||||
}
|
||||
if (!agent.Icon || typeof agent.Icon !== 'string') {
|
||||
console.error(`❌ 智能体${index + 1}缺少Icon字段或格式错误`)
|
||||
return false
|
||||
}
|
||||
if (!agent.Profile || typeof agent.Profile !== 'string') {
|
||||
console.error(`❌ 智能体${index + 1}缺少Profile字段或格式错误`)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证API配置
|
||||
if (!validateApiConfig(agent)) {
|
||||
console.error(`❌ 智能体${index + 1}API配置验证失败`)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -137,21 +94,17 @@ const readFileContent = (file: File) => {
|
||||
api
|
||||
.setAgents(processedAgents)
|
||||
.then(() => {
|
||||
console.log('✅ 后端API调用成功')
|
||||
ElMessage.success('智能体上传成功')
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('❌ 后端API调用失败:', error)
|
||||
.catch(() => {
|
||||
ElMessage.error('智能体上传失败')
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('❌ JSON解析错误:', error)
|
||||
} catch {
|
||||
ElMessage.error('JSON解析错误')
|
||||
}
|
||||
}
|
||||
|
||||
reader.onerror = error => {
|
||||
console.error('❌ 文件读取错误:', error)
|
||||
reader.onerror = () => {
|
||||
ElMessage.error('文件读取错误')
|
||||
}
|
||||
|
||||
|
||||
@@ -23,15 +23,14 @@ const emit = defineEmits<{
|
||||
(e: 'save-edit', stepId: string, processId: string, value: string): void
|
||||
}>()
|
||||
|
||||
// 🔄 从 currentTask 中获取数据(与分支切换联动)
|
||||
//从 currentTask 中获取数据
|
||||
const currentTaskProcess = computed(() => {
|
||||
// ✅ 优先使用 currentTask(包含分支切换后的数据)
|
||||
const currentTask = agentsStore.currentTask
|
||||
if (currentTask && currentTask.Id === props.step.Id && currentTask.TaskProcess) {
|
||||
return currentTask.TaskProcess
|
||||
}
|
||||
|
||||
// ⚠️ 降级:从 agentRawPlan 中获取原始数据(不受分支切换影响)
|
||||
//从 agentRawPlan 中获取原始数据
|
||||
const collaborationProcess = agentsStore.agentRawPlan.data?.['Collaboration Process'] || []
|
||||
const rawData = collaborationProcess.find((task: any) => task.Id === props.step.Id)
|
||||
return rawData?.TaskProcess || []
|
||||
@@ -39,19 +38,18 @@ const currentTaskProcess = computed(() => {
|
||||
|
||||
// 当前正在编辑的process ID
|
||||
const editingProcessId = ref<string | null>(null)
|
||||
// 编辑框的值
|
||||
const editValue = ref('')
|
||||
// 鼠标悬停的process ID
|
||||
const hoverProcessId = ref<string | null>(null)
|
||||
|
||||
// 🆕 处理卡片点击事件(非编辑模式下)
|
||||
// 处理卡片点击事件
|
||||
function handleCardClick() {
|
||||
// 如果正在编辑,不处理点击
|
||||
if (editingProcessId.value) return
|
||||
|
||||
// 设置当前任务,与任务大纲联动
|
||||
if (props.step.Id) {
|
||||
agentsStore.setCurrentTask(props.step)
|
||||
agentsStore.setCurrentTask(props.step as any)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, nextTick, onMounted } from 'vue'
|
||||
import { ref, computed, nextTick, onMounted } from 'vue'
|
||||
import { VueFlow, useVueFlow, Handle, Position, type Node, type Edge } from '@vue-flow/core'
|
||||
import { Controls } from '@vue-flow/controls'
|
||||
import '@vue-flow/core/dist/style.css'
|
||||
import '@vue-flow/core/dist/theme-default.css'
|
||||
import '@vue-flow/controls/dist/style.css'
|
||||
import {
|
||||
useAgentsStore,
|
||||
useSelectionStore,
|
||||
@@ -22,7 +20,7 @@ const agentsStore = useAgentsStore()
|
||||
const selectionStore = useSelectionStore()
|
||||
const { onConnect, addEdges, fitView: fit } = useVueFlow()
|
||||
|
||||
// 🆕 直接从 store 获取当前任务和任务过程数据
|
||||
// 直接从 store 获取当前任务和任务过程数据
|
||||
const currentTask = computed(() => agentsStore.currentTask)
|
||||
const taskProcess = computed(() => agentsStore.currentTask?.TaskProcess ?? [])
|
||||
|
||||
@@ -50,12 +48,10 @@ let isSyncing = false
|
||||
//初始化标记,避免重复初始化
|
||||
const BRANCHES_INIT_KEY_PREFIX = 'plan-task-branches-initialized-'
|
||||
|
||||
// 🆕 最后选中的分支ID
|
||||
//最后选中的分支ID
|
||||
const LAST_SELECTED_BRANCH_KEY = 'plan-task-last-selected-branch'
|
||||
|
||||
// ==================== 辅助函数定义 ====================
|
||||
|
||||
// 🆕 获取分支的所有节点(只沿着分支创建方向遍历:right handle连接)
|
||||
// 获取分支的所有节点
|
||||
const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
const visited = new Set<string>()
|
||||
const toVisit: string[] = [startNodeId]
|
||||
@@ -68,14 +64,14 @@ const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
}
|
||||
visited.add(currentId)
|
||||
|
||||
// 🆕 只查找通过 right handle 连接的后续节点(分支创建方向)
|
||||
// 只查找通过 right handle 连接的后续节点
|
||||
const outgoingEdges = edges.value.filter(
|
||||
edge => edge.source === currentId && edge.sourceHandle === 'right'
|
||||
)
|
||||
|
||||
for (const edge of outgoingEdges) {
|
||||
const targetNodeId = edge.target
|
||||
// 只访问分支节点(不包含主流程节点和根节点)
|
||||
// 只访问分支节点
|
||||
if (
|
||||
!visited.has(targetNodeId) &&
|
||||
targetNodeId !== 'root' &&
|
||||
@@ -89,7 +85,7 @@ const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
return Array.from(visited)
|
||||
}
|
||||
|
||||
// 🆕 获取从指定节点回溯到根节点的路径(只包含主流程节点)
|
||||
//获取从指定节点回溯到根节点的路径(只包含主流程节点)
|
||||
const getPathToRoot = (targetNodeId: string): string[] => {
|
||||
const path: string[] = []
|
||||
const visited = new Set<string>()
|
||||
@@ -126,7 +122,7 @@ const getPathToRoot = (targetNodeId: string): string[] => {
|
||||
return path
|
||||
}
|
||||
|
||||
// 🆕 向上回溯分支的父节点链(只包含分支节点)
|
||||
// 向上回溯分支的父节点链(只包含分支节点)
|
||||
const getBranchParentChain = (targetNodeId: string): string[] => {
|
||||
const parentChain: string[] = []
|
||||
let currentId = targetNodeId
|
||||
@@ -153,8 +149,7 @@ const getBranchParentChain = (targetNodeId: string): string[] => {
|
||||
|
||||
return parentChain
|
||||
}
|
||||
|
||||
// ==================== 初始化流程图 ====================
|
||||
// 初始化流程图
|
||||
const initializeFlow = () => {
|
||||
if (!currentTask.value) {
|
||||
nodes.value = []
|
||||
@@ -162,20 +157,17 @@ const initializeFlow = () => {
|
||||
return
|
||||
}
|
||||
|
||||
// 🆕 获取当前流程数据
|
||||
// 获取当前流程数据
|
||||
const taskStepId = currentTask.value.Id
|
||||
// 🆕 获取当前 agent 组合(用于区分不同 agent 组合的分支数据)
|
||||
// 获取当前 agent 组合(用于区分不同 agent 组合的分支数据)
|
||||
const currentAgents = currentTask.value.AgentSelection || []
|
||||
|
||||
// 🆕 直接使用 taskProcess.value 作为数据源
|
||||
// 注意:虽然 currentTask.id 相同,但不同的 agent 组合对应的 agent 任务过程不同
|
||||
// taskProcess.value 从 currentTask.TaskProcess 获取,能正确反映当前 agent 组合的任务过程
|
||||
// 直接使用 taskProcess.value 作为数据源
|
||||
const currentTaskProcess = taskProcess.value
|
||||
console.log('currentTaskProcess:', currentTaskProcess)
|
||||
// 🆕 立即保存为副本(深拷贝)
|
||||
// 立即保存为副本(深拷贝)
|
||||
const taskProcessCopy = JSON.parse(JSON.stringify(currentTaskProcess))
|
||||
|
||||
// 🆕 使用副本数据创建节点(而不是 currentTaskProcess)
|
||||
// 使用副本数据创建节点(而不是 currentTaskProcess)
|
||||
const taskProcessForNodes = taskProcessCopy
|
||||
const newNodes: Node[] = []
|
||||
const newEdges: Edge[] = []
|
||||
@@ -233,7 +225,14 @@ const initializeFlow = () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#43a8aa', strokeWidth: 2 }
|
||||
style: { stroke: '#43a8aa', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -247,21 +246,27 @@ const initializeFlow = () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#43a8aa', strokeWidth: 2 }
|
||||
style: { stroke: '#43a8aa', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
nodes.value = newNodes
|
||||
edges.value = newEdges
|
||||
|
||||
// 📂 从 store 恢复已保存的任务过程分支数据
|
||||
// taskStepId 已在前面声明 (line 163)
|
||||
// 从 store 恢复已保存的任务过程分支数据
|
||||
|
||||
if (taskStepId) {
|
||||
// 🆕 使用当前 agent 组合获取分支数据
|
||||
// 使用当前 agent 组合获取分支数据
|
||||
const savedBranches = selectionStore.getTaskProcessBranches(taskStepId, currentAgents)
|
||||
|
||||
// 🆕 检查是否已经初始化过(针对该任务和 agent 组合)
|
||||
// 检查是否已经初始化过(针对该任务和 agent 组合)
|
||||
const branchesInitKey = `${BRANCHES_INIT_KEY_PREFIX}${taskStepId}_${selectionStore.getAgentGroupKey(
|
||||
currentAgents
|
||||
)}`
|
||||
@@ -272,17 +277,17 @@ const initializeFlow = () => {
|
||||
edges.value = []
|
||||
|
||||
savedBranches.forEach(branch => {
|
||||
// 恢复节点(深拷贝,避免引用问题)
|
||||
// 恢复节点
|
||||
branch.nodes.forEach(node => {
|
||||
nodes.value.push(JSON.parse(JSON.stringify(node)))
|
||||
})
|
||||
// 恢复边(深拷贝)
|
||||
// 恢复边
|
||||
branch.edges.forEach(edge => {
|
||||
edges.value.push(JSON.parse(JSON.stringify(edge)))
|
||||
})
|
||||
})
|
||||
|
||||
// 🆕 恢复最后选中的分支
|
||||
// 恢复最后选中的分支
|
||||
const lastSelectedBranchId = sessionStorage.getItem(LAST_SELECTED_BRANCH_KEY)
|
||||
if (lastSelectedBranchId) {
|
||||
const lastSelectedBranch = savedBranches.find(branch => branch.id === lastSelectedBranchId)
|
||||
@@ -313,7 +318,7 @@ const initializeFlow = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 🆕 使用多级分支逻辑:获取父节点链和子节点
|
||||
// 获取父节点链和子节点
|
||||
const branchParentChain = getBranchParentChain(firstBranchNode.id)
|
||||
const branchChildNodes = getAllBranchNodes(firstBranchNode.id)
|
||||
|
||||
@@ -338,11 +343,11 @@ const initializeFlow = () => {
|
||||
selectedNodeIds.value = new Set(mainProcessNodes)
|
||||
}
|
||||
} else {
|
||||
// 🆕 首次初始化:设置节点和边,并保存为"初始流程"分支
|
||||
// 首次初始化:设置节点和边,并保存为"初始流程"分支
|
||||
nodes.value = newNodes
|
||||
edges.value = newEdges
|
||||
|
||||
const initialBranchNodes = newNodes // ✅ 保留所有节点,包括根节点
|
||||
const initialBranchNodes = newNodes
|
||||
const initialBranchEdges = [...newEdges]
|
||||
|
||||
const initialBranchId = selectionStore.addTaskProcessBranch(taskStepId, currentAgents, {
|
||||
@@ -351,13 +356,13 @@ const initializeFlow = () => {
|
||||
branchType: 'root',
|
||||
nodes: JSON.parse(JSON.stringify(initialBranchNodes)),
|
||||
edges: JSON.parse(JSON.stringify(initialBranchEdges)),
|
||||
tasks: taskProcessCopy // 👈 使用副本(已经是深拷贝)
|
||||
tasks: taskProcessCopy
|
||||
})
|
||||
|
||||
// 🆕 标记已初始化(针对该任务步骤和 agent 组合)
|
||||
// 标记已初始化(针对该任务步骤和 agent 组合)
|
||||
sessionStorage.setItem(branchesInitKey, 'true')
|
||||
|
||||
// 🆕 首次初始化时,设置初始流程为当前选中分支
|
||||
// 首次初始化时,设置初始流程为当前选中分支
|
||||
selectionStore.setActiveTaskProcessBranch(taskStepId, currentAgents, initialBranchId)
|
||||
|
||||
// 默认选中"初始流程"的高亮状态
|
||||
@@ -369,166 +374,6 @@ const initializeFlow = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 同步当前所有分支数据到 store
|
||||
const syncBranchesToStore = () => {
|
||||
if (isSyncing || !currentTask.value?.Id) return
|
||||
|
||||
isSyncing = true
|
||||
const taskStepId = currentTask.value.Id
|
||||
// 🆕 获取当前 agent 组合
|
||||
const currentAgents = currentTask.value.AgentSelection || []
|
||||
|
||||
// 🔄 获取现有的分支数据(用于保留初始流程分支)
|
||||
const existingBranches = selectionStore.getTaskProcessBranches(taskStepId, currentAgents)
|
||||
const existingBranchesMap = new Map<string, any>()
|
||||
existingBranches.forEach(branch => {
|
||||
// 使用分支ID作为key
|
||||
existingBranchesMap.set(branch.id, branch)
|
||||
})
|
||||
|
||||
// 获取当前所有分支节点(标记为 isBranchTask)
|
||||
const currentBranchNodes = nodes.value.filter((n: Node) => n.data.isBranchTask)
|
||||
|
||||
if (currentBranchNodes.length === 0) {
|
||||
isSyncing = false
|
||||
return
|
||||
}
|
||||
|
||||
// 按照分支分组节点和边
|
||||
// 通过 parentId 将节点分组
|
||||
const branchesMap = new Map<
|
||||
string,
|
||||
{
|
||||
nodes: Node[]
|
||||
edges: Edge[]
|
||||
branchContent: string
|
||||
branchType: 'root' | 'task'
|
||||
createdAt: number
|
||||
tasks?: any[] // 🆕 添加 tasks 字段
|
||||
}
|
||||
>()
|
||||
|
||||
currentBranchNodes.forEach((node: Node) => {
|
||||
// 找到连接到该节点的边,确定父节点
|
||||
const incomingEdge = edges.value.find((e: Edge) => e.target === node.id)
|
||||
const parentNodeId = incomingEdge?.source || 'root'
|
||||
const isFirstBranchNode = incomingEdge?.sourceHandle === 'bottom'
|
||||
|
||||
if (isFirstBranchNode) {
|
||||
if (!branchesMap.has(parentNodeId)) {
|
||||
// 🆕 从现有分支数据中恢复元数据
|
||||
const existingMetadata = existingBranchesMap.get(node.id)
|
||||
|
||||
branchesMap.set(parentNodeId, {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
branchContent: existingMetadata?.branchContent || '分支',
|
||||
branchType: existingMetadata?.branchType || (parentNodeId === 'root' ? 'root' : 'task'),
|
||||
createdAt: Date.now(),
|
||||
tasks: existingMetadata?.tasks //
|
||||
})
|
||||
}
|
||||
|
||||
// 收集该分支的所有节点(从第一个节点开始,通过 right handle 连接的节点)
|
||||
const branchNodes: Node[] = []
|
||||
let currentNode: Node | undefined = node
|
||||
|
||||
while (currentNode) {
|
||||
branchNodes.push(currentNode)
|
||||
|
||||
// 查找通过 right handle 连接的下一个节点
|
||||
const outgoingEdge = edges.value.find(
|
||||
(e: Edge) => e.source === currentNode!.id && e.sourceHandle === 'right'
|
||||
)
|
||||
if (outgoingEdge) {
|
||||
currentNode = currentBranchNodes.find((n: Node) => n.id === outgoingEdge.target)
|
||||
} else {
|
||||
currentNode = undefined
|
||||
}
|
||||
}
|
||||
|
||||
// 添加所有分支节点
|
||||
branchNodes.forEach((n: Node) => {
|
||||
if (
|
||||
!branchesMap
|
||||
.get(parentNodeId)!
|
||||
.nodes.find((existingNode: Node) => existingNode.id === n.id)
|
||||
) {
|
||||
branchesMap.get(parentNodeId)!.nodes.push(n)
|
||||
}
|
||||
})
|
||||
|
||||
// 找到该分支的所有边
|
||||
branchNodes.forEach((branchNode: Node) => {
|
||||
const branchEdges = edges.value.filter(
|
||||
(e: Edge) => e.source === branchNode.id || e.target === branchNode.id
|
||||
)
|
||||
branchEdges.forEach((edge: Edge) => {
|
||||
if (!branchesMap.get(parentNodeId)!.edges.find((e: Edge) => e.id === edge.id)) {
|
||||
branchesMap.get(parentNodeId)!.edges.push(edge)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 保存所有分支到 store(使用深拷贝)
|
||||
branchesMap.forEach((branchData, parentNodeId) => {
|
||||
// 🆕 优先使用恢复的 tasks 数据,如果没有才重新创建
|
||||
let tasks = branchData.tasks
|
||||
|
||||
if (!tasks || tasks.length === 0) {
|
||||
// 转换节点数据为 IRawStepTask 格式
|
||||
tasks = branchData.nodes.map((node: Node) => ({
|
||||
Id: node.id,
|
||||
StepName: node.data.actionTypeName,
|
||||
TaskContent: node.data.agentDescription,
|
||||
InputObject_List: [],
|
||||
OutputObject: '',
|
||||
AgentSelection: [node.data.agentName],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {}
|
||||
} as any,
|
||||
TaskProcess: []
|
||||
}))
|
||||
} else {
|
||||
}
|
||||
|
||||
selectionStore.addTaskProcessBranch(taskStepId, currentAgents, {
|
||||
parentNodeId,
|
||||
branchContent: JSON.parse(JSON.stringify(branchData.branchContent)),
|
||||
branchType: JSON.parse(JSON.stringify(branchData.branchType)),
|
||||
nodes: JSON.parse(JSON.stringify(branchData.nodes)),
|
||||
edges: JSON.parse(JSON.stringify(branchData.edges)),
|
||||
tasks: JSON.parse(JSON.stringify(tasks)) // 🆕 优先使用恢复的 tasks
|
||||
})
|
||||
})
|
||||
|
||||
// 延迟重置标志,避免连续触发
|
||||
setTimeout(() => {
|
||||
isSyncing = false
|
||||
}, 100)
|
||||
}
|
||||
|
||||
// 监听节点和边的变化,同步到 store
|
||||
// ⚠️ 已禁用自动同步,因为会导致分支ID变化,sessionStorage中保存的选中分支无法恢复
|
||||
// 分支数据在添加分支时就已经保存到store了,不需要在nodes/edges变化时重新同步
|
||||
// watch(
|
||||
// [nodes, edges],
|
||||
// () => {
|
||||
// // 如果正在同步,跳过
|
||||
// if (isSyncing) return
|
||||
|
||||
// // 只在有分支节点时才同步
|
||||
// const hasBranchNodes = nodes.value.some((n: Node) => n.data.isBranchTask)
|
||||
// if (hasBranchNodes && currentTask.value) {
|
||||
// syncBranchesToStore()
|
||||
// }
|
||||
// },
|
||||
// { deep: true }
|
||||
// )
|
||||
|
||||
// 组件挂载后初始化
|
||||
onMounted(() => {
|
||||
if (currentTask.value) {
|
||||
@@ -556,7 +401,7 @@ const cancelAddBranch = () => {
|
||||
branchInput.value = ''
|
||||
}
|
||||
|
||||
// 🆕 节点点击事件
|
||||
// 节点点击事件
|
||||
const onNodeClick = (event: any) => {
|
||||
const nodeId = event.node.id
|
||||
const nodeData = event.node.data as any
|
||||
@@ -571,10 +416,10 @@ const onNodeClick = (event: any) => {
|
||||
|
||||
if (isBranchNode) {
|
||||
// 点击的是分支节点
|
||||
// 🆕 向上回溯分支父节点链(多级分支)
|
||||
// 向上回溯分支父节点链(多级分支)
|
||||
const branchParentChain = getBranchParentChain(nodeId)
|
||||
|
||||
// 🆕 向下遍历分支的子节点(只沿right handle方向)
|
||||
// 向下遍历分支的子节点(只沿right handle方向)
|
||||
const branchChildNodes = getAllBranchNodes(nodeId)
|
||||
|
||||
// 找到最顶层的分支父节点(连接到主流程或根节点的)
|
||||
@@ -599,7 +444,7 @@ const onNodeClick = (event: any) => {
|
||||
// 回溯到根节点,获取主流程路径
|
||||
const pathToRoot = getPathToRoot(parentNodeId)
|
||||
|
||||
// 🔧 getPathToRoot 已经返回正序(从左到右),不需要反转
|
||||
// getPathToRoot 已经返回正序(从左到右),不需要反转
|
||||
const correctPathToRoot = pathToRoot // [agent-0, agent-1, agent-2, ...]
|
||||
const correctBranchParentChain = [...branchParentChain].reverse() // 顶层分支 → ... → 直接父分支(正序)
|
||||
|
||||
@@ -611,27 +456,18 @@ const onNodeClick = (event: any) => {
|
||||
]
|
||||
selectedNodeIds.value = new Set(allNodesToHighlight)
|
||||
|
||||
console.log('📋 路径顺序(从上到下、从左到右):', {
|
||||
pathToRoot: correctPathToRoot,
|
||||
branchParentChain: correctBranchParentChain,
|
||||
branchChildNodes: branchChildNodes,
|
||||
total: allNodesToHighlight.length
|
||||
})
|
||||
|
||||
// 🆕 保存完整的 TaskProcess 数据(主流程 + 分支)到 store
|
||||
// 保存完整的 TaskProcess 数据(主流程 + 分支)到 store
|
||||
if (currentTask.value) {
|
||||
const completeTaskProcess: any[] = []
|
||||
|
||||
// 🆕 从 store 中获取"初始流程"副本(而不是使用 taskProcess.value)
|
||||
// 从 store 中获取"初始流程"副本(而不是使用 taskProcess.value)
|
||||
const taskStepId = currentTask.value.Id
|
||||
const currentAgents = currentTask.value.AgentSelection || []
|
||||
const branches = selectionStore.getTaskProcessBranches(taskStepId, currentAgents)
|
||||
const initialBranch = branches.find(branch => branch.branchContent === '初始流程')
|
||||
const mainProcessData = initialBranch?.tasks || taskProcess.value
|
||||
|
||||
console.log('🔍 开始按高亮路径收集数据,总节点数:', allNodesToHighlight.length)
|
||||
|
||||
// 🆕 按照高亮路径顺序收集每个节点的数据
|
||||
// 按照高亮路径顺序收集每个节点的数据
|
||||
allNodesToHighlight.forEach(nodeId => {
|
||||
const node = nodes.value.find(n => n.id === nodeId)
|
||||
|
||||
@@ -644,7 +480,6 @@ const onNodeClick = (event: any) => {
|
||||
const processData = mainProcessData[originalIndex]
|
||||
if (processData && processData.ID && processData.AgentName && processData.Description) {
|
||||
completeTaskProcess.push(processData)
|
||||
console.log(` 📦 添加主流程节点: ${nodeId}, 索引: ${originalIndex}`)
|
||||
}
|
||||
} else if (node.data.isBranchTask) {
|
||||
// 分支节点:从对应的分支数据中获取(按索引匹配)
|
||||
@@ -657,25 +492,19 @@ const onNodeClick = (event: any) => {
|
||||
const taskData = parentBranch.tasks[nodeIndex]
|
||||
if (taskData.ID && taskData.AgentName && taskData.Description) {
|
||||
completeTaskProcess.push(taskData)
|
||||
console.log(
|
||||
` 📦 添加分支节点: ${nodeId}, 分支: ${parentBranch.branchContent}, 索引: ${nodeIndex}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`✅ 数据收集完成,总任务数: ${completeTaskProcess.length}`)
|
||||
|
||||
// 🆕 找到当前点击节点所属的分支,用于保存选中状态
|
||||
// 找到当前点击节点所属的分支,用于保存选中状态
|
||||
const matchedBranch = branches.find(branch => {
|
||||
return branch.nodes.some(node => node.id === nodeId)
|
||||
})
|
||||
|
||||
if (matchedBranch) {
|
||||
sessionStorage.setItem(LAST_SELECTED_BRANCH_KEY, matchedBranch.id)
|
||||
console.log(`💾 保存选中的分支ID: ${matchedBranch.id}`)
|
||||
}
|
||||
|
||||
selectionStore.setActiveTaskProcessData(
|
||||
@@ -691,14 +520,14 @@ const onNodeClick = (event: any) => {
|
||||
selectedNodeIds.value = new Set(allBranchNodes)
|
||||
}
|
||||
} else {
|
||||
// 🆕 点击的是主流程节点,高亮所有主流程节点(初始流程)
|
||||
// 点击的是主流程节点,高亮所有主流程节点(初始流程)
|
||||
const mainProcessNodes = nodes.value
|
||||
.filter(n => !n.data.isBranchTask && n.id !== 'root')
|
||||
.map(n => n.id)
|
||||
|
||||
selectedNodeIds.value = new Set(mainProcessNodes)
|
||||
|
||||
// 🆕 点击主流程节点时,从 store 读取"初始流程"分支的副本
|
||||
// 点击主流程节点时,从 store 读取"初始流程"分支的副本
|
||||
if (currentTask.value) {
|
||||
const taskStepId = currentTask.value.Id
|
||||
if (!taskStepId) {
|
||||
@@ -712,17 +541,17 @@ const onNodeClick = (event: any) => {
|
||||
// 使用 store 中保存的初始流程副本
|
||||
selectionStore.setActiveTaskProcessData(taskStepId, currentAgents, initialBranch.tasks)
|
||||
|
||||
// 🆕 同步更新 currentTask.TaskProcess(实现全局数据联动)
|
||||
// 同步更新 currentTask.TaskProcess(实现全局数据联动)
|
||||
agentsStore.setCurrentTaskProcess(initialBranch.tasks)
|
||||
|
||||
// 🆕 保存选中的分支ID到 sessionStorage
|
||||
// 保存选中的分支ID到 sessionStorage
|
||||
sessionStorage.setItem(LAST_SELECTED_BRANCH_KEY, initialBranch.id)
|
||||
} else {
|
||||
// 降级:使用 taskProcess.value
|
||||
const originalTaskProcess = taskProcess.value
|
||||
selectionStore.setActiveTaskProcessData(taskStepId, currentAgents, originalTaskProcess)
|
||||
|
||||
// 🆕 同步更新 currentTask.TaskProcess(实现全局数据联动)
|
||||
// 同步更新 currentTask.TaskProcess(实现全局数据联动)
|
||||
agentsStore.setCurrentTaskProcess(originalTaskProcess)
|
||||
}
|
||||
}
|
||||
@@ -747,8 +576,8 @@ const submitBranch = async () => {
|
||||
branchLoading.value = true
|
||||
|
||||
try {
|
||||
// ==================== 移动已有分支 ====================
|
||||
// 🆕 只移动在当前父节点下方的分支节点(Y坐标 > 父节点Y坐标)
|
||||
// 移动已有分支
|
||||
// 只移动在当前父节点下方的分支节点(Y坐标 > 父节点Y坐标)
|
||||
const parentNodeY = parentNode.position.y
|
||||
|
||||
// 查找所有已有的分支任务节点(标记为 isBranchTask)
|
||||
@@ -761,10 +590,6 @@ const submitBranch = async () => {
|
||||
|
||||
const branchIdsBelowParent = branchesBelowParent.map((n: Node) => n.id)
|
||||
|
||||
console.log(
|
||||
`📍 移动了 ${branchIdsBelowParent.length} 个分支(Y坐标 > ${parentNodeY}),总共 ${allExistingBranchNodes.length} 个分支`
|
||||
)
|
||||
|
||||
// 将当前父节点下方的分支向下移动250px(通过创建新节点来触发响应式更新)
|
||||
nodes.value = nodes.value.map((node: Node) => {
|
||||
if (branchIdsBelowParent.includes(node.id)) {
|
||||
@@ -779,7 +604,7 @@ const submitBranch = async () => {
|
||||
return node
|
||||
})
|
||||
|
||||
// 💾 同步更新 store 中保存的分支位置
|
||||
// 同步更新 store 中保存的分支位置
|
||||
if (currentTask.value?.Id) {
|
||||
const taskStepId = currentTask.value.Id
|
||||
const currentAgents = currentTask.value.AgentSelection || []
|
||||
@@ -800,21 +625,21 @@ const submitBranch = async () => {
|
||||
|
||||
// 判断是根节点还是 agent 节点
|
||||
if (parentNodeId === 'root') {
|
||||
// ========== 根节点分支 ==========
|
||||
// 根节点分支
|
||||
let newAgentActions: IApiAgentAction[] = []
|
||||
|
||||
if (USE_MOCK_DATA) {
|
||||
// 使用 Mock API
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
|
||||
// 🆕 根节点分支:从零开始生成完整方案
|
||||
// 根节点分支:从零开始生成完整方案
|
||||
// Baseline_Completion = 0 表示没有已完成的部分,需要生成所有阶段
|
||||
// Existing_Steps 传空数组,不传递初始流程信息
|
||||
const response = await api.mockBranchTaskProcess({
|
||||
branch_Number: 1,
|
||||
Modification_Requirement: branchContent,
|
||||
Existing_Steps: [], // ← 根节点分支不传递现有步骤
|
||||
Baseline_Completion: 0, // ← 从零开始
|
||||
Existing_Steps: [], // ← 根节点分支不传递现有步骤
|
||||
Baseline_Completion: 0, // ← 从零开始
|
||||
stepTaskExisting: currentTask.value,
|
||||
goal: generalGoal
|
||||
})
|
||||
@@ -842,14 +667,14 @@ const submitBranch = async () => {
|
||||
// 调用真实 API
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
|
||||
// 🆕 根节点分支:从零开始生成完整方案
|
||||
// 根节点分支:从零开始生成完整方案
|
||||
// Baseline_Completion = 0 表示没有已完成的部分,需要生成所有阶段
|
||||
// Existing_Steps 传空数组,不传递初始流程信息
|
||||
const response = await api.branchTaskProcess({
|
||||
branch_Number: 1,
|
||||
Modification_Requirement: branchContent,
|
||||
Existing_Steps: [], // ← 根节点分支不传递现有步骤
|
||||
Baseline_Completion: 0, // ← 从零开始
|
||||
Existing_Steps: [], // ← 根节点分支不传递现有步骤
|
||||
Baseline_Completion: 0, // ← 从零开始
|
||||
stepTaskExisting: currentTask.value,
|
||||
goal: generalGoal
|
||||
})
|
||||
@@ -933,7 +758,14 @@ const submitBranch = async () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#67c23a', strokeWidth: 2, strokeDasharray: '5,5' }
|
||||
style: { stroke: '#67c23a', strokeWidth: 2, strokeDasharray: '5,5' },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -948,14 +780,21 @@ const submitBranch = async () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#67c23a', strokeWidth: 2 }
|
||||
style: { stroke: '#67c23a', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
}
|
||||
})
|
||||
|
||||
// 📂 保存分支数据到 store
|
||||
// 保存分支数据到 store
|
||||
if (newBranchNodes.length > 0) {
|
||||
// 将 IApiAgentAction 转换为 TaskProcess 格式用于存储
|
||||
// 与 fill-step-task-mock.ts 中的 TaskProcess 格式保持一致
|
||||
@@ -986,7 +825,7 @@ const submitBranch = async () => {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ========== Agent 节点分支 ==========
|
||||
// Agent 节点分支
|
||||
const parentIsBranchTask = parentNode.data.isBranchTask || false
|
||||
const parentOriginalIndex = parentNode.data.originalIndex ?? 0
|
||||
let newAgentActions: IApiAgentAction[] = []
|
||||
@@ -996,7 +835,7 @@ const submitBranch = async () => {
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
const currentTaskProcess = taskProcess.value || []
|
||||
|
||||
// 🆕 根据父节点类型构建 existingSteps
|
||||
// 根据父节点类型构建 existingSteps
|
||||
let existingSteps: any[] = []
|
||||
let baselineCompletion = 100
|
||||
|
||||
@@ -1078,7 +917,7 @@ const submitBranch = async () => {
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
const currentTaskProcess = taskProcess.value || []
|
||||
|
||||
// 🆕 根据父节点类型构建 existingSteps
|
||||
// 根据父节点类型构建 existingSteps
|
||||
let existingSteps: any[] = []
|
||||
let baselineCompletion = 100
|
||||
|
||||
@@ -1135,7 +974,6 @@ const submitBranch = async () => {
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
console.log('branchTaskProcess response:', response)
|
||||
// 后端返回格式: [[action1, action2], [action3, action4]]
|
||||
// 取第一个分支
|
||||
if (response && response.length > 0) {
|
||||
@@ -1215,7 +1053,14 @@ const submitBranch = async () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#409eff', strokeWidth: 2, strokeDasharray: '5,5' }
|
||||
style: { stroke: '#409eff', strokeWidth: 2, strokeDasharray: '5,5' },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -1230,17 +1075,22 @@ const submitBranch = async () => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#409eff', strokeWidth: 2 }
|
||||
style: { stroke: '#409eff', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
}
|
||||
})
|
||||
|
||||
// 📂 保存分支数据到 store
|
||||
// 保存分支数据到 store
|
||||
if (newBranchNodes.length > 0) {
|
||||
// 将 IApiAgentAction 转换为 TaskProcess 格式用于存储
|
||||
// 与 fill-step-task-mock.ts 中的 TaskProcess 格式保持一致
|
||||
const branchTasks = newAgentActions.map(action => ({
|
||||
ID: action.id || uuidv4(),
|
||||
ActionType: action.type,
|
||||
@@ -1317,9 +1167,6 @@ onConnect(params => addEdges(params))
|
||||
@node-click="onNodeClick"
|
||||
class="vue-flow-container"
|
||||
>
|
||||
<!-- <Background /> -->
|
||||
<!-- <Controls /> -->
|
||||
|
||||
<template #node-root="nodeProps">
|
||||
<div class="root-task-node-wrapper">
|
||||
<Handle type="source" :position="Position.Right" id="right" />
|
||||
@@ -1645,7 +1492,7 @@ onConnect(params => addEdges(params))
|
||||
|
||||
.el-input__inner {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-primary);
|
||||
color: #000;
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
@@ -1684,7 +1531,7 @@ onConnect(params => addEdges(params))
|
||||
opacity: 0.9;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
// 🆕 分支选中高亮样式
|
||||
// 分支选中高亮样式
|
||||
&.is-branch-selected {
|
||||
box-shadow: 0 0 0 3px #000, 0 0 20px rgba(0, 0, 0, 0.5);
|
||||
z-index: 10;
|
||||
@@ -1719,17 +1566,6 @@ onConnect(params => addEdges(params))
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.vue-flow__controls) {
|
||||
button {
|
||||
background-color: #43a8aa;
|
||||
border-color: #43a8aa;
|
||||
|
||||
&:hover {
|
||||
background-color: #358d8f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 智能体悬浮提示样式 */
|
||||
:deep(.agent-tooltip-popper) {
|
||||
z-index: 4000 !important;
|
||||
|
||||
@@ -12,21 +12,19 @@ const props = defineProps<{
|
||||
step?: any
|
||||
}>()
|
||||
|
||||
// 获取分支数量 - 主分支(1) + 额外分支数量
|
||||
// 获取分支数量
|
||||
const branchCount = computed(() => {
|
||||
if (!props.step?.Id) return 1
|
||||
|
||||
// 获取该任务步骤的分支数据
|
||||
const taskStepId = props.step.Id
|
||||
// 🆕 获取该任务的 agent 组合
|
||||
// 获取该任务的 agent 组合
|
||||
const agents = props.step.AgentSelection || []
|
||||
const branches = selectionStore.getTaskProcessBranches(taskStepId, agents)
|
||||
|
||||
// 主分支(1) + 额外分支数量
|
||||
return branches.length || 1
|
||||
})
|
||||
|
||||
// 🆕 判断按钮是否可点击(只有当前按钮对应的任务是任务大纲中选中的任务时才可点击)
|
||||
// 判断按钮是否可点击
|
||||
const isClickable = computed(() => {
|
||||
if (!props.step?.Id || !agentsStore.currentTask?.Id) {
|
||||
return false
|
||||
@@ -35,7 +33,7 @@ const isClickable = computed(() => {
|
||||
})
|
||||
|
||||
const handleClick = (event?: MouseEvent) => {
|
||||
// 🆕 只有可点击时才执行操作
|
||||
// 只有可点击时才执行操作
|
||||
if (!isClickable.value) {
|
||||
return
|
||||
}
|
||||
@@ -102,7 +100,7 @@ const handleClick = (event?: MouseEvent) => {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
// 🆕 禁用状态
|
||||
// 禁用状态
|
||||
&.is-disabled {
|
||||
background-color: #bdc3c7;
|
||||
cursor: not-allowed;
|
||||
|
||||
@@ -59,7 +59,7 @@ function handlePrev() {
|
||||
<!-- <div>{{ `${displayIndex + 1}/${data.length}` }}</div>
|
||||
<el-button type="primary" size="small" @click="handleNext">下一个</el-button> -->
|
||||
<!-- 关闭 -->
|
||||
<SvgIcon icon-class="close" size="15px" />
|
||||
<!-- <SvgIcon icon-class="close" size="15px" /> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
|
||||
@@ -38,9 +38,9 @@ watch(
|
||||
)
|
||||
|
||||
// 编辑逻辑
|
||||
const editMode = ref(false) //全局编辑开关
|
||||
const editMap = reactive<Record<string, boolean>>({}) //行级编辑状态
|
||||
const editBuffer = reactive<Record<string, string | undefined>>({}) //临时输入
|
||||
const editMode = ref(false)
|
||||
const editMap = reactive<Record<string, boolean>>({})
|
||||
const editBuffer = reactive<Record<string, string | undefined>>({})
|
||||
const showPopover = ref(false)
|
||||
function getProcessDescription(stepId: string, processId: string) {
|
||||
const step = collaborationProcess.value.find(s => s.Id === stepId)
|
||||
@@ -201,7 +201,6 @@ async function handleTaskProcess() {
|
||||
// 重置执行结果
|
||||
function handleRefresh() {
|
||||
agentsStore.setExecutePlan([])
|
||||
console.log('🔄 已重置执行结果')
|
||||
}
|
||||
|
||||
// 添加滚动状态标识
|
||||
@@ -241,10 +240,8 @@ function clear() {
|
||||
jsplumb.reset()
|
||||
}
|
||||
|
||||
// 🆕 封装连线重绘方法
|
||||
//封装连线重绘方法
|
||||
const redrawInternalLines = (highlightId?: string) => {
|
||||
console.log('🔄 TaskResult: 重新绘制连线', highlightId ? `高亮: ${highlightId}` : '')
|
||||
|
||||
// 等待 DOM 更新完成
|
||||
nextTick(() => {
|
||||
// 清除旧连线
|
||||
@@ -253,28 +250,25 @@ const redrawInternalLines = (highlightId?: string) => {
|
||||
// 等待 DOM 稳定后重新绘制
|
||||
setTimeout(() => {
|
||||
createInternalLine(highlightId)
|
||||
console.log('✅ TaskResult: 连线重绘完成,任务数:', collaborationProcess.value.length)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 🆕 监听 collaborationProcess 变化,自动重绘连线
|
||||
//监听 collaborationProcess 变化,自动重绘连线
|
||||
watch(
|
||||
() => collaborationProcess,
|
||||
() => {
|
||||
console.log('🔍 TaskResult: collaborationProcess 发生变化,触发重绘')
|
||||
redrawInternalLines()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 🆕 组件挂载后初始化连线
|
||||
// 组件挂载后初始化连线
|
||||
onMounted(() => {
|
||||
// 初始化时绘制连线
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
createInternalLine()
|
||||
console.log('✅ TaskResult: 初始化连线完成')
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
@@ -328,7 +322,6 @@ onUnmounted(() => {
|
||||
})
|
||||
// 计算按钮类名
|
||||
const processBtnClass = computed(() => {
|
||||
// 当刷新或执行按钮悬停时,过程按钮变圆形
|
||||
if (buttonHoverState.value === 'refresh' || buttonHoverState.value === 'execute') {
|
||||
return 'circle'
|
||||
}
|
||||
@@ -336,20 +329,16 @@ const processBtnClass = computed(() => {
|
||||
})
|
||||
|
||||
const executeBtnClass = computed(() => {
|
||||
// 鼠标悬停在过程按钮或刷新按钮上时,执行按钮变圆形
|
||||
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'refresh') {
|
||||
return 'circle'
|
||||
}
|
||||
//如果有任务数据就显示椭圆形,否则显示圆形
|
||||
return agentsStore.agentRawPlan.data ? 'ellipse' : 'circle'
|
||||
})
|
||||
|
||||
const refreshBtnClass = computed(() => {
|
||||
// 当过程或执行按钮悬停时,刷新按钮变圆形
|
||||
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'execute') {
|
||||
return 'circle'
|
||||
}
|
||||
// 有执行结果就显示椭圆形,否则显示圆形
|
||||
return agentsStore.executePlan.length > 0 ? 'ellipse' : 'circle'
|
||||
})
|
||||
|
||||
@@ -359,9 +348,7 @@ const showProcessText = computed(() => {
|
||||
})
|
||||
|
||||
const showExecuteText = computed(() => {
|
||||
// 鼠标悬停在过程按钮上时,执行按钮不显示文字
|
||||
if (buttonHoverState.value === 'process') return false
|
||||
// 其他情况:如果有任务数据就显示文字,否则不显示
|
||||
return agentsStore.agentRawPlan.data
|
||||
})
|
||||
|
||||
@@ -398,7 +385,7 @@ defineExpose({
|
||||
<div class="text-[18px] font-bold mb-[7px] flex justify-between items-center px-[20px]">
|
||||
<span class="text-[var(--color-text-title-header)]">执行结果</span>
|
||||
<div
|
||||
class="flex items-center justify-end gap-[14px] task-button-group min-w-[175px]"
|
||||
class="flex items-center justify-end gap-[10px] task-button-group w-[230px]"
|
||||
@mouseleave="handleButtonMouseLeave"
|
||||
>
|
||||
<!-- 刷新按钮 -->
|
||||
@@ -758,7 +745,7 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 新增:按钮交互样式 ==========
|
||||
//按钮交互样式
|
||||
.task-button-group {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
@@ -766,7 +753,8 @@ defineExpose({
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
transition: width 0.2s ease-out, padding 0.2s ease-out, border-radius 0.2s ease-out, transform 0.2s ease-out, box-shadow 0.2s ease-out, filter 0.2s ease-out !important;
|
||||
transition: width 0.2s ease-out, padding 0.2s ease-out, border-radius 0.2s ease-out,
|
||||
transform 0.2s ease-out, box-shadow 0.2s ease-out, filter 0.2s ease-out !important;
|
||||
overflow: hidden !important;
|
||||
white-space: nowrap !important;
|
||||
border: 1px solid transparent !important;
|
||||
@@ -812,6 +800,7 @@ defineExpose({
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
min-width: 40px !important;
|
||||
max-width: 40px !important;
|
||||
padding: 0 !important;
|
||||
border-radius: 50% !important;
|
||||
|
||||
|
||||
@@ -50,8 +50,6 @@ import type { Node, Edge } from '@vue-flow/core'
|
||||
import { useAgentsStore, useSelectionStore, type IRawStepTask } from '@/stores'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import api from '@/api'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import '@vue-flow/core/dist/style.css'
|
||||
import '@vue-flow/core/dist/theme-default.css'
|
||||
import '@vue-flow/minimap/dist/style.css'
|
||||
@@ -64,8 +62,7 @@ import TaskNode from './components/TaskNode.vue'
|
||||
const agentsStore = useAgentsStore()
|
||||
const selectionStore = useSelectionStore()
|
||||
|
||||
// Mock 数据配置
|
||||
// 开关:控制是否使用 mock 数据(开发时设置为 true,生产时设置为 false)
|
||||
// Mock 数据开关
|
||||
const USE_MOCK_DATA = false
|
||||
|
||||
// 获取协作流程数据
|
||||
@@ -80,16 +77,13 @@ const edges = ref<Edge[]>([])
|
||||
// Vue Flow 实例方法
|
||||
const { fitView: fit, setTransform, updateNode, findNode } = useVueFlow()
|
||||
|
||||
// 编辑状态管理
|
||||
const editingTasks = ref<Record<string, string>>({})
|
||||
|
||||
// 当前正在添加分支的节点 ID
|
||||
const currentAddingBranchNodeId = ref<string | null>(null)
|
||||
|
||||
// 当前选中的节点ID集合
|
||||
const selectedNodeIds = ref<Set<string>>(new Set())
|
||||
|
||||
// 获取从目标节点回溯到根节点的路径
|
||||
// 回溯到根节点的路径
|
||||
const getPathToRoot = (targetNodeId: string): string[] => {
|
||||
const path: string[] = []
|
||||
const visited = new Set<string>()
|
||||
@@ -121,7 +115,7 @@ const getPathToRoot = (targetNodeId: string): string[] => {
|
||||
return path
|
||||
}
|
||||
|
||||
// 获取分支的所有子节点(只向右遍历,不跨分支)
|
||||
// 获取分支的所有子节点
|
||||
const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
const visited = new Set<string>()
|
||||
const toVisit: string[] = [startNodeId]
|
||||
@@ -134,7 +128,7 @@ const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
}
|
||||
visited.add(currentId)
|
||||
|
||||
// 只查找通过 right handle 连接的后续节点(分支创建方向)
|
||||
// 查找分支创建方向的后续节点
|
||||
const outgoingEdges = edges.value.filter(
|
||||
edge => edge.source === currentId && edge.sourceHandle === 'right'
|
||||
)
|
||||
@@ -155,7 +149,7 @@ const getAllBranchNodes = (startNodeId: string): string[] => {
|
||||
return Array.from(visited)
|
||||
}
|
||||
|
||||
// 向上回溯分支的父节点链(只包含分支节点)
|
||||
// 回溯分支的父节点链
|
||||
const getBranchParentChain = (targetNodeId: string): string[] => {
|
||||
const parentChain: string[] = []
|
||||
let currentId = targetNodeId
|
||||
@@ -170,12 +164,12 @@ const getBranchParentChain = (targetNodeId: string): string[] => {
|
||||
|
||||
const sourceNode = nodes.value.find(n => n.id === incomingEdge.source)
|
||||
|
||||
// 如果父节点不是分支节点,停止回溯
|
||||
// 非分支节点停止回溯
|
||||
if (!sourceNode || !sourceNode.id.startsWith('branch-task-')) {
|
||||
break
|
||||
}
|
||||
|
||||
// 添加父节点到链中
|
||||
// 添加父节点
|
||||
parentChain.push(sourceNode.id)
|
||||
currentId = sourceNode.id
|
||||
}
|
||||
@@ -183,35 +177,35 @@ const getBranchParentChain = (targetNodeId: string): string[] => {
|
||||
return parentChain
|
||||
}
|
||||
|
||||
// 判断节点是否为主流程节点
|
||||
// 判断是否为主流程节点
|
||||
const isMainProcessNode = (nodeId: string): boolean => {
|
||||
return nodeId.startsWith('task-') && !nodeId.startsWith('branch-task-')
|
||||
}
|
||||
|
||||
// 分支操作加载状态
|
||||
// 分支加载状态
|
||||
const branchLoading = ref(false)
|
||||
|
||||
// 初始化标记,避免重复适应视图(使用 sessionStorage 持久化)
|
||||
// 初始化标记
|
||||
const INIT_KEY = 'plan-modification-initialized'
|
||||
const isInitialized = ref(sessionStorage.getItem(INIT_KEY) === 'true')
|
||||
|
||||
// 分支初始化标记
|
||||
// 分支初始化标记
|
||||
const BRANCHES_INIT_KEY = 'plan-modification-branches-initialized'
|
||||
|
||||
// 最后选中的分支ID
|
||||
// 最后选中的分支ID
|
||||
const LAST_SELECTED_BRANCH_KEY = 'plan-modification-last-selected-branch'
|
||||
|
||||
// 标记是否已经挂载
|
||||
// 挂载标记
|
||||
const isMounted = ref(false)
|
||||
|
||||
// 节点尺寸配置
|
||||
const NODE_WIDTH = 120 // 任务节点宽度
|
||||
const ROOT_WIDTH = 200 // 根节点宽度
|
||||
const NODE_GAP = 80 // 节点间距
|
||||
const START_X = 40 // 起始 X 坐标
|
||||
const START_Y = 50 // 起始 Y 坐标
|
||||
// 节点尺寸配置
|
||||
const NODE_WIDTH = 120
|
||||
const ROOT_WIDTH = 200
|
||||
const NODE_GAP = 80
|
||||
const START_X = 40
|
||||
const START_Y = 50
|
||||
|
||||
// 初始化流程图 - 横向布局(根节点为初始目标,只展示流程卡片)
|
||||
// 初始化流程图
|
||||
const initializeFlow = () => {
|
||||
const branchesInitialized = sessionStorage.getItem(BRANCHES_INIT_KEY) === 'true'
|
||||
const savedBranches = selectionStore.getAllFlowBranches()
|
||||
@@ -308,16 +302,16 @@ const initializeFlow = () => {
|
||||
return
|
||||
}
|
||||
|
||||
// 首次初始化:创建完整的流程
|
||||
// 首次初始化
|
||||
|
||||
const newNodes: Node[] = []
|
||||
const newEdges: Edge[] = []
|
||||
|
||||
// 获取初始目标作为根节点
|
||||
// 获取根节点
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal']
|
||||
const initialInput = agentsStore.agentRawPlan.data?.['Initial Input Object']
|
||||
|
||||
// 创建根节点(初始目标)
|
||||
// 创建根节点
|
||||
if (generalGoal) {
|
||||
newNodes.push({
|
||||
id: 'root-goal',
|
||||
@@ -331,7 +325,7 @@ const initializeFlow = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 遍历协作流程,创建任务节点
|
||||
// 创建任务节点
|
||||
collaborationProcess.value.forEach((task, index) => {
|
||||
const taskId = task.Id || `task-${index}`
|
||||
|
||||
@@ -364,13 +358,21 @@ const initializeFlow = () => {
|
||||
animated: true,
|
||||
type: 'smoothstep',
|
||||
style: { stroke: '#e6a23c', strokeWidth: 2 },
|
||||
label: ''
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 如果不是第一个任务,创建从前一个任务到当前任务的连接
|
||||
if (index > 0) {
|
||||
const prevTaskId = collaborationProcess.value[index - 1].Id || `task-${index - 1}`
|
||||
// const prevTaskId = collaborationProcess.value[index - 1].Id || `task-${index - 1}`
|
||||
const prev = collaborationProcess.value[index - 1]
|
||||
const prevTaskId = prev?.Id || `task-${index - 1}`
|
||||
newEdges.push({
|
||||
id: `edge-task-${prevTaskId}-${taskId}`,
|
||||
source: `task-${prevTaskId}`,
|
||||
@@ -380,7 +382,13 @@ const initializeFlow = () => {
|
||||
animated: true,
|
||||
type: 'smoothstep',
|
||||
style: { stroke: '#409eff', strokeWidth: 2 },
|
||||
label: ''
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -388,8 +396,7 @@ const initializeFlow = () => {
|
||||
nodes.value = newNodes
|
||||
edges.value = newEdges
|
||||
|
||||
// 🆕 检查是否需要保存初始流程为分支
|
||||
// 如果没有任何分支(首次初始化),将初始流程保存为一个分支
|
||||
// 检查是否需要保存初始流程为分支
|
||||
if (savedBranches.length === 0) {
|
||||
const initialBranchNodes = newNodes.filter(node => node.id !== 'root-goal')
|
||||
const initialBranchEdges = [...newEdges]
|
||||
@@ -406,7 +413,7 @@ const initializeFlow = () => {
|
||||
sessionStorage.setItem(BRANCHES_INIT_KEY, 'true')
|
||||
}
|
||||
|
||||
// 后续初始化:从 store 恢复所有分支节点
|
||||
// 从 store 恢复分支
|
||||
if (savedBranches.length > 0) {
|
||||
savedBranches.forEach(branch => {
|
||||
branch.nodes.forEach(node => {
|
||||
@@ -425,7 +432,7 @@ const initializeFlow = () => {
|
||||
.map(node => node.id)
|
||||
selectedNodeIds.value = new Set(mainProcessNodeIds)
|
||||
|
||||
// 只在首次挂载后初始化时适应视图,后续数据变化不适应
|
||||
// 首次挂载后适应视图
|
||||
if (isMounted.value && !isInitialized.value) {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
@@ -437,15 +444,15 @@ const initializeFlow = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 监听 currentTask 变化,自动高亮对应分支并更新节点数据
|
||||
// 监听 currentTask 变化
|
||||
watch(
|
||||
() => agentsStore.currentTask,
|
||||
(newTask, oldTask) => {
|
||||
newTask => {
|
||||
if (!newTask) {
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 找到包含 currentTask 的分支
|
||||
// 找到包含 currentTask 的分支
|
||||
const allBranches = selectionStore.getAllFlowBranches()
|
||||
|
||||
const matchedBranch = allBranches.find(branch => {
|
||||
@@ -456,7 +463,7 @@ watch(
|
||||
const branchNodeIds = matchedBranch.nodes.map(node => node.id)
|
||||
selectedNodeIds.value = new Set(branchNodeIds)
|
||||
|
||||
// 更新对应节点的 task 数据(同步 AgentAllocation 中的修改)
|
||||
// 更新节点数据
|
||||
if (newTask.StepName) {
|
||||
const matchedNodes = nodes.value.filter(node => {
|
||||
return node.data?.task?.StepName === newTask.StepName
|
||||
@@ -474,11 +481,24 @@ watch(
|
||||
})
|
||||
|
||||
const nodeIndex = nodes.value.findIndex(n => n.id === node.id)
|
||||
// if (nodeIndex !== -1) {
|
||||
// const updatedNode = {
|
||||
// ...nodes.value[nodeIndex],
|
||||
// data: {
|
||||
// ...nodes.value[nodeIndex].data,
|
||||
// task: { ...newTask },
|
||||
// updateKey: newUpdateKey
|
||||
// }
|
||||
// }
|
||||
// nodes.value.splice(nodeIndex, 1, updatedNode)
|
||||
// }
|
||||
if (nodeIndex !== -1) {
|
||||
const existingNode = nodes.value[nodeIndex]
|
||||
const existingData = existingNode?.data || {}
|
||||
const updatedNode = {
|
||||
...nodes.value[nodeIndex],
|
||||
...existingNode,
|
||||
data: {
|
||||
...nodes.value[nodeIndex].data,
|
||||
...existingData,
|
||||
task: { ...newTask },
|
||||
updateKey: newUpdateKey
|
||||
}
|
||||
@@ -497,7 +517,7 @@ onMounted(() => {
|
||||
isMounted.value = true
|
||||
initializeFlow()
|
||||
|
||||
// 主动同步 currentTask 数据到节点(解决组件晚挂载的问题)
|
||||
// 同步 currentTask 数据
|
||||
if (agentsStore.currentTask && agentsStore.currentTask.StepName) {
|
||||
const matchedNodes = nodes.value.filter(node => {
|
||||
return node.data?.task?.StepName === agentsStore.currentTask!.StepName
|
||||
@@ -508,10 +528,12 @@ onMounted(() => {
|
||||
const nodeIndex = nodes.value.findIndex(n => n.id === node.id)
|
||||
|
||||
if (nodeIndex !== -1) {
|
||||
const existingNode = nodes.value[nodeIndex]
|
||||
const existingData = existingNode?.data || {}
|
||||
const updatedNode = {
|
||||
...nodes.value[nodeIndex],
|
||||
...existingNode,
|
||||
data: {
|
||||
...nodes.value[nodeIndex].data,
|
||||
...existingData,
|
||||
task: { ...agentsStore.currentTask! },
|
||||
updateKey: newUpdateKey
|
||||
}
|
||||
@@ -537,7 +559,7 @@ const onNodeClick = (event: any) => {
|
||||
const nodeId = event.node.id
|
||||
const nodeData = event.node.data as any
|
||||
|
||||
// 如果点击的是根节点,不做处理(根节点不参与高亮)
|
||||
// 根节点不参与高亮
|
||||
if (nodeId === 'root-goal') {
|
||||
return
|
||||
}
|
||||
@@ -549,7 +571,7 @@ const onNodeClick = (event: any) => {
|
||||
// 点击的是主流程节点,高亮所有主流程节点
|
||||
nodesToHighlight = nodes.value.filter(node => isMainProcessNode(node.id)).map(node => node.id)
|
||||
|
||||
// 🆕 切换到初始流程分支
|
||||
// 切换到初始流程分支
|
||||
const allBranches = selectionStore.getAllFlowBranches()
|
||||
const initialBranch = allBranches.find(branch => branch.branchContent === '初始流程')
|
||||
|
||||
@@ -598,7 +620,7 @@ const onNodeClick = (event: any) => {
|
||||
})
|
||||
|
||||
if (matchedBranch) {
|
||||
// 🆕 按照高亮路径顺序收集每个节点的任务数据
|
||||
// 按照高亮路径顺序收集每个节点的任务数据
|
||||
const fullProcessTasks: IRawStepTask[] = []
|
||||
const allBranches = selectionStore.getAllFlowBranches()
|
||||
|
||||
@@ -635,7 +657,7 @@ const onNodeClick = (event: any) => {
|
||||
}
|
||||
})
|
||||
|
||||
// 🆕 保存最后选中的分支ID
|
||||
// 保存最后选中的分支ID
|
||||
sessionStorage.setItem(LAST_SELECTED_BRANCH_KEY, matchedBranch.id)
|
||||
}
|
||||
} else {
|
||||
@@ -648,15 +670,7 @@ const onNodeClick = (event: any) => {
|
||||
selectedNodeIds.value = new Set(nodesToHighlight)
|
||||
}
|
||||
|
||||
// 编辑任务
|
||||
const handleEditTask = (taskId: string) => {
|
||||
const node = nodes.value.find(n => n.id === taskId)
|
||||
if (node && node.data.task) {
|
||||
editingTasks.value[taskId] = node.data.task.TaskContent || ''
|
||||
node.data.isEditing = true
|
||||
}
|
||||
}
|
||||
// 开始添加分支(确保同一时间只有一个输入框)
|
||||
// 开始添加分支
|
||||
const handleStartAddBranch = (nodeId: string) => {
|
||||
currentAddingBranchNodeId.value = nodeId
|
||||
}
|
||||
@@ -668,42 +682,39 @@ const handleCancelAddBranch = () => {
|
||||
|
||||
// 添加分支
|
||||
const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
// 获取父节点
|
||||
// 获取父节点数据
|
||||
const parentNode = nodes.value.find(n => n.id === taskId)
|
||||
if (!parentNode) return
|
||||
|
||||
// ==================== 移动已有分支 ====================
|
||||
// 查找所有已有的分支任务节点(标记为 isBranchTask)
|
||||
// 查找已有分支节点
|
||||
const allExistingBranchNodes = nodes.value.filter(n => n.data.isBranchTask)
|
||||
|
||||
// 🆕 只移动在当前父节点下方的分支节点(Y坐标 > 父节点Y坐标)
|
||||
// 移动父节点下方的分支
|
||||
const parentNodeY = parentNode.position.y
|
||||
const branchesBelowParent = allExistingBranchNodes.filter(node => node.position.y > parentNodeY)
|
||||
|
||||
// 将当前父节点下方的分支向下移动200px
|
||||
// 向下移动分支
|
||||
branchesBelowParent.forEach(node => {
|
||||
node.position.y += 200
|
||||
})
|
||||
|
||||
// 开始加载
|
||||
// 加载中
|
||||
branchLoading.value = true
|
||||
|
||||
try {
|
||||
// 创建分支节点ID
|
||||
const branchId = `branch-${Date.now()}`
|
||||
|
||||
// 计算分支节点位置
|
||||
// 根节点分支:向下分叉
|
||||
// 任务节点分支:向右下方分叉
|
||||
// 计算分支位置
|
||||
let branchX: number
|
||||
let branchY: number
|
||||
|
||||
if (taskId === 'root-goal') {
|
||||
// 根节点分支:在根节点下方
|
||||
// 根节点分支位置
|
||||
branchX = parentNode.position.x
|
||||
branchY = parentNode.position.y + 200
|
||||
} else {
|
||||
// 任务节点分支:在任务节点右下方
|
||||
// 任务节点分支位置
|
||||
branchX = parentNode.position.x + 200
|
||||
branchY = parentNode.position.y + 150
|
||||
}
|
||||
@@ -770,11 +781,18 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
// 直接获取协作流程数据(API 返回二维数组 [[task1, task2, ...]],取第一个分支)
|
||||
newTasks = response?.[0] || []
|
||||
|
||||
// 调试日志:验证数据提取
|
||||
|
||||
// 直接获取协作流程数据
|
||||
// newTasks = response?.[0] || []
|
||||
// 直接获取协作流程数据:兼容返回数组或对象的情况,优先处理二维数组返回
|
||||
if (Array.isArray(response)) {
|
||||
// 可能是二维数组
|
||||
newTasks = (response as any[])[0] || []
|
||||
} else if (response && (response as any)['Collaboration Process']) {
|
||||
// 如果返回的是对象,尝试读取 Collaboration Process 字段
|
||||
newTasks = (response as any)['Collaboration Process'] || []
|
||||
} else {
|
||||
newTasks = []
|
||||
}
|
||||
// ========== 填充每个任务的 TaskProcess ==========
|
||||
for (let i = 0; i < newTasks.length; i++) {
|
||||
const task = newTasks[i]
|
||||
@@ -834,7 +852,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
|
||||
// 创建连接边
|
||||
if (index === 0) {
|
||||
// 第一个任务连接到父节点(从根节点底部到第一个任务左边)
|
||||
// 连接到父节点
|
||||
const newEdge: Edge = {
|
||||
id: `edge-${taskId}-${taskNodeId}`,
|
||||
source: taskId,
|
||||
@@ -844,7 +862,13 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#409eff', strokeWidth: 2, strokeDasharray: '5,5' },
|
||||
label: ''
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -859,7 +883,14 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#409eff', strokeWidth: 2 }
|
||||
style: { stroke: '#409eff', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -867,7 +898,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
// 保存分支数据到 store
|
||||
// 保存分支到 store
|
||||
if (newBranchNodes.length > 0) {
|
||||
selectionStore.addFlowBranch({
|
||||
parentNodeId: taskId,
|
||||
@@ -886,7 +917,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
const newBranchNodes: Node[] = []
|
||||
const newBranchEdges: Edge[] = []
|
||||
|
||||
// 🆕 判断父节点是否是分支节点
|
||||
// 判断父节点是否是分支节点
|
||||
const parentIsBranchTask = parentNode.data.isBranchTask || false
|
||||
|
||||
if (USE_MOCK_DATA) {
|
||||
@@ -894,7 +925,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
const initialInput = agentsStore.agentRawPlan.data?.['Initial Input Object'] || []
|
||||
|
||||
// 🆕 根据父节点类型构建 existingSteps
|
||||
// 根据父节点类型构建 existingSteps
|
||||
let existingSteps: any[] = []
|
||||
let baselineCompletion = 0
|
||||
|
||||
@@ -958,8 +989,6 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
|
||||
// 从响应中获取协作流程数据
|
||||
newTasks = response['Collaboration Process'] || []
|
||||
|
||||
// ========== 填充每个任务的 TaskProcess ==========
|
||||
for (let i = 0; i < newTasks.length; i++) {
|
||||
const task = newTasks[i]
|
||||
if (!task) continue
|
||||
@@ -984,7 +1013,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
const initialInput = agentsStore.agentRawPlan.data?.['Initial Input Object'] || []
|
||||
|
||||
// 🆕 根据父节点类型构建 existingSteps
|
||||
//根据父节点类型构建 existingSteps
|
||||
let existingSteps: any[] = []
|
||||
let baselineCompletion = 0
|
||||
|
||||
@@ -1045,12 +1074,17 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
initialInputs: Array.isArray(initialInput) ? initialInput : [initialInput],
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
console.log('API Response:', response)
|
||||
// 直接获取协作流程数据(API 返回二维数组 [[task1, task2, ...]],取第一个分支)
|
||||
newTasks = response?.[0] || []
|
||||
console.log('获取到的新newTasks:', newTasks)
|
||||
// ========== 填充每个任务的 TaskProcess ==========
|
||||
// 直接获取协作流程数据
|
||||
// newTasks = response?.[0] || []
|
||||
if (Array.isArray(response)) {
|
||||
// 可能是二维数组
|
||||
newTasks = (response as any[])[0] || []
|
||||
} else if (response && (response as any)['Collaboration Process']) {
|
||||
// 如果返回的是对象,尝试读取 Collaboration Process 字段
|
||||
newTasks = (response as any)['Collaboration Process'] || []
|
||||
} else {
|
||||
newTasks = []
|
||||
}
|
||||
for (let i = 0; i < newTasks.length; i++) {
|
||||
const task = newTasks[i]
|
||||
if (!task) continue
|
||||
@@ -1118,7 +1152,13 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#67c23a', strokeWidth: 2, strokeDasharray: '5,5' },
|
||||
label: ''
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -1133,7 +1173,14 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
targetHandle: 'left',
|
||||
type: 'smoothstep',
|
||||
animated: true,
|
||||
style: { stroke: '#67c23a', strokeWidth: 2 }
|
||||
style: { stroke: '#67c23a', strokeWidth: 2 },
|
||||
markerEnd: {
|
||||
type: 'arrow' as any,
|
||||
color: '#43a8aa',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
edges.value.push(newEdge)
|
||||
newBranchEdges.push(newEdge)
|
||||
@@ -1141,7 +1188,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
// 📂 保存分支数据到 store(新增)
|
||||
// 保存分支数据到 store
|
||||
if (newBranchNodes.length > 0) {
|
||||
selectionStore.addFlowBranch({
|
||||
parentNodeId: taskId,
|
||||
@@ -1157,7 +1204,7 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
// 重置当前添加分支的节点 ID
|
||||
currentAddingBranchNodeId.value = null
|
||||
|
||||
// 适应视图以显示新节点
|
||||
// 适应视图
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
fit({ padding: 100, duration: 300 })
|
||||
@@ -1172,21 +1219,12 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分支
|
||||
const handleDeleteBranch = (branchId: string) => {
|
||||
// 删除分支节点
|
||||
nodes.value = nodes.value.filter(n => n.id !== branchId)
|
||||
|
||||
// 删除相关的边
|
||||
edges.value = edges.value.filter(e => e.source !== branchId && e.target !== branchId)
|
||||
}
|
||||
|
||||
// 重置视图
|
||||
const resetView = () => {
|
||||
setTransform({ x: 0, y: 0, zoom: 0.5 })
|
||||
}
|
||||
|
||||
// 重置初始化状态并重新适应视图
|
||||
// 重新适应视图
|
||||
const refitView = () => {
|
||||
isInitialized.value = false
|
||||
sessionStorage.removeItem(INIT_KEY)
|
||||
@@ -1199,7 +1237,7 @@ const refitView = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
initializeFlow,
|
||||
resetView,
|
||||
|
||||
@@ -335,7 +335,7 @@ const handleBranchKeydown = (event: KeyboardEvent) => {
|
||||
|
||||
.el-input__inner {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-primary);
|
||||
color: #000;
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ const handleBranchKeydown = (event: KeyboardEvent) => {
|
||||
|
||||
.el-input__inner {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-primary);
|
||||
color: #000;
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const isDisabled = computed(() => {
|
||||
return !agentsStore.currentTask
|
||||
})
|
||||
|
||||
// 获取agent组合卡片数量 - 当前任务agents(1) + 已确认的agent组合数量
|
||||
// 获取agent组合卡片数量
|
||||
const agentGroupCount = computed(() => {
|
||||
if (!agentsStore.currentTask?.Id) return 1
|
||||
|
||||
|
||||
@@ -8,16 +8,15 @@ const emit = defineEmits<{
|
||||
(e: 'click'): void
|
||||
}>()
|
||||
|
||||
// 获取分支数量 - 主分支(1) + 额外分支数量
|
||||
// 获取分支数量
|
||||
const branchCount = computed(() => {
|
||||
// flowBranches 包含所有通过 Branch 创建的分支
|
||||
const extraBranches = selectionStore.flowBranches?.length || 1
|
||||
// 始终至少有1个主分支
|
||||
|
||||
return extraBranches
|
||||
})
|
||||
|
||||
const handleClick = () => {
|
||||
// console.log('点击分支按钮')
|
||||
emit('click')
|
||||
// 触发打开分支窗口
|
||||
agentsStore.openPlanModification()
|
||||
|
||||
@@ -201,10 +201,8 @@ function clear() {
|
||||
jsplumb.reset()
|
||||
}
|
||||
|
||||
// 🆕 封装连线重绘方法
|
||||
// 封装连线重绘方法
|
||||
const redrawConnections = () => {
|
||||
console.log('🔄 重新绘制 jsplumb 连线')
|
||||
|
||||
// 等待 DOM 更新完成
|
||||
nextTick(() => {
|
||||
// 清除旧连线
|
||||
@@ -221,22 +219,20 @@ const redrawConnections = () => {
|
||||
})
|
||||
|
||||
jsplumb.connects(arr)
|
||||
console.log('✅ jsplumb 连线重绘完成,任务数:', collaborationProcess.value.length)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 🆕 监听 collaborationProcess 变化,自动重绘连线
|
||||
// 监听 collaborationProcess 变化,自动重绘连线
|
||||
watch(
|
||||
() => collaborationProcess,
|
||||
() => {
|
||||
console.log('🔍 collaborationProcess 发生变化,触发重绘')
|
||||
redrawConnections()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 🆕 组件挂载后初始化连线
|
||||
// 组件挂载后初始化连线
|
||||
onMounted(() => {
|
||||
// 初始化时绘制连线
|
||||
nextTick(() => {
|
||||
@@ -246,7 +242,6 @@ onMounted(() => {
|
||||
arr.push(...handleCurrentTask(item, true))
|
||||
})
|
||||
jsplumb.connects(arr)
|
||||
console.log('✅ 初始化 jsplumb 连线完成')
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
@@ -440,7 +435,7 @@ defineExpose({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BranchButton v-dev-only v-if="planReady" @click="openPlanModification" />
|
||||
<BranchButton v-if="planReady" @click="openPlanModification" />
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user