feat(task): 添加任务过程编辑功能
- 新增 ProcessCard 组件用于展示和编辑任务流程 - 实现双击编辑任务描述功能 - 添加编辑状态下的卡片式输入界面 - 支持保存和取消编辑操作 - 实现鼠标悬停高亮效果 - 添加颜色处理函数用于界面美化 - 集成到 TaskResult 组件中展示任务过程 - 支持动态创建和管理任务流程连接线 - 添加额外产物编辑功能 - 实现按钮交互状态管理 - 添加滚动和折叠面板事件处理 - 集成 AgentAllocation 组件用于智能体分配 - 实现椭圆框交互效果展示选中状态 - 添加智能体等级颜色配置 - 支持智能体选中状态切换和排序
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { getActionTypeDisplay } from '@/layout/components/config.ts'
|
||||
|
||||
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
|
||||
}>()
|
||||
|
||||
// 当前正在编辑的process ID
|
||||
const editingProcessId = ref<string | null>(null)
|
||||
// 编辑框的值
|
||||
const editValue = ref('')
|
||||
// 鼠标悬停的process ID
|
||||
const hoverProcessId = ref<string | null>(null)
|
||||
|
||||
// 获取颜色浅两号的函数
|
||||
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')}`
|
||||
}
|
||||
|
||||
// 处理鼠标进入
|
||||
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>
|
||||
<div class="process-card">
|
||||
<div class="process-content">
|
||||
<!-- 显示模式 -->
|
||||
<div class="display-content">
|
||||
<span
|
||||
v-for="process in step.TaskProcess"
|
||||
: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">
|
||||
<el-input
|
||||
v-model="editValue"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
placeholder="请输入描述内容"
|
||||
autofocus
|
||||
/>
|
||||
<div class="edit-buttons">
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
icon="Check"
|
||||
@click="handleSave(process.ID)"
|
||||
title="保存"
|
||||
>
|
||||
√
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
icon="Close"
|
||||
@click="handleCancel"
|
||||
title="取消"
|
||||
>
|
||||
×
|
||||
</el-button>
|
||||
</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
|
||||
? getLightColor(getActionTypeDisplay(process.ActionType)?.color || '#909399')
|
||||
: 'transparent'
|
||||
}"
|
||||
@dblclick="handleDblClick(process.ID, process.Description)"
|
||||
>
|
||||
{{ process.Description }}
|
||||
</span>
|
||||
|
||||
<span class="separator" v-if="!process.Description.endsWith('。')">。</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.process-card {
|
||||
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);
|
||||
|
||||
.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 {
|
||||
position: relative;
|
||||
background: #f0f2f5;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-buttons {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
bottom: 8px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
.el-button {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
|
||||
&:first-child {
|
||||
background-color: #67c23a;
|
||||
border-color: #67c23a;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
background-color: #f56c6c;
|
||||
border-color: #f56c6c;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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>
|
||||
Reference in New Issue
Block a user