From 9b96bd0ba607c1104c64ad1929e02059089cc1a0 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Fri, 22 Aug 2025 23:17:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E9=87=8D=E6=9E=84=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E4=BD=93=E9=85=8D=E7=BD=AE=E4=B8=BA=E4=BE=A7=E8=BE=B9?= =?UTF-8?q?=E6=A0=8F=E5=BD=A2=E5=BC=8F=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BA=A4?= =?UTF-8?q?=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将智能体配置从弹窗改为侧边栏形式,提升用户体验 添加配置侧边栏与聊天侧边栏的互斥逻辑 在智能体选择按钮上添加图标增强视觉提示 移除已完成的任务项标记 --- docs/changelog/update.md | 1 - web/src/components/AgentChatComponent.vue | 5 +- web/src/components/AgentConfigSidebar.vue | 1073 +++++++++++++++++++++ web/src/views/AgentView.vue | 352 +------ 4 files changed, 1107 insertions(+), 324 deletions(-) create mode 100644 web/src/components/AgentConfigSidebar.vue diff --git a/docs/changelog/update.md b/docs/changelog/update.md index e0938a0a..73fc635d 100644 --- a/docs/changelog/update.md +++ b/docs/changelog/update.md @@ -20,7 +20,6 @@ - [x] 文件上传模块 UI的边距、配色有问题 - [x] 知识图谱页面的节点数量统计方法 #236 - [x] 当没有手动添加节点的时候,尝试检索,会出现为创建索引的情况 #236 -- [ ] 删除知识库的时候,没有正常将数据从 Neo4j / Milvus 数据库中删除(需要添加检测脚本) # 💯 More: diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index a3dd4b3b..333cddb9 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -1222,7 +1222,6 @@ watch([convs, () => onGoingConv.messages], () => { scrollToBottom(); }, { deep: true }); - // ==================== 用户交互处理 ==================== // 检查是否在底部(允许一定误差) @@ -1289,6 +1288,10 @@ const scrollToBottom = async () => { const toggleSidebar = () => { state.isSidebarOpen = !state.isSidebarOpen; localStorage.setItem('chat_sidebar_open', state.isSidebarOpen); + // 当打开聊天侧边栏时,关闭配置侧边栏 + if (state.isSidebarOpen) { + emit('close-config-sidebar'); + } console.log("toggleSidebar", state.isSidebarOpen); } diff --git a/web/src/components/AgentConfigSidebar.vue b/web/src/components/AgentConfigSidebar.vue new file mode 100644 index 00000000..4ab58da0 --- /dev/null +++ b/web/src/components/AgentConfigSidebar.vue @@ -0,0 +1,1073 @@ + + + + + \ No newline at end of file diff --git a/web/src/views/AgentView.vue b/web/src/views/AgentView.vue index 850f6c66..bfe9e063 100644 --- a/web/src/views/AgentView.vue +++ b/web/src/views/AgentView.vue @@ -4,6 +4,7 @@
+ 选择:{{ selectedAgent.name || '选择智能体' }}
@@ -27,213 +28,6 @@
- - -
-
-

详细配置信

-

{{ selectedAgent.description }}

