15 KiB
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 # ✓ 已有
核心设计原则
- 页面独立性 - 每个页面是独立的 component,通过
if current-view == "xxx"条件渲染 - Callback 驱动 - 所有数据通过 callback 从 Rust 获取,页面只负责展示
- 状态提升 - 应用状态(当前页面、数据)在主应用层管理,向下传递
- 组件复用 - 最大化复用现有 components,缺失的通用组件补充到 components/
- 固定布局 - 桌面应用,不需要响应式布局(800x600 最小尺寸)
- Emoji 图标 - 使用 emoji 作为图标方案(简单且项目已在使用)
数据结构设计
核心数据类型(ui/types.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)
export component App inherits Window {
// ===== 应用状态 =====
in-out property <string> current-view: "home";
in-out property <bool> sidebar-collapsed: false;
数据状态 =====
in-out property <Profile> 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 调用流程
- 页面初始化时调用
load-xxx()获取数据 - 用户交互触发操作 callback(如
select-profile) - Rust 处理后更新对应的 property
- Slint 自动重新渲染相关 UI
布局组件设计
PageLayout(ui/layouts/page-layout.slint)
页面布局:包含固定头部 + 可滚动内容区
export component PageLayout inherits Rectangle {
in property <string> title;
in property <bool> 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)
内容容器:带边框和圆角的卡片式容器
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
ui/types.slint- 数据结构定义(~50 行)ui/layouts/container.slint- 容器组件(~30 行)ui/layouts/page-layout.slint- 页面布局(~70 行)ui/app.slint- 主应用框架(侧边栏 + 路由)(~200 行)build.rs- 修改编译入口为 app.slint(~5 行)src/main.rs- 基础 callback 框架(~100 行)- 恢复
ui/theme/目录(从 git 历史)
Phase 2: 简单页面 ✓
优先级: 高 预估代码量: ~180 行 完成日期: 2026-01-30
ui/components/empty.slint- 空状态组件(~40 行)ui/pages/connections.slint- 连接列表(~60 行)ui/pages/logs.slint- 日志查看(~210 行)
Phase 3: 中等复杂页面 ✓
优先级: 中 预估代码量: ~350 行 完成日期: 2026-01-30
ui/pages/settings.slint- 设置页面(~280 行)ui/pages/profiles.slint- 配置文件管理(~230 行)
Phase 4: 复杂页面 ✓
优先级: 中 预估代码量: ~550 行 完成日期: 2026-01-30
ui/pages/home.slint- 首页(~380 行)ui/pages/proxies.slint- 代理管理(~280 行)
Phase 5: Rust 集成 ✓
优先级: 低 预估代码量: ~200 行 完成日期: 2026-01-30
src/main.rs- 实现所有 callback 的 mock 数据(~450 行)- Mock 数据生成函数
- 用户交互处理
- 数据状态更新
项目完成总结
实现成果
总代码量: ~2100 行(超出预估的 ~1430 行)
完成时间: 2026-01-30(单日完成)
实现的文件:
-
基础设施(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 集成
-
UI 组件(1 个新增)
ui/components/empty.slint- 空状态组件
-
页面模块(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 个活动连接
- 多条日志记录
- 完整的设置项
技术亮点
- 模块化架构 - 清晰的目录结构和职责划分
- Callback 驱动 - 单向数据流,易于维护
- 组件复用 - 最大化利用现有 shadcn-slint 组件
- 类型安全 - Slint 类型系统保证数据一致性
- Mock 数据完整 - 所有页面都有真实的数据展示
运行方式
# 编译并运行
cargo run
# 发布版本
cargo run --release
下一步建议
-
后端集成
- 替换 mock 数据为真实的 Tauri 命令调用
- 实现配置文件的增删改查
- 实现代理节点的延迟测试
- 实现实时连接监控
-
功能增强
- 添加搜索和过滤功能
- 实现配置导入导出
- 添加更多设置选项
- 实现 TUN 模式配置对话框
-
用户体验优化
- 添加加载状态指示器
- 优化动画效果
- 添加键盘快捷键
- 实现拖拽排序
-
性能优化
- 虚拟滚动(大量数据时)
- 按需加载数据
- 优化渲染性能
总体进度
总预估代码量: ~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/ 理由: 清晰的职责划分,易于维护和扩展
后续优化方向
-
性能优化
- 虚拟滚动(如果列表数据量大)
- 按需加载页面数据
-
用户体验
- 加载状态提示
- 错误处理和提示
- 操作确认对话框
-
功能扩展
- 搜索和过滤
- 排序功能
- 导入导出配置
参考资料
- 原 Tauri 实现:
web/src/目录 - Slint 文档:https://slint.dev/
- 现有组件库:
ui/components/目录