设计文档-CC-Switch-Web前端设计文档
CC-Switch-Web前端设计文档
这是基于https://github.com/cp-yu/cc-switch-web网页版本,使用Claude生成的前端设计。
版本:基于
tui-v0.2分支
技术栈:React 18 + TypeScript + Vite + TailwindCSS + Framer Motion
访问地址:http://127.0.0.1:17666
目录
1. 项目概述
CC Switch 是一个 AI 编程助手供应商切换器,支持多个 AI 代码工具(Claude Code、Claude Desktop、Codex、Gemini、OpenCode、OpenClaw、Hermes)的 API 供应商管理与快速切换。
核心功能: - 供应商管理:添加、编辑、删除、复制、拖拽排序供应商 - 一键切换:切换当前激活的 API 供应商 - 本地代理:启动本地代理服务器进行 API 请求路由,支持故障转移 - 提示词管理:为不同应用管理系统提示词 - Skills 管理:安装、更新、卸载 AI 工具技能 - 会话管理:浏览和管理历史对话记录 - MCP 管理:管理 MCP 服务器配置(支持多应用) - 用量统计:通过自定义脚本查询 API 用量
2. 技术架构
1 | src/ |
通信机制
应用通过 src/lib/transport.ts 的 invoke 函数与后端通信,支持两种模式: - Tauri 桌面模式:直接调用 Tauri 命令 - Web 模式(WebSocket/HTTP):通过 /api/invoke HTTP 接口或 WebSocket 通道
事件监听通过 listen 函数实现,支持 Tauri 事件和 WebSocket 事件推送。
状态管理
- 服务端状态:使用
@tanstack/react-query管理,Key 格式为["providers", appId]、["settings"]等 - 本地 UI 状态:
useState管理视图切换、弹窗开关等 - 持久化状态:
localStorage持久化上次选中的 App(cc-switch-last-app)和视图(cc-switch-last-view)
3. 页面结构与路由
CC Switch 是 单页应用(SPA),无前端路由。视图切换通过 currentView 状态变量控制:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15type View =
| "providers" // 主页面:供应商列表
| "settings" // 设置页面
| "prompts" // 提示词管理
| "skills" // Skills 管理
| "skillsDiscovery" // 技能发现页面
| "mcp" // MCP 服务器管理
| "agents" // Agents 配置
| "universal" // 统一供应商面板
| "sessions" // 会话管理
| "workspace" // 工作区文件管理
| "openclawEnv" // OpenClaw 环境变量
| "openclawTools" // OpenClaw 工具配置
| "openclawAgents" // OpenClaw Agents 配置
| "hermesMemory"; // Hermes 记忆管理
视图切换动画:使用 Framer Motion AnimatePresence + opacity: 0→1 淡入淡出(duration: 200ms)。
布局结构
1 | ┌─────────────────────────────────────────┐ |
Header 高度固定 64px,主内容区 paddingTop: 64px。
4. 页面设计详解
4.1 主页面(供应商列表)
组件:src/components/providers/ProviderList.tsx + ProviderCard.tsx
界面布局
1 | Header 右侧工具栏(currentView === "providers"): |
AppSwitcher:横向标签切换,显示各 AI 应用的图标和名称: - Claude / Claude Desktop / Codex / Gemini / OpenCode / OpenClaw / Hermes - 通过 settingsData.visibleApps 控制哪些应用显示
工具栏图标组(在 bg-muted rounded-xl 圆角容器中): - 根据当前 App 动态变化(使用 Framer Motion AnimatePresence) - 默认 App:Skills (🔧) | 提示词 (📖) | 会话 (🕐) | MCP (M) - OpenClaw App:工作区 (📁) | 环境变量 (🔑) | 工具 (🛡) | Agents (⚙) | 会话 (🕐) - Hermes App:Skills (🔧) | 记忆 (🧠) | Web UI (📊) | MCP (M)
添加按钮:橙色圆形按钮 (bg-orange-500),固定尺寸 w-8 h-8,带橙色阴影
ProviderCard 供应商卡片
每个供应商以卡片形式展示,包含:
| 区域 | 内容 |
|---|---|
| 左侧拖拽柄 | GripVertical 图标,hover 时显示 |
| 供应商图标 | 8×8 圆角方形,显示自定义图标或首字母 |
| 供应商名称 | text-base font-semibold,旁边有状态标签 |
| URL/备注 | text-sm text-blue-500,可点击打开外部链接 |
| 右侧用量显示 | 订阅/Copilot/通用用量数据(inline 模式) |
| 操作按钮组 | hover 时淡入显示(opacity 0→1, duration 200ms) |
卡片状态颜色: - 当前激活(普通模式):蓝色边框 border-blue-500/60 + 蓝色渐变背景 from-blue-500/10 - 当前激活(代理接管模式):绿色边框 border-emerald-500/60 + 绿色渐变背景 from-emerald-500/10 - 拖拽中:scale-105 + shadow-lg - 默认:hover 时 border-border-active
操作按钮(鼠标悬停卡片时显示): - 使用中 / 启用(切换供应商) - 编辑 - 复制(复制到新供应商) - 测试模型 - 配置用量查询 - 打开终端(仅 Claude App) - 删除
状态标签(显示在供应商名称右侧): - OMO:紫色背景,OMO 模式 - Slim:靛蓝背景,OMO Slim 模式 - 需要路由:天蓝背景,Claude Desktop 代理模式 - Hermes Managed:灰色背景,Hermes 托管只读供应商 - 健康状态徽章(ProviderHealthBadge) - 故障转移优先级徽章(FailoverPriorityBadge) - ⭐ 官方合作伙伴标记
代理控制
在 Header 右侧(非 OpenCode/OpenClaw/Hermes 应用): - ProxyToggle:开关控件,启用/停止本地代理服务器 - FailoverToggle:开关,启用自动故障转移 - ClaudeDesktopRouteToggle(仅 Claude Desktop):路由切换
代理启用时,Logo “CC Switch” 变为绿色 (text-emerald-500),否则为蓝色 (text-blue-500)。
添加/编辑供应商对话框
组件:AddProviderDialog.tsx / EditProviderDialog.tsx
包含表单字段(根据 App 类型不同而差异): - 供应商名称、分类 - API Key、Base URL - 模型配置 - 图标选择(IconPicker)+ 颜色选择(ColorPicker) - 端点测速(EndpointSpeedTest) - 通用配置编辑器
4.2 设置页面
组件:src/components/settings/SettingsPage.tsx
通过 Tabs 组件分为 6 个标签页:
| 标签 | 内容 |
|---|---|
| 通用 | 界面语言 / 外观主题 / 主页面显示 / Skills 存储 / 窗口行为 / 首选终端 |
| 路由 | 本地路由(代理服务器状态/端口)/ 自动故障转移 / 整流器 / 全局出站代理 |
| 认证 | GitHub Copilot 账号 / Codex OAuth 账号 / 访问密码(Web 模式) |
| 高级 | 配置目录覆盖 / 导入导出 / WebDAV 同步 / 工具版本管理 / 数据库备份 |
| 使用统计 | 代理用量图表(按时间/应用/模型/供应商统计)/ 请求日志 |
| 关于 | 版本信息 / 检查更新 / 项目链接 |
通用标签 语言选项:中文 / 繁体中文 / English / 日本語
外观主题:浅色 / 深色 / 跟随系统
4.3 提示词管理
组件:src/components/prompts/PromptPanel.tsx
- Header 按钮:添加提示词
- 列表显示所有提示词,带统计(共 N 个 · 已启用 M 个)
- 每条提示词:名称、描述、启用开关(
PromptToggle)、编辑/删除操作 - 支持导入已有 CLAUDE.md 文件
- 空状态展示友好提示
数据结构:Prompt —— { id, name, content, description, enabled, createdAt, updatedAt }
4.4 Skills 管理
组件:src/components/skills/UnifiedSkillsPanel.tsx + SkillsPage.tsx
管理视图(skills): - Header 按钮:从备份中恢复 / 从 ZIP 安装 / 导入已有 / 发现技能 - 顶部统计条:各应用已安装数量(Claude: N / Codex: N / …) - 批量更新按钮 - 技能卡片列表
发现视图(skillsDiscovery): - 从远程仓库拉取可用技能 - 搜索框 - 技能卡片:名称、描述、安装按钮 - 仓库管理(添加自定义 GitHub 仓库) - 刷新按钮
每个技能卡片显示:应用适用标签、安装/卸载操作、版本信息、应用启用状态切换
4.5 会话管理
组件:src/components/sessions/SessionManagerPage.tsx
双栏布局(宽屏): - 左栏:会话列表,支持按应用筛选,显示标题和时间 - 右栏:会话详情 - 会话标题、时间戳、项目目录 - claude --resume <session-id> 恢复命令(可复制) - 对话记录列表(用户/AI 消息,带时间戳) - 从该会话启动终端 - 删除会话
批量管理模式:多选会话,批量删除。
4.6 MCP 服务器管理
组件:src/components/mcp/UnifiedMcpPanel.tsx
- Header 按钮:导入已有 / 添加 MCP
- 统计:各应用已配置数量
- 服务器卡片:名称、类型(stdio/http/sse)、应用启用开关
- 添加向导(
McpWizardModal):引导式填写 command/url/args/env - 添加表单(
McpFormModal):完整表单 + JSON 编辑器
服务器类型: - stdio:命令行服务器,填写 command + args + env - http / sse:远程服务器,填写 URL + headers
4.7 登录页面
组件:src/components/LoginPage.tsx
仅在 Web 模式且启用访问密码时显示,提供密码输入框,验证通过后进入主界面。
5. 交互逻辑
5.1 应用切换
- 点击 AppSwitcher 中的 App 标签
setActiveApp(appId)更新当前应用- 持久化到
localStorage(key:cc-switch-last-app) - 触发
useProvidersQuery重新获取该应用的供应商列表 - ProviderList 以 Framer Motion fade 动画重新渲染(duration: 150ms)
5.2 供应商切换
- 点击供应商卡片上的”启用”按钮
- 调用
switchProvider(provider)→providersApi.switch(id, appId) - 后端写入配置文件,发送
provider-switched事件 - 前端监听事件,调用
refetch()刷新列表 - 代理接管模式(
isProxyTakeover)下实现热切换,无需重启 App
5.3 代理模式工作流
- 点击 ProxyToggle 开关
- 调用
proxyApi.startProxyServer()启动本地代理 - 后端返回代理监听地址/端口
- 代理拦截 App 的 API 请求,转发给当前激活供应商
- 切换供应商时调用
proxyApi.switchProxyProvider()实时切换,无需修改 App 配置
故障转移: - 开启后自动监控供应商健康状态 - 供应商故障时自动切换到下一个优先级供应商 - 在 ProviderCard 上显示健康状态徽章和故障转移优先级
5.4 拖拽排序
使用 @dnd-kit/core + @dnd-kit/sortable 实现: 1. 拖拽 GripVertical 手柄 2. 松手后调用 providersApi.updateSortOrder(updates, appId) 3. 排序持久化到数据库 sortIndex 字段
5.5 键盘快捷键
| 快捷键 | 功能 |
|---|---|
Cmd/Ctrl + , | 打开设置 |
Escape | 返回供应商列表(在非 providers 视图下) |
5.6 环境变量冲突检测
启动时和切换 App 时调用 checkAllEnvConflicts() / checkEnvConflicts(appId): - 检测环境变量与配置文件的冲突 - 有冲突时显示 EnvWarningBanner 提示横幅 - 用户可手动关闭(session 级持久化)
5.7 实时事件推送
监听的后端事件: | 事件名 | 触发场景 | 前端响应 | |——–|———-|———-| | provider-switched | 供应商切换 | 刷新供应商列表 | | universal-provider-synced | 统一供应商同步 | 刷新所有供应商 + 更新托盘菜单 | | webdav-sync-status-updated | WebDAV 同步状态变化 | 刷新设置 + 显示错误 Toast | | proxy-official-warning | 代理接管+官方供应商 | 显示警告 Toast |
6. API 接口
所有 API 通过 invoke(command, payload) 调用后端命令,Web 模式下通过 POST /api/invoke 传输。
6.1 供应商 API(providersApi)
| 方法 | 命令 | 描述 |
|---|---|---|
getAll(appId) | get_providers | 获取指定应用的所有供应商 |
getCurrent(appId) | get_current_provider | 获取当前激活供应商 ID |
add(provider, appId, addToLive?) | add_provider | 添加供应商 |
update(provider, appId, originalId?) | update_provider | 更新供应商 |
delete(id, appId) | delete_provider | 删除供应商 |
switch(id, appId) | switch_provider | 切换当前供应商 |
removeFromLiveConfig(id, appId) | remove_provider_from_live_config | 从 live 配置移除(不删数据库) |
updateSortOrder(updates, appId) | update_providers_sort_order | 批量更新排序 |
openTerminal(providerId, appId, opts) | open_provider_terminal | 用供应商配置打开终端 |
getOpenCodeLiveProviderIds() | get_opencode_live_provider_ids | OpenCode live 配置中的供应商 ID 列表 |
getOpenClawLiveProviderIds() | get_openclaw_live_provider_ids | OpenClaw live 配置中的供应商 ID 列表 |
getHermesLiveProviderIds() | get_hermes_live_provider_ids | Hermes live 配置中的供应商 ID 列表 |
6.2 设置 API(settingsApi)
| 方法 | 命令 | 描述 |
|---|---|---|
get() | get_settings | 获取全局设置 |
save(settings) | save_settings | 保存全局设置 |
restart() | restart_app | 重启应用 |
checkUpdates() | check_for_updates | 检查更新 |
exportConfigToFile(filePath) | export_config_to_file | 导出配置到本地文件 |
importConfigFromFile(filePath) | import_config_from_file | 从本地文件导入配置 |
exportConfigForDownload() | GET /api/export-config | 下载配置(Web 模式) |
importConfigFromUpload(file) | POST /api/import-config | 上传配置(Web 模式) |
webdavSyncUpload() | webdav_sync_upload | WebDAV 上传同步 |
webdavSyncDownload() | webdav_sync_download | WebDAV 下载同步 |
getToolVersions(tools?) | get_tool_versions | 获取工具版本信息 |
runToolLifecycleAction(tools, action) | run_tool_lifecycle_action | 安装/更新工具 |
openExternal(url) | — | 打开外部链接(浏览器) |
6.3 代理 API(proxyApi)
| 方法 | 命令 | 描述 |
|---|---|---|
startProxyServer() | start_proxy_server | 启动本地代理服务器 |
stopProxyWithRestore() | stop_proxy_with_restore | 停止代理并恢复配置 |
getProxyStatus() | get_proxy_status | 获取代理状态 |
switchProxyProvider(appType, providerId) | switch_proxy_provider | 代理模式下切换供应商 |
setProxyTakeoverForApp(appType, enabled) | set_proxy_takeover_for_app | 开启/关闭代理接管 |
getGlobalProxyConfig() | get_global_proxy_config | 获取全局代理配置 |
updateGlobalProxyConfig(config) | update_global_proxy_config | 更新全局代理配置 |
6.4 MCP API(mcpApi)
| 方法 | 命令 | 描述 |
|---|---|---|
getAllServers() | get_mcp_servers | 获取所有 MCP 服务器(统一结构) |
upsertUnifiedServer(server) | upsert_mcp_server | 添加/更新 MCP 服务器 |
deleteUnifiedServer(id) | delete_mcp_server | 删除 MCP 服务器 |
toggleApp(serverId, app, enabled) | toggle_mcp_app | 切换服务器在指定应用的启用状态 |
importFromApps() | import_mcp_from_apps | 从所有应用导入已有 MCP 配置 |
6.5 提示词 API(promptsApi)
| 方法 | 命令 | 描述 |
|---|---|---|
getPrompts(app) | get_prompts | 获取指定应用的提示词列表 |
upsertPrompt(app, id, prompt) | upsert_prompt | 添加/更新提示词 |
deletePrompt(app, id) | delete_prompt | 删除提示词 |
enablePrompt(app, id) | enable_prompt | 启用提示词 |
importFromFile(app) | import_prompt_from_file | 从文件导入 |
getCurrentFileContent(app) | get_current_prompt_file_content | 获取当前提示词文件内容 |
6.6 Skills API(skillsApi)
| 方法 | 命令 | 描述 |
|---|---|---|
getInstalled() | get_installed_skills | 获取所有已安装技能 |
installUnified(skill, currentApp) | install_skill_unified | 安装技能 |
uninstallUnified(id) | uninstall_skill_unified | 卸载技能 |
toggleApp(id, app, enabled) | toggle_skill_app | 切换技能的应用启用状态 |
checkUpdates() | check_skill_updates | 检查技能更新 |
updateSkill(id) | update_skill | 更新单个技能 |
discoverAvailable() | discover_available_skills | 发现可安装技能(从仓库) |
searchSkillsSh(query, limit, offset) | search_skills_sh | 搜索 skills.sh 公共目录 |
installFromZip(filePath, currentApp) | install_skills_from_zip | 从 ZIP 安装技能 |
scanUnmanaged() | scan_unmanaged_skills | 扫描未管理的技能 |
importFromApps(imports) | import_skills_from_apps | 从应用目录导入技能 |
getBackups() | get_skill_backups | 获取技能备份列表 |
restoreBackup(backupId, currentApp) | restore_skill_backup | 从备份恢复 |
getRepos() | get_skill_repos | 获取技能仓库列表 |
addRepo(repo) | add_skill_repo | 添加技能仓库 |
6.7 会话 API(sessionsApi)
| 方法 | 命令 | 描述 |
|---|---|---|
list() | list_sessions | 获取会话列表 |
getMessages(providerId, sourcePath) | get_session_messages | 获取会话消息记录 |
delete(options) | delete_session | 删除会话 |
deleteMany(items) | delete_sessions | 批量删除会话 |
launchTerminal(options) | launch_session_terminal | 从会话启动终端 |
6.8 用量 API(usageApi)
| 方法 | 命令 | 描述 |
|---|---|---|
query(providerId, appId) | queryProviderUsage | 查询供应商用量 |
testScript(...) | testUsageScript | 测试用量查询脚本 |
getUsageSummary(startDate?, endDate?, appType?) | get_usage_summary | 获取用量汇总 |
getUsageTrends(...) | get_usage_trends | 获取用量趋势(每日统计) |
getProviderStats(...) | get_provider_stats | 按供应商统计用量 |
getModelStats(...) | get_model_stats | 按模型统计用量 |
getRequestLogs(filters, page, pageSize) | get_request_logs | 获取请求日志 |
syncSessionUsage() | sync_session_usage | 同步会话用量数据 |
6.9 认证 API(authApi)
Web 模式使用 HTTP 直接调用(绕过 WebSocket): - checkStatus() → POST /api/invoke { command: "auth.status" } — 检查密码保护状态 - login(password) → POST /api/invoke { command: "auth.login" } — 密码登录 - checkSession() → POST /api/invoke { command: "auth.check" } — 验证会话
托管账号(Copilot/Codex OAuth): - authStartLogin(provider, githubDomain?) — 启动 OAuth 设备码流程 - authPollForAccount(provider, deviceCode) — 轮询等待授权 - authListAccounts(provider) — 列出已登录账号 - authRemoveAccount(provider, accountId) — 移除账号
6.10 统一供应商 API(universalProvidersApi)
| 方法 | 命令 | 描述 |
|---|---|---|
getAll() | get_universal_providers | 获取所有统一供应商 |
upsert(provider) | upsert_universal_provider | 添加/更新统一供应商 |
delete(id) | delete_universal_provider | 删除统一供应商 |
sync(id) | sync_universal_provider | 手动同步到各应用 |
7. 核心数据结构
7.1 Provider(供应商)
1 | interface Provider { |
7.2 ProviderMeta(供应商元数据)
1 | interface ProviderMeta { |
7.3 Settings(全局设置)
1 | interface Settings { |
7.4 McpServer(MCP 服务器)
1 | interface McpServer { |
7.5 UsageScript(用量查询脚本)
1 | interface UsageScript { |
7.6 SessionMeta(会话元数据)
1 | interface SessionMeta { |
7.7 InstalledSkill(已安装技能)
1 | interface InstalledSkill { |
7.8 UniversalProvider(统一供应商)
1 | interface UniversalProvider { |
8. 效果图展示
主页面 - 供应商列表

主页面展示供应商卡片列表,顶部 Header 包含:应用切换标签(Claude/Codex/Gemini 等)、工具图标组、代理开关、添加按钮。当前激活供应商(AgnesAI)显示蓝色高亮边框和背景渐变。
设置页面 - 通用设置

设置页面通过 Tabs 布局,通用标签包含语言选择、外观主题(浅色/深色/跟随系统)、主页面应用显示、Skills 存储配置等。
设置页面 - 路由设置

路由标签以折叠面板形式展示:本地路由(含运行状态)、自动故障转移、整流器、全局出站代理配置。
设置页面 - 认证

认证标签管理 GitHub Copilot 和 Codex OAuth 账号,以及 Web 访问密码设置。
Skills 管理

Skills 管理页面显示各应用的技能安装数量统计,支持批量更新,空状态引导用户发现和安装技能。
提示词管理

提示词管理页显示统计信息(共 N 个 · 已启用 M 个),空状态提示引导用户添加。
会话管理

会话管理为双栏布局:左侧列出历史会话,右侧展示对话详情、恢复命令和消息记录。
MCP 服务器管理

MCP 管理页显示各应用的服务器数量统计,提供导入和添加功能入口。
添加供应商对话框

添加供应商弹窗包含供应商预设选择、名称/API Key/Base URL 等配置字段,支持自定义图标和颜色。