feat(agent): 更新代理面板和输入区域,优化状态管理和界面交互

This commit is contained in:
Wenjie Zhang 2026-05-12 15:26:48 +08:00
parent 369a749c78
commit ef963617fc
4 changed files with 28 additions and 93 deletions

View File

@ -12,8 +12,12 @@
</div>
</div>
<div class="header__right">
<!-- AgentState 显示按钮已移动到输入框底部 -->
<slot name="header-right"></slot>
<slot
name="header-right"
:is-agent-panel-open="isAgentPanelOpen"
:has-active-thread="!!currentChatId"
:toggle-agent-panel="toggleAgentPanel"
></slot>
</div>
</div>
@ -150,12 +154,10 @@
:send-button-disabled="isSendButtonDisabled"
:mention="mentionConfig"
:supports-file-upload="supportsFileUpload"
:is-panel-open="isAgentPanelOpen"
:has-active-thread="!!currentChatId"
:todos="currentTodos"
@send="handleSendOrStop"
@upload-attachment="handleAttachmentUpload"
@toggle-panel="toggleAgentPanel"
>
<template #actions-left-extra>
<slot name="input-actions-left"></slot>
@ -193,8 +195,7 @@
ref="panelWrapperRef"
:class="{
'is-visible': isAgentPanelOpen,
'no-transition': isResizing,
'is-expanded': isAgentPanelExpanded
'no-transition': isResizing
}"
:style="{
flexBasis: isAgentPanelOpen ? `${panelRatio * 100}%` : '0px'
@ -208,10 +209,7 @@
:agent-id="currentThread?.agent_id || currentAgentId"
:agent-config-id="selectedAgentConfigId"
:panel-ratio="panelRatio"
:is-expanded="isAgentPanelExpanded"
@refresh="handleAgentStateRefresh"
@close="toggleAgentPanel"
@toggle-expand="togglePanelExpanded"
@resize="handlePanelResize"
@resizing="handleResizingChange"
/>
@ -360,7 +358,6 @@ const localUIState = reactive({
// Agent Panel State
const isAgentPanelOpen = ref(false)
const isAgentPanelExpanded = ref(false)
const isResizing = ref(false)
const panelRatio = ref(0.3) // (0-1)
const panelWrapperRef = ref(null) // DOM
@ -1583,20 +1580,11 @@ const toggleAgentPanel = async () => {
const nextOpen = !isAgentPanelOpen.value
isAgentPanelOpen.value = nextOpen
if (!nextOpen) {
isAgentPanelExpanded.value = false
}
if (nextOpen) {
await handleAgentStateRefresh()
}
}
const togglePanelExpanded = () => {
if (!isAgentPanelOpen.value) return
isAgentPanelExpanded.value = !isAgentPanelExpanded.value
}
// 使
// (deltaX > 0)(deltaX < 0)
const handlePanelResize = (clientX) => {
@ -2006,11 +1994,11 @@ watch(currentChatId, (threadId, oldThreadId) => {
.agent-panel-wrapper {
flex: 0 0 auto;
align-self: flex-end;
height: 70vh;
align-self: stretch;
height: auto;
overflow: hidden;
z-index: 20;
margin: 28px 8px;
margin: 0 8px 8px;
margin-left: 0;
background: var(--gray-0);
border-radius: 16px;
@ -2019,22 +2007,6 @@ watch(currentChatId, (threadId, oldThreadId) => {
will-change: flex-basis;
}
.agent-panel-wrapper.is-expanded {
align-self: stretch;
height: calc(100% - 16px);
margin-top: 8px;
margin-bottom: 8px;
}
@media (max-height: 700px) {
.agent-panel-wrapper {
height: calc(100% - 56px);
}
.agent-panel-wrapper.is-expanded {
height: calc(100% - 16px);
}
}
/* Workbench transition animations */
.agent-panel-wrapper {

View File

@ -87,16 +87,6 @@
</template>
<template #actions-right>
<div class="input-actions-right">
<button
v-if="hasActiveThread"
class="input-action-btn"
:class="{ active: isPanelOpen }"
@click.stop="$emit('toggle-panel')"
title="查看文件"
>
<FolderKanban :size="18" />
<span>文件</span>
</button>
<slot name="actions-left-extra"></slot>
</div>
</template>
@ -108,7 +98,7 @@ import { computed, ref, watch } from 'vue'
import MessageInputComponent from '@/components/MessageInputComponent.vue'
import ImagePreviewComponent from '@/components/ImagePreviewComponent.vue'
import AttachmentOptionsComponent from '@/components/AttachmentOptionsComponent.vue'
import { FolderKanban, SquareCheck } from 'lucide-vue-next'
import { SquareCheck } from 'lucide-vue-next'
import {
CheckCircleOutlined,
ClockCircleOutlined,
@ -124,7 +114,6 @@ const props = defineProps({
sendButtonDisabled: { type: Boolean, default: false },
mention: { type: Object, default: () => null },
supportsFileUpload: { type: Boolean, default: false },
isPanelOpen: { type: Boolean, default: false },
hasActiveThread: { type: Boolean, default: true },
todos: {
type: Array,
@ -132,13 +121,7 @@ const props = defineProps({
}
})
const emit = defineEmits([
'update:modelValue',
'send',
'keydown',
'upload-attachment',
'toggle-panel'
])
const emit = defineEmits(['update:modelValue', 'send', 'keydown', 'upload-attachment'])
const inputRef = ref(null)
const currentImage = ref(null)

View File

@ -11,16 +11,6 @@
<button class="header-action-btn" title="刷新" @click="emitRefresh">
<RefreshCw :size="15" />
</button>
<button
class="header-action-btn"
:title="isExpanded ? '恢复高度' : '向上展开'"
@click="emit('toggle-expand')"
>
<component :is="isExpanded ? ChevronsDownUp : ChevronsUpDown" :size="15" />
</button>
<button class="close-btn" @click="$emit('close')">
<X :size="18" />
</button>
</div>
</div>
</div>
@ -124,7 +114,7 @@
<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { ChevronsDownUp, ChevronsUpDown, Download, RefreshCw, Trash2, X } from 'lucide-vue-next'
import { Download, RefreshCw, Trash2 } from 'lucide-vue-next'
import { Modal, message } from 'ant-design-vue'
import FileTreeComponent from '@/components/FileTreeComponent.vue'
import AgentFilePreview from '@/components/AgentFilePreview.vue'
@ -159,14 +149,10 @@ const props = defineProps({
panelRatio: {
type: Number,
default: 0.35
},
isExpanded: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['refresh', 'close', 'resize', 'resizing', 'toggle-expand'])
const emit = defineEmits(['refresh', 'resize', 'resizing'])
const INLINE_PREVIEW_MIN_WIDTH = 920
const DEFAULT_EXPANDED_ROOT_DIRECTORY_NAME = 'user-data'
@ -751,23 +737,6 @@ watch(useInlinePreview, (isInline) => {
flex-shrink: 0;
}
.close-btn {
border: none;
background: transparent;
cursor: pointer;
color: var(--gray-500);
padding: 4px;
border-radius: 4px;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background: var(--gray-100);
color: var(--gray-700);
}
}
.tab-content {
flex: 1;

View File

@ -72,9 +72,20 @@
</a-dropdown>
</template>
<template #header-right v-if="userStore.isAdmin">
<template #header-right="{ isAgentPanelOpen, hasActiveThread, toggleAgentPanel }">
<button
v-if="hasActiveThread"
type="button"
class="agent-nav-btn agent-state-btn"
:class="{ active: isAgentPanelOpen }"
title="查看文件"
@click.stop="toggleAgentPanel"
>
<FolderKanban size="18" class="nav-btn-icon" />
<span class="hide-text">文件</span>
</button>
<div
v-if="selectedAgentId"
v-if="userStore.isAdmin && selectedAgentId"
ref="moreButtonRef"
type="button"
class="agent-nav-btn"
@ -141,7 +152,7 @@
import { computed, ref, watch } from 'vue'
import { MessageOutlined, ShareAltOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { Settings2, Ellipsis, ChevronDown, Check, Plus } from 'lucide-vue-next'
import { Settings2, Ellipsis, ChevronDown, Check, Plus, FolderKanban } from 'lucide-vue-next'
import { useRoute, useRouter } from 'vue-router'
import AgentChatComponent from '@/components/AgentChatComponent.vue'
import AgentConfigSidebar from '@/components/AgentConfigSidebar.vue'