feat:任务大纲编辑文字悬浮边框重构
This commit is contained in:
@@ -7,12 +7,14 @@ import websocket from '@/utils/websocket'
|
|||||||
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
||||||
import { useNotification } from '@/composables/useNotification'
|
import { useNotification } from '@/composables/useNotification'
|
||||||
import AssignmentButton from './TaskTemplate/TaskSyllabus/components/AssignmentButton.vue'
|
import AssignmentButton from './TaskTemplate/TaskSyllabus/components/AssignmentButton.vue'
|
||||||
import HistoryList from './TaskTemplate/HistoryList/index.vue'
|
|
||||||
import { withRetry } from '@/utils/retry'
|
import { withRetry } from '@/utils/retry'
|
||||||
import { Clock } from '@element-plus/icons-vue'
|
import UnifiedSettingsPanel from './TaskTemplate/UnifiedSettingsPanel.vue'
|
||||||
|
import { Setting } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'search-start'): void
|
(e: 'search-start'): void
|
||||||
(e: 'search', value: string): void
|
(e: 'search', value: string): void
|
||||||
|
(e: 'open-history'): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const agentsStore = useAgentsStore()
|
const agentsStore = useAgentsStore()
|
||||||
@@ -32,13 +34,11 @@ const currentGenerationId = ref('')
|
|||||||
const currentTaskID = ref('') // 后端数据库主键
|
const currentTaskID = ref('') // 后端数据库主键
|
||||||
|
|
||||||
// 监听 currentTaskID 变化,同步到全局变量(供分支保存使用)
|
// 监听 currentTaskID 变化,同步到全局变量(供分支保存使用)
|
||||||
watch(currentTaskID, (newVal) => {
|
watch(currentTaskID, newVal => {
|
||||||
;(window as any).__CURRENT_TASK_ID__ = newVal || ''
|
;(window as any).__CURRENT_TASK_ID__ = newVal || ''
|
||||||
console.log('♻️ [Task] currentTaskID 同步到全局变量:', (window as any).__CURRENT_TASK_ID__)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentPlanOutline = ref<any>(null) // 用于恢复的完整大纲数据
|
const currentPlanOutline = ref<any>(null) // 用于恢复的完整大纲数据
|
||||||
const historyDialogVisible = ref(false) // 历史记录弹窗控制
|
|
||||||
|
|
||||||
// 解析URL参数
|
// 解析URL参数
|
||||||
function getUrlParam(param: string): string | null {
|
function getUrlParam(param: string): string | null {
|
||||||
@@ -165,11 +165,14 @@ async function handleStop() {
|
|||||||
|
|
||||||
// 发送停止请求(不等待响应,后端设置 should_stop = True)
|
// 发送停止请求(不等待响应,后端设置 should_stop = True)
|
||||||
if (websocket.connected && currentGenerationId.value) {
|
if (websocket.connected && currentGenerationId.value) {
|
||||||
websocket.send('stop_generation', {
|
websocket
|
||||||
|
.send('stop_generation', {
|
||||||
generation_id: currentGenerationId.value
|
generation_id: currentGenerationId.value
|
||||||
}).then((result: any) => {
|
})
|
||||||
|
.then((result: any) => {
|
||||||
console.log('停止生成响应:', result)
|
console.log('停止生成响应:', result)
|
||||||
}).catch((error: any) => {
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
console.log('停止生成请求失败(可能已经停止):', error?.message)
|
console.log('停止生成请求失败(可能已经停止):', error?.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -229,7 +232,12 @@ async function handleSearch() {
|
|||||||
outlineData = response.data.basePlan
|
outlineData = response.data.basePlan
|
||||||
currentGenerationId.value = response.data.generation_id || ''
|
currentGenerationId.value = response.data.generation_id || ''
|
||||||
currentTaskID.value = response.data.task_id || ''
|
currentTaskID.value = response.data.task_id || ''
|
||||||
console.log('📋 WebSocket格式: 从basePlan提取数据, generation_id:', currentGenerationId.value, 'TaskID:', currentTaskID.value)
|
console.log(
|
||||||
|
'📋 WebSocket格式: 从basePlan提取数据, generation_id:',
|
||||||
|
currentGenerationId.value,
|
||||||
|
'TaskID:',
|
||||||
|
currentTaskID.value
|
||||||
|
)
|
||||||
} else if (response?.data) {
|
} else if (response?.data) {
|
||||||
// 可能是WebSocket旧格式或REST API格式
|
// 可能是WebSocket旧格式或REST API格式
|
||||||
outlineData = response.data
|
outlineData = response.data
|
||||||
@@ -285,10 +293,10 @@ async function handleSearch() {
|
|||||||
TaskContent: step.TaskContent,
|
TaskContent: step.TaskContent,
|
||||||
InputObject_List: step.InputObject_List,
|
InputObject_List: step.InputObject_List,
|
||||||
OutputObject: step.OutputObject,
|
OutputObject: step.OutputObject,
|
||||||
Id: step.Id, // 传递步骤ID用于后端定位
|
Id: step.Id // 传递步骤ID用于后端定位
|
||||||
},
|
},
|
||||||
generation_id: fillTaskGenerationId,
|
generation_id: fillTaskGenerationId,
|
||||||
TaskID: fillTaskTaskID, // 后端数据库主键
|
TaskID: fillTaskTaskID // 后端数据库主键
|
||||||
})
|
})
|
||||||
console.log(`📥 fillStepTask 返回完成: 步骤=${step.StepName}`)
|
console.log(`📥 fillStepTask 返回完成: 步骤=${step.StepName}`)
|
||||||
updateStepDetail(step.StepName, detailedStep)
|
updateStepDetail(step.StepName, detailedStep)
|
||||||
@@ -296,8 +304,8 @@ async function handleSearch() {
|
|||||||
{
|
{
|
||||||
maxRetries: 2, // 减少重试次数,因为是串行填充
|
maxRetries: 2, // 减少重试次数,因为是串行填充
|
||||||
initialDelayMs: 1000, // 使用较小的延迟
|
initialDelayMs: 1000, // 使用较小的延迟
|
||||||
shouldRetry: () => isFillingSteps.value && !agentsStore.isStopping, // 可取消的重试
|
shouldRetry: () => isFillingSteps.value && !agentsStore.isStopping // 可取消的重试
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -367,17 +375,12 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
// 打开历史记录弹窗
|
// 打开历史记录弹窗
|
||||||
const openHistoryDialog = () => {
|
const openHistoryDialog = () => {
|
||||||
historyDialogVisible.value = true
|
emit('open-history')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理历史任务恢复
|
// 从历史记录恢复任务
|
||||||
const handleRestorePlan = (plan: any) => {
|
const restoreFromHistory = (plan: any) => {
|
||||||
console.log('♻️ [Task] 恢复历史任务:', plan)
|
// 1. 设置搜索值为历史任务的目标
|
||||||
|
|
||||||
// 1. 关闭弹窗
|
|
||||||
historyDialogVisible.value = false
|
|
||||||
|
|
||||||
// 2. 设置搜索值为历史任务的目标
|
|
||||||
searchValue.value = plan.general_goal
|
searchValue.value = plan.general_goal
|
||||||
|
|
||||||
// 3. 设置当前任务的 task_id(供分支保存使用)
|
// 3. 设置当前任务的 task_id(供分支保存使用)
|
||||||
@@ -402,7 +405,10 @@ const handleRestorePlan = (plan: any) => {
|
|||||||
// 5. 如果有智能体评分数据,更新到 store
|
// 5. 如果有智能体评分数据,更新到 store
|
||||||
if (plan.agent_scores && currentPlanOutline.value) {
|
if (plan.agent_scores && currentPlanOutline.value) {
|
||||||
const tasks = currentPlanOutline.value['Collaboration Process'] || []
|
const tasks = currentPlanOutline.value['Collaboration Process'] || []
|
||||||
console.log('🔍 [Task] 所有步骤名称:', tasks.map((t: any) => t.StepName))
|
console.log(
|
||||||
|
'🔍 [Task] 所有步骤名称:',
|
||||||
|
tasks.map((t: any) => t.StepName)
|
||||||
|
)
|
||||||
console.log('🔍 [Task] agent_scores 的 key:', Object.keys(plan.agent_scores))
|
console.log('🔍 [Task] agent_scores 的 key:', Object.keys(plan.agent_scores))
|
||||||
|
|
||||||
for (const task of tasks) {
|
for (const task of tasks) {
|
||||||
@@ -473,8 +479,13 @@ const handleRestorePlan = (plan: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 恢复任务过程分支
|
// 恢复任务过程分支
|
||||||
if (plan.branches.task_process_branches && typeof plan.branches.task_process_branches === 'object') {
|
if (
|
||||||
console.log('♻️ [Task] 恢复任务过程分支:', { stepCount: Object.keys(plan.branches.task_process_branches).length })
|
plan.branches.task_process_branches &&
|
||||||
|
typeof plan.branches.task_process_branches === 'object'
|
||||||
|
) {
|
||||||
|
console.log('♻️ [Task] 恢复任务过程分支:', {
|
||||||
|
stepCount: Object.keys(plan.branches.task_process_branches).length
|
||||||
|
})
|
||||||
selectionStore.restoreTaskProcessBranchesFromDB(plan.branches.task_process_branches)
|
selectionStore.restoreTaskProcessBranchesFromDB(plan.branches.task_process_branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,10 +509,20 @@ const handleRestorePlan = (plan: any) => {
|
|||||||
success('成功', '已恢复历史任务')
|
success('成功', '已恢复历史任务')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置面板引用
|
||||||
|
const unifiedSettingsPanelRef = ref<InstanceType<typeof UnifiedSettingsPanel> | null>(null)
|
||||||
|
|
||||||
|
// 打开设置面板
|
||||||
|
const openSettingsPanel = () => {
|
||||||
|
unifiedSettingsPanelRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
// 暴露给父组件
|
// 暴露给父组件
|
||||||
defineExpose({
|
defineExpose({
|
||||||
currentTaskID,
|
currentTaskID,
|
||||||
openHistoryDialog
|
openHistoryDialog,
|
||||||
|
restoreFromHistory,
|
||||||
|
openSettingsPanel
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -566,29 +587,14 @@ defineExpose({
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<AssignmentButton v-if="planReady" @click="openAgentAllocationDialog" />
|
<AssignmentButton v-if="planReady" @click="openAgentAllocationDialog" />
|
||||||
<!-- 历史记录按钮 -->
|
<!-- 设置按钮 -->
|
||||||
<el-button
|
<el-button class="setting-button" circle title="设置" @click="openSettingsPanel">
|
||||||
class="history-button"
|
<el-icon size="18px"><Setting /></el-icon>
|
||||||
circle
|
|
||||||
:title="'历史记录'"
|
|
||||||
@click.stop="openHistoryDialog"
|
|
||||||
>
|
|
||||||
<el-icon size="18px"><Clock /></el-icon>
|
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<!-- 统一设置面板 -->
|
||||||
|
<UnifiedSettingsPanel ref="unifiedSettingsPanelRef" />
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
<!-- 历史记录弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
v-model="historyDialogVisible"
|
|
||||||
title="历史任务"
|
|
||||||
width="600px"
|
|
||||||
:close-on-click-modal="true"
|
|
||||||
destroy-on-close
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<HistoryList @restore="handleRestorePlan" />
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -728,8 +734,8 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 历史记录按钮
|
// 设置按钮
|
||||||
.history-button {
|
.setting-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 70px;
|
right: 70px;
|
||||||
top: 28px;
|
top: 28px;
|
||||||
@@ -741,7 +747,7 @@ defineExpose({
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--color-bg-hover);
|
background: var(--color-bg-hover);
|
||||||
color: var(--color-text-hover);
|
color: var(--color-text-taskbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1197,9 +1197,9 @@ const processBtnClass = computed(() => {
|
|||||||
|
|
||||||
const executeBtnClass = computed(() => {
|
const executeBtnClass = computed(() => {
|
||||||
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'refresh') {
|
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(() => {
|
const refreshBtnClass = computed(() => {
|
||||||
@@ -1295,7 +1295,6 @@ defineExpose({
|
|||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button
|
<el-button
|
||||||
:class="executeBtnClass"
|
:class="executeBtnClass"
|
||||||
:color="variables.tertiary"
|
|
||||||
:title="isStreaming ? (isPaused ? '点击继续执行' : '点击暂停执行') : executeBtnTitle"
|
:title="isStreaming ? (isPaused ? '点击继续执行' : '点击暂停执行') : executeBtnTitle"
|
||||||
:disabled="
|
:disabled="
|
||||||
!agentsStore.agentRawPlan.data || (!isStreaming && loading) || isButtonLoading
|
!agentsStore.agentRawPlan.data || (!isStreaming && loading) || isButtonLoading
|
||||||
@@ -1338,7 +1337,7 @@ defineExpose({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 默认状态:显示 action 图标 -->
|
<!-- 默认状态:显示 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-if="showExecuteText && !isStreaming" class="btn-text">任务执行</span>
|
||||||
<span v-else-if="isStreaming && isPaused" 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;
|
animation: fadeInRight 0.3s ease forwards;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// .btn-text {
|
// 任务执行按钮渐变样式
|
||||||
// display: inline-block !important;
|
.task-execute-btn {
|
||||||
// font-size: 14px;
|
background: linear-gradient(to right, #00c5d1, #305ab3) !important;
|
||||||
// font-weight: 500;
|
background-color: transparent !important;
|
||||||
// margin-left: 4px;
|
background-origin: border-box !important;
|
||||||
// opacity: 1;
|
background-clip: border-box !important;
|
||||||
// animation: fadeIn 0.3s ease forwards;
|
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 {
|
@keyframes fadeInLeft {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
import AgentRepo from './AgentRepo/index.vue'
|
import AgentRepo from './AgentRepo/index.vue'
|
||||||
import TaskSyllabus from './TaskSyllabus/index.vue'
|
import TaskSyllabus from './TaskSyllabus/index.vue'
|
||||||
import TaskResult from './TaskResult/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 { Jsplumb } from './utils.ts'
|
||||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||||
import { BezierConnector } from '@jsplumb/browser-ui'
|
import { BezierConnector } from '@jsplumb/browser-ui'
|
||||||
@@ -12,8 +14,29 @@ const props = defineProps<{
|
|||||||
TaskID?: string // 任务唯一标识,用于写入数据库
|
TaskID?: string // 任务唯一标识,用于写入数据库
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'restore', plan: any): void
|
||||||
|
}>()
|
||||||
|
|
||||||
const agentsStore = useAgentsStore()
|
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', {
|
const agentRepoJsplumb = new Jsplumb('task-template', {
|
||||||
connector: {
|
connector: {
|
||||||
@@ -78,6 +101,7 @@ function clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
openHistoryDialog,
|
||||||
changeTask,
|
changeTask,
|
||||||
resetAgentRepoLine,
|
resetAgentRepoLine,
|
||||||
clear
|
clear
|
||||||
@@ -111,6 +135,22 @@ defineExpose({
|
|||||||
@set-current-task="handleTaskResultCurrentTask"
|
@set-current-task="handleTaskResultCurrentTask"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -125,4 +165,86 @@ defineExpose({
|
|||||||
padding-bottom: 20px;
|
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>
|
</style>
|
||||||
|
|||||||
@@ -3,8 +3,12 @@ import Task from './Task.vue'
|
|||||||
import TaskTemplate from './TaskTemplate/index.vue'
|
import TaskTemplate from './TaskTemplate/index.vue'
|
||||||
import { nextTick, ref } from 'vue'
|
import { nextTick, ref } from 'vue'
|
||||||
|
|
||||||
const taskRef = ref<{ currentTaskID: string }>()
|
const taskRef = ref<{ currentTaskID: string; restoreFromHistory: (plan: any) => void }>()
|
||||||
const taskTemplateRef = ref<{ changeTask: () => void; clear: () => void }>()
|
const taskTemplateRef = ref<{
|
||||||
|
changeTask: () => void
|
||||||
|
clear: () => void
|
||||||
|
openHistoryDialog: () => void
|
||||||
|
}>()
|
||||||
|
|
||||||
function handleSearch() {
|
function handleSearch() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -17,16 +21,34 @@ function getTaskID(): string {
|
|||||||
return taskRef.value?.currentTaskID || ''
|
return taskRef.value?.currentTaskID || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开历史记录弹窗
|
||||||
|
function openHistoryDialog() {
|
||||||
|
taskTemplateRef.value?.openHistoryDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理历史任务恢复
|
||||||
|
function handleRestorePlan(plan: any) {
|
||||||
|
taskRef.value?.restoreFromHistory(plan)
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getTaskID
|
getTaskID,
|
||||||
|
openHistoryDialog
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="p-[24px] h-[calc(100%-60px)]">
|
<div class="p-[24px] h-[calc(100%-60px)]">
|
||||||
<Task ref="taskRef" @search="handleSearch" @search-start="taskTemplateRef?.clear" />
|
<Task
|
||||||
<TaskTemplate ref="taskTemplateRef" :TaskID="taskRef?.currentTaskID" />
|
ref="taskRef"
|
||||||
|
@search="handleSearch"
|
||||||
|
@search-start="taskTemplateRef?.clear"
|
||||||
|
@open-history="openHistoryDialog"
|
||||||
|
/>
|
||||||
|
<TaskTemplate
|
||||||
|
ref="taskTemplateRef"
|
||||||
|
:TaskID="taskRef?.currentTaskID"
|
||||||
|
@restore="handleRestorePlan"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
|
||||||
|
|||||||
@@ -7,15 +7,16 @@ import PlanModification from './components/Main/TaskTemplate/TaskSyllabus/Branch
|
|||||||
import { useAgentsStore } from '@/stores/modules/agents'
|
import { useAgentsStore } from '@/stores/modules/agents'
|
||||||
import PlanTask from './components/Main/TaskTemplate/TaskProcess/components/PlanTask.vue'
|
import PlanTask from './components/Main/TaskTemplate/TaskProcess/components/PlanTask.vue'
|
||||||
import AgentAllocation from './components/Main/TaskTemplate/TaskSyllabus/components/AgentAllocation.vue'
|
import AgentAllocation from './components/Main/TaskTemplate/TaskSyllabus/components/AgentAllocation.vue'
|
||||||
|
import { Clock } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const isDarkMode = ref(false)
|
const isDarkMode = ref(false)
|
||||||
const agentsStore = useAgentsStore()
|
const agentsStore = useAgentsStore()
|
||||||
const mainRef = ref<{ currentTaskID: string } | null>(null)
|
const mainRef = ref<{ currentTaskID: string; openHistoryDialog: () => void } | null>(null)
|
||||||
|
|
||||||
// 获取当前的 taskId
|
// 打开历史记录
|
||||||
const currentTaskId = computed(() => {
|
const openHistory = () => {
|
||||||
return mainRef.value?.currentTaskID || ''
|
mainRef.value?.openHistoryDialog()
|
||||||
})
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 等待 Main 组件挂载后获取 taskId
|
// 等待 Main 组件挂载后获取 taskId
|
||||||
@@ -76,7 +77,23 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full relative">
|
<div class="h-full relative">
|
||||||
<!-- 主题切换按钮 - 放置在页面右上角 -->
|
<!-- 左上角按钮组 -->
|
||||||
|
<div class="absolute top-4 left-4 z-50 flex gap-3">
|
||||||
|
<!-- 历史记录按钮 -->
|
||||||
|
<button
|
||||||
|
@click="openHistory"
|
||||||
|
class="w-10 h-10 rounded-full transition-all duration-300 flex items-center justify-center"
|
||||||
|
:class="{
|
||||||
|
'bg-[#ebebeb] hover:bg-[var(--color-bg-hover)]': !isDarkMode,
|
||||||
|
'bg-[#0e131c] hover:bg-[var(--color-bg-hover)]': isDarkMode
|
||||||
|
}"
|
||||||
|
title="历史记录"
|
||||||
|
>
|
||||||
|
<el-icon size="20px"><Clock /></el-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右上角按钮 -->
|
||||||
<div class="absolute top-4 right-4 z-50">
|
<div class="absolute top-4 right-4 z-50">
|
||||||
<button
|
<button
|
||||||
@click="toggleTheme"
|
@click="toggleTheme"
|
||||||
@@ -107,7 +124,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
<Main />
|
<Main ref="mainRef" />
|
||||||
|
|
||||||
<FloatWindow
|
<FloatWindow
|
||||||
v-if="agentsStore.planModificationWindow"
|
v-if="agentsStore.planModificationWindow"
|
||||||
|
|||||||
@@ -114,6 +114,10 @@
|
|||||||
--color-tab-text: #FDFFFF;
|
--color-tab-text: #FDFFFF;
|
||||||
// 智能体标签文字颜色(未选中)
|
// 智能体标签文字颜色(未选中)
|
||||||
--color-tab-text-inactive: rgba(253, 255, 255, 0.4);
|
--color-tab-text-inactive: rgba(253, 255, 255, 0.4);
|
||||||
|
// 任务编辑框悬浮边框颜色
|
||||||
|
--color-task-edit-hover-border: #D6D6D6;
|
||||||
|
// 编辑图标背景色
|
||||||
|
--color-edit-icon-bg: rgba(255, 255, 255, 0.5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,6 +237,10 @@ html.dark {
|
|||||||
--color-tab-text: #FDFFFF;
|
--color-tab-text: #FDFFFF;
|
||||||
// 智能体标签文字颜色(未选中)
|
// 智能体标签文字颜色(未选中)
|
||||||
--color-tab-text-inactive: rgba(253, 255, 255, 0.4);
|
--color-tab-text-inactive: rgba(253, 255, 255, 0.4);
|
||||||
|
// 任务编辑框悬浮边框颜色
|
||||||
|
--color-task-edit-hover-border: #ADA9A7;
|
||||||
|
// 编辑图标背景色
|
||||||
|
--color-edit-icon-bg: rgba(255, 255, 255, 0.5);
|
||||||
|
|
||||||
--el-fill-color-blank: transparent !important;
|
--el-fill-color-blank: transparent !important;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user