feat(ui): 新增暗色模式支持并调整智能体选择器位置

将智能体选择器从侧边栏移动到主聊天界面头部
调整相关样式以匹配新的布局
This commit is contained in:
Wenjie Zhang 2025-11-23 19:42:51 +08:00
parent 0ff771dc19
commit fb3b864565
5 changed files with 46 additions and 59 deletions

View File

@ -11,7 +11,7 @@
- 开发与生产环境隔离,构建生产镜像 <Badge type="info" text="0.4" />
- 集成 LangFuse (观望) 添加用户日志与用户反馈模块,可以在 AgentView 中查看信息
- 集成 neo4j mcp (或者自己构建工具)
- 文档解析部分的 markdown 中的图片替换为内部可访问的链接
- 文档解析部分的 markdown 中的图片替换为内部可访问的链接 (2/4)
### Bugs
- 部分异常状态下,智能体的模型名称出现重叠[#279](https://github.com/xerrors/Yuxi-Know/issues/279)
@ -28,6 +28,7 @@
- 新增基于知识库文件生成示例问题功能([#335](https://github.com/xerrors/Yuxi-Know/pull/335#issuecomment-3530976425)
- 新增知识库支持文件夹/压缩包上传的功能([#335](https://github.com/xerrors/Yuxi-Know/pull/335#issuecomment-3530976425)
- 新增自定义模型支持、新增 dashscope rerank/embeddings 模型的支持
- 新增暗色模式支持并调整整体 UI[#343](https://github.com/xerrors/Yuxi-Know/pull/343)
### 修复
- 修复重排序模型实际未生效的问题

View File

@ -30,7 +30,7 @@
<div type="button" class="agent-nav-btn" v-if="!chatUIStore.isSidebarOpen" @click="toggleSidebar">
<PanelLeftOpen class="nav-btn-icon" size="18"/>
</div>
<div
<div
type="button"
class="agent-nav-btn"
v-if="!chatUIStore.isSidebarOpen"
@ -41,6 +41,15 @@
<MessageCirclePlus v-else class="nav-btn-icon" size="18"/>
<span class="text" :class="{'hide-text': isMediumContainer}">新对话</span>
</div>
<div
v-if="!props.singleMode"
class="agent-nav-btn"
@click="openAgentModal"
>
<span class="text">{{ currentAgentName || '选择智能体' }}</span>
<ChevronDown size="16" class="switch-icon" />
</div>
</div>
<div class="header__right">
<!-- AgentState 显示按钮 - 只在智能体支持 todo files 能力时显示 -->
@ -234,7 +243,7 @@ import AgentMessageComponent from '@/components/AgentMessageComponent.vue'
import ImagePreviewComponent from '@/components/ImagePreviewComponent.vue'
import ChatSidebarComponent from '@/components/ChatSidebarComponent.vue'
import RefsComponent from '@/components/RefsComponent.vue'
import { PanelLeftOpen, MessageCirclePlus, LoaderCircle, Layers } from 'lucide-vue-next';
import { PanelLeftOpen, MessageCirclePlus, LoaderCircle, Layers, ChevronDown } from 'lucide-vue-next';
import { handleChatError, handleValidationError } from '@/utils/errorHandler';
import { ScrollController } from '@/utils/scrollController';
import { AgentValidator } from '@/utils/agentValidator';
@ -1432,10 +1441,19 @@ watch(conversations, () => {
align-items: center;
padding: 1rem 8px;
.header__left, .header__right, .header__center {
.header__left, .header__right {
display: flex;
align-items: center;
}
.switch-icon {
color: var(--gray-500);
transition: all 0.2s ease;
}
.agent-nav-btn:hover .switch-icon {
color: var(--main-500);
}
}
}

View File

@ -22,7 +22,7 @@
<p class="agent-description">{{ selectedAgent.description }}</p>
</div>
<a-divider />
<!-- <a-divider /> -->
<div v-if="selectedAgentId && configurableItems" class="config-form-content">
<!-- 配置表单 -->
@ -357,7 +357,8 @@ const closeSidebar = () => {
const getConfigLabel = (key, value) => {
// console.log(configurableItems)
if (value.description && value.name !== key) {
return `${value.name}${key}`;
return `${value.name}`;
// return `${value.name}${key}`;
}
return key;
};
@ -695,7 +696,14 @@ watch(() => props.isOpen, (newVal) => {
}
.config-item {
margin: 30px 0;
background-color: var(--gray-50);
padding: 12px;
border-radius: 8px;
box-shadow: 0px 1px 1px var(--shadow-2);
:deep(label.form_item_model) {
font-weight: 600;
}
.config-description {
margin: 4px 0 8px 0;

View File

@ -2,15 +2,7 @@
<div class="chat-sidebar" :class="{'sidebar-open': chatUIStore.isSidebarOpen, 'no-transition': isInitialRender}">
<div class="sidebar-content">
<div class="sidebar-header">
<div class="header-title" v-if="singleMode">{{ selectedAgentName }}</div>
<div
v-else
class="agent-selector"
@click="openAgentModal"
>
<span class="agent-name">{{ selectedAgentName || '选择智能体' }}</span>
<ChevronDown size="16" class="switch-icon" />
</div>
<div class="header-title">{{ branding.name }}</div>
<div class="header-actions">
<div class="toggle-sidebar nav-btn" v-if="chatUIStore.isSidebarOpen" @click="toggleCollapse">
<PanelLeftClose size="20" color="var(--gray-800)"/>
@ -73,12 +65,17 @@ import {
MoreOutlined
} from '@ant-design/icons-vue';
import { message, Modal } from 'ant-design-vue';
import { PanelLeftClose, MessageSquarePlus, ChevronDown, LoaderCircle } from 'lucide-vue-next';
import { PanelLeftClose, MessageSquarePlus, LoaderCircle } from 'lucide-vue-next';
import dayjs, { parseToShanghai } from '@/utils/time';
import { useChatUIStore } from '@/stores/chatUI';
import { useInfoStore } from '@/stores/info';
import { storeToRefs } from 'pinia';
// 使 chatUI store
const chatUIStore = useChatUIStore();
const infoStore = useInfoStore();
const { branding } = storeToRefs(infoStore);
const props = defineProps({
currentAgentId: {
@ -113,13 +110,7 @@ const props = defineProps({
const emit = defineEmits(['create-chat', 'select-chat', 'delete-chat', 'rename-chat', 'toggle-sidebar', 'open-agent-modal']);
const selectedAgentName = computed(() => {
if (props.selectedAgentId && props.agents && props.agents.length > 0) {
const agent = props.agents.find(a => a.id === props.selectedAgentId);
return agent ? agent.name : '';
}
return '';
});
const groupedChats = computed(() => {
const groups = {
@ -221,16 +212,14 @@ const toggleCollapse = () => {
emit('toggle-sidebar');
};
const openAgentModal = () => {
emit('open-agent-modal');
};
</script>
<style lang="less" scoped>
.chat-sidebar {
width: 0;
height: 100%;
background-color: var(--gray-25);
background-color: var(--gray-0);
transition: all 0.3s ease;
display: flex;
flex-direction: column;
@ -280,7 +269,7 @@ const openAgentModal = () => {
flex-shrink: 0;
.header-title {
font-weight: 500;
font-weight: 600;
font-size: 16px;
color: var(--gray-900);
white-space: nowrap;
@ -479,34 +468,5 @@ const openAgentModal = () => {
}
}
//
.agent-selector {
cursor: pointer;
font-size: 15px;
color: var(--gray-900);
transition: color 0.2s ease;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
.agent-name {
transition: color 0.2s ease;
}
.switch-icon {
color: var(--gray-500);
transition: all 0.2s ease;
}
&:hover {
.agent-name {
color: var(--main-500);
}
.switch-icon {
color: var(--main-500);
transform: translateY(1px);
}
}
}
</style>

View File

@ -202,7 +202,7 @@ const mainList = [{
</RouterLink>
</div>
<div class="header-mobile">
<RouterLink to="/chat" class="nav-item" active-class="active">对话</RouterLink>
<RouterLink to="/agent" class="nav-item" active-class="active">对话</RouterLink>
<RouterLink to="/database" class="nav-item" active-class="active">知识</RouterLink>
<RouterLink to="/setting" class="nav-item" active-class="active">设置</RouterLink>
</div>