feat:1.任务大纲编排窗口重构及样式调整2.删除按钮添加
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useAgentsStore } from '@/stores'
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import PlanModification from './TaskSyllabus/Branch/PlanModification.vue'
|
||||
import AgentAllocation from './TaskSyllabus/components/AgentAllocation.vue'
|
||||
import PlanTask from './TaskProcess/components/PlanTask.vue'
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
|
||||
// 面板显示状态
|
||||
const visible = ref(false)
|
||||
const activeTab = ref('outline')
|
||||
|
||||
// 判断是否有流程数据
|
||||
const planReady = computed(() => {
|
||||
return agentsStore.agentRawPlan.data !== undefined
|
||||
})
|
||||
|
||||
// 判断是否选中了任务
|
||||
const hasSelectedTask = computed(() => {
|
||||
return !!agentsStore.currentTask
|
||||
})
|
||||
|
||||
// 标签页配置
|
||||
const tabs = [
|
||||
{ key: 'outline', label: '任务大纲编排', icon: 'One', required: '' },
|
||||
{ key: 'agent', label: '专家智能体评选', icon: 'Two', required: 'selectedTask' },
|
||||
{ key: 'process', label: '执行过程编排', icon: 'Three', required: 'selectedTask' }
|
||||
]
|
||||
|
||||
// 判断标签是否可用
|
||||
const isTabDisabled = (tab: typeof tabs[0]) => {
|
||||
if (tab.required === 'selectedTask') {
|
||||
return !hasSelectedTask.value
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取禁用原因的提示文本
|
||||
const getDisabledReason = (tab: typeof tabs[0]) => {
|
||||
if (tab.required === 'selectedTask' && !hasSelectedTask.value) {
|
||||
return '请先在任务大纲中选中一个任务'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// 打开面板
|
||||
const open = () => {
|
||||
visible.value = true
|
||||
// 默认选中可用的第一个标签
|
||||
const firstAvailableTab = tabs.find(t => !isTabDisabled(t))
|
||||
if (firstAvailableTab) {
|
||||
activeTab.value = firstAvailableTab.key
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭面板
|
||||
const close = () => {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
// 切换标签
|
||||
const handleTabChange = (tabKey: string) => {
|
||||
activeTab.value = tabKey
|
||||
}
|
||||
|
||||
// 暴露给父组件
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<!-- 面板主体 -->
|
||||
<Transition name="slide-up">
|
||||
<div v-if="visible" class="settings-panel">
|
||||
<!-- 标签栏 -->
|
||||
<div class="panel-header">
|
||||
<div class="tabs-container">
|
||||
<div
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
:class="[
|
||||
'tab-item',
|
||||
{ 'is-active': activeTab === tab.key },
|
||||
{ 'is-disabled': isTabDisabled(tab) }
|
||||
]"
|
||||
:title="getDisabledReason(tab)"
|
||||
@click="!isTabDisabled(tab) && handleTabChange(tab.key)"
|
||||
>
|
||||
<SvgIcon :icon-class="tab.icon" size="18px" />
|
||||
<span class="tab-label">{{ tab.label }}</span>
|
||||
<span v-if="isTabDisabled(tab)" class="tab-disabled-hint">
|
||||
{{ getDisabledReason(tab) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="close-btn" @click="close">
|
||||
<SvgIcon icon-class="close" size="20px" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="panel-content">
|
||||
<!-- 任务大纲 -->
|
||||
<div v-show="activeTab === 'outline'" class="tab-content first-tab">
|
||||
<PlanModification />
|
||||
</div>
|
||||
|
||||
<!-- 智能体 -->
|
||||
<div v-show="activeTab === 'agent'" class="tab-content">
|
||||
<AgentAllocation />
|
||||
</div>
|
||||
|
||||
<!-- 任务过程 -->
|
||||
<div v-show="activeTab === 'process'" class="tab-content">
|
||||
<PlanTask />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// 面板主体
|
||||
.settings-panel {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
margin-left: -40%;
|
||||
width: 80%;
|
||||
max-width: 1200px;
|
||||
height: 70vh;
|
||||
background: var(--color-bg-three);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 -4px 30px rgba(0, 0, 0.4);
|
||||
z-index: 3000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 标题栏(包含标签栏)
|
||||
.panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 10px 0 30px;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
color: var(--color-text-secondary);
|
||||
transition: all 0.3s;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
|
||||
&:hover {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-secondary);
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 0.2s;
|
||||
position: relative;
|
||||
margin: 0 4px;
|
||||
|
||||
&:hover:not(.is-disabled) {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: var(--color-primary);
|
||||
background: var(--color-settings-panel-content-bg);
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
&:hover:not(.is-disabled)::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: calc(100% - 8px);
|
||||
height: calc(100% - 8px);
|
||||
background: var(--color-bg-detail);
|
||||
border-radius: 40px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
:deep(.svg-icon) {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
&:hover:not(.is-disabled) :deep(.svg-icon) {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
&.is-active :deep(.svg-icon) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tab-disabled-hint {
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--color-bg-detail);
|
||||
color: var(--color-text-secondary);
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.tab-item.is-disabled:hover .tab-disabled-hint {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// 内容区域
|
||||
.panel-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: var(--color-settings-panel-content-bg);
|
||||
margin: 0 10px 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
// 空状态
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: var(--color-text-secondary);
|
||||
gap: 16px;
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
// 动画效果
|
||||
.slide-up-enter-active,
|
||||
.slide-up-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.slide-up-enter-from,
|
||||
.slide-up-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user