style: 优化部分细节样式

This commit is contained in:
Wenjie Zhang 2025-06-29 15:43:40 +08:00
parent 2a0f650963
commit c89ba37617
7 changed files with 157 additions and 265 deletions

View File

@ -7,20 +7,20 @@ class AgentManager:
self._classes = {} self._classes = {}
self._instances = {} # 存储已创建的 agent 实例 self._instances = {} # 存储已创建的 agent 实例
def register_agent(self, agent_id, agent_class): def register_agent(self, agent_class):
self._classes[agent_id] = agent_class self._classes[agent_class.name] = agent_class
def init_all_agents(self): def init_all_agents(self):
for agent_id, agent_class in self._classes.items(): for agent_class in self._classes.values():
self.get_agent(agent_id) self.get_agent(agent_class.name)
def get_agent(self, agent_id, **kwargs): def get_agent(self, agent_name, **kwargs):
# 检查是否已经创建了该 agent 的实例 # 检查是否已经创建了该 agent 的实例
if agent_id not in self._instances: if agent_name not in self._instances:
agent_class = self._classes[agent_id] agent_class = self._classes[agent_name]
self._instances[agent_id] = agent_class() self._instances[agent_name] = agent_class()
return self._instances[agent_id] return self._instances[agent_name]
def get_agents(self): def get_agents(self):
return list(self._instances.values()) return list(self._instances.values())
@ -31,8 +31,8 @@ class AgentManager:
agent_manager = AgentManager() agent_manager = AgentManager()
agent_manager.register_agent("chatbot", ChatbotAgent) agent_manager.register_agent(ChatbotAgent)
agent_manager.register_agent("react", ReActAgent) # 暂时屏蔽 ReActAgent agent_manager.register_agent(ReActAgent) # 暂时屏蔽 ReActAgent
agent_manager.init_all_agents() agent_manager.init_all_agents()
__all__ = ["agent_manager"] __all__ = ["agent_manager"]

View File

@ -7,7 +7,7 @@ from src.agents.registry import BaseAgent
from src.agents.react.configuration import ReActConfiguration from src.agents.react.configuration import ReActConfiguration
class ReActAgent(BaseAgent): class ReActAgent(BaseAgent):
name = "react" name = "ReAct"
description = "A react agent that can answer questions and help with tasks." description = "A react agent that can answer questions and help with tasks."
config_schema = ReActConfiguration config_schema = ReActConfiguration

View File

@ -550,6 +550,10 @@ const toggleToolCall = (toolCallId) => {
-moz-tab-size: 4; -moz-tab-size: 4;
background-color: var(--gray-100); background-color: var(--gray-100);
} }
p:last-child {
margin-bottom: 0;
}
} }
.chat-box.font-smaller #preview-only-preview { .chat-box.font-smaller #preview-only-preview {

View File

