feat: 新增客户端应用目录结构

新增 clients/ 目录:
- 外部控制应用的统一目录
- 支持多种客户端类型:
  - 移动端:iOS, Android, Flutter
  - 小程序:微信、支付宝、抖音
  - Web:响应式 Web 应用、桌面应用
  - 智能设备:手表、音箱、智能家居

目录结构:
- shared/ - 共享代码(API 客户端、数据模型)
- web/ - Web 应用
- flutter/ - Flutter 跨平台应用
- ios/ - iOS 原生应用
- android/ - Android 原生应用
- wechat-miniapp/ - 微信小程序
- desktop/ - Electron 桌面应用
- docs/ - 客户端开发文档

文档:
- clients/README.md - 客户端总览和开发计划
- clients/docs/API.md - HTTP API 完整文档
- clients/docs/DESIGN.md - 设计规范和组件库

更新 PLUGIN_DEPENDENCY.md:
- 明确 WiFi + BLE 双架构模型
- BLE 既可配置 WiFi,也可独立提供网络功能
- 新增双架构设计原则
This commit is contained in:
showen
2026-03-12 06:46:05 +08:00
parent 7aa42cc9af
commit fa692cd873
5 changed files with 959 additions and 37 deletions

View File

@@ -14,6 +14,8 @@
**示例**:
- screen - 屏幕管理(唤醒锁、光标控制)
- wifi - WiFi 管理(扫描、连接、热点)
- video - 视频播放(状态机、渲染)
- ble - 蓝牙服务GATT、配网**双架构**:既可配置 WiFi也可独立提供网络功能
### 依赖插件Dependent Plugins
**定义**: 依赖其他插件的功能,需要特定插件先启动
@@ -25,7 +27,6 @@
- 通过消息机制与依赖插件通信
**示例**:
- ble - 依赖 wifi通过 BLE 配置 WiFi
- http - 依赖 video通过 HTTP API 控制视频播放)
---
@@ -33,27 +34,36 @@
## 依赖关系图
```
独立插件层:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ screen │ │ wifi │ │ video │
└─────────┘ └─────────┘ └─────────┘
↑ ↑ ↑
│ │ │
└────────────────────────┘
独立插件层(双架构):
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ screen │ │ wifi │ │ video │ │ ble │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
↑ ↑ ↑
│ │ │
└────────────────────────┘
│ ↕ │
│ (双架构通信) │
│ │
└─────────────────────────┘
core
依赖插件层:
┌─────────┐ ┌─────────┐
│ ble │ │ http │
│ (依赖 │ │ (依赖 │
│ wifi) │ │ video) │
└─────────┘ └─────────┘
└────────────┘
┌─────────┐
│ http │
│ (依赖 │
│ video) │
└─────────┘
core
```
**双架构说明**
- WiFi 和 BLE 是两套独立的网络架构
- BLE 可以配置 WiFi通过消息通信
- BLE 也可以独立提供网络功能(不依赖 WiFi
- 用户可以选择使用 WiFi 或 BLE 进行网络连接
---
## 插件依赖声明
@@ -77,23 +87,29 @@ pub trait Plugin: Send {
### 依赖声明示例
```rust
impl Plugin for BlePlugin {
fn dependencies(&self) -> Vec<&'static str> {
vec!["wifi"] // BLE 依赖 WiFi 插件
}
}
impl Plugin for HttpPlugin {
fn dependencies(&self) -> Vec<&'static str> {
vec!["video"] // HTTP 依赖 Video 插件
}
}
impl Plugin for BlePlugin {
fn dependencies(&self) -> Vec<&'static str> {
vec![] // BLE 是独立插件,通过消息与 WiFi 通信
}
}
impl Plugin for WifiPlugin {
fn dependencies(&self) -> Vec<&'static str> {
vec![] // WiFi 是独立插件
}
}
impl Plugin for VideoPlugin {
fn dependencies(&self) -> Vec<&'static str> {
vec![] // Video 是独立插件
}
}
```
---
@@ -118,13 +134,13 @@ impl Plugin for WifiPlugin {
### 示例启动顺序
```
Phase 1: 独立插件
Phase 1: 独立插件(并行启动)
- screen.init() → screen.start()
- wifi.init() → wifi.start()
- video.init() → video.start()
- ble.init() → ble.start()
Phase 2: 依赖插件
- ble.init() → ble.start() (依赖 wifi)
- http.init() → http.start() (依赖 video)
```
@@ -144,16 +160,30 @@ Phase 2: 依赖插件
### 消息路由示例
```rust
// BLE 请求 WiFi 扫描
ble_plugin.send(Message::WifiCommand(WifiCommand::Scan));
// WiFi 返回扫描结果(Broadcast
wifi_plugin.send(Message::WifiResult(result));
// BLE 接收到 WifiResult 消息
// 场景1: BLE 配置 WiFi(双架构协作)
ble_plugin.send(Message::WifiCommand(WifiCommand::Connect { ssid, password }));
wifi_plugin.handle_message(Message::WifiCommand(...));
wifi_plugin.send(Message::WifiResult(result)); // Broadcast
ble_plugin.handle_message(Message::WifiResult(result));
// 场景2: BLE 独立提供网络功能(不依赖 WiFi
// 用户通过 BLE 直接与设备通信,不需要 WiFi
ble_plugin.handle_gatt_request(request);
ble_plugin.send_gatt_response(response);
// 场景3: HTTP 控制 Video强依赖
http_plugin.send(Message::PlayerCommand(PlayerCommand::Play));
video_plugin.handle_message(Message::PlayerCommand(...));
video_plugin.send(Message::PlayerStatus(status)); // Broadcast
```
**关键区别**
- **双架构WiFi + BLE**:两套独立的网络方案,可以互相配置,也可以独立工作
- BLE 可以配置 WiFi松耦合通过消息
- BLE 可以独立提供网络功能(不依赖 WiFi
- WiFi 可以独立工作(不依赖 BLE
- **强依赖HTTP → Video**HTTP 必须在 Video 启动后才能工作
---
## 当前插件分类
@@ -162,15 +192,23 @@ ble_plugin.handle_message(Message::WifiResult(result));
| 插件 | 功能 | 依赖 | 状态 |
|------|------|------|------|
| screen | 屏幕管理 | core | ✅ 完成 |
| wifi | WiFi 管理 | core | ✅ 完成 |
| wifi | WiFi 网络 | core | ✅ 完成 |
| video | 视频播放 | core | ✅ 完成 |
| ble | 蓝牙网络 | core | ✅ 完成 |
**双架构说明**
- **WiFi 架构**:通过 WiFi 连接网络,支持扫描、连接、热点
- **BLE 架构**:通过蓝牙连接网络,支持 GATT 服务、配网
- **协作模式**BLE 可以配置 WiFi通过消息通信
- **独立模式**BLE 和 WiFi 都可以独立提供网络功能
### 依赖插件
| 插件 | 功能 | 依赖 | 状态 |
|------|------|------|------|
| ble | 蓝牙配网 | core + wifi | ✅ 完成 |
| http | HTTP API | core + video | ✅ 完成 |
**说明**HTTP 必须依赖 Video因为 HTTP API 的核心功能是控制视频播放。
---
## 未来插件规划
@@ -214,6 +252,12 @@ ble_plugin.handle_message(Message::WifiResult(result));
- 独立插件可以单独测试
- 依赖插件可以集成测试
### 5. 双架构原则(新增)
- 支持多套独立架构并存(如 WiFi + BLE
- 架构之间可以协作(通过消息)
- 架构之间可以独立工作(不强依赖)
- 用户可以选择使用哪套架构
---
## 实现任务

View File

@@ -139,7 +139,8 @@
[当前] 陈逸飞(CEO) → 张婉琳(产品):
任务:梳理 Phase 1/2/3 所有插件的功能和依赖关系
- 阅读 PLUGIN_DEPENDENCY.md
- 确认当前插件分类是否合理
- **重要更正**BLE 是独立插件,不依赖 WiFi通过消息通信
- 确认当前插件分类独立插件screen, wifi, video, ble依赖插件http→video
- 规划 Phase 2/3 新插件的依赖关系
- 输出:更新 PRD.md包含插件依赖说明
- 与架构师王思远、需求分析师李明哲协作
@@ -147,15 +148,17 @@
[当前] 陈逸飞(CEO) → 王思远(架构师):
任务:设计插件依赖机制的技术实现
- 阅读 PLUGIN_DEPENDENCY.md
- **重要更正**BLE 是独立插件,不依赖 WiFi
- 区分强依赖http→video和松耦合ble↔wifi 通过消息)
- 扩展 Plugin trait添加 dependencies() 方法
- 设计 ServiceManager 依赖检查和拓扑排序算法
- 设计循环依赖检测机制
- 输出:技术设计文档 TECH_DESIGN_PLUGIN_DEPENDENCY.md
- 与产品张婉琳、PM 刘建国协作
[当前] 陈逸飞(CEO) → 刘建国(PM):
任务:组织开发团队梳理现有插件依赖
- 阅读 PLUGIN_DEPENDENCY.md
- **重要更正**BLE 是独立插件dependencies() 返回空
- 让开发团队为现有 5个插件添加 dependencies() 实现
- 验证启动顺序和消息通信
- 输出:更新代码,在 TEAM_CHAT.md 记录梳理结果

191
clients/README.md Normal file
View File

@@ -0,0 +1,191 @@
# ShowenV2 客户端应用
本目录包含 ShowenV2 的外部控制应用,用户可以通过这些客户端远程控制 ShowenV2 设备。
## 客户端类型
### 1. 移动端应用
- **iOS App** - `ios/` - 原生 iOS 应用Swift/SwiftUI
- **Android App** - `android/` - 原生 Android 应用Kotlin/Jetpack Compose
- **Flutter App** - `flutter/` - 跨平台移动应用iOS + Android
### 2. 小程序
- **微信小程序** - `wechat-miniapp/` - 微信生态
- **支付宝小程序** - `alipay-miniapp/` - 支付宝生态
- **抖音小程序** - `douyin-miniapp/` - 抖音生态
### 3. Web 应用
- **Web App** - `web/` - 响应式 Web 应用React/Vue
- **桌面应用** - `desktop/` - Electron 桌面应用Windows/macOS/Linux
### 4. 智能设备
- **智能手表** - `watch/` - Apple Watch / Wear OS
- **智能音箱** - `voice/` - 语音控制集成
- **智能家居** - `smarthome/` - HomeKit / 米家 / 小度
## 通信协议
所有客户端通过以下方式与 ShowenV2 设备通信:
### HTTP API
- **地址**: `http://<device-ip>:8080/api/`
- **协议**: RESTful API
- **格式**: JSON
- **认证**: Token / API Key
### WebSocket
- **地址**: `ws://<device-ip>:8080/ws`
- **用途**: 实时状态推送
- **格式**: JSON
### BLE (蓝牙)
- **协议**: GATT
- **用途**: 近场控制、配网
- **服务**: 自定义 GATT Service
## 核心功能
### 设备管理
- 设备发现和配对
- WiFi 配置
- 设备状态监控
### 播放控制
- 播放/暂停/停止
- 上一个/下一个
- 跳转到指定视频
- 音量控制
### 状态机控制
- 触发状态切换
- 场景切换
- 查看当前状态
### 配置管理
- 查看配置
- 修改配置
- 导入/导出配置
### 内容管理
- 浏览视频列表
- 上传新视频
- 删除视频
- 视频预览
## 开发计划
### Phase 1当前
- [ ] Web App - 基础控制界面
- [ ] HTTP API 文档
### Phase 23个月
- [ ] Flutter App - 跨平台移动应用
- [ ] 微信小程序 - 快速访问
- [ ] WebSocket 实时推送
### Phase 36个月
- [ ] iOS 原生 App
- [ ] Android 原生 App
- [ ] 智能音箱集成
### Phase 412个月
- [ ] 智能手表应用
- [ ] 智能家居集成
- [ ] 桌面应用
## 技术栈
### 移动端
- **iOS**: Swift 5.9+, SwiftUI, Combine
- **Android**: Kotlin 1.9+, Jetpack Compose, Coroutines
- **Flutter**: Flutter 3.x, Dart 3.x
### Web 端
- **前端**: React 18+ / Vue 3+, TypeScript
- **状态管理**: Redux / Pinia
- **UI 框架**: Ant Design / Element Plus
- **构建工具**: Vite / Webpack
### 小程序
- **微信**: 原生小程序框架 / uni-app
- **支付宝**: 原生小程序框架
- **抖音**: 原生小程序框架
### 桌面端
- **Electron**: Electron 28+, React/Vue
- **Tauri**: Tauri 1.x, Rust + Web
## 目录结构
```
clients/
├── README.md # 本文件
├── shared/ # 共享代码
│ ├── api/ # API 客户端库
│ ├── models/ # 数据模型
│ └── utils/ # 工具函数
├── web/ # Web 应用
│ ├── package.json
│ ├── src/
│ └── public/
├── flutter/ # Flutter 应用
│ ├── pubspec.yaml
│ ├── lib/
│ └── assets/
├── ios/ # iOS 应用
│ ├── ShowenV2.xcodeproj
│ └── ShowenV2/
├── android/ # Android 应用
│ ├── build.gradle
│ └── app/
├── wechat-miniapp/ # 微信小程序
│ ├── app.json
│ └── pages/
├── desktop/ # 桌面应用
│ ├── package.json
│ └── src/
└── docs/ # 客户端开发文档
├── API.md # API 文档
├── DESIGN.md # 设计规范
└── DEVELOPMENT.md # 开发指南
```
## 快速开始
### Web App
```bash
cd clients/web
npm install
npm run dev
```
### Flutter App
```bash
cd clients/flutter
flutter pub get
flutter run
```
### 微信小程序
```bash
cd clients/wechat-miniapp
# 使用微信开发者工具打开
```
## API 文档
详见 `docs/API.md`
## 设计规范
详见 `docs/DESIGN.md`
## 贡献指南
欢迎贡献新的客户端实现!请参考 `docs/DEVELOPMENT.md`
---
**文档版本**: v1.0
**最后更新**: 2026-03-12
**负责人**: 赵雨薇 (前端 & 屏幕工程师)

379
clients/docs/API.md Normal file
View File

@@ -0,0 +1,379 @@
# ShowenV2 HTTP API 文档
## 基础信息
- **Base URL**: `http://<device-ip>:8080/api`
- **协议**: HTTP/1.1
- **格式**: JSON
- **编码**: UTF-8
## 认证
当前版本暂不需要认证(局域网内使用)。未来版本将支持 Token 认证。
---
## 播放控制 API
### 播放
```http
POST /api/play
```
**响应**:
```json
{
"ok": true,
"action": "play"
}
```
### 暂停
```http
POST /api/pause
```
**响应**:
```json
{
"ok": true,
"action": "pause"
}
```
### 停止
```http
POST /api/stop
```
**响应**:
```json
{
"ok": true,
"action": "stop"
}
```
### 下一个
```http
POST /api/next
```
**响应**:
```json
{
"ok": true,
"action": "next"
}
```
### 上一个
```http
POST /api/previous
```
**响应**:
```json
{
"ok": true,
"action": "previous"
}
```
### 跳转到指定视频
```http
POST /api/goto/:index
```
**参数**:
- `index` (path): 视频索引(从 0 开始)
**响应**:
```json
{
"ok": true,
"action": "goto",
"index": 0
}
```
---
## 状态机控制 API
### 触发状态切换
```http
POST /api/trigger/:name
```
**参数**:
- `name` (path): 触发器名称(如 "happy", "sad", "angry"
**响应**:
```json
{
"ok": true,
"action": "trigger",
"name": "happy"
}
```
### 切换场景
```http
POST /api/scene/:index
```
**参数**:
- `index` (path): 场景索引(从 0 开始)
**响应**:
```json
{
"ok": true,
"action": "scene",
"index": 0
}
```
---
## 状态查询 API
### 获取播放状态
```http
GET /api/status
```
**响应**:
```json
{
"ok": true,
"status": {
"playing": true,
"current_index": 0,
"current_state": "idle",
"current_scene": 0,
"playlist_length": 10
}
}
```
### 获取配置
```http
GET /api/config
```
**响应**:
```json
{
"ok": true,
"config": {
"device_name": "ShowenV2",
"render_width": 1920,
"render_height": 1080,
"scenes": [...]
}
}
```
---
## WiFi 管理 API
### 扫描 WiFi
```http
POST /api/wifi/scan
```
**响应**:
```json
{
"ok": true,
"networks": [
{
"ssid": "MyWiFi",
"signal": -50,
"security": "WPA2"
}
]
}
```
### 连接 WiFi
```http
POST /api/wifi/connect
Content-Type: application/json
{
"ssid": "MyWiFi",
"password": "password123"
}
```
**响应**:
```json
{
"ok": true,
"action": "connect",
"ssid": "MyWiFi"
}
```
### 断开 WiFi
```http
POST /api/wifi/disconnect
```
**响应**:
```json
{
"ok": true,
"action": "disconnect"
}
```
### 开启热点
```http
POST /api/wifi/hotspot/start
```
**响应**:
```json
{
"ok": true,
"action": "hotspot_start"
}
```
### 关闭热点
```http
POST /api/wifi/hotspot/stop
```
**响应**:
```json
{
"ok": true,
"action": "hotspot_stop"
}
```
---
## Web UI
### 访问 Web 控制界面
```http
GET /
```
返回 HTML 控制界面。
---
## WebSocket API
### 连接
```
ws://<device-ip>:8080/ws
```
### 消息格式
```json
{
"type": "status_update",
"data": {
"playing": true,
"current_index": 0
}
}
```
### 消息类型
- `status_update`: 状态更新
- `config_update`: 配置更新
- `error`: 错误消息
---
## 错误响应
所有 API 在出错时返回:
```json
{
"ok": false,
"error": "错误描述"
}
```
**HTTP 状态码**:
- `200 OK`: 成功
- `400 Bad Request`: 请求参数错误
- `404 Not Found`: 资源不存在
- `500 Internal Server Error`: 服务器错误
---
## 示例代码
### JavaScript (Fetch API)
```javascript
// 播放
fetch('http://192.168.1.100:8080/api/play', {
method: 'POST'
})
.then(res => res.json())
.then(data => console.log(data));
// 获取状态
fetch('http://192.168.1.100:8080/api/status')
.then(res => res.json())
.then(data => console.log(data.status));
```
### Python (requests)
```python
import requests
# 播放
response = requests.post('http://192.168.1.100:8080/api/play')
print(response.json())
# 获取状态
response = requests.get('http://192.168.1.100:8080/api/status')
print(response.json()['status'])
```
### Swift (URLSession)
```swift
//
let url = URL(string: "http://192.168.1.100:8080/api/play")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
URLSession.shared.dataTask(with: request) { data, response, error in
//
}.resume()
```
### Kotlin (OkHttp)
```kotlin
// 播放
val client = OkHttpClient()
val request = Request.Builder()
.url("http://192.168.1.100:8080/api/play")
.post(RequestBody.create(null, ByteArray(0)))
.build()
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
// 处理响应
}
})
```
---
**文档版本**: v1.0
**最后更新**: 2026-03-12
**维护者**: ShowenV2 团队

305
clients/docs/DESIGN.md Normal file
View File

@@ -0,0 +1,305 @@
# ShowenV2 客户端设计规范
## 设计理念
### 核心价值
- **简洁直观**: 界面简洁,操作直观,用户一看就懂
- **响应迅速**: 操作反馈及时,状态更新实时
- **一致体验**: 跨平台体验一致,学习成本低
- **科技感**: 体现数字生命窗口的科技属性
### 设计原则
1. **移动优先**: 优先考虑移动端体验
2. **触控友好**: 按钮大小适合手指点击
3. **暗色主题**: 默认暗色,适合夜间使用
4. **动效流畅**: 过渡动画自然流畅
---
## 视觉设计
### 配色方案
#### 主色调
- **主色**: `#6366F1` (Indigo 500) - 科技感蓝紫色
- **辅助色**: `#8B5CF6` (Violet 500) - 渐变辅助
- **强调色**: `#EC4899` (Pink 500) - 重要操作
#### 功能色
- **成功**: `#10B981` (Green 500)
- **警告**: `#F59E0B` (Amber 500)
- **错误**: `#EF4444` (Red 500)
- **信息**: `#3B82F6` (Blue 500)
#### 中性色(暗色主题)
- **背景**: `#0F172A` (Slate 900)
- **卡片**: `#1E293B` (Slate 800)
- **边框**: `#334155` (Slate 700)
- **文字主**: `#F1F5F9` (Slate 100)
- **文字次**: `#94A3B8` (Slate 400)
### 字体
#### 中文
- **主字体**: 苹方 / 思源黑体 / Noto Sans SC
- **等宽**: Fira Code / JetBrains Mono
#### 英文
- **主字体**: Inter / SF Pro / Roboto
- **等宽**: Fira Code / JetBrains Mono
#### 字号
- **标题 H1**: 32px / 2rem
- **标题 H2**: 24px / 1.5rem
- **标题 H3**: 20px / 1.25rem
- **正文**: 16px / 1rem
- **辅助**: 14px / 0.875rem
- **说明**: 12px / 0.75rem
### 圆角
- **小**: 4px
- **中**: 8px
- **大**: 16px
- **圆形**: 50%
### 阴影
- **浅**: `0 1px 3px rgba(0, 0, 0, 0.12)`
- **中**: `0 4px 6px rgba(0, 0, 0, 0.16)`
- **深**: `0 10px 15px rgba(0, 0, 0, 0.20)`
### 间距
- **xs**: 4px
- **sm**: 8px
- **md**: 16px
- **lg**: 24px
- **xl**: 32px
- **2xl**: 48px
---
## 组件设计
### 按钮
#### 主按钮
```
背景: 主色渐变
文字: 白色
圆角: 8px
高度: 48px (移动端) / 40px (桌面端)
```
#### 次按钮
```
背景: 透明
边框: 1px 主色
文字: 主色
圆角: 8px
```
#### 图标按钮
```
大小: 48x48px (移动端) / 40x40px (桌面端)
圆角: 50%
背景: 半透明
```
### 卡片
```
背景: 卡片色
圆角: 16px
内边距: 16px
阴影: 中
```
### 输入框
```
背景: 背景色
边框: 1px 边框色
圆角: 8px
高度: 48px (移动端) / 40px (桌面端)
内边距: 12px
```
### 开关
```
宽度: 48px
高度: 28px
圆角: 14px
动画: 0.2s ease
```
### 滑块
```
轨道高度: 4px
滑块大小: 20x20px
颜色: 主色
```
---
## 界面布局
### 移动端
#### 底部导航
```
位置: 固定底部
高度: 64px
项目: 3-5个
图标: 24x24px
文字: 12px
```
#### 顶部栏
```
高度: 56px
标题: 居中 / 居左
操作: 右侧图标按钮
```
#### 内容区
```
内边距: 16px
卡片间距: 16px
```
### 桌面端
#### 侧边栏
```
宽度: 240px
位置: 固定左侧
可折叠
```
#### 主内容区
```
最大宽度: 1200px
居中显示
内边距: 24px
```
---
## 交互设计
### 点击反馈
- **按钮**: 按下缩小 0.95,松开恢复
- **卡片**: 悬停提升阴影
- **列表项**: 悬停背景变亮
### 加载状态
- **全局加载**: 顶部进度条
- **局部加载**: 骨架屏 / 加载动画
- **按钮加载**: 禁用 + 加载图标
### 错误提示
- **Toast**: 3秒自动消失
- **Modal**: 需要用户确认
- **Inline**: 表单验证错误
### 动画时长
- **快速**: 0.15s - 小元素出现/消失
- **标准**: 0.3s - 页面切换、弹窗
- **慢速**: 0.5s - 大型动画
---
## 页面设计
### 首页
- 设备状态卡片
- 快捷操作按钮
- 当前播放信息
### 播放控制
- 大型播放/暂停按钮
- 进度条
- 上一个/下一个
- 播放列表
### 状态机
- 当前状态显示
- 触发器列表
- 场景切换
### 设置
- WiFi 配置
- 设备信息
- 关于
---
## 图标设计
### 图标库
推荐使用:
- **Heroicons** - 简洁现代
- **Lucide** - 一致性好
- **Material Icons** - 丰富全面
### 图标规范
- **大小**: 24x24px (默认)
- **线宽**: 2px
- **风格**: 线性 / 填充
- **颜色**: 继承文字颜色
---
## 响应式设计
### 断点
- **xs**: < 640px (手机)
- **sm**: 640px - 768px (大屏手机)
- **md**: 768px - 1024px (平板)
- **lg**: 1024px - 1280px (小屏电脑)
- **xl**: > 1280px (大屏电脑)
### 适配策略
- **移动端**: 单列布局,底部导航
- **平板**: 双列布局,侧边栏可选
- **桌面**: 多列布局,固定侧边栏
---
## 无障碍设计
### 对比度
- **正常文字**: 至少 4.5:1
- **大文字**: 至少 3:1
- **图标**: 至少 3:1
### 触控目标
- **最小尺寸**: 44x44px (iOS) / 48x48px (Android)
- **间距**: 至少 8px
### 键盘导航
- 支持 Tab 键切换
- 支持 Enter/Space 激活
- 焦点状态明显
### 屏幕阅读器
- 图片添加 alt 文本
- 按钮添加 aria-label
- 状态变化通知
---
## 设计资源
### Figma 文件
- 组件库
- 页面模板
- 图标集
### 设计规范
- 颜色变量
- 字体样式
- 组件样式
---
**文档版本**: v1.0
**最后更新**: 2026-03-12
**设计负责人**: 赵雨薇 (前端 & 屏幕工程师)