diff --git a/docs/plans/2026-01-30-slint-proxy-app-design.md b/docs/plans/2026-01-30-slint-proxy-app-design.md new file mode 100644 index 0000000..465e0be --- /dev/null +++ b/docs/plans/2026-01-30-slint-proxy-app-design.md @@ -0,0 +1,537 @@ +# 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/` 目录 diff --git a/ui/theme/theme.slint b/ui/theme/theme.slint index f32d2a6..cefe5e4 100644 --- a/ui/theme/theme.slint +++ b/ui/theme/theme.slint @@ -4,7 +4,6 @@ import { ColorPalette, LightColors, DarkColors } from "colors.slint"; import { Typography } from "typography.slint"; import { SpacingSystem } from "spacing.slint"; -import { Animations } from "../utils/animations.slint"; // Global theme manager (singleton) export global Theme { @@ -24,4 +23,4 @@ export global Theme { } // Re-export for convenience -export { Typography, SpacingSystem, Animations } +export { Typography, SpacingSystem }