@ -263,7 +263,6 @@ const toggleCollapse = () => {
.conversation-title { .conversation-title {
font-size: 14px; font-size: 14px;
color: var(--gray-900); color: var(--gray-900);
margin-bottom: 4px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@ -2,13 +2,9 @@
<div :class="['log-viewer', { fullscreen: state.isFullscreen }]" ref="logViewer"> <div :class="['log-viewer', { fullscreen: state.isFullscreen }]" ref="logViewer">
<div class="control-panel"> <div class="control-panel">
<div class="button-group"> <div class="button-group">
<a-button @click="fetchLogs" :loading="state.fetching"> <a-button @click="fetchLogs" :loading="state.fetching" :icon="h(ReloadOutlined)" class="icon-only">
<template #icon><ReloadOutlined /></template>
刷新
</a-button> </a-button>
<a-button @click="clearLogs"> <a-button @click="clearLogs" :icon="h(ClearOutlined)" class="icon-only">
<template #icon><ClearOutlined /></template>
清空
</a-button> </a-button>
<a-button @click="printSystemConfig"> <a-button @click="printSystemConfig">
<template #icon><SettingOutlined /></template> <template #icon><SettingOutlined /></template>
@ -98,7 +94,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, onActivated, onUnmounted, nextTick, reactive, computed } from 'vue'; import { ref, onMounted, onActivated, onUnmounted, nextTick, reactive, computed, h } from 'vue';
import { useConfigStore } from '@/stores/config'; import { useConfigStore } from '@/stores/config';
import { useUserStore } from '@/stores/user'; import { useUserStore } from '@/stores/user';
import { useDatabaseStore } from '@/stores/database'; import { useDatabaseStore } from '@/stores/database';
@ -428,10 +424,6 @@ const printAgentConfig = async () => {
.control-panel { .control-panel {
margin-bottom: 16px; margin-bottom: 16px;
padding: 16px;
background: var(--gray-50);
border-radius: 8px;
border: 1px solid var(--gray-200);
} }
.button-group { .button-group {
@ -448,6 +440,11 @@ const printAgentConfig = async () => {
border-color: var(--gray-300); border-color: var(--gray-300);
color: var(--gray-700); color: var(--gray-700);
&.icon-only {
min-width: 32px;
padding: 0;
}
&:hover { &:hover {
border-color: var(--main-color); border-color: var(--main-color);
color: var(--main-color); color: var(--main-color);

View File

@ -479,17 +479,7 @@ const filteredModels = computed(() => {
&.available { &.available {
position: relative; position: relative;
overflow: visible; overflow: visible;
&::after { box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.05);
content: '';
position: absolute;
top: -1px;
right: -1px;
width: 6px;
height: 6px;
background: #10b981;
border: 1px solid white;
border-radius: 50%;
}
} }
} }
} }

View File

@ -3,8 +3,8 @@
<div class="agent-view-header"> <div class="agent-view-header">
<div class="header-left"> <div class="header-left">
<div class="header-item"> <div class="header-item">
<a-button class="header-button" @click="toggleSidebar"> <a-button class="header-button" @click="toggleConf">
<template #icon><MenuOutlined /></template> <template #icon><SettingOutlined /></template>
</a-button> </a-button>
</div> </div>
<div class="header-item"> <div class="header-item">
@ -55,8 +55,16 @@
</div> </div>
</div> </div>
<div class="agent-view-body"> <div class="agent-view-body">
<!-- 左侧智能体列表侧边栏 --> <!-- 配置弹窗 -->
<div class="sidebar" :class="{ 'is-open': state.agentSiderbarConfigOpen }"> <a-modal
v-model:open="state.agentConfOpen"
title="智能体详细配置"
:width="600"
:footer="null"
:maskClosable="false"
class="conf-modal"
>
<div class="conf-content">
<div class="agent-info"> <div class="agent-info">
<h3>详细配置信<span @click="toggleDebugMode"></span></h3> <h3>详细配置信<span @click="toggleDebugMode"></span></h3>
<p>{{ selectedAgent.description }}</p> <p>{{ selectedAgent.description }}</p>
@ -166,6 +174,7 @@
</div> </div>
</div> </div>
</a-modal>
<!-- 中间内容区域 --> <!-- 中间内容区域 -->
<div class="content"> <div class="content">
@ -173,7 +182,7 @@
:agent-id="selectedAgentId" :agent-id="selectedAgentId"
:config="agentConfig" :config="agentConfig"
:state="state" :state="state"
@open-config="toggleConfigSidebar(true)" @open-config="toggleConf"
> >
</AgentChatComponent> </AgentChatComponent>
</div> </div>
@ -189,7 +198,6 @@ import {
SettingOutlined, SettingOutlined,
LinkOutlined, LinkOutlined,
StarOutlined, StarOutlined,
MenuOutlined,
StarFilled, StarFilled,
CheckCircleOutlined, CheckCircleOutlined,
PlusCircleOutlined PlusCircleOutlined
@ -210,7 +218,7 @@ const agents = ref({});
const selectedAgentId = ref(null); const selectedAgentId = ref(null);
const defaultAgentId = ref(null); // ID const defaultAgentId = ref(null); // ID
const state = reactive({ const state = reactive({
agentSiderbarConfigOpen: false, agentConfOpen: false,
debug_mode: false, debug_mode: false,
isEmptyConfig: computed(() => isEmptyConfig: computed(() =>
!selectedAgentId.value || !selectedAgentId.value ||
@ -483,8 +491,8 @@ const toggleDebugMode = () => {
console.log("debug_mode", state.debug_mode); console.log("debug_mode", state.debug_mode);
}; };
const toggleSidebar = () => { const toggleConf = () => {
state.agentSiderbarConfigOpen = !state.agentSiderbarConfigOpen state.agentConfOpen = !state.agentConfOpen
} }
</script> </script>
@ -496,7 +504,6 @@ const toggleSidebar = () => {
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
--agent-view-header-height: 60px; --agent-view-header-height: 60px;
--agent-sidebar-width: 450px;
} }
.agent-view-header { .agent-view-header {
@ -533,112 +540,30 @@ const toggleSidebar = () => {
padding: var(--gap-radius); padding: var(--gap-radius);
gap: var(--gap-radius); gap: var(--gap-radius);
.sidebar.is-open,
.content { .content {
border-radius: var(--gap-radius); border-radius: var(--gap-radius);
border: 1px solid var(--gray-300); border: 1px solid var(--gray-300);
} }
} }
.sidebar {
width: 0;
max-width: var(--agent-sidebar-width);
background-color: var(--bg-sider);
overflow-y: auto;
transition: width 0.3s ease;
overflow: hidden;
&.is-open {
width: var(--agent-sidebar-width);
box-sizing: content-box;
}
}
.sidebar-title {
height: var(--header-height);
font-weight: bold;
user-select: none;
white-space: nowrap;
overflow: hidden;
padding-bottom: 1rem;
font-size: 1rem;
border-bottom: 1px solid var(--main-light-3);
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
margin: 0;
}
.agent-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.agent-item {
display: flex;
align-items: center;
padding: 12px;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s;
&:hover {
background-color: var(--main-light-4);
}
&.active {
background-color: var(--main-light-3);
}
}
.agent-info {
padding: 16px;
min-width: calc(var(--agent-sidebar-width) - 16px);
overflow-y: auto;
max-height: calc(100vh - 60px); /* 减去标题栏的高度 */
scrollbar-width: thin;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
background-color: var(--main-light-4);
border-radius: 4px;
}
}
.agent-name {
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.agent-desc {
font-size: 12px;
color: #666;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.agent-model {
width: 100%;
}
.content { .content {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
} }
//
.conf-content {
max-height: 70vh;
overflow-y: auto;
.agent-info {
padding: 0;
width: 100%;
overflow-y: visible;
max-height: none;
}
}
// requirements // requirements
.info-section { .info-section {
margin-top: 16px; margin-top: 16px;
@ -661,35 +586,8 @@ const toggleSidebar = () => {
} }
} }
@media (max-width: 520px) { .agent-model {
.sidebar { width: 100%;
position: absolute;
z-index: 101;
width: 0;
height: 100%;
border-radius: 0 16px 16px 0;
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.05);
&.is-open {
width: var(--agent-sidebar-width);
padding: 16px;
}
}
.config-sidebar {
position: absolute;
z-index: 101;
right: 0;
width: 0;
height: 100%;
border-radius: 16px 0 0 16px;
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.05);
&.is-open {
width: 90%;
max-width: var(--config-sidebar-width);
}
}
} }
.config-modal-content { .config-modal-content {
@ -849,12 +747,16 @@ const toggleSidebar = () => {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
.conf-content {
max-height: 60vh;
}
} }
</style> </style>
<style lang="less"> <style lang="less">
.toggle-sidebar { .toggle-conf {
cursor: pointer; cursor: pointer;
&.nav-btn { &.nav-btn {