feat:任务大纲编辑文字悬浮边框重构

This commit is contained in:
liailing1026
2026-02-27 11:45:16 +08:00
parent c009db12a6
commit c14430cfae
6 changed files with 263 additions and 81 deletions

View File

@@ -968,10 +968,10 @@ async function restartFromStep(stepIndex: number) {
isStreaming.value = true
currentExecutionId.value = executionId
},
newExecutionId, // 传入前端生成的 execution_id
newExecutionId, // 传入前端生成的 execution_id
stepIndex,
truncatedLog,
props.TaskID || undefined // 传入 TaskID 用于更新数据库
props.TaskID || undefined // 传入 TaskID 用于更新数据库
)
success('重新执行', `正在从步骤 ${stepIndex + 1} 重新执行...`)
@@ -1197,9 +1197,9 @@ const processBtnClass = computed(() => {
const executeBtnClass = computed(() => {
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'refresh') {
return 'circle'
return 'circle task-execute-btn'
}
return agentsStore.agentRawPlan.data ? 'ellipse' : 'circle'
return agentsStore.agentRawPlan.data ? 'ellipse task-execute-btn' : 'circle task-execute-btn'
})
const refreshBtnClass = computed(() => {
@@ -1295,7 +1295,6 @@ defineExpose({
<template #reference>
<el-button
:class="executeBtnClass"
:color="variables.tertiary"
:title="isStreaming ? (isPaused ? '点击继续执行' : '点击暂停执行') : executeBtnTitle"
:disabled="
!agentsStore.agentRawPlan.data || (!isStreaming && loading) || isButtonLoading
@@ -1338,7 +1337,7 @@ defineExpose({
/>
<!-- 默认状态显示 action 图标 -->
<svg-icon v-else icon-class="action" />
<svg-icon v-else icon-class="action" color="var(--color-text-title-header)" />
<span v-if="showExecuteText && !isStreaming" class="btn-text">任务执行</span>
<span v-else-if="isStreaming && isPaused" class="btn-text">继续执行</span>
@@ -1773,15 +1772,23 @@ defineExpose({
animation: fadeInRight 0.3s ease forwards;
}
}
}
// .btn-text {
// display: inline-block !important;
// font-size: 14px;
// font-weight: 500;
// margin-left: 4px;
// opacity: 1;
// animation: fadeIn 0.3s ease forwards;
// }
// 任务执行按钮渐变样式
.task-execute-btn {
background: linear-gradient(to right, #00c5d1, #305ab3) !important;
background-color: transparent !important;
background-origin: border-box !important;
background-clip: border-box !important;
border-radius: 20px !important;
transition: background 0.3s ease !important;
&:hover {
background: linear-gradient(to right, #6431b4, #315ab4) !important;
background-color: transparent !important;
background-origin: border-box !important;
background-clip: border-box !important;
}
}
@keyframes fadeInLeft {

View File

@@ -2,6 +2,8 @@
import AgentRepo from './AgentRepo/index.vue'
import TaskSyllabus from './TaskSyllabus/index.vue'
import TaskResult from './TaskResult/index.vue'
import HistoryList from './HistoryList/index.vue'
import SvgIcon from '@/components/SvgIcon/index.vue'
import { Jsplumb } from './utils.ts'
import { type IRawStepTask, useAgentsStore } from '@/stores'
import { BezierConnector } from '@jsplumb/browser-ui'
@@ -12,8 +14,29 @@ const props = defineProps<{
TaskID?: string // 任务唯一标识,用于写入数据库
}>()
// 定义事件
const emit = defineEmits<{
(e: 'restore', plan: any): void
}>()
const agentsStore = useAgentsStore()
// 历史记录弹窗控制
const historyDialogVisible = ref(false)
// 打开历史记录弹窗
const openHistoryDialog = () => {
historyDialogVisible.value = true
}
// 处理历史任务恢复
const handleRestorePlan = (plan: any) => {
// 关闭弹窗
historyDialogVisible.value = false
// 发送恢复事件给父组件
emit('restore', plan)
}
// 智能体库
const agentRepoJsplumb = new Jsplumb('task-template', {
connector: {
@@ -78,6 +101,7 @@ function clear() {
}
defineExpose({
openHistoryDialog,
changeTask,
resetAgentRepoLine,
clear
@@ -111,6 +135,22 @@ defineExpose({
@set-current-task="handleTaskResultCurrentTask"
/>
</div>
<!-- 历史记录弹窗 -->
<div v-if="historyDialogVisible" class="history-drawer">
<div class="history-drawer-content">
<div class="history-drawer-header">
<span class="history-drawer-title">历史记录</span>
<button class="history-drawer-close" @click="historyDialogVisible = false">
<SvgIcon icon-class="close" size="20px" />
</button>
</div>
<div class="h-[1px] w-full bg-[var(--color-border-separate)] my-[8px]"></div>
<div class="history-drawer-body">
<HistoryList @restore="handleRestorePlan" />
</div>
</div>
</div>
</div>
</template>
@@ -125,4 +165,86 @@ defineExpose({
padding-bottom: 20px;
}
}
// 历史记录 Drawer 样式
:deep(.history-drawer) {
// 强制使用绝对定位,相对于父容器
position: absolute !important;
top: 0 !important;
bottom: 0 !important;
z-index: 1000;
// 高度由 top/bottom 控制
height: auto !important;
background-color: var(--color-bg-three);
border: 1px solid var(--color-card-border-three);
border-radius: 24px;
box-shadow: var(--color-card-shadow-three);
padding-top: 20px;
padding-bottom: 20px;
// 动画
animation: drawer-slide-in 0.5s ease-out;
// 头部
.history-drawer-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px;
background-color: var(--color-bg-three);
}
// 标题
.history-drawer-title {
color: var(--color-text-primary);
font-size: 16px;
font-weight: 600;
padding-left: 8px;
}
// 关闭按钮
.history-drawer-close {
background: none;
border: none;
cursor: pointer;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
color: var(--color-text-regular);
transition: transform 0.3s ease;
&:hover {
transform: rotate(360deg);
}
}
:deep(.el-drawer__body) {
background-color: var(--color-bg-three);
padding: 0;
opacity: 0;
animation: drawer-fade-in 0.5s ease-out forwards;
}
}
@keyframes drawer-slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes drawer-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>