2025-12-15 20:47:51 +08:00
|
|
|
|
<script setup lang="ts">
|
2026-01-09 13:54:32 +08:00
|
|
|
|
import { ref, computed } from 'vue'
|
2025-12-15 20:47:51 +08:00
|
|
|
|
import { getActionTypeDisplay } from '@/layout/components/config.ts'
|
2025-12-31 19:04:58 +08:00
|
|
|
|
import { useAgentsStore } from '@/stores'
|
|
|
|
|
|
import BranchButton from './components/TaskButton.vue'
|
|
|
|
|
|
|
|
|
|
|
|
const agentsStore = useAgentsStore()
|
2025-12-15 20:47:51 +08:00
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
step: {
|
|
|
|
|
|
Id?: string
|
|
|
|
|
|
TaskProcess: Array<{
|
|
|
|
|
|
ID: string
|
|
|
|
|
|
ActionType: string
|
|
|
|
|
|
AgentName: string
|
|
|
|
|
|
Description: string
|
|
|
|
|
|
}>
|
|
|
|
|
|
}
|
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
(e: 'open-edit', stepId: string, processId: string): void
|
|
|
|
|
|
(e: 'save-edit', stepId: string, processId: string, value: string): void
|
|
|
|
|
|
}>()
|
|
|
|
|
|
|
2026-01-14 17:54:00 +08:00
|
|
|
|
//从 currentTask 中获取数据
|
2026-01-09 13:54:32 +08:00
|
|
|
|
const currentTaskProcess = computed(() => {
|
|
|
|
|
|
const currentTask = agentsStore.currentTask
|
|
|
|
|
|
if (currentTask && currentTask.Id === props.step.Id && currentTask.TaskProcess) {
|
|
|
|
|
|
return currentTask.TaskProcess
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-14 17:54:00 +08:00
|
|
|
|
//从 agentRawPlan 中获取原始数据
|
2026-01-09 13:54:32 +08:00
|
|
|
|
const collaborationProcess = agentsStore.agentRawPlan.data?.['Collaboration Process'] || []
|
|
|
|
|
|
const rawData = collaborationProcess.find((task: any) => task.Id === props.step.Id)
|
|
|
|
|
|
return rawData?.TaskProcess || []
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-12-15 20:47:51 +08:00
|
|
|
|
// 当前正在编辑的process ID
|
|
|
|
|
|
const editingProcessId = ref<string | null>(null)
|
|
|
|
|
|
const editValue = ref('')
|
|
|
|
|
|
// 鼠标悬停的process ID
|
|
|
|
|
|
const hoverProcessId = ref<string | null>(null)
|
|
|
|
|
|
|
2026-01-14 17:54:00 +08:00
|
|
|
|
// 处理卡片点击事件
|
2026-01-09 13:54:32 +08:00
|
|
|
|
function handleCardClick() {
|
|
|
|
|
|
// 如果正在编辑,不处理点击
|
|
|
|
|
|
if (editingProcessId.value) return
|
|
|
|
|
|
|
|
|
|
|
|
// 设置当前任务,与任务大纲联动
|
|
|
|
|
|
if (props.step.Id) {
|
2026-01-14 17:54:00 +08:00
|
|
|
|
agentsStore.setCurrentTask(props.step as any)
|
2026-01-09 13:54:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 19:04:58 +08:00
|
|
|
|
// 检测当前是否是深色模式
|
|
|
|
|
|
function isDarkMode(): boolean {
|
|
|
|
|
|
return document.documentElement.classList.contains('dark')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-15 20:47:51 +08:00
|
|
|
|
// 获取颜色浅两号的函数
|
|
|
|
|
|
function getLightColor(color: string, level: number = 2): string {
|
|
|
|
|
|
if (!color || color.length !== 7 || color[0] !== '#') return color
|
|
|
|
|
|
|
|
|
|
|
|
const r = parseInt(color.substr(1, 2), 16)
|
|
|
|
|
|
const g = parseInt(color.substr(3, 2), 16)
|
|
|
|
|
|
const b = parseInt(color.substr(5, 2), 16)
|
|
|
|
|
|
|
|
|
|
|
|
// 增加亮度(浅两号)
|
|
|
|
|
|
const lightenAmount = level * 20
|
|
|
|
|
|
const newR = Math.min(255, r + lightenAmount)
|
|
|
|
|
|
const newG = Math.min(255, g + lightenAmount)
|
|
|
|
|
|
const newB = Math.min(255, b + lightenAmount)
|
|
|
|
|
|
|
|
|
|
|
|
return `#${Math.round(newR).toString(16).padStart(2, '0')}${Math.round(newG)
|
|
|
|
|
|
.toString(16)
|
|
|
|
|
|
.padStart(2, '0')}${Math.round(newB).toString(16).padStart(2, '0')}`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 19:04:58 +08:00
|
|
|
|
// 获取颜色深两号的函数
|
|
|
|
|
|
function getDarkColor(color: string, level: number = 2): string {
|
|
|
|
|
|
if (!color || color.length !== 7 || color[0] !== '#') return color
|
|
|
|
|
|
|
|
|
|
|
|
const r = parseInt(color.substr(1, 2), 16)
|
|
|
|
|
|
const g = parseInt(color.substr(3, 2), 16)
|
|
|
|
|
|
const b = parseInt(color.substr(5, 2), 16)
|
|
|
|
|
|
|
|
|
|
|
|
// 降低亮度(深两号)
|
|
|
|
|
|
const darkenAmount = level * 20
|
|
|
|
|
|
const newR = Math.max(0, r - darkenAmount)
|
|
|
|
|
|
const newG = Math.max(0, g - darkenAmount)
|
|
|
|
|
|
const newB = Math.max(0, b - darkenAmount)
|
|
|
|
|
|
|
|
|
|
|
|
return `#${Math.round(newR).toString(16).padStart(2, '0')}${Math.round(newG)
|
|
|
|
|
|
.toString(16)
|
|
|
|
|
|
.padStart(2, '0')}${Math.round(newB).toString(16).padStart(2, '0')}`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据主题模式获取调整后的颜色
|
|
|
|
|
|
function getAdjustedColor(color: string, level: number = 2): string {
|
|
|
|
|
|
if (isDarkMode()) {
|
|
|
|
|
|
return getDarkColor(color, level)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return getLightColor(color, level)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-15 20:47:51 +08:00
|
|
|
|
// 处理鼠标进入
|
|
|
|
|
|
function handleMouseEnter(processId: string) {
|
|
|
|
|
|
hoverProcessId.value = processId
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理鼠标离开
|
|
|
|
|
|
function handleMouseLeave() {
|
|
|
|
|
|
hoverProcessId.value = null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理双击编辑(针对单个process)
|
|
|
|
|
|
function handleDblClick(processId: string, currentDescription: string) {
|
|
|
|
|
|
editingProcessId.value = processId
|
|
|
|
|
|
editValue.value = currentDescription
|
|
|
|
|
|
emit('open-edit', props.step.Id || '', processId)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理保存编辑
|
|
|
|
|
|
function handleSave(processId: string) {
|
|
|
|
|
|
if (!editingProcessId.value) return
|
|
|
|
|
|
|
|
|
|
|
|
emit('save-edit', props.step.Id || '', processId, editValue.value)
|
|
|
|
|
|
editingProcessId.value = null
|
|
|
|
|
|
editValue.value = ''
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理取消编辑
|
|
|
|
|
|
function handleCancel() {
|
|
|
|
|
|
editingProcessId.value = null
|
|
|
|
|
|
editValue.value = ''
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
2026-01-09 13:54:32 +08:00
|
|
|
|
<div class="process-card" @click="handleCardClick">
|
2025-12-15 20:47:51 +08:00
|
|
|
|
<div class="process-content">
|
|
|
|
|
|
<!-- 显示模式 -->
|
|
|
|
|
|
<div class="display-content">
|
|
|
|
|
|
<span
|
2026-01-09 13:54:32 +08:00
|
|
|
|
v-for="process in currentTaskProcess"
|
2025-12-15 20:47:51 +08:00
|
|
|
|
:key="process.ID"
|
|
|
|
|
|
class="process-segment"
|
|
|
|
|
|
@mouseenter="handleMouseEnter(process.ID)"
|
|
|
|
|
|
@mouseleave="handleMouseLeave"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="agent-name"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
backgroundColor: getActionTypeDisplay(process.ActionType)?.color || '#909399',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
padding: '2px 6px',
|
|
|
|
|
|
borderRadius: '3px',
|
|
|
|
|
|
marginRight: '4px'
|
|
|
|
|
|
}"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ process.AgentName }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 编辑模式 - 修改为卡片样式 -->
|
|
|
|
|
|
<div v-if="editingProcessId === process.ID" class="edit-container">
|
|
|
|
|
|
<div class="edit-card">
|
2025-12-31 19:04:58 +08:00
|
|
|
|
<div class="flex flex-col gap-3">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="editValue"
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
:autosize="{ minRows: 3, maxRows: 6 }"
|
|
|
|
|
|
placeholder="请输入描述内容"
|
|
|
|
|
|
autofocus
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div class="flex justify-end">
|
|
|
|
|
|
<svg-icon
|
|
|
|
|
|
icon-class="Check"
|
|
|
|
|
|
size="20px"
|
|
|
|
|
|
color="#328621"
|
|
|
|
|
|
class="cursor-pointer mr-4"
|
|
|
|
|
|
@click="handleSave(process.ID)"
|
|
|
|
|
|
title="保存"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<svg-icon
|
|
|
|
|
|
icon-class="Cancel"
|
|
|
|
|
|
size="20px"
|
|
|
|
|
|
color="#8e0707"
|
|
|
|
|
|
class="cursor-pointer mr-1"
|
|
|
|
|
|
@click="handleCancel"
|
|
|
|
|
|
title="取消"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-12-15 20:47:51 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 显示模式 -->
|
|
|
|
|
|
<span
|
|
|
|
|
|
v-else
|
|
|
|
|
|
class="process-description"
|
|
|
|
|
|
:class="{ hovered: hoverProcessId === process.ID }"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
border: `1px solid ${getActionTypeDisplay(process.ActionType)?.border}`,
|
|
|
|
|
|
backgroundColor:
|
|
|
|
|
|
hoverProcessId === process.ID
|
2025-12-31 19:04:58 +08:00
|
|
|
|
? getAdjustedColor(getActionTypeDisplay(process.ActionType)?.color || '#909399')
|
2025-12-15 20:47:51 +08:00
|
|
|
|
: 'transparent'
|
|
|
|
|
|
}"
|
|
|
|
|
|
@dblclick="handleDblClick(process.ID, process.Description)"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ process.Description }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
2026-01-09 13:54:32 +08:00
|
|
|
|
<span class="separator" v-if="process.Description && !process.Description.endsWith('。')"
|
|
|
|
|
|
>。</span
|
|
|
|
|
|
>
|
2025-12-15 20:47:51 +08:00
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-09 13:54:32 +08:00
|
|
|
|
<!-- 按钮点击不会冒泡到卡片 -->
|
2025-12-31 19:04:58 +08:00
|
|
|
|
<BranchButton :step="step" />
|
2025-12-15 20:47:51 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.process-card {
|
2025-12-31 19:04:58 +08:00
|
|
|
|
position: relative;
|
2025-12-15 20:47:51 +08:00
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
background: var(--color-bg-list);
|
|
|
|
|
|
border: 1px solid var(--color-border-default);
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
2026-01-09 13:54:32 +08:00
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.2s ease;
|
2025-12-15 20:47:51 +08:00
|
|
|
|
|
|
|
|
|
|
.process-content {
|
|
|
|
|
|
min-height: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
.display-content {
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: var(--el-text-color-primary);
|
|
|
|
|
|
|
|
|
|
|
|
.process-segment {
|
|
|
|
|
|
display: inline;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.agent-name {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
|
cursor: default;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.edit-container {
|
|
|
|
|
|
display: block; // 改为块级元素,使其换行显示
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
.edit-card {
|
2025-12-21 19:57:33 +08:00
|
|
|
|
//background: #f0f2f5;
|
2025-12-15 20:47:51 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 600px;
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-textarea) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
.el-textarea__inner {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
min-height: 60px;
|
2025-12-21 19:57:33 +08:00
|
|
|
|
color: var(--color-text-taskbar);
|
2025-12-15 20:47:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.edit-buttons {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 8px;
|
2025-12-31 19:04:58 +08:00
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
margin-top: 8px;
|
2025-12-15 20:47:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.process-description {
|
|
|
|
|
|
display: inline;
|
|
|
|
|
|
white-space: normal;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
padding: 2px 4px;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&.hovered {
|
|
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.separator {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child .separator {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.process-card:hover {
|
|
|
|
|
|
border-color: var(--el-border-color);
|
|
|
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|