-
This commit is contained in:
537
docs/plans/2026-01-30-slint-proxy-app-design.md
Normal file
537
docs/plans/2026-01-30-slint-proxy-app-design.md
Normal file
@@ -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 <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 调用流程
|
||||
|
||||
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 <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)
|
||||
|
||||
内容容器:带边框和圆角的卡片式容器
|
||||
|
||||
```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/` 目录
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user