-
{{ selectedAgent }}
- - - -
- - - - - - - - - - -
-
- 保存并发布配置 - 重置 -
-
-
-
- -
-
-
- - - -
- -
-
-
-
- {{ tool.name }} -
- - -
-
-
{{ tool.description }}
- -
-
-
- -
-
-
+ + + @@ -294,12 +101,13 @@ import { PlusCircleOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; +import { Bot } from 'lucide-vue-next'; import AgentChatComponent from '@/components/AgentChatComponent.vue'; import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue'; +import AgentConfigSidebar from '@/components/AgentConfigSidebar.vue'; import { useUserStore } from '@/stores/user'; import { chatApi } from '@/apis/auth_api'; import { agentConfigApi } from '@/apis/system_api'; -import { toolsApi } from '@/apis/tools'; // 路由 const router = useRouter(); @@ -310,38 +118,16 @@ const agents = ref({}); const selectedAgentId = ref(null); const defaultAgentId = ref(null); // 存储默认智能体ID const state = reactive({ - agentConfOpen: false, debug_mode: false, - toolsModalOpen: false, agentModalOpen: false, + isConfigSidebarOpen: false, isEmptyConfig: computed(() => !selectedAgentId.value || Object.keys(configurableItems.value).length === 0 ) }); -// 工具相关状态 -const availableTools = ref([]); -const selectedTools = ref([]); -const toolsSearchText = ref(''); -// 过滤后的工具列表 -const filteredTools = computed(() => { - if (!toolsSearchText.value) { - return availableTools.value; - } - const searchLower = toolsSearchText.value.toLowerCase(); - return availableTools.value.filter(tool => - tool.name.toLowerCase().includes(searchLower) || - tool.description.toLowerCase().includes(searchLower) - ); -}); - -// 根据工具ID获取工具名称 -const getToolNameById = (toolId) => { - const tool = availableTools.value.find(t => t.id === toolId); - return tool ? tool.name : toolId; -}; const selectedAgent = computed(() => agents.value[selectedAgentId.value] || {}); const configSchema = computed(() => selectedAgent.value.config_schema || {}); @@ -380,88 +166,9 @@ const setAsDefaultAgent = async () => { } }; -// 多选组件相关方法 -const ensureArray = (key) => { - if (!agentConfig.value[key] || !Array.isArray(agentConfig.value[key])) { - agentConfig.value[key] = []; - } -}; -const isOptionSelected = (key, option) => { - ensureArray(key); - return agentConfig.value[key].includes(option); -}; -const getSelectedCount = (key) => { - ensureArray(key); - return agentConfig.value[key].length; -}; -const toggleOption = (key, option) => { - ensureArray(key); - - const currentOptions = [...agentConfig.value[key]]; - const index = currentOptions.indexOf(option); - - if (index > -1) { - currentOptions.splice(index, 1); - } else { - currentOptions.push(option); - } - - agentConfig.value[key] = currentOptions; -}; - -const clearSelection = (key) => { - agentConfig.value[key] = []; -}; - -// 工具选择相关方法 -const openToolsModal = async () => { - try { - // 如果工具列表还没有加载,则加载 - if (availableTools.value.length === 0) { - await loadAvailableTools(); - } - - // 初始化已选择的工具 - selectedTools.value = [...(agentConfig.value.tools || [])]; - - // 打开弹窗 - state.toolsModalOpen = true; - } catch (error) { - console.error('打开工具选择弹窗失败:', error); - message.error('打开工具选择弹窗失败'); - } -}; - -const toggleToolSelection = (toolId) => { - const index = selectedTools.value.indexOf(toolId); - if (index > -1) { - selectedTools.value.splice(index, 1); - } else { - selectedTools.value.push(toolId); - } -}; - -const removeSelectedTool = (toolId) => { - const index = agentConfig.value.tools.indexOf(toolId); - if (index > -1) { - agentConfig.value.tools.splice(index, 1); - } -}; - -const confirmToolsSelection = () => { - agentConfig.value.tools = [...selectedTools.value]; - state.toolsModalOpen = false; - toolsSearchText.value = ''; -}; - -const cancelToolsSelection = () => { - state.toolsModalOpen = false; - toolsSearchText.value = ''; - selectedTools.value = []; -}; // 获取默认智能体ID const fetchDefaultAgent = async () => { @@ -627,15 +334,7 @@ const selectAgentFromModal = (agentId) => { state.agentModalOpen = false; }; -// 加载工具列表 -const loadAvailableTools = async () => { - try { - const response = await toolsApi.getTools(); - availableTools.value = Object.values(response.tools || {}); - } catch (error) { - console.error('加载工具列表失败:', error); - } -}; + // 初始化 onMounted(async () => { @@ -644,7 +343,7 @@ onMounted(async () => { // 获取智能体列表 await fetchAgents(); // 加载工具列表 - await loadAvailableTools(); + // 恢复上次选择的智能体 const lastSelectedAgent = localStorage.getItem('last-selected-agent'); @@ -690,7 +389,11 @@ const toggleDebugMode = () => { }; const toggleConf = () => { - state.agentConfOpen = !state.agentConfOpen + state.isConfigSidebarOpen = !state.isConfigSidebarOpen + // 当打开配置侧边栏时,关闭聊天侧边栏 + if (state.isConfigSidebarOpen) { + state.isChatSidebarOpen = false + } } @@ -726,8 +429,11 @@ const toggleConf = () => { align-items: center; gap: 10px; - button { + button.header-button { border-radius: 6px; + display: flex; + align-items: center; + gap: 6px; } } } @@ -735,10 +441,12 @@ const toggleConf = () => { .agent-view-body { --gap-radius: 6px; display: flex; + flex-direction: row; width: 100%; flex: 1; min-height: calc(100% - var(--agent-view-header-height)); overflow: hidden; + position: relative; // padding: var(--gap-radius); // gap: var(--gap-radius);