Files
shadcn-slint/docs/plans/2026-01-30-slint-proxy-app-design.md
2026-01-30 20:27:24 +08:00

538 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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,
}
```
## 主应用架构
### 应用状态与 Callbackui/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;
// ===== CallbacksRust 实现) =====
// 数据加载
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
## 布局组件设计
### PageLayoutui/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;
}
}
}
}
```
### Containerui/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/` 目录