From 5b14b3f48da6fba6bd7c627d6d708c12790f9cc8 Mon Sep 17 00:00:00 2001 From: baiyanyun Date: Tue, 14 Jul 2026 16:38:29 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=B8=8E=E8=AE=BE=E7=BD=AE=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent-electron-client/src/main/main.ts | 6 + .../src/renderer/App.tsx | 227 +++++++++--------- .../renderer/components/layout/AppSidebar.tsx | 172 ++++++------- .../components/pages/SystemSettingsPage.tsx | 59 +++++ .../components/pages/ToolIntegrationPage.tsx | 65 +++++ .../components/settings/MCPSettings.tsx | 7 +- .../src/renderer/index.css | 179 +++++++++----- .../renderer/styles/components/App.module.css | 11 - .../styles/components/AppSidebar.module.css | 141 +++++++---- .../components/SystemSettingsPage.module.css | 57 +++++ .../components/ToolIntegrationPage.module.css | 28 +++ 11 files changed, 616 insertions(+), 336 deletions(-) create mode 100644 qimingclaw/crates/agent-electron-client/src/renderer/components/pages/SystemSettingsPage.tsx create mode 100644 qimingclaw/crates/agent-electron-client/src/renderer/components/pages/ToolIntegrationPage.tsx delete mode 100644 qimingclaw/crates/agent-electron-client/src/renderer/styles/components/App.module.css create mode 100644 qimingclaw/crates/agent-electron-client/src/renderer/styles/components/SystemSettingsPage.module.css create mode 100644 qimingclaw/crates/agent-electron-client/src/renderer/styles/components/ToolIntegrationPage.module.css diff --git a/qimingclaw/crates/agent-electron-client/src/main/main.ts b/qimingclaw/crates/agent-electron-client/src/main/main.ts index 638c583d..bf981137 100644 --- a/qimingclaw/crates/agent-electron-client/src/main/main.ts +++ b/qimingclaw/crates/agent-electron-client/src/main/main.ts @@ -187,6 +187,12 @@ function createWindow() { minHeight: DEFAULT_WINDOW_MIN_HEIGHT, title: APP_DISPLAY_NAME, icon: getIconPath(), + ...(process.platform === "darwin" + ? { + titleBarStyle: "hiddenInset" as const, + trafficLightPosition: { x: 18, y: 16 }, + } + : {}), webPreferences: { preload: path.join(__dirname, "..", "preload", "index.js"), contextIsolation: true, diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx b/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx index 2fe2b176..59c7c0da 100644 --- a/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx +++ b/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx @@ -15,7 +15,7 @@ import { notification, message, } from "antd"; -import { ArrowLeftOutlined, ReloadOutlined } from "@ant-design/icons"; +import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons"; import { setupService, authService, @@ -29,7 +29,11 @@ import { logout, isLoggedIn as checkIsLoggedIn, } from "./services/core/auth"; -import { AUTH_KEYS, normalizeAgentEngine } from "@shared/constants"; +import { + APP_DISPLAY_NAME, + AUTH_KEYS, + normalizeAgentEngine, +} from "@shared/constants"; import type { QuickInitConfig } from "@shared/types/quickInit"; import type { UpdateState } from "@shared/types/updateTypes"; import { t, getCurrentLang } from "./services/core/i18n"; @@ -38,12 +42,6 @@ import LoginPage from "./components/setup/LoginPage"; import SetupDependencies from "./components/setup/SetupDependencies"; import ClientPage from "./components/pages/ClientPage"; import OverviewPage from "./components/pages/OverviewPage"; -import SettingsPage from "./components/pages/SettingsPage"; -import DependenciesPage from "./components/pages/DependenciesPage"; -import AboutPage from "./components/pages/AboutPage"; -import LogViewer from "./components/pages/LogViewer"; -import PermissionsPage from "./components/pages/PermissionsPage"; -import SessionsPage from "./components/pages/SessionsPage"; import AiChatPage from "./components/pages/AiChatPage"; import AutomationPage from "./components/pages/AutomationPage"; import KnowledgePage from "./components/pages/KnowledgePage"; @@ -53,15 +51,15 @@ import McpMarketplacePage from "./components/pages/McpMarketplacePage"; import WorkflowMarketplacePage from "./components/pages/WorkflowMarketplacePage"; import DataFetchPage from "./components/pages/DataFetchPage"; import DocumentEditorPage from "./components/pages/DocumentEditorPage"; -import MCPSettings from "./components/settings/MCPSettings"; -import AppSidebar, { - NavKey, - LegacyTabKey, -} from "./components/layout/AppSidebar"; -import type { WebviewHeaderActions } from "./components/pages/SessionsPage"; +import ToolIntegrationPage, { + ToolIntegrationTab, +} from "./components/pages/ToolIntegrationPage"; +import SystemSettingsPage, { + SystemSettingsTab, +} from "./components/pages/SystemSettingsPage"; +import AppSidebar, { NavKey } from "./components/layout/AppSidebar"; import type { AiAgentLaunchContext } from "./services/core/aiChat"; import { createLogger } from "./services/utils/rendererLog"; -import styles from "./styles/components/App.module.css"; import { lightTheme, darkTheme } from "./styles/theme"; import { FEATURES } from "@shared/featureFlags"; @@ -105,9 +103,7 @@ export function useI18nLang(): I18nContextValue { // Tab 类型定义(对齐 Tauri 客户端) type TabKey = | "overview" - | "client" | "sessions" - | "legacySessions" | "automation" | "knowledge" | "document" @@ -116,12 +112,8 @@ type TabKey = | "agents" | "mcpLibrary" | "workflow" - | "mcp" - | "settings" - | "dependencies" - | "permissions" - | "logs" - | "about"; + | "toolIntegration" + | "systemSettings"; /** macOS/Linux 无 download-progress 时,用本地模拟进度避免长期显示 0%。 */ const UPDATE_SIMULATED_PROGRESS_CAP = 90; @@ -340,11 +332,14 @@ function App() { // ============================================ const [activeTab, setActiveTab] = useState("overview"); const [activeNavKey, setActiveNavKey] = useState("overview"); + const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + const [toolIntegrationTab, setToolIntegrationTab] = + useState("mcp"); + const [systemSettingsTab, setSystemSettingsTab] = + useState("settings"); const [sessionsAutoOpen, setSessionsAutoOpen] = useState(false); const [aiAgentLaunchContext, setAiAgentLaunchContext] = useState(null); - const [webviewActions, setWebviewActions] = - useState(null); const [username, setUsername] = useState(""); const [userEmail, setUserEmail] = useState(""); const [onlineStatus, setOnlineStatus] = useState(null); @@ -903,7 +898,9 @@ function App() { // 监听设置菜单 const handleSettings = () => { console.log("[App] Received menu:settings event"); - setActiveTab("settings"); + setSystemSettingsTab("settings"); + setActiveTab("systemSettings"); + setActiveNavKey("systemSettings"); }; window.electronAPI.on("menu:settings", handleSettings); cleanupHandlers.push(() => @@ -913,7 +910,9 @@ function App() { // 监听依赖管理菜单 const handleDependencies = () => { console.log("[App] Received menu:dependencies event"); - setActiveTab("dependencies"); + setToolIntegrationTab("dependencies"); + setActiveTab("toolIntegration"); + setActiveNavKey("toolIntegration"); }; window.electronAPI.on("menu:dependencies", handleDependencies); cleanupHandlers.push(() => @@ -923,7 +922,9 @@ function App() { // 监听 MCP 设置菜单 const handleMcpSettings = () => { console.log("[App] Received menu:mcp-settings event"); - setActiveTab("settings"); + setToolIntegrationTab("mcp"); + setActiveTab("toolIntegration"); + setActiveNavKey("toolIntegration"); }; window.electronAPI.on("menu:mcp-settings", handleMcpSettings); cleanupHandlers.push(() => @@ -1099,36 +1100,19 @@ function App() { return; } - if (key === "toolIntegration" || key === "systemSettings") { - setActiveTab("settings"); + if (key === "toolIntegration") { + setActiveTab("toolIntegration"); + return; + } + + if (key === "systemSettings") { + setActiveTab("systemSettings"); return; } setActiveTab("overview"); }, []); - const handleLegacySelect = useCallback((key: LegacyTabKey) => { - if (key === "sessions") { - setActiveTab("legacySessions"); - setActiveNavKey("aiChat"); - return; - } - - setActiveTab(key); - const navByLegacyTab: Partial> = { - client: "overview", - sessions: "aiChat", - automation: "automation", - mcp: "systemSettings", - settings: "systemSettings", - dependencies: "systemSettings", - permissions: "systemSettings", - logs: "systemSettings", - about: "systemSettings", - }; - setActiveNavKey(navByLegacyTab[key] || "systemSettings"); - }, []); - const handleDownloadUpdate = useCallback(async () => { if (updateState.canAutoUpdate === false) { await window.electronAPI?.app?.openReleasesPage?.(); @@ -1311,48 +1295,44 @@ function App() { value={{ themeMode, isDarkMode, setThemeMode: handleSetThemeMode }} >
- {webviewActions && ( -
-
- - -
+ {isMacOS && ( +
+
{APP_DISPLAY_NAME}
+
)} {/* 主体部分 */}
- {/* 左侧边栏 (hidden when webview is active) */} - {!webviewActions && ( - - )} + setSidebarCollapsed((current) => !current)} + onLogout={handleSidebarLogout} + /> {/* 主内容区:flex 子撑满,便于日志等页占满高度 */}
{activeTab === "overview" && } - {activeTab === "client" && ( - { - if (tab === "sessions") setSessionsAutoOpen(true); - setActiveTab(tab); - setActiveNavKey( - tab === "sessions" ? "aiChat" : "overview", - ); - }} - services={services} - servicesLoading={servicesLoading} - startingServices={startingServices} - setStartingServices={setStartingServices} - onRefreshServices={pollServicesStatus} - authRefreshTrigger={authRefreshTrigger} - onAuthChange={handleAuthChange} - onLoginStarted={handleLoginStarted} - /> - )} {activeTab === "sessions" && ( setSessionsAutoOpen(false)} /> )} - {activeTab === "legacySessions" && ( - - )} {activeTab === "automation" && } {activeTab === "knowledge" && } {activeTab === "document" && } @@ -1412,12 +1367,52 @@ function App() { )} {activeTab === "mcpLibrary" && } {activeTab === "workflow" && } - {activeTab === "mcp" && } - {activeTab === "settings" && } - {activeTab === "dependencies" && } - {activeTab === "permissions" && } - {activeTab === "logs" && } - {activeTab === "about" && } + {activeTab === "toolIntegration" && ( + { + if (tab === "sessions") { + setSessionsAutoOpen(true); + setActiveTab("sessions"); + setActiveNavKey("aiChat"); + return; + } + if ( + tab === "client" || + tab === "dependencies" || + tab === "permissions" + ) { + setToolIntegrationTab(tab); + setActiveTab("toolIntegration"); + setActiveNavKey("toolIntegration"); + return; + } + setSystemSettingsTab(tab); + setActiveTab("systemSettings"); + setActiveNavKey("systemSettings"); + }} + services={services} + servicesLoading={servicesLoading} + startingServices={startingServices} + setStartingServices={setStartingServices} + onRefreshServices={pollServicesStatus} + authRefreshTrigger={authRefreshTrigger} + onAuthChange={handleAuthChange} + onLoginStarted={handleLoginStarted} + /> + } + isMacOS={isMacOS} + onTabChange={setToolIntegrationTab} + /> + )} + {activeTab === "systemSettings" && ( + + )}
diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/components/layout/AppSidebar.tsx b/qimingclaw/crates/agent-electron-client/src/renderer/components/layout/AppSidebar.tsx index 45f20b94..95391bdd 100644 --- a/qimingclaw/crates/agent-electron-client/src/renderer/components/layout/AppSidebar.tsx +++ b/qimingclaw/crates/agent-electron-client/src/renderer/components/layout/AppSidebar.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Popover } from "antd"; +import { Tooltip } from "antd"; import { AppstoreOutlined, ApiOutlined, @@ -8,15 +8,12 @@ import { CommentOutlined, DatabaseOutlined, FileTextOutlined, - FolderOutlined, - InfoCircleOutlined, LogoutOutlined, MenuFoldOutlined, + MenuUnfoldOutlined, ProjectOutlined, RobotOutlined, - SafetyOutlined, SettingOutlined, - TeamOutlined, ThunderboltOutlined, ToolOutlined, } from "@ant-design/icons"; @@ -37,17 +34,6 @@ export type NavKey = | "toolIntegration" | "systemSettings"; -export type LegacyTabKey = - | "client" - | "sessions" - | "automation" - | "mcp" - | "settings" - | "dependencies" - | "permissions" - | "logs" - | "about"; - interface NavItem { key: NavKey; label: string; @@ -55,12 +41,6 @@ interface NavItem { badge?: string; } -interface LegacyItem { - key: LegacyTabKey; - label: string; - icon: React.ReactNode; -} - interface UpdateNotice { tone: "available" | "downloading" | "install"; label: string; @@ -69,13 +49,14 @@ interface UpdateNotice { interface AppSidebarProps { activeNavKey: NavKey; + collapsed: boolean; username: string; email?: string; onlineStatus: boolean | null; - isMacOS: boolean; updateNotice?: UpdateNotice; + showToggle?: boolean; onNavSelect: (key: NavKey) => void; - onLegacySelect: (key: LegacyTabKey) => void; + onToggle: () => void; onLogout: () => void; } @@ -100,27 +81,6 @@ const settingItems: NavItem[] = [ { key: "systemSettings", label: "系统设置", icon: }, ]; -function getLegacyItems(isMacOS: boolean): LegacyItem[] { - const items: LegacyItem[] = [ - { key: "client", label: "客户端", icon: }, - { key: "sessions", label: "会话", icon: }, - { key: "mcp", label: "MCP", icon: }, - { key: "settings", label: "设置", icon: }, - { key: "dependencies", label: "依赖", icon: }, - ]; - - if (isMacOS) { - items.push({ key: "permissions", label: "授权", icon: }); - } - - items.push( - { key: "logs", label: "日志", icon: }, - { key: "about", label: "关于", icon: }, - ); - - return items; -} - function getInitial(name: string): string { const trimmed = name.trim(); if (!trimmed) return "陇"; @@ -131,16 +91,17 @@ function renderNavItem( item: NavItem, activeNavKey: NavKey, onNavSelect: (key: NavKey) => void, + collapsed: boolean, ) { const active = activeNavKey === item.key; const isStatusBadge = item.badge === "运行中"; - return ( + const button = ( ); + + return ( + + {button} + + ); } export default function AppSidebar({ activeNavKey, + collapsed, username, email, onlineStatus, - isMacOS, updateNotice, + showToggle = true, onNavSelect, - onLegacySelect, + onToggle, onLogout, }: AppSidebarProps) { const displayName = username || "陈星宇"; const displayEmail = email || "xingyu@feitian.com"; - const legacyItems = getLegacyItems(isMacOS); const online = onlineStatus !== false; const updateNoticeToneClass = updateNotice ? styles[ @@ -176,27 +147,20 @@ export default function AppSidebar({ ] : ""; - const historyMenu = ( -
-
历史菜单
- {legacyItems.map((item) => ( - - ))} -
- ); - return ( -