refactor(ui): 优化调试模式实现并改进界面样式

- 将调试模式状态管理移至 infoStore 实现全局统一控制
- 移除各组件中分散的调试模式状态管理代码
- 调整侧边栏和头部组件的边框和背景颜色
- 优化按钮和交互元素的悬停效果
- 更新文档中的 changelog 记录待办事项
This commit is contained in:
Wenjie Zhang 2025-09-11 03:09:17 +08:00
parent 95b084ec69
commit d6dfa2b5e3
9 changed files with 65 additions and 71 deletions

View File

@ -9,6 +9,8 @@
- [x] 将现在的 graphview.vue 文件中 GraphContainer相关的代码分离到一个单独的组件中然后 actions 和 footer 都是作为 slot top/bottom 提供的
- [x] 然后应用到 web/src/components/ToolCallingResult/KnowledgeGraphResult.vue 中,替换现有的 GraphContainer。
- [ ] 知识图谱的上传和可视化,支持属性,标签的展示
- [ ] 集成智能体评估,首先使用命令行来实现,然后考虑放在 UI 里面展示
- [ ] 开发与生产环境隔离
🐛**BUGs**
- [x] LlightRAG 知识库中,点击边,没有显示,但是在全屏的时候却又能够显示出来。

View File

@ -100,7 +100,6 @@
:message="message"
:key="msgIndex"
:is-processing="isProcessing && conv.status === 'streaming' && msgIndex === conv.messages.length - 1"
:debug-mode="state.debug_mode"
:show-refs="showMsgRefs(message)"
@retry="retryMessage(message)"
>
@ -207,7 +206,6 @@ const threadMessages = ref({});
const uiState = reactive({
...props.state,
debug_mode: computed(() => props.state.debug_mode ?? false),
isSidebarOpen: localStorage.getItem('chat_sidebar_open', 'true') === 'true',
isInitialRender: true,
showRenameButton: false,
@ -1004,8 +1002,8 @@ watch(conversations, () => {
.example-chip {
padding: 6px 12px;
background: var(--gray-100);
border: 1px solid var(--gray-200);
background: var(--gray-25);
// border: 1px solid var(--gray-100);
border-radius: 16px;
cursor: pointer;
font-size: 0.8rem;
@ -1017,11 +1015,10 @@ watch(conversations, () => {
text-overflow: ellipsis;
&:hover {
background: var(--main-50);
// background: var(--main-25);
border-color: var(--main-200);
color: var(--main-700);
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
box-shadow: 0 0px 4px rgba(0, 0, 0, 0.03);
}
&:active {

View File

@ -21,11 +21,6 @@
<div class="agent-info" v-if="selectedAgent">
<div class="agent-basic-info">
<p class="agent-description">{{ selectedAgent.description }}</p>
<!-- <div class="debug-toggle" v-if="selectedAgent.name">
<span class="debug-text">调试信息</span>
<a-switch v-model:checked="debugMode" size="small" />
</div>
<pre v-if="debugMode && selectedAgent.name" class="debug-info">{{ selectedAgent }}</pre> -->
</div>
<a-divider />
@ -334,7 +329,6 @@ const {
// console.log(availableTools.value)
//
const debugMode = ref(false);
const toolsModalOpen = ref(false);
const selectedTools = ref([]);
const toolsSearchText = ref('');
@ -362,10 +356,6 @@ const closeSidebar = () => {
emit('close');
};
const toggleDebugMode = () => {
debugMode.value = !debugMode.value;
};
const getConfigLabel = (key, value) => {
// console.log(configurableItems)
if (value.description && value.name !== key) {
@ -648,30 +638,6 @@ watch(() => props.isOpen, (newVal) => {
color: var(--gray-700);
line-height: 1.5;
}
.debug-toggle {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
cursor: pointer;
.debug-text {
font-size: 13px;
color: var(--gray-600);
}
}
.debug-info {
margin-top: 12px;
padding: 12px;
background: var(--gray-50);
border-radius: 6px;
font-size: 12px;
color: var(--gray-700);
max-height: 200px;
overflow-y: auto;
}
}
}

View File

@ -71,7 +71,7 @@
<!-- 错误消息 -->
</div>
<div v-if="debugMode" class="status-info">{{ message }}</div>
<div v-if="infoStore.debugMode" class="status-info">{{ message }}</div>
<!-- 自定义内容 -->
<slot></slot>
@ -85,6 +85,7 @@ import RefsComponent from '@/components/RefsComponent.vue'
import { Loader, CircleCheckBig } from 'lucide-vue-next';
import { ToolResultRenderer } from '@/components/ToolCallingResult'
import { useAgentStore } from '@/stores/agent'
import { useInfoStore } from '@/stores/info'
import { storeToRefs } from 'pinia'
@ -112,12 +113,13 @@ const props = defineProps({
type: [Array, Boolean],
default: () => false
},
debugMode: {
//
isLatestMessage: {
type: Boolean,
default: false
},
//
isLatestMessage: {
// (使 infoStore.debugMode)
debugMode: {
type: Boolean,
default: false
}
@ -133,6 +135,7 @@ const expandedToolCalls = ref(new Set()); // 展开的工具调用集合
// store
const agentStore = useAgentStore();
const infoStore = useInfoStore();
const { availableTools } = storeToRefs(agentStore);
//

View File

@ -244,7 +244,7 @@ const openAgentModal = () => {
align-items: center;
justify-content: space-between;
padding: 0 16px;
border-bottom: 1px solid var(--gray-200);
border-bottom: 1px solid var(--gray-50);
flex-shrink: 0;
.header-title {
@ -261,6 +261,7 @@ const openAgentModal = () => {
display: flex;
align-items: center;
gap: 8px;
// color: var(--gray-600);
}
}
@ -360,10 +361,10 @@ const openAgentModal = () => {
}
&:hover {
background-color: var(--gray-50);
background-color: var(--gray-25);
.actions-mask {
background: linear-gradient(to right, transparent, var(--gray-100) 20px);
background: linear-gradient(to right, transparent, var(--gray-25) 20px);
}
.actions-mask, .conversation-actions {
@ -372,14 +373,14 @@ const openAgentModal = () => {
}
&.active {
background-color: var(--gray-100);
background-color: var(--gray-50);
.conversation-title {
color: var(--main-600);
font-weight: 500;
}
.actions-mask {
background: linear-gradient(to right, transparent, var(--gray-100) 20px);
background: linear-gradient(to right, transparent, var(--gray-50) 20px);
}
}
}
@ -415,20 +416,25 @@ const openAgentModal = () => {
justify-content: center;
align-items: center;
border-radius: 8px;
color: var(--gray-500);
// padding: 0.5rem;
transition: background-color 0.3s;
&:hover {
color: var(--main-color);
svg {
stroke: var(--gray-600);
}
&:hover svg {
stroke: var(--main-color);
}
}
//
.agent-selector {
cursor: pointer;
font-size: 14px;
font-size: 15px;
color: var(--gray-900);
transition: color 0.2s ease;
font-weight: 500;
&:hover {
color: var(--main-500);

View File

@ -22,6 +22,10 @@
<template #icon><RobotOutlined /></template>
智能体配置
</a-button>
<a-button @click="toggleDebugMode" :type="infoStore.debugMode ? 'primary' : 'default'">
<template #icon><BugOutlined /></template>
Debug 模式: {{ infoStore.debugMode ? '开启' : '关闭' }}
</a-button>
<a-button @click="toggleFullscreen">
<template #icon>
<FullscreenOutlined v-if="!state.isFullscreen" />
@ -99,6 +103,7 @@ import { useConfigStore } from '@/stores/config';
import { useUserStore } from '@/stores/user';
import { useDatabaseStore } from '@/stores/database';
import { useAgentStore } from '@/stores/agent';
import { useInfoStore } from '@/stores/info';
import { useThrottleFn } from '@vueuse/core';
import { message } from 'ant-design-vue';
import {
@ -112,7 +117,8 @@ import {
PlusCircleOutlined,
UserOutlined,
DatabaseOutlined,
RobotOutlined
RobotOutlined,
BugOutlined
} from '@ant-design/icons-vue';
import dayjs from 'dayjs';
import { configApi } from '@/apis/system_api';
@ -122,6 +128,7 @@ const configStore = useConfigStore()
const userStore = useUserStore();
const databaseStore = useDatabaseStore();
const agentStore = useAgentStore();
const infoStore = useInfoStore();
const config = configStore.config;
@ -366,6 +373,12 @@ const printDatabaseInfo = async () => {
}
};
// Debug
const toggleDebugMode = () => {
if (!checkAdminPermission()) return;
infoStore.toggleDebugMode();
};
//
const printAgentConfig = async () => {
if (!checkAdminPermission()) return;

View File

@ -245,7 +245,7 @@ div.header, #app-router-view {
background-color: var(--main-10);
height: 100%;
width: var(--header-width);
border-right: 1px solid var(--gray-300);
border-right: 1px solid var(--gray-100);
.nav {
display: flex;

View File

@ -7,6 +7,7 @@ export const useInfoStore = defineStore('info', () => {
const infoConfig = ref({})
const isLoading = ref(false)
const isLoaded = ref(false)
const debugMode = ref(false)
// 计算属性 - 组织信息
const organization = computed(() => infoConfig.value.organization || {
@ -41,6 +42,14 @@ export const useInfoStore = defineStore('info', () => {
isLoaded.value = true
}
function setDebugMode(enabled) {
debugMode.value = enabled
}
function toggleDebugMode() {
debugMode.value = !debugMode.value
}
async function loadInfoConfig(force = false) {
// 如果已经加载过且不强制刷新,则不重新加载
if (isLoaded.value && !force) {
@ -93,6 +102,7 @@ export const useInfoStore = defineStore('info', () => {
infoConfig,
isLoading,
isLoaded,
debugMode,
// 计算属性
organization,
@ -102,6 +112,8 @@ export const useInfoStore = defineStore('info', () => {
// 方法
setInfoConfig,
setDebugMode,
toggleDebugMode,
loadInfoConfig,
reloadInfoConfig
}

View File

@ -2,19 +2,19 @@
<div class="agent-view">
<div class="agent-view-header">
<div class="header-left">
<div class="header-item">
<span class="brandname">{{ infoStore.branding?.title }}</span>
</div>
<div class="header-item">
<a-button class="header-button" @click="openAgentModal">
<Bot size="18" stroke-width="1.75" />
选择{{ selectedAgent?.name || '选择智能体' }}
</a-button>
<span class="brandname">{{ infoStore.branding?.title }}</span>
</div>
</div>
<div class="header-center">
</div>
<div class="header-right">
<div class="header-item">
<a-button class="header-button" @click="openAgentModal">
<Bot size="18" stroke-width="1.75" />
切换智能体
</a-button>
</div>
<div class="header-item">
<a-button class="header-button" @click="toggleConf" :icon="h(SettingOutlined)"> 配置 </a-button>
</div>
@ -118,7 +118,6 @@ const {
configurableItems,
} = storeToRefs(agentStore);
const state = reactive({
debug_mode: false,
agentModalOpen: false,
isConfigSidebarOpen: false,
isEmptyConfig: computed(() =>
@ -217,11 +216,6 @@ const goToAgentPage = () => {
}
};
const toggleDebugMode = () => {
state.debug_mode = !state.debug_mode;
console.log("debug_mode", state.debug_mode);
};
const toggleConf = () => {
state.isConfigSidebarOpen = !state.isConfigSidebarOpen
}
@ -240,7 +234,7 @@ const toggleConf = () => {
.agent-view-header {
height: var(--agent-view-header-height);
background-color: var(--bg-sider);
border-bottom: 1px solid var(--gray-200);
border-bottom: 1px solid var(--gray-100);
display: flex;
justify-content: space-between;
align-items: center;
@ -260,7 +254,7 @@ const toggleConf = () => {
gap: 10px;
span.brandname {
font-size: 17px;
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin-right: 16px;
@ -271,6 +265,7 @@ const toggleConf = () => {
display: flex;
align-items: center;
gap: 6px;
border-color: var(--gray-100);
}
}
}