# Slint 代理管理应用设计文档 **创建日期:** 2026-01-30 **状态:** 设计完成,待实施 ## 项目概述 将 web 目录下的 Tauri + React 实现的代理管理工具,使用 Slint UI 组件库完整重新实现。应用包含 6 个主要页面,采用模块化架构,通过 Callback 与 Rust 后端交互。 ## 整体架构 ### 目录结构 ``` ui/ ├── app.slint # 主应用入口(替代 demo.slint) ├── types.slint # 数据结构定义 ├── components/ # 通用组件(已有 + 新增) │ ├── button.slint # ✓ 已有 │ ├── badge.slint # ✓ 已有 │ ├── card.slint # ✓ 已有 │ ├── input.slint # ✓ 已有 │ ├── item.slint # ✓ 已有 │ ├── dialog.slint # ✓ 已有 │ ├── toast.slint # ✓ 已有 │ ├── sidebar.slint # ✓ 已有 │ ├── tabs.slint # ✓ 已有 │ ├── accordion.slint # ✓ 已有 │ ├── switch.slint # ✓ 已有 │ ├── select.slint # ✓ 已有 │ ├── label.slint # ✓ 已有 │ ├── progress.slint # ✓ 已有 │ ├── separator.slint # ✓ 已有 │ ├── tooltip.slint # ✓ 已有 │ └── empty.slint # ☐ 待实现 ├── layouts/ # 布局组件(新增) │ ├── page-layout.slint # ☐ 待实现 │ └── container.slint # ☐ 待实现 ├── pages/ # 页面模块(新增) │ ├── home.slint # ☐ 待实现 │ ├── proxies.slint # ☐ 待实现 │ ├── profiles.slint # ☐ 待实现 │ ├── connections.slint # ☐ 待实现 │ ├── logs.slint # ☐ 待实现 │ └── settings.slint # ☐ 待实现 └── theme/ # 主题系统(已有) ├── theme.slint # ✓ 已有 ├── colors.slint # ✓ 已有 ├── spacing.slint # ✓ 已有 └── typography.slint # ✓ 已有 ``` ### 核心设计原则 1. **页面独立性** - 每个页面是独立的 component,通过 `if current-view == "xxx"` 条件渲染 2. **Callback 驱动** - 所有数据通过 callback 从 Rust 获取,页面只负责展示 3. **状态提升** - 应用状态(当前页面、数据)在主应用层管理,向下传递 4. **组件复用** - 最大化复用现有 components,缺失的通用组件补充到 components/ 5. **固定布局** - 桌面应用,不需要响应式布局(800x600 最小尺寸) 6. **Emoji 图标** - 使用 emoji 作为图标方案(简单且项目已在使用) ## 数据结构设计 ### 核心数据类型(ui/types.slint) ```slint // 配置文件信息 export struct Profile { id: string, name: string, url: string, type: string, // "remote" | "local" updated-at: string, usage: string, // "1.26GB / 100GB" expire-at: string, selected: bool, } // 代理节点 export struct ProxyNode { name: string, type: string, // "Vmess", "Shadowsocks", etc. delay: int, // 延迟 ms,-1 表示未测试 udp: bool, } // 代理组 export struct ProxyGroup { name: string, type: string, // "Selector", "URLTest", etc. now: string, // 当前选中的节点 nodes: [ProxyNode], } // 连接信息 export struct Connection { id: string, host: string, process: string, rule: string, chains: string, upload: string, download: string, tring, } // 日志条目 export struct LogEntry { time: string, level: string, // "debug", "info", "warn", "error" message: string, } // 设置项 export struct SettingItem { key: string, label: string, value: string, type: string, // "switch", "select", "button", "text" enabled: bool, } ``` ## 主应用架构 ### 应用状态与 Callback(ui/app.slint) ```slint export component App inherits Window { // ===== 应用状态 ===== in-out property current-view: "home"; in-out property sidebar-collapsed: false; 数据状态 ===== in-out property current-profile; in-out property <[Profile]> profiles; in-out property <[ProxyGroup]> proxy-groups; in-out property <[Connection]> connections; in-out property <[LogEntry]> mihomo-logs; in-out property <[LogEntry]> app-logs; in-out property <[SettingItem]> app-settings; in-out property <[SettingItem]> clash-settings; // ===== Callbacks(Rust 实现) ===== // 数据加载 callback load-profiles(); callback load-proxy-groups(string /* mode: rule/global/direct */); callback load-connections(); callback load-logs(string /* type: mihomo/app */); callback load-settings(); // 用户操作 callback select-profile(string /* profile-id */); callback select-proxy(string /* group-name */, string /* node-name */); callback test-proxy-delay(string /* node-name */); callback toggle-setting(string /* key */, bool /* value */); callback update-profile(string /* profile-id */); callback delete-profile(string /* profile-id */); callback add-profile(string /* url */); // Toast 通知 callback show-toast(string /* message */, string /* type */); } ``` ### Callback 调用流程 1. 页面初始化时调用 `load-xxx()` 获取数据 2. 用户交互触发操作 callback(如 `select-profile`) 3. Rust 处理后更新对应的 property 4. Slint 自动重新渲染相关 UI ## 布局组件设计 ### PageLayout(ui/layouts/page-layout.slint) 页面布局:包含固定头部 + 可滚动内容区 ```slint export component PageLayout inherits Rectangle { in property title; in property show-actions: false; @children // 头部右侧操作区(可选) background: Theme.colors.background; VerticalLayout { // 固定头部(48px) Rectangle { height: 48px; HorizontalLayout { padding: SpacingSystem.spacing.s4; alignment: space-between; Text { text: root.title; } // 右侧操作区 } } // 可滚动内容 Flickable { VerticalLayout { padding: SpacingSystem.spacing.s4; spacing: SpacingSystem.spacing.s4; } } } } ``` ### Container(ui/layouts/container.slint) 内容容器:带边框和圆角的卡片式容器 ```slint export component Container inherits Rectangle { @children background: Theme.colors.card; border-radius: SpacingSystem.radius.md; border-width: 1px; border-color: Theme.colors.border; VerticalLayout { padding: SpacingSystem.spacing.s4; spacing: SpacingSystem.spacing.s3; } } ``` ## 页面功能说明 ### 1. Home 页面(ui/pages/home.slint) **功能:** 显示当前配置文件信息、位置信息、快捷设置 **布局:** - ProfileCard:当前配置文件信息(名称、类型、流量使用、到期时间) - LocationCard:当前连接位置信息 - SettingCard:快捷设置开关 **数据依赖:** - `current-profile: Profile` - 部分 `app-settings` 和 `clash-settings` ### 2. Proxies 页面(ui/pages/proxies.slint) **功能:** 代理节点管理,支持 Rule/Global/Direct 三种模式 **布局:** - Tabs:切换模式(Rule/Global/Direct) - 每个模式下: - 多个 Accordion(代理组) - 每个 Accordion 内:网格ode 卡片 **数据依赖:** - `proxy-groups: [ProxyGroup]` **交互:** - 切换 Tab 时调用 `load-proxy-groups(mode)` - 点击节点时调用 `select-proxy(group, node)` - 测试延迟调用 `test-proxy-delay(node)` ### 3. Profiles 页面(ui/pages/profiles.slint) **功能:** 配置文件管理,网格布局展示所有配置文件 **布局:** - 头部:标题 + 添加按钮 + 刷新按钮 - 网格布局:ProfileCard 列表(每行自适应,最小 18rem) **数据依赖:** - `profiles: [Profile]` **交互:** - 点击配置文件调用 `select-profile(id)` - 更新配置文件调用 `update-profile(id)` - 删除配置文件调用 `delete-profile(id)` - 添加配置文件调用 `add-profile(url)` ### 4. Connections 页面(ui/pages/connections.slint) **功能:** 显示当前活动连接列表 **布局:** - 简单列表,每个连接使用 Item 组件展示 **数据依赖:** - `connections: [Connection]` **交互:** - 定时刷新(每秒调用 `load-connections()`) ### 5. Logs 页面(ui/pages/logs.slint) **功能:** 日志查看,支持 Mihomo 日志和 App 日志切换 **布局:** - Tabs:切换日志类型(Mihomo/App) - 每个 Tab:滚动列表展示日志条目 - 日志条目:时间 + 级别 + 消息(不同级别不同颜色) **数据依赖:** - `mihomo-logs: [LogEntry]` - `app-logs: [LogEntry]` **交互:** - 切换 Tab 时调用 `load-logs(type)` - 定时刷新(每秒) ### 6. Settings 页面(ui/pages/settings.slint) **功能:** 应用设置和 Clash 设置 **布局:** - 多个 Container,每个包含一组设置项 - 设置项使用 Item 组件:图标 + 标题 + Switch/Button **数据依赖:** - `app-settings: [SettingItem]` - `clash-settings: [SettingItem]` **交互:** - 切换开关调用 `tg(key, value)` ## 实现计划 ### Phase 1: 基础设施 ✓ **优先级:** 最高 **预估代码量:** ~150 行 **完成日期:** 2026-01-30 - [x] `ui/types.slint` - 数据结构定义(~50 行) - [x] `ui/layouts/container.slint` - 容器组件(~30 行) - [x] `ui/layouts/page-layout.slint` - 页面布局(~70 行) - [x] `ui/app.slint` - 主应用框架(侧边栏 + 路由)(~200 行) - [x] `build.rs` - 修改编译入口为 app.slint(~5 行) - [x] `src/main.rs` - 基础 callback 框架(~100 行) - [x] 恢复 `ui/theme/` 目录(从 git 历史) ### Phase 2: 简单页面 ✓ **优先级:** 高 **预估代码量:** ~180 行 **完成日期:** 2026-01-30 - [x] `ui/components/empty.slint` - 空状态组件(~40 行) - [x] `ui/pages/connections.slint` - 连接列表(~60 行) - [x] `ui/pages/logs.slint` - 日志查看(~210 行) ### Phase 3: 中等复杂页面 ✓ **优先级:** 中 **预估代码量:** ~350 行 **完成日期:** 2026-01-30 - [x] `ui/pages/settings.slint` - 设置页面(~280 行) - [x] `ui/pages/profiles.slint` - 配置文件管理(~230 行) ### Phase 4: 复杂页面 ✓ **优先级:** 中 **预估代码量:** ~550 行 **完成日期:** 2026-01-30 - [x] `ui/pages/home.slint` - 首页(~380 行) - [x] `ui/pages/proxies.slint` - 代理管理(~280 行) ### Phase 5: Rust 集成 ✓ **优先级:** 低 **预估代码量:** ~200 行 **完成日期:** 2026-01-30 - [x] `src/main.rs` - 实现所有 callback 的 mock 数据(~450 行) - Mock 数据生成函数 - 用户交互处理 - 数据状态更新 ## 项目完成总结 ### 实现成果 **总代码量:** ~2100 行(超出预估的 ~1430 行) **完成时间:** 2026-01-30(单日完成) **实现的文件:** 1. **基础设施(7 个文件)** - `ui/types.slint` - 数据结构定义 - `ui/layouts/container.slint` - 容器组件 - `ui/layouts/page-layout.slint` - 页面布局 - `ui/app.slint` - 主应用框架 - `ui/theme/` - 主题系统(从 git 恢复) - `build.rs` - 编译配置 - `src/main.rs` - Rust 集成 2. **UI 组件(1 个新增)** - `ui/components/empty.slint` - 空状态组件 3. **页面模块(6 个页面)** - `ui/pages/home.slint` - 首页 - `ui/pages/proxies.slint` - 代理管理 - `ui/pages/profiles.slint` - 配置文件管理 - `ui/pages/connections.slint` - 连接列表 - `ui/pages/logs.slint` - 日志查看 - `ui/pages/settings.slint` - 设置页面 ### 功能特性 ✅ **完整的 6 页面应用** - Home - 配置文件信息、位置、快捷设置 - Proxies - 代理节点管理(Rule/Global/Direct 模式) - Profiles - 配置文件管理(网格布局) - Connections - 活动连接列表 - Logs - 日志查看(Mihomo/App 切换) - Settings - 应用和 Clash 设置 ✅ **主题系统** - 亮色/暗色模式切换 - 响应式主题颜色 - 统一的设计系统 ✅ **交互功能** - 侧边栏导航 - 页面路由 - 数据加载和更新 - Toast 通知 - 用户操作反馈 ✅ **Mock 数据** - 3 个配置文件 - 2 个代理组(多个节点) - 3 个活动连接 - 多条日志记录 - 完整的设置项 ### 技术亮点 1. **模块化架构** - 清晰的目录结构和职责划分 2. **Callback 驱动** - 单向数据流,易于维护 3. **组件复用** - 最大化利用现有 shadcn-slint 组件 4. **类型安全** - Slint 类型系统保证数据一致性 5. **Mock 数据完整** - 所有页面都有真实的数据展示 ### 运行方式 ```bash # 编译并运行 cargo run # 发布版本 cargo run --release ``` ### 下一步建议 1. **后端集成** - 替换 mock 数据为真实的 Tauri 命令调用 - 实现配置文件的增删改查 - 实现代理节点的延迟测试 - 实现实时连接监控 2. **功能增强** - 添加搜索和过滤功能 - 实现配置导入导出 - 添加更多设置选项 - 实现 TUN 模式配置对话框 3. **用户体验优化** - 添加加载状态指示器 - 优化动画效果 - 添加键盘快捷键 - 实现拖拽排序 4. **性能优化** - 虚拟滚动(大量数据时) - 按需加载数据 - 优化渲染性能 ## 总体进度 **总预估代码量:** ~1430 行 **完成情况:** - ✓ Phase 1: 基础设施(7/7) - ✓ Phase 2: 简单页面(3/3) - ✓ Phase 3: 中等复杂页面(2/2) - ✓ Phase 4: 复杂页面(2/2) - ✓ Phase 5: Rust 集成(1/1) **总进度:** 15/15 (100%) ✅ **项目状态:** 已完成 ## 技术决策 ### 图标方案 **选择:** Emoji **理由:** 简单、无需额外资前项目已在使用 ### 布局方案 **选择:** 固定桌面布局 **理由:** 桌面应用,不需要响应式 ### 数据流方案 **选择:** Callback + Property **理由:** 清晰的单向数据流,便于维护和测试 ### 模块划分方案 **选择:** pages/ + layouts/ + components/ **理由:** 清晰的职责划分,易于维护和扩展 ## 后续优化方向 1. **性能优化** - 虚拟滚动(如果列表数据量大) - 按需加载页面数据 2. **用户体验** - 加载状态提示 - 错误处理和提示 - 操作确认对话框 3. **功能扩展** - 搜索和过滤 - 排序功能 - 导入导出配置 ## 参考资料 - 原 Tauri 实现:`web/src/` 目录 - Slint 文档:https://slint.dev/ - 现有组件库:`ui/components/` 目录