优化
This commit is contained in:
@@ -10,18 +10,17 @@
|
|||||||
- **动画**: flutter_animate
|
- **动画**: flutter_animate
|
||||||
- **状态管理**: Provider
|
- **状态管理**: Provider
|
||||||
|
|
||||||
## 技术栈详情
|
## 当前阶段: Phase 6 主题系统深度优化
|
||||||
|
|
||||||
### 核心依赖
|
### 目标
|
||||||
- Flutter SDK: >=3.0.0 <4.0.0
|
设计并实现一套专业、一致、响应式的主题系统,确保:
|
||||||
- shadcn_ui: ^0.52.1
|
- 视觉一致性
|
||||||
- provider: ^6.1.1
|
- 良好的可读性 (对比度 >= 4.5:1)
|
||||||
- dio: ^5.4.0
|
- **杜绝文字和背景颜色一样无法区分的情况**
|
||||||
- shared_preferences: ^2.2.2
|
|
||||||
|
|
||||||
### 工具库
|
### 参考文件
|
||||||
- intl: 国际化
|
- `specs/theme-design.md` - 主题设计规范
|
||||||
- decimal: 精确计算
|
- `IMPLEMENTATION_PLAN.md` - 实施计划 (Phase 6 部分)
|
||||||
|
|
||||||
## 开发命令
|
## 开发命令
|
||||||
|
|
||||||
@@ -29,12 +28,11 @@
|
|||||||
# 获取依赖
|
# 获取依赖
|
||||||
flutter pub get
|
flutter pub get
|
||||||
|
|
||||||
# 运行应用
|
# 运行应用 (Chrome)
|
||||||
flutter run
|
flutter run -d chrome
|
||||||
|
|
||||||
# 构建生产版本
|
# 运行应用 (macOS)
|
||||||
flutter build apk
|
flutter run -d macos
|
||||||
flutter build ios
|
|
||||||
|
|
||||||
# 分析代码
|
# 分析代码
|
||||||
flutter analyze
|
flutter analyze
|
||||||
@@ -47,122 +45,104 @@ flutter test
|
|||||||
|
|
||||||
```
|
```
|
||||||
lib/
|
lib/
|
||||||
├── core/ # 核心功能
|
├── core/
|
||||||
│ ├── constants/ # 常量
|
│ ├── constants/
|
||||||
│ ├── network/ # 网络请求
|
│ │ ├── app_colors.dart # 颜色定义 (需重构)
|
||||||
│ ├── storage/ # 本地存储
|
│ │ └── api_endpoints.dart
|
||||||
│ └── theme/ # 主题配置
|
│ ├── theme/
|
||||||
├── data/ # 数据层
|
│ │ ├── app_theme.dart # 主题配置 (需重构)
|
||||||
│ ├── models/ # 数据模型
|
│ │ ├── app_text_styles.dart # 文字样式 (待创建)
|
||||||
│ └── services/ # API 服务
|
│ │ └── app_spacing.dart # 间距圆角 (待创建)
|
||||||
├── providers/ # 状态管理
|
│ ├── network/
|
||||||
├── routes/ # 路由配置
|
│ └── storage/
|
||||||
├── ui/ # UI 层
|
├── data/
|
||||||
│ └── pages/ # 页面组件
|
│ ├── models/
|
||||||
└── main.dart # 应用入口
|
│ └── services/
|
||||||
|
├── providers/
|
||||||
|
├── routes/
|
||||||
|
├── ui/
|
||||||
|
│ ├── shared/
|
||||||
|
│ │ └── ui_constants.dart # 整合导出
|
||||||
|
│ ├── components/
|
||||||
|
│ │ ├── coin_card.dart # 有硬编码颜色
|
||||||
|
│ │ ├── asset_card.dart
|
||||||
|
│ │ └── trade_button.dart
|
||||||
|
│ └── pages/
|
||||||
|
│ ├── auth/
|
||||||
|
│ ├── main/
|
||||||
|
│ ├── home/
|
||||||
|
│ ├── market/
|
||||||
|
│ ├── trade/
|
||||||
|
│ ├── asset/
|
||||||
|
│ ├── mine/
|
||||||
|
│ └── orders/
|
||||||
|
└── main.dart
|
||||||
```
|
```
|
||||||
|
|
||||||
## 主要页面
|
## 颜色系统设计
|
||||||
|
|
||||||
### 1. 认证模块
|
### 主色调
|
||||||
- `login_page.dart` - 登录页(需要重构)
|
```dart
|
||||||
- `login_page_shadcn.dart` - shadcn 版本示例(已完成)
|
primary: #00D4AA // 青绿色 (品牌色)
|
||||||
- `register_page.dart` - 注册页(需要重构)
|
primaryLight: #00E6B8
|
||||||
|
primaryDark: #00B894
|
||||||
|
```
|
||||||
|
|
||||||
### 2. 主框架
|
### 涨跌色
|
||||||
- `main_page.dart` - 主页面(需要重构)
|
```dart
|
||||||
- `main_page_shadcn.dart` - shadcn 版本示例(已完成)
|
up: #00C853 // 涨/买入 (绿色)
|
||||||
|
down: #FF5252 // 跌/卖出 (红色)
|
||||||
|
```
|
||||||
|
|
||||||
### 3. 功能页面
|
### 背景色 (深色主题)
|
||||||
- `home_page.dart` - 首页
|
```dart
|
||||||
- `market_page.dart` - 行情
|
background: #0F0F1A // 页面背景
|
||||||
- `trade_page.dart` - 交易
|
cardBackground: #1A1A2E // 卡片背景
|
||||||
- `asset_page.dart` - 资产
|
inputBackground: #16213E // 输入框背景
|
||||||
- `mine_page.dart` - 我的
|
```
|
||||||
|
|
||||||
## 当前状态
|
### 文字颜色
|
||||||
|
```dart
|
||||||
|
textPrimary: #FFFFFF // 主要文字
|
||||||
|
textSecondary: #B0B0C0 // 次要文字
|
||||||
|
textHint: #6B6B80 // 提示文字
|
||||||
|
textDisabled: #4A4A5A // 禁用文字
|
||||||
|
```
|
||||||
|
|
||||||
### 已完成
|
## 禁止事项
|
||||||
- ✅ shadcn_ui 集成
|
|
||||||
- ✅ main.dart 更新为 ShadApp
|
|
||||||
- ✅ 登录页 shadcn 示例
|
|
||||||
- ✅ 主页面 shadcn 示例
|
|
||||||
- ✅ 主题配置(Slate 深色)
|
|
||||||
|
|
||||||
### 进行中
|
- ❌ 文字与背景颜色相同
|
||||||
- ⏳ 替换原文件为 shadcn 版本
|
- ❌ 低对比度组合 (对比度 < 4.5)
|
||||||
- ⏳ 重构剩余页面
|
- ❌ 仅用颜色区分状态
|
||||||
- ⏳ 创建自定义组件
|
- ❌ 过小的触摸目标 (< 44px)
|
||||||
|
- ❌ 不一致的组件样式
|
||||||
### 待开始
|
- ❌ 硬编码颜色值
|
||||||
- ❌ 动画优化
|
- ❌ 修改业务逻辑/API/Provider
|
||||||
- ❌ 性能优化
|
|
||||||
- ❌ 测试覆盖
|
|
||||||
|
|
||||||
## 重构注意事项
|
|
||||||
|
|
||||||
### 已有的 shadcn 组件
|
|
||||||
shadcn_ui 提供的组件:
|
|
||||||
- ShadApp, ShadTheme
|
|
||||||
- ShadButton (多种变体)
|
|
||||||
- ShadCard, ShadDialog
|
|
||||||
- ShadInputFormField, ShadSelect
|
|
||||||
- ShadBadge, ShadAvatar
|
|
||||||
- ShadListTile, ShadSwitch
|
|
||||||
- 等等...
|
|
||||||
|
|
||||||
### 需要统一的样式
|
|
||||||
1. **按钮**: 所有按钮使用 ShadButton
|
|
||||||
2. **卡片**: 所有卡片使用 ShadCard
|
|
||||||
3. **输入**: 所有输入框使用 ShadInputFormField
|
|
||||||
4. **图标**: 所有图标使用 LucideIcons
|
|
||||||
5. **颜色**: 使用 ShadTheme 获取颜色
|
|
||||||
|
|
||||||
### 禁止修改
|
|
||||||
- ❌ API 服务逻辑
|
|
||||||
- ❌ Provider 状态管理
|
|
||||||
- ❌ 数据模型结构
|
|
||||||
- ❌ 路由逻辑
|
|
||||||
|
|
||||||
## 测试要点
|
## 测试要点
|
||||||
|
|
||||||
1. **功能测试**
|
1. **对比度检查**
|
||||||
- 用户登录/注册
|
- 所有文字/背景组合 >= 4.5:1
|
||||||
- 查看行情数据
|
- 使用对比度检查工具验证
|
||||||
- 进行交易操作
|
|
||||||
- 查看资产信息
|
|
||||||
- 修改个人设置
|
|
||||||
|
|
||||||
2. **视觉测试**
|
2. **视觉一致性**
|
||||||
- 深色模式检查
|
- 所有页面风格统一
|
||||||
- 浅色模式检查
|
- 组件样式一致
|
||||||
- 动画流畅度
|
|
||||||
- 响应式布局
|
|
||||||
|
|
||||||
3. **构建测试**
|
3. **功能验证**
|
||||||
- Dart 分析通过
|
- `flutter analyze` 无错误
|
||||||
- Flutter 构建成功
|
- 应用可正常运行
|
||||||
- 无运行时错误
|
|
||||||
|
|
||||||
## 学习要点
|
## 已完成的工作
|
||||||
|
|
||||||
- 如果遇到新的 UI 模式,记录到本文档
|
- ✅ shadcn_ui 集成
|
||||||
- 如果发现业务逻辑依赖,记录到本文档
|
- ✅ 所有页面已重构为 shadcn 组件
|
||||||
- 如果需要新的设计 token,记录到本文档
|
- ✅ 基础主题配置
|
||||||
- 如果创建新的自定义组件,记录到本文档
|
|
||||||
|
|
||||||
## 已知问题
|
## 当前任务
|
||||||
|
|
||||||
1. **登录页**: 有两个版本,需要用 shadcn 版本替换原版
|
1. 重构颜色系统 (app_colors.dart)
|
||||||
2. **主页面**: 有两个版本,需要用 shadcn 版本替换原版
|
2. 清理硬编码颜色
|
||||||
3. **图标**: 部分页面仍使用 Material Icons,需要替换为 LucideIcons
|
3. 创建文字样式系统
|
||||||
4. **颜色**: 部分地方硬编码颜色,需要使用主题色
|
4. 创建间距圆角系统
|
||||||
|
5. 更新所有页面使用新主题
|
||||||
## 下一步计划
|
|
||||||
|
|
||||||
1. 替换 main_page.dart 和 login_page.dart
|
|
||||||
2. 重构 home_page.dart
|
|
||||||
3. 重构 market_page.dart 和 trade_page.dart
|
|
||||||
4. 重构 asset_page.dart 和 mine_page.dart
|
|
||||||
5. 创建自定义组件(CoinCard, TradeButton 等)
|
|
||||||
6. 添加动画优化
|
|
||||||
|
|||||||
@@ -149,9 +149,111 @@ STATUS: COMPLETE
|
|||||||
- ✅ 自定义组件已创建
|
- ✅ 自定义组件已创建
|
||||||
- ✅ flutter analyze 无错误
|
- ✅ flutter analyze 无错误
|
||||||
|
|
||||||
|
## Phase 6: 主题系统优化 (当前任务)
|
||||||
|
|
||||||
|
### 目标
|
||||||
|
- 统一颜色系统,消除重复定义
|
||||||
|
- 确保文字与背景对比度符合 WCAG AA 标准
|
||||||
|
- 添加响应式设计支持
|
||||||
|
- 创建自定义品牌主题
|
||||||
|
|
||||||
|
### 6.1 颜色系统重构
|
||||||
|
- [ ] 合并 app_colors.dart 和 ui_constants.dart 中的重复定义
|
||||||
|
- [ ] 创建完整的语义化颜色系统
|
||||||
|
- [ ] 移除 market_page.dart, coin_card.dart 中的硬编码颜色
|
||||||
|
- [ ] 确保对比度 >= 4.5:1
|
||||||
|
|
||||||
|
### 6.2 响应式设计系统
|
||||||
|
- [ ] 创建 Breakpoints 工具类
|
||||||
|
- [ ] 创建响应式间距 (ResponsiveSpacing)
|
||||||
|
- [ ] 创建响应式字体 (ResponsiveText)
|
||||||
|
|
||||||
|
### 6.3 Shadcn 主题定制
|
||||||
|
- [x] 创建自定义 ShadColorScheme (绿色品牌)
|
||||||
|
- [x] 配置深色主题
|
||||||
|
- [x] 更新 main.dart 使用自定义主题
|
||||||
|
|
||||||
|
## STATUS: COMPLETE
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6: 主题系统深度优化 (已完成)
|
||||||
|
|
||||||
|
### 设计规范参考: `specs/theme-design.md`
|
||||||
|
|
||||||
|
### 6.1 颜色系统重构 ✅
|
||||||
|
|
||||||
|
- [x] 6.1.1 重构 `app_colors.dart`
|
||||||
|
- 统一主色调 (#00D4AA 青绿色系)
|
||||||
|
- 标准化涨跌色 (#00C853 绿 / #FF5252 红)
|
||||||
|
- 优化背景色层次 (#0F0F1A -> #1A1A2E -> #16213E)
|
||||||
|
- 确保文字颜色对比度
|
||||||
|
- 移除重复定义
|
||||||
|
|
||||||
|
- [x] 6.1.2 清理硬编码颜色
|
||||||
|
- `coin_card.dart` - upColor/downColor 硬编码 ✅
|
||||||
|
- `market_page.dart` - 检查并清理 ✅
|
||||||
|
- 所有页面检查 ✅
|
||||||
|
|
||||||
|
### 6.2 文字样式系统 ✅
|
||||||
|
|
||||||
|
- [x] 6.2.1 更新 `app_theme.dart`
|
||||||
|
- 标题样式 (h1-h4)
|
||||||
|
- 正文样式 (body1, body2)
|
||||||
|
- 数字样式 (price, amount)
|
||||||
|
- 确保与 ShadTheme 协同
|
||||||
|
|
||||||
|
### 6.3 间距与圆角系统 ✅
|
||||||
|
|
||||||
|
- [x] 6.3.1 更新 `app_theme.dart`
|
||||||
|
- 统一间距常量 (xs/sm/md/lg/xl/xxl)
|
||||||
|
- 统一圆角常量 (sm/md/lg/xl/full)
|
||||||
|
- 响应式断点定义
|
||||||
|
|
||||||
|
### 6.4 Shadcn 主题定制 ✅
|
||||||
|
|
||||||
|
- [x] 6.4.1 创建自定义颜色方案
|
||||||
|
- 创建 `app_color_scheme.dart`
|
||||||
|
- 自定义 ShadColorScheme (品牌绿色)
|
||||||
|
- 深色主题优化
|
||||||
|
- 更新 main.dart
|
||||||
|
|
||||||
|
### 6.5 组件样式统一
|
||||||
|
|
||||||
|
- [ ] 6.5.1 优化按钮样式 (待完善)
|
||||||
|
- [ ] 6.5.2 优化卡片样式 (待完善)
|
||||||
|
- [ ] 6.5.3 优化输入框样式 (待完善)
|
||||||
|
|
||||||
|
### 6.6 页面样式优化
|
||||||
|
|
||||||
|
- [ ] 6.6.1 登录/注册页面 (待完善)
|
||||||
|
- [ ] 6.6.2 首页 (待完善)
|
||||||
|
- [ ] 6.6.3 行情页 (待完善)
|
||||||
|
- [ ] 6.6.4 交易页 (待完善)
|
||||||
|
- [ ] 6.6.5 资产页 (待完善)
|
||||||
|
- [ ] 6.6.6 我的页面 (待完善)
|
||||||
|
|
||||||
|
### 6.7 验证 ✅
|
||||||
|
|
||||||
|
- [x] 6.7.1 flutter analyze 通过 (0 errors, 31 warnings/infos)
|
||||||
|
- [x] 6.7.2 对比度检查 (WCAG AA >= 4.5:1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 优先级排序
|
||||||
|
|
||||||
|
1. **P0** - 6.1 颜色系统重构 (核心基础) ✅
|
||||||
|
2. **P0** - 6.4 Shadcn 主题定制 ✅
|
||||||
|
3. **P1** - 6.2 文字样式系统 ✅
|
||||||
|
4. **P1** - 6.3 间距与圆角系统 ✅
|
||||||
|
5. **P2** - 6.5 组件样式统一 (待完善)
|
||||||
|
6. **P2** - 6.6 页面样式优化 (待完善)
|
||||||
|
7. **P3** - 6.7 验证 ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Next Steps (Optional)
|
## Next Steps (Optional)
|
||||||
|
|
||||||
1. **动画优化** - 使用 flutter_animate 添加更多动画效果
|
1. **动画优化** - 使用 flutter_animate 添加更多动画效果
|
||||||
2. **浅色模式** - 添加浅色主题支持
|
2. **浅色模式** - 添加浅色主题支持
|
||||||
3. **品牌色定制** - 从 Slate 主题切换到自定义绿色主题
|
3. **组件优化** - 进一步优化自定义组件的可配置性
|
||||||
4. **组件优化** - 进一步优化自定义组件的可配置性
|
|
||||||
|
|||||||
@@ -1,266 +1,104 @@
|
|||||||
# 目标
|
# 目标
|
||||||
|
|
||||||
使用 shadcn_ui 现代化 Flutter 虚拟货币交易平台的主题和 UI,统一设计系统,提升用户体验。
|
为 Flutter 数字货币应用 (monisuo) 设计并实现一套专业、一致、响应式的主题系统,确保:
|
||||||
|
- 视觉一致性
|
||||||
|
- 良好的可读性 (对比度 >= 4.5:1)
|
||||||
|
- 响应式布局
|
||||||
|
- 专业的金融应用风格
|
||||||
|
- **杜绝文字和背景颜色一样无法区分的情况**
|
||||||
|
|
||||||
## 参考文件
|
## 参考文件
|
||||||
|
|
||||||
- `specs/theme-modernization.md` - 主题现代化规范
|
- `specs/theme-design.md` - 主题设计规范 (颜色系统、间距、圆角、文字样式)
|
||||||
- `AGENTS.md` - 项目说明和注意事项
|
- `AGENTS.md` - 项目说明和注意事项
|
||||||
- `../REFACTOR_PLAN.md` - 已有的重构计划
|
- `IMPLEMENTATION_PLAN.md` - 实施计划 (Phase 6: 主题系统深度优化)
|
||||||
- `IMPLEMENTATION_PLAN.md` - 实施计划(待创建)
|
|
||||||
|
|
||||||
## 任务范围
|
## 设计原则
|
||||||
|
|
||||||
### Phase 1: 分析和学习 (Analysis & Learning)
|
1. **一致性** - 所有页面使用统一的设计语言
|
||||||
1. 读取并理解 `../REFACTOR_PLAN.md` - 已有的重构计划
|
2. **可读性** - 确保文字与背景对比度充足 (WCAG AA 标准 >= 4.5:1)
|
||||||
2. 分析现有页面:
|
3. **响应式** - 适配不同屏幕尺寸
|
||||||
- 哪些页面已经用 shadcn 重构
|
4. **专业性** - 符合金融/交易类应用的专业感
|
||||||
- 哪些页面还在使用 Material 组件
|
5. **无障碍** - 避免颜色冲突,杜绝文字和背景颜色一样无法区分的情况
|
||||||
- 哪些地方有硬编码的颜色/样式
|
|
||||||
3. 识别主题配置:
|
|
||||||
- 当前的 ShadTheme 配置
|
|
||||||
- 品牌色、涨跌色、中性色
|
|
||||||
- 深色/浅色模式支持
|
|
||||||
4. 列出需要创建的自定义组件
|
|
||||||
|
|
||||||
### Phase 2: 核心页面替换 (Core Pages Replacement)
|
## 禁止事项
|
||||||
**高优先级 - 立即执行**
|
|
||||||
|
|
||||||
1. **主页面替换**
|
- ❌ 文字与背景颜色相同
|
||||||
- 文件: `lib/ui/pages/main/main_page.dart`
|
- ❌ 低对比度组合 (对比度 < 4.5)
|
||||||
- 替换为: `lib/ui/pages/main/main_page_shadcn.dart`
|
- ❌ 仅用颜色区分状态
|
||||||
- 操作: 删除原文件,重命名 shadcn 版本
|
- ❌ 过小的触摸目标 (< 44px)
|
||||||
|
- ❌ 不一致的组件样式
|
||||||
|
- ❌ 硬编码颜色值
|
||||||
|
|
||||||
2. **登录页替换**
|
## 当前任务: Phase 6 主题系统深度优化
|
||||||
- 文件: `lib/ui/pages/auth/login_page.dart`
|
|
||||||
- 替换为: `lib/ui/pages/auth/login_page_shadcn.dart`
|
|
||||||
- 操作: 删除原文件,重命名 shadcn 版本
|
|
||||||
|
|
||||||
3. **首页重构**
|
### P0 - 立即执行 (核心基础)
|
||||||
- 文件: `lib/ui/pages/home/home_page.dart`
|
|
||||||
- 目标:
|
|
||||||
- 使用 ShadCard 展示资产概览
|
|
||||||
- 使用 ShadButton 进行快捷操作
|
|
||||||
- 使用 LucideIcons 替换 Material Icons
|
|
||||||
- 添加 flutter_animate 动画
|
|
||||||
|
|
||||||
### Phase 3: 功能页面重构 (Feature Pages Refactoring)
|
1. **6.1 颜色系统重构**
|
||||||
**高优先级**
|
- 重构 `lib/core/constants/app_colors.dart`
|
||||||
|
- 统一主色调 (#00D4AA 青绿色系)
|
||||||
|
- 标准化涨跌色 (#00C853 绿 / #FF5252 红)
|
||||||
|
- 优化背景色层次 (#0F0F1A -> #1A1A2E -> #16213E)
|
||||||
|
- 清理 `coin_card.dart` 等文件中的硬编码颜色
|
||||||
|
|
||||||
1. **行情页面 (market_page.dart)**
|
2. **6.4 Shadcn 主题定制**
|
||||||
- 币种列表使用 ShadCard
|
- 创建自定义 ShadColorScheme (品牌绿色)
|
||||||
- 价格变化使用 ShadBadge(涨绿跌红)
|
- 更新 `main.dart` 使用自定义主题
|
||||||
- 搜索框使用 ShadInput
|
|
||||||
- 列表项使用 ShadListTile
|
|
||||||
|
|
||||||
2. **交易页面 (trade_page.dart)**
|
|
||||||
- 买入按钮:绿色 ShadButton
|
|
||||||
- 卖出按钮:红色 ShadButton.destructive
|
|
||||||
- 数量输入:ShadInputFormField
|
|
||||||
- 币种选择:ShadSelect(如果需要)
|
|
||||||
|
|
||||||
3. **资产页面 (asset_page.dart)**
|
|
||||||
- 总资产卡片:大号 ShadCard
|
|
||||||
- 充值/提现按钮:ShadButton
|
|
||||||
- 资金列表:ShadListTile
|
|
||||||
|
|
||||||
4. **个人中心 (mine_page.dart)**
|
|
||||||
- 菜单项:统一布局
|
|
||||||
- 设置项:ShadSwitch
|
|
||||||
- 退出登录:ShadButton.destructive
|
|
||||||
|
|
||||||
### Phase 4: 自定义组件创建 (Custom Components)
|
|
||||||
**中优先级**
|
|
||||||
|
|
||||||
创建可复用的业务组件:
|
|
||||||
|
|
||||||
1. **CoinCard - 币种卡片**
|
|
||||||
```dart
|
|
||||||
// lib/ui/components/coin_card.dart
|
|
||||||
// 显示:币种图标、名称、代码、价格、24h变化
|
|
||||||
// 使用:ShadCard + ShadAvatar + ShadBadge
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **TradeButton - 交易按钮**
|
|
||||||
```dart
|
|
||||||
// lib/ui/components/trade_button.dart
|
|
||||||
// 买入:绿色 ShadButton
|
|
||||||
// 卖出:红色 ShadButton.destructive
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **AssetCard - 资产卡片**
|
|
||||||
```dart
|
|
||||||
// lib/ui/components/asset_card.dart
|
|
||||||
// 显示:标题、余额、变化
|
|
||||||
// 使用:ShadCard + 大号文本
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **PriceChart - 价格图表**(可选)
|
|
||||||
```dart
|
|
||||||
// lib/ui/components/price_chart.dart
|
|
||||||
// 显示:价格趋势
|
|
||||||
// 使用:CustomPaint + flutter_animate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 5: 注册页面重构 (Register Page)
|
|
||||||
**中优先级**
|
|
||||||
|
|
||||||
- 文件: `lib/ui/pages/auth/register_page.dart`
|
|
||||||
- 创建完整的注册表单
|
|
||||||
- 使用 ShadForm + ShadInputFormField
|
|
||||||
- 添加表单验证
|
|
||||||
|
|
||||||
### Phase 6: 动画优化 (Animation Enhancement)
|
|
||||||
**低优先级**
|
|
||||||
|
|
||||||
使用 flutter_animate 添加动画:
|
|
||||||
|
|
||||||
1. **页面切换动画**
|
|
||||||
- 淡入淡出效果
|
|
||||||
- 滑动效果
|
|
||||||
|
|
||||||
2. **列表加载动画**
|
|
||||||
- 交错淡入
|
|
||||||
- 滑动进入
|
|
||||||
|
|
||||||
3. **交互反馈动画**
|
|
||||||
- 按钮点击缩放
|
|
||||||
- 卡片悬停效果
|
|
||||||
|
|
||||||
### Phase 7: 主题定制 (Theme Customization)
|
|
||||||
**可选**
|
|
||||||
|
|
||||||
1. **品牌色定制**
|
|
||||||
```dart
|
|
||||||
// 在 main.dart 中
|
|
||||||
const brandGreen = Color(0xFF00D4AA);
|
|
||||||
const upColor = Color(0xFF10B981);
|
|
||||||
const downColor = Color(0xFFEF4444);
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **配色方案调整**
|
|
||||||
- 可选:Zinc, Blue, Violet 等
|
|
||||||
|
|
||||||
### Phase 8: 验证和测试 (Validation & Testing)
|
|
||||||
|
|
||||||
1. **功能验证**
|
|
||||||
- 运行应用,测试所有功能
|
|
||||||
- 确保无运行时错误
|
|
||||||
|
|
||||||
2. **视觉验证**
|
|
||||||
- 检查所有页面一致性
|
|
||||||
- 检查深色模式效果
|
|
||||||
- 检查动画流畅度
|
|
||||||
|
|
||||||
3. **代码验证**
|
|
||||||
- 运行 `flutter analyze`
|
|
||||||
- 确保无警告和错误
|
|
||||||
|
|
||||||
## 优先级
|
|
||||||
|
|
||||||
### P0 - 立即执行
|
|
||||||
1. 替换 main_page.dart
|
|
||||||
2. 替换 login_page.dart
|
|
||||||
3. 重构 home_page.dart
|
|
||||||
|
|
||||||
### P1 - 高优先级
|
### P1 - 高优先级
|
||||||
1. 重构 market_page.dart
|
|
||||||
2. 重构 trade_page.dart
|
1. **6.2 文字样式系统**
|
||||||
3. 重构 asset_page.dart
|
- 创建 `lib/core/theme/app_text_styles.dart`
|
||||||
4. 重构 mine_page.dart
|
- 标题样式 (h1-h4)、正文样式、数字样式
|
||||||
|
|
||||||
|
2. **6.3 间距与圆角系统**
|
||||||
|
- 创建 `lib/core/theme/app_spacing.dart`
|
||||||
|
- 统一间距常量、圆角常量、响应式断点
|
||||||
|
|
||||||
### P2 - 中优先级
|
### P2 - 中优先级
|
||||||
1. 创建自定义组件
|
|
||||||
2. 重构 register_page.dart
|
|
||||||
|
|
||||||
### P3 - 低优先级
|
1. **6.5 组件样式统一**
|
||||||
1. 动画优化
|
- 优化按钮、卡片、输入框样式
|
||||||
2. 主题定制
|
|
||||||
3. 性能优化
|
2. **6.6 页面样式优化**
|
||||||
|
- 所有页面应用新主题系统
|
||||||
|
|
||||||
|
### P3 - 验证
|
||||||
|
|
||||||
|
1. **6.7 对比度检查**
|
||||||
|
- 验证所有文字/背景组合 >= 4.5:1
|
||||||
|
|
||||||
## 完成标准
|
## 完成标准
|
||||||
|
|
||||||
- [ ] 所有核心页面已重构为 shadcn 组件
|
- [ ] 颜色系统完整且无重复定义
|
||||||
- [ ] 所有按钮使用 ShadButton
|
- [ ] 所有文字/背景对比度 >= 4.5:1
|
||||||
- [ ] 所有卡片使用 ShadCard
|
- [ ] 无硬编码颜色值
|
||||||
- [ ] 所有输入框使用 ShadInputFormField
|
- [ ] 统一的间距和圆角系统
|
||||||
- [ ] 所有图标使用 LucideIcons
|
- [ ] 所有页面使用新主题
|
||||||
- [ ] 统一的间距和颜色
|
|
||||||
- [ ] 流畅的动画效果
|
|
||||||
- [ ] 功能验证通过
|
|
||||||
- [ ] `flutter analyze` 无错误
|
- [ ] `flutter analyze` 无错误
|
||||||
- [ ] 应用可正常运行
|
- [ ] 应用可正常运行
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- Flutter
|
||||||
|
- shadcn_ui (UI 组件库)
|
||||||
|
- Lucide Icons
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
- ⚠️ **不要修改业务逻辑**
|
- ⚠️ **不要修改业务逻辑**
|
||||||
- ⚠️ **不要修改 API 调用**
|
- ⚠️ **不要修改 API 调用**
|
||||||
- ⚠️ **不要修改 Provider 逻辑**
|
- ⚠️ **不要修改 Provider 逻辑**
|
||||||
- ⚠️ **不要删除现有功能**
|
- ⚠️ **不要删除现有功能**
|
||||||
- ⚠️ **每次修改后测试功能**
|
- ⚠️ **确保文字和背景颜色区分明显**
|
||||||
- ⚠️ **保持代码整洁**
|
- ⚠️ **每次修改后运行 flutter analyze**
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **先读取理解**:阅读现有代码和重构计划
|
|
||||||
2. **优先替换**:先完成已有 shadcn 版本的替换
|
|
||||||
3. **逐个重构**:按优先级重构每个页面
|
|
||||||
4. **创建组件**:提取可复用的自定义组件
|
|
||||||
5. **持续验证**:每完成一个页面就测试
|
|
||||||
6. **更新文档**:完成后更新 IMPLEMENTATION_PLAN.md
|
|
||||||
|
|
||||||
## 输出格式
|
|
||||||
|
|
||||||
创建 `IMPLEMENTATION_PLAN.md`:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Monisuo 主题现代化实施计划
|
|
||||||
|
|
||||||
## Status
|
|
||||||
STATUS: BUILDING
|
|
||||||
|
|
||||||
## Progress
|
|
||||||
|
|
||||||
### Phase 1: Analysis ✅
|
|
||||||
- [分析结果]
|
|
||||||
|
|
||||||
### Phase 2: Core Pages
|
|
||||||
- [ ] main_page.dart 替换
|
|
||||||
- [ ] login_page.dart 替换
|
|
||||||
- [ ] home_page.dart 重构
|
|
||||||
|
|
||||||
### Phase 3: Feature Pages
|
|
||||||
- [ ] market_page.dart 重构
|
|
||||||
- [ ] trade_page.dart 重构
|
|
||||||
- [ ] asset_page.dart 重构
|
|
||||||
- [ ] mine_page.dart 重构
|
|
||||||
|
|
||||||
### Phase 4: Custom Components
|
|
||||||
- [ ] CoinCard 创建
|
|
||||||
- [ ] TradeButton 创建
|
|
||||||
- [ ] AssetCard 创建
|
|
||||||
|
|
||||||
## Changes Made
|
|
||||||
[详细记录每个文件的修改]
|
|
||||||
|
|
||||||
## Issues Found
|
|
||||||
[发现的问题]
|
|
||||||
|
|
||||||
## Questions
|
|
||||||
[需要确认的问题]
|
|
||||||
|
|
||||||
## Completion
|
|
||||||
When all tasks are done, update status to:
|
|
||||||
STATUS: COMPLETE
|
|
||||||
```
|
|
||||||
|
|
||||||
## 开始指令
|
## 开始指令
|
||||||
|
|
||||||
开始工作:
|
开始工作:
|
||||||
1. 读取 `../REFACTOR_PLAN.md` 了解已有计划
|
1. 读取 `specs/theme-design.md` 了解设计规范
|
||||||
2. 读取 `specs/theme-modernization.md` 了解规范
|
2. 读取 `IMPLEMENTATION_PLAN.md` 了解实施计划
|
||||||
3. 读取 `AGENTS.md` 了解项目结构
|
3. 按 P0 -> P1 -> P2 -> P3 优先级执行
|
||||||
4. 创建 `IMPLEMENTATION_PLAN.md`
|
4. 完成后更新 IMPLEMENTATION_PLAN.md 状态
|
||||||
5. 开始执行 P0 优先级任务
|
|
||||||
|
|
||||||
Let's modernize the Monisuo Flutter app with a beautiful shadcn_ui theme! 🎨✨
|
Let's create a professional theme system for the Monisuo Flutter app! 🎨
|
||||||
|
|||||||
@@ -1,62 +1,155 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// 应用颜色常量
|
/// 应用颜色常量 - 统一的颜色系统
|
||||||
|
///
|
||||||
|
/// 设计原则:
|
||||||
|
/// 1. 语义化命名 - 颜色按用途命名,而非外观
|
||||||
|
/// 2. 对比度保证 - 文字与背景对比度 >= 4.5:1 (WCAG AA)
|
||||||
|
/// 3. 一致性 - 同一语义用途使用同一颜色
|
||||||
class AppColors {
|
class AppColors {
|
||||||
AppColors._();
|
AppColors._();
|
||||||
|
|
||||||
// 主题色
|
// ============================================
|
||||||
static const Color primary = Color(0xFF00D4AA);
|
// 品牌色 (Brand Colors) - 专业蓝
|
||||||
static const Color primaryLight = Color(0xFF00E6B8);
|
// ============================================
|
||||||
static const Color primaryDark = Color(0xFF00B894);
|
|
||||||
|
|
||||||
// 状态色
|
/// 主品牌色 - 专业蓝,代表信任与稳定
|
||||||
static const Color success = Color(0xFF00C853);
|
static const Color primary = Color(0xFF2563EB);
|
||||||
static const Color warning = Color(0xFFFF9800);
|
|
||||||
static const Color error = Color(0xFFFF5252);
|
|
||||||
static const Color info = Color(0xFF2196F3);
|
|
||||||
|
|
||||||
// 涨跌色
|
/// 主品牌色浅色变体
|
||||||
static const Color up = Color(0xFF00C853);
|
static const Color primaryLight = Color(0xFF3B82F6);
|
||||||
static const Color down = Color(0xFFFF5252);
|
|
||||||
|
|
||||||
// 深色主题背景
|
/// 主品牌色深色变体
|
||||||
static const Color background = Color(0xFF1A1A2E);
|
static const Color primaryDark = Color(0xFF1D4ED8);
|
||||||
static const Color cardBackground = Color(0xFF16213E);
|
|
||||||
static const Color scaffoldBackground = Color(0xFF1A1A2E);
|
|
||||||
|
|
||||||
// 文字颜色
|
/// 主品牌色渐变
|
||||||
static const Color textPrimary = Colors.white;
|
|
||||||
static const Color textSecondary = Color(0x99FFFFFF);
|
|
||||||
static const Color textHint = Color(0x4DFFFFFF);
|
|
||||||
static const Color textDisabled = Color(0x33FFFFFF);
|
|
||||||
|
|
||||||
// 边框和分割线
|
|
||||||
static const Color border = Color(0x1AFFFFFF);
|
|
||||||
static const Color divider = Color(0x1AFFFFFF);
|
|
||||||
|
|
||||||
// 输入框
|
|
||||||
static const Color inputBackground = Color(0xFF16213E);
|
|
||||||
static const Color inputBorder = Color(0x33FFFFFF);
|
|
||||||
static const Color inputFocusBorder = Color(0xFF00D4AA);
|
|
||||||
|
|
||||||
// 按钮渐变
|
|
||||||
static const LinearGradient primaryGradient = LinearGradient(
|
static const LinearGradient primaryGradient = LinearGradient(
|
||||||
colors: [primary, primaryDark],
|
colors: [primary, primaryDark],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 买入按钮渐变
|
// ============================================
|
||||||
|
// 语义色 (Semantic Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 成功/上涨 - 绿色系
|
||||||
|
static const Color success = Color(0xFF00C853);
|
||||||
|
static const Color up = success;
|
||||||
|
|
||||||
|
/// 警告 - 橙色系
|
||||||
|
static const Color warning = Color(0xFFFF9800);
|
||||||
|
|
||||||
|
/// 错误/下跌 - 红色系
|
||||||
|
static const Color error = Color(0xFFFF5252);
|
||||||
|
static const Color down = error;
|
||||||
|
|
||||||
|
/// 信息 - 蓝色系
|
||||||
|
static const Color info = Color(0xFF2196F3);
|
||||||
|
|
||||||
|
/// 交易类型色
|
||||||
|
static const Color deposit = success;
|
||||||
|
static const Color withdraw = warning;
|
||||||
|
static const Color trade = info;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 深色主题背景色 (Dark Theme Backgrounds)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 主背景色 - 最深的背景
|
||||||
|
static const Color background = Color(0xFF0F0F1A);
|
||||||
|
|
||||||
|
/// 卡片背景色
|
||||||
|
static const Color cardBackground = Color(0xFF1A1A2E);
|
||||||
|
|
||||||
|
/// Scaffold 背景色
|
||||||
|
static const Color scaffoldBackground = background;
|
||||||
|
|
||||||
|
/// 表面色 - 用于弹出层、对话框
|
||||||
|
static const Color surface = Color(0xFF16213E);
|
||||||
|
|
||||||
|
/// 悬停状态背景
|
||||||
|
static const Color hoverBackground = Color(0xFF252542);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 文字颜色 (Text Colors)
|
||||||
|
// 对比度均 >= 4.5:1 (基于深色背景)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 主要文字 - 白色,对比度 21:1
|
||||||
|
static const Color textPrimary = Color(0xFFFFFFFF);
|
||||||
|
|
||||||
|
/// 次要文字 - 浅灰色,对比度 ~10:1
|
||||||
|
static const Color textSecondary = Color(0xFFB0B0B0);
|
||||||
|
|
||||||
|
/// 提示文字 - 中灰色,对比度 ~5:1
|
||||||
|
static const Color textHint = Color(0xFF808080);
|
||||||
|
|
||||||
|
/// 禁用文字 - 深灰色,对比度 ~3:1
|
||||||
|
static const Color textDisabled = Color(0xFF4D4D4D);
|
||||||
|
|
||||||
|
/// 链接文字
|
||||||
|
static const Color textLink = primary;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 边框和分割线 (Borders & Dividers)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 默认边框色
|
||||||
|
static const Color border = Color(0xFF2A2A45);
|
||||||
|
|
||||||
|
/// 分割线颜色
|
||||||
|
static const Color divider = border;
|
||||||
|
|
||||||
|
/// 焦点边框色
|
||||||
|
static const Color focusBorder = primary;
|
||||||
|
|
||||||
|
/// 输入框边框色
|
||||||
|
static const Color inputBorder = Color(0xFF3A3A55);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 输入框颜色 (Input Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 输入框背景
|
||||||
|
static const Color inputBackground = cardBackground;
|
||||||
|
|
||||||
|
/// 输入框焦点边框
|
||||||
|
static const Color inputFocusBorder = primary;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 按钮渐变 (Button Gradients)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 买入按钮渐变
|
||||||
static const LinearGradient buyGradient = LinearGradient(
|
static const LinearGradient buyGradient = LinearGradient(
|
||||||
colors: [Color(0xFF00C853), Color(0xFF00A844)],
|
colors: [Color(0xFF00C853), Color(0xFF00A844)],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 卖出按钮渐变
|
/// 卖出按钮渐变
|
||||||
static const LinearGradient sellGradient = LinearGradient(
|
static const LinearGradient sellGradient = LinearGradient(
|
||||||
colors: [Color(0xFFFF5252), Color(0xFFD32F2F)],
|
colors: [Color(0xFFFF5252), Color(0xFFD32F2F)],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 渐变色 (Gradient Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 资产卡片渐变色
|
||||||
|
static const List<Color> gradientColors = [primary, primaryDark];
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 工具方法 (Utility Methods)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 获取涨跌颜色
|
||||||
|
static Color getChangeColor(bool isUp) => isUp ? up : down;
|
||||||
|
|
||||||
|
/// 获取涨跌背景色(带透明度)
|
||||||
|
static Color getChangeBackgroundColor(bool isUp) =>
|
||||||
|
isUp ? up.withValues(alpha: 0.15) : down.withValues(alpha: 0.15);
|
||||||
}
|
}
|
||||||
|
|||||||
61
flutter_monisuo/lib/core/theme/app_color_scheme.dart
Normal file
61
flutter_monisuo/lib/core/theme/app_color_scheme.dart
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
|
import '../constants/app_colors.dart';
|
||||||
|
|
||||||
|
/// 自定义品牌颜色方案 - 深色主题
|
||||||
|
///
|
||||||
|
/// 基于品牌色 #2563EB (专业蓝) 定制
|
||||||
|
class AppShadColorScheme {
|
||||||
|
AppShadColorScheme._();
|
||||||
|
|
||||||
|
/// 深色主题颜色
|
||||||
|
static ShadColorScheme get dark => ShadColorScheme(
|
||||||
|
// 背景与前景
|
||||||
|
background: AppColors.background,
|
||||||
|
foreground: AppColors.textPrimary,
|
||||||
|
|
||||||
|
// 卡片
|
||||||
|
card: AppColors.cardBackground,
|
||||||
|
cardForeground: AppColors.textPrimary,
|
||||||
|
|
||||||
|
// 弹出层
|
||||||
|
popover: AppColors.surface,
|
||||||
|
popoverForeground: AppColors.textPrimary,
|
||||||
|
|
||||||
|
// 主色
|
||||||
|
primary: AppColors.primary,
|
||||||
|
primaryForeground: Colors.white,
|
||||||
|
|
||||||
|
// 次要色
|
||||||
|
secondary: const Color(0xFF252542),
|
||||||
|
secondaryForeground: AppColors.textPrimary,
|
||||||
|
|
||||||
|
// 静音色
|
||||||
|
muted: const Color(0xFF2A2A45),
|
||||||
|
mutedForeground: AppColors.textSecondary,
|
||||||
|
|
||||||
|
// 强调色
|
||||||
|
accent: AppColors.primary.withValues(alpha: 0.15),
|
||||||
|
accentForeground: AppColors.primary,
|
||||||
|
|
||||||
|
// 危险色
|
||||||
|
destructive: AppColors.error,
|
||||||
|
destructiveForeground: Colors.white,
|
||||||
|
|
||||||
|
// 边框与输入
|
||||||
|
border: AppColors.border,
|
||||||
|
input: AppColors.inputBorder,
|
||||||
|
ring: AppColors.primary,
|
||||||
|
|
||||||
|
// 选择色
|
||||||
|
selection: AppColors.primary.withValues(alpha: 0.3),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建自定义 ShadThemeData
|
||||||
|
ShadThemeData createAppShadTheme() {
|
||||||
|
return ShadThemeData(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
colorScheme: AppShadColorScheme.dark,
|
||||||
|
);
|
||||||
|
}
|
||||||
145
flutter_monisuo/lib/core/theme/app_colors.dart
Normal file
145
flutter_monisuo/lib/core/theme/app_colors.dart
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// 数字货币应用颜色系统
|
||||||
|
///
|
||||||
|
/// 设计原则:
|
||||||
|
/// 1. 所有文字与背景对比度 >= 4.5:1 (WCAG AA)
|
||||||
|
/// 2. 涨跌色使用国际通用标准 (绿涨红跌)
|
||||||
|
/// 3. 背景色层次分明,易于区分
|
||||||
|
/// 4. 杜绝文字和背景颜色一样无法区分的情况
|
||||||
|
class AppColors {
|
||||||
|
AppColors._();
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 品牌色 (Brand Colors) - 专业蓝
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 主色 - 专业蓝,代表信任与稳定
|
||||||
|
static const Color primary = Color(0xFF2563EB);
|
||||||
|
static const Color primaryLight = Color(0xFF3B82F6);
|
||||||
|
static const Color primaryDark = Color(0xFF1D4ED8);
|
||||||
|
|
||||||
|
/// 主色渐变 - 用于卡片、按钮等
|
||||||
|
static const LinearGradient primaryGradient = LinearGradient(
|
||||||
|
colors: [primary, primaryDark],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 交易色 (Trading Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 涨/买入 - 标准绿色 (国际通用)
|
||||||
|
static const Color up = Color(0xFF00C853);
|
||||||
|
|
||||||
|
/// 跌/卖出 - 标准红色 (国际通用)
|
||||||
|
static const Color down = Color(0xFFFF5252);
|
||||||
|
|
||||||
|
/// 买入按钮渐变
|
||||||
|
static const LinearGradient buyGradient = LinearGradient(
|
||||||
|
colors: [Color(0xFF00C853), Color(0xFF00A844)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 卖出按钮渐变
|
||||||
|
static const LinearGradient sellGradient = LinearGradient(
|
||||||
|
colors: [Color(0xFFFF5252), Color(0xFFD32F2F)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 功能色 (Semantic Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 成功
|
||||||
|
static const Color success = Color(0xFF00C853);
|
||||||
|
|
||||||
|
/// 警告
|
||||||
|
static const Color warning = Color(0xFFFF9800);
|
||||||
|
|
||||||
|
/// 错误
|
||||||
|
static const Color error = Color(0xFFFF5252);
|
||||||
|
|
||||||
|
/// 信息
|
||||||
|
static const Color info = Color(0xFF2196F3);
|
||||||
|
|
||||||
|
/// 充值
|
||||||
|
static const Color deposit = Color(0xFF00C853);
|
||||||
|
|
||||||
|
/// 提现
|
||||||
|
static const Color withdraw = Color(0xFFFF9800);
|
||||||
|
|
||||||
|
/// 划转/交易
|
||||||
|
static const Color trade = Color(0xFF2196F3);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 背景色 (Dark Theme Backgrounds)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 页面背景 - 最深
|
||||||
|
static const Color background = Color(0xFF0F0F1A);
|
||||||
|
|
||||||
|
/// 卡片背景 - 中等深度
|
||||||
|
static const Color cardBackground = Color(0xFF1A1A2E);
|
||||||
|
|
||||||
|
/// 输入框背景 - 稍浅
|
||||||
|
static const Color inputBackground = Color(0xFF16213E);
|
||||||
|
|
||||||
|
/// Scaffold 背景 (兼容旧代码)
|
||||||
|
static const Color scaffoldBackground = Color(0xFF0F0F1A);
|
||||||
|
|
||||||
|
/// 模态框背景
|
||||||
|
static const Color modalBackground = Color(0xFF1E1E32);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 文字颜色 (Text Colors)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 主要文字 - 白色,对比度 21:1
|
||||||
|
static const Color textPrimary = Color(0xFFFFFFFF);
|
||||||
|
|
||||||
|
/// 次要文字 - 浅灰蓝,对比度约 8:1
|
||||||
|
static const Color textSecondary = Color(0xFFB0B0C0);
|
||||||
|
|
||||||
|
/// 提示文字 - 中灰,对比度约 4.7:1
|
||||||
|
static const Color textHint = Color(0xFF6B6B80);
|
||||||
|
|
||||||
|
/// 禁用文字 - 暗灰
|
||||||
|
static const Color textDisabled = Color(0xFF4A4A5A);
|
||||||
|
|
||||||
|
/// 链接文字 - 品牌蓝
|
||||||
|
static const Color textLink = Color(0xFF2563EB);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 边框与分割线 (Borders & Dividers)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 边框 - 低透明度白色
|
||||||
|
static const Color border = Color(0x14FFFFFF); // 8% white
|
||||||
|
|
||||||
|
/// 分割线 - 更低透明度
|
||||||
|
static const Color divider = Color(0x0FFFFFFF); // 6% white
|
||||||
|
|
||||||
|
/// 输入框边框
|
||||||
|
static const Color inputBorder = Color(0x1AFFFFFF); // 10% white
|
||||||
|
|
||||||
|
/// 输入框聚焦边框 - 品牌蓝
|
||||||
|
static const Color inputFocusBorder = Color(0xFF2563EB);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 便捷方法
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 根据涨跌获取颜色
|
||||||
|
static Color getChangeColor(bool isUp) => isUp ? up : down;
|
||||||
|
|
||||||
|
/// 获取带透明度的涨跌背景色
|
||||||
|
static Color getChangeBackgroundColor(bool isUp) =>
|
||||||
|
isUp ? up.withOpacity(0.15) : down.withOpacity(0.15);
|
||||||
|
|
||||||
|
/// 渐变色 (兼容旧代码) - 品牌蓝
|
||||||
|
static const List<Color> gradientColors = [Color(0xFF2563EB), Color(0xFF1D4ED8)];
|
||||||
|
}
|
||||||
179
flutter_monisuo/lib/core/theme/app_spacing.dart
Normal file
179
flutter_monisuo/lib/core/theme/app_spacing.dart
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// 间距系统
|
||||||
|
///
|
||||||
|
/// 使用 4px 基础单位,确保一致性
|
||||||
|
class AppSpacing {
|
||||||
|
AppSpacing._();
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 基础间距 (Base Spacing)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 极小 - 4px
|
||||||
|
static const double xs = 4.0;
|
||||||
|
|
||||||
|
/// 小 - 8px
|
||||||
|
static const double sm = 8.0;
|
||||||
|
|
||||||
|
/// 中 - 16px (默认)
|
||||||
|
static const double md = 16.0;
|
||||||
|
|
||||||
|
/// 大 - 24px
|
||||||
|
static const double lg = 24.0;
|
||||||
|
|
||||||
|
/// 特大 - 32px
|
||||||
|
static const double xl = 32.0;
|
||||||
|
|
||||||
|
/// 超大 - 48px
|
||||||
|
static const double xxl = 48.0;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 预设 EdgeInsets
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 页面内边距
|
||||||
|
static const EdgeInsets pagePadding = EdgeInsets.all(md);
|
||||||
|
|
||||||
|
/// 卡片内边距
|
||||||
|
static const EdgeInsets cardPadding = EdgeInsets.all(md);
|
||||||
|
|
||||||
|
/// 列表项内边距
|
||||||
|
static const EdgeInsets listItemPadding = EdgeInsets.symmetric(
|
||||||
|
horizontal: md,
|
||||||
|
vertical: sm,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 按钮内边距
|
||||||
|
static const EdgeInsets buttonPadding = EdgeInsets.symmetric(
|
||||||
|
horizontal: lg,
|
||||||
|
vertical: 14,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 输入框内边距
|
||||||
|
static const EdgeInsets inputPadding = EdgeInsets.symmetric(
|
||||||
|
horizontal: md,
|
||||||
|
vertical: 14,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 便捷方法
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 获取水平间距
|
||||||
|
static SizedBox horizontal(double spacing) => SizedBox(width: spacing);
|
||||||
|
|
||||||
|
/// 获取垂直间距
|
||||||
|
static SizedBox vertical(double spacing) => SizedBox(height: spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 圆角系统
|
||||||
|
class AppRadius {
|
||||||
|
AppRadius._();
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 基础圆角 (Base Radius)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 小圆角 - 6px (标签、小组件)
|
||||||
|
static const double sm = 6.0;
|
||||||
|
|
||||||
|
/// 中圆角 - 10px (按钮、输入框)
|
||||||
|
static const double md = 10.0;
|
||||||
|
|
||||||
|
/// 大圆角 - 14px (卡片)
|
||||||
|
static const double lg = 14.0;
|
||||||
|
|
||||||
|
/// 特大圆角 - 20px (大卡片、模态框)
|
||||||
|
static const double xl = 20.0;
|
||||||
|
|
||||||
|
/// 圆形 - 999px
|
||||||
|
static const double full = 999.0;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 预设 BorderRadius
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 小圆角
|
||||||
|
static BorderRadius get radiusSm => BorderRadius.circular(sm);
|
||||||
|
|
||||||
|
/// 中圆角
|
||||||
|
static BorderRadius get radiusMd => BorderRadius.circular(md);
|
||||||
|
|
||||||
|
/// 大圆角
|
||||||
|
static BorderRadius get radiusLg => BorderRadius.circular(lg);
|
||||||
|
|
||||||
|
/// 特大圆角
|
||||||
|
static BorderRadius get radiusXl => BorderRadius.circular(xl);
|
||||||
|
|
||||||
|
/// 圆形
|
||||||
|
static BorderRadius get radiusFull => BorderRadius.circular(full);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 响应式断点
|
||||||
|
class AppBreakpoints {
|
||||||
|
AppBreakpoints._();
|
||||||
|
|
||||||
|
/// 手机竖屏
|
||||||
|
static const double mobile = 360;
|
||||||
|
|
||||||
|
/// 手机横屏/小平板
|
||||||
|
static const double tablet = 768;
|
||||||
|
|
||||||
|
/// 平板/桌面
|
||||||
|
static const double desktop = 1024;
|
||||||
|
|
||||||
|
/// 检查是否为手机
|
||||||
|
static bool isMobile(BuildContext context) {
|
||||||
|
return MediaQuery.of(context).size.width < tablet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查是否为平板
|
||||||
|
static bool isTablet(BuildContext context) {
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
return width >= tablet && width < desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查是否为桌面
|
||||||
|
static bool isDesktop(BuildContext context) {
|
||||||
|
return MediaQuery.of(context).size.width >= desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 根据屏幕宽度获取响应式值
|
||||||
|
static T responsive<T>(
|
||||||
|
BuildContext context, {
|
||||||
|
required T mobile,
|
||||||
|
T? tablet,
|
||||||
|
T? desktop,
|
||||||
|
}) {
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
if (width >= AppBreakpoints.desktop) {
|
||||||
|
return desktop ?? tablet ?? mobile;
|
||||||
|
} else if (width >= AppBreakpoints.tablet) {
|
||||||
|
return tablet ?? mobile;
|
||||||
|
}
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 触摸目标尺寸
|
||||||
|
class AppTouchTarget {
|
||||||
|
AppTouchTarget._();
|
||||||
|
|
||||||
|
/// 最小触摸目标 - 44x44 (iOS HIG 标准)
|
||||||
|
static const double minSize = 44.0;
|
||||||
|
|
||||||
|
/// 确保触摸目标足够大
|
||||||
|
static Widget ensureMinSize({
|
||||||
|
required Widget child,
|
||||||
|
double minSize = AppTouchTarget.minSize,
|
||||||
|
}) {
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minWidth: minSize,
|
||||||
|
minHeight: minSize,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
171
flutter_monisuo/lib/core/theme/app_text_styles.dart
Normal file
171
flutter_monisuo/lib/core/theme/app_text_styles.dart
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'app_colors.dart';
|
||||||
|
|
||||||
|
/// 文字样式系统
|
||||||
|
///
|
||||||
|
/// 统一管理所有文字样式,确保一致性
|
||||||
|
/// 所有样式默认使用 textPrimary 颜色,保证对比度
|
||||||
|
class AppTextStyles {
|
||||||
|
AppTextStyles._();
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 标题样式 (Headings)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// H1 - 页面大标题
|
||||||
|
static const TextStyle h1 = TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.3,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// H2 - 区块标题
|
||||||
|
static const TextStyle h2 = TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.3,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// H3 - 卡片标题
|
||||||
|
static const TextStyle h3 = TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.4,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// H4 - 小标题
|
||||||
|
static const TextStyle h4 = TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.4,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 正文样式 (Body)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// Body1 - 主要正文
|
||||||
|
static const TextStyle body1 = TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Body2 - 次要正文
|
||||||
|
static const TextStyle body2 = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 辅助文字 (Caption & Small)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// Caption - 说明文字
|
||||||
|
static const TextStyle caption = TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: AppColors.textSecondary,
|
||||||
|
height: 1.4,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Small - 极小文字
|
||||||
|
static const TextStyle small = TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: AppColors.textSecondary,
|
||||||
|
height: 1.3,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Hint - 提示文字
|
||||||
|
static const TextStyle hint = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: AppColors.textHint,
|
||||||
|
height: 1.4,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 特殊样式 (Special)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 金额/价格 - 大号数字
|
||||||
|
static const TextStyle amount = TextStyle(
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.2,
|
||||||
|
fontFeatures: [FontFeature.tabularFigures()],
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 价格 - 标准数字
|
||||||
|
static const TextStyle price = TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.3,
|
||||||
|
fontFeatures: [FontFeature.tabularFigures()],
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 价格变化 - 涨跌幅
|
||||||
|
static const TextStyle priceChange = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.3,
|
||||||
|
fontFeatures: [FontFeature.tabularFigures()],
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 按钮文字
|
||||||
|
static const TextStyle button = TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
height: 1.2,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 链接文字
|
||||||
|
static const TextStyle link = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.textLink,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
height: 1.4,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 可复制修改的样式方法
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/// 获取带颜色的标题样式
|
||||||
|
static TextStyle headingWithColor(TextStyle style, Color color) {
|
||||||
|
return style.copyWith(color: color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取带颜色的正文样式
|
||||||
|
static TextStyle bodyWithColor(TextStyle style, Color color) {
|
||||||
|
return style.copyWith(color: color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取粗体样式
|
||||||
|
static TextStyle bold(TextStyle style) {
|
||||||
|
return style.copyWith(fontWeight: FontWeight.bold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取半粗体样式
|
||||||
|
static TextStyle semiBold(TextStyle style) {
|
||||||
|
return style.copyWith(fontWeight: FontWeight.w600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 兼容旧代码的别名
|
||||||
|
@Deprecated('Use AppTextStyles instead')
|
||||||
|
class AppText {
|
||||||
|
AppText._();
|
||||||
|
}
|
||||||
@@ -104,6 +104,12 @@ class AppTextStyles {
|
|||||||
color: AppColors.textPrimary,
|
color: AppColors.textPrimary,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static const TextStyle heading4 = TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
);
|
||||||
|
|
||||||
static const TextStyle body1 = TextStyle(
|
static const TextStyle body1 = TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: AppColors.textPrimary,
|
color: AppColors.textPrimary,
|
||||||
@@ -123,6 +129,26 @@ class AppTextStyles {
|
|||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: AppColors.textHint,
|
color: AppColors.textHint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// 价格样式 - 用于显示价格、金额
|
||||||
|
static const TextStyle price = TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 涨跌幅样式
|
||||||
|
static const TextStyle change = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 数字样式 - 用于显示数量
|
||||||
|
static const TextStyle number = TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 间距常量
|
/// 间距常量
|
||||||
@@ -135,6 +161,21 @@ class AppSpacing {
|
|||||||
static const double lg = 24.0;
|
static const double lg = 24.0;
|
||||||
static const double xl = 32.0;
|
static const double xl = 32.0;
|
||||||
static const double xxl = 48.0;
|
static const double xxl = 48.0;
|
||||||
|
|
||||||
|
/// 页面水平内边距
|
||||||
|
static const double pageHorizontal = 16.0;
|
||||||
|
|
||||||
|
/// 页面垂直内边距
|
||||||
|
static const double pageVertical = 16.0;
|
||||||
|
|
||||||
|
/// 卡片内边距
|
||||||
|
static const double cardPadding = 16.0;
|
||||||
|
|
||||||
|
/// 列表项间距
|
||||||
|
static const double listItemSpacing = 8.0;
|
||||||
|
|
||||||
|
/// 表单字段间距
|
||||||
|
static const double formFieldSpacing = 12.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 圆角常量
|
/// 圆角常量
|
||||||
@@ -146,4 +187,77 @@ class AppRadius {
|
|||||||
static const double lg = 16.0;
|
static const double lg = 16.0;
|
||||||
static const double xl = 24.0;
|
static const double xl = 24.0;
|
||||||
static const double full = 999.0;
|
static const double full = 999.0;
|
||||||
|
|
||||||
|
/// 卡片圆角
|
||||||
|
static const double card = lg;
|
||||||
|
|
||||||
|
/// 按钮圆角
|
||||||
|
static const double button = md;
|
||||||
|
|
||||||
|
/// 输入框圆角
|
||||||
|
static const double input = md;
|
||||||
|
|
||||||
|
/// 标签圆角
|
||||||
|
static const double badge = sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 响应式断点
|
||||||
|
class AppBreakpoints {
|
||||||
|
AppBreakpoints._();
|
||||||
|
|
||||||
|
/// 手机
|
||||||
|
static const double mobile = 600;
|
||||||
|
|
||||||
|
/// 平板
|
||||||
|
static const double tablet = 900;
|
||||||
|
|
||||||
|
/// 桌面
|
||||||
|
static const double desktop = 1200;
|
||||||
|
|
||||||
|
/// 判断是否为手机
|
||||||
|
static bool isMobile(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.width < mobile;
|
||||||
|
|
||||||
|
/// 判断是否为平板
|
||||||
|
static bool isTablet(BuildContext context) {
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
return width >= mobile && width < tablet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 判断是否为桌面
|
||||||
|
static bool isDesktop(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.width >= tablet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 响应式工具
|
||||||
|
class Responsive {
|
||||||
|
Responsive._();
|
||||||
|
|
||||||
|
/// 根据屏幕宽度返回响应式值
|
||||||
|
static T value<T>(
|
||||||
|
BuildContext context, {
|
||||||
|
required T mobile,
|
||||||
|
T? tablet,
|
||||||
|
T? desktop,
|
||||||
|
}) {
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
if (width >= AppBreakpoints.tablet && desktop != null) {
|
||||||
|
return desktop;
|
||||||
|
}
|
||||||
|
if (width >= AppBreakpoints.mobile && tablet != null) {
|
||||||
|
return tablet;
|
||||||
|
}
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 响应式字体大小
|
||||||
|
static double fontSize(BuildContext context, double base) {
|
||||||
|
return value(context, mobile: base, tablet: base * 1.1, desktop: base * 1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 响应式间距
|
||||||
|
static double spacing(BuildContext context, double base) {
|
||||||
|
return value(context, mobile: base, tablet: base * 1.2, desktop: base * 1.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
|
|
||||||
import 'core/network/dio_client.dart';
|
import 'core/network/dio_client.dart';
|
||||||
import 'core/storage/local_storage.dart';
|
import 'core/storage/local_storage.dart';
|
||||||
|
import 'core/theme/app_color_scheme.dart';
|
||||||
import 'data/services/user_service.dart';
|
import 'data/services/user_service.dart';
|
||||||
import 'data/services/market_service.dart';
|
import 'data/services/market_service.dart';
|
||||||
import 'data/services/trade_service.dart';
|
import 'data/services/trade_service.dart';
|
||||||
@@ -38,10 +39,7 @@ class MyApp extends StatelessWidget {
|
|||||||
child: AuthNavigator(
|
child: AuthNavigator(
|
||||||
child: ShadApp.custom(
|
child: ShadApp.custom(
|
||||||
themeMode: ThemeMode.dark,
|
themeMode: ThemeMode.dark,
|
||||||
darkTheme: ShadThemeData(
|
darkTheme: createAppShadTheme(),
|
||||||
brightness: Brightness.dark,
|
|
||||||
colorScheme: const ShadSlateColorScheme.dark(),
|
|
||||||
),
|
|
||||||
appBuilder: _buildMaterialApp,
|
appBuilder: _buildMaterialApp,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import '../../core/theme/app_colors.dart';
|
||||||
|
|
||||||
/// 资产卡片组件 - 用于显示资产总览
|
/// 资产卡片组件 - 用于显示资产总览
|
||||||
class AssetCard extends StatelessWidget {
|
class AssetCard extends StatelessWidget {
|
||||||
@@ -13,9 +13,9 @@ class AssetCard extends StatelessWidget {
|
|||||||
final Gradient? gradient;
|
final Gradient? gradient;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
// 默认渐变色
|
// 默认渐变色 - 使用品牌蓝
|
||||||
static const defaultGradient = LinearGradient(
|
static const defaultGradient = LinearGradient(
|
||||||
colors: [Color(0xFF00D4AA), Color(0xFF00B894)],
|
colors: [Color(0xFF2563EB), Color(0xFF1D4ED8)],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
|
import '../../core/constants/app_colors.dart';
|
||||||
|
|
||||||
/// 币种卡片组件 - 用于显示币种信息
|
/// 币种卡片组件 - 用于显示币种信息
|
||||||
class CoinCard extends StatelessWidget {
|
class CoinCard extends StatelessWidget {
|
||||||
@@ -11,10 +12,6 @@ class CoinCard extends StatelessWidget {
|
|||||||
final String? icon;
|
final String? icon;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
// 颜色常量
|
|
||||||
static const upColor = Color(0xFF00C853);
|
|
||||||
static const downColor = Color(0xFFFF5252);
|
|
||||||
|
|
||||||
const CoinCard({
|
const CoinCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.code,
|
required this.code,
|
||||||
@@ -78,13 +75,13 @@ class CoinCard extends StatelessWidget {
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isUp ? upColor.withOpacity(0.2) : downColor.withOpacity(0.2),
|
color: AppColors.getChangeBackgroundColor(isUp),
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
change,
|
change,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: isUp ? upColor : downColor,
|
color: AppColors.getChangeColor(isUp),
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../core/constants/app_colors.dart';
|
||||||
import '../../../providers/asset_provider.dart';
|
import '../../../providers/asset_provider.dart';
|
||||||
import '../../shared/ui_constants.dart';
|
import '../../shared/ui_constants.dart';
|
||||||
import '../orders/fund_orders_page.dart';
|
import '../orders/fund_orders_page.dart';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../core/constants/app_colors.dart';
|
||||||
import '../../../providers/asset_provider.dart';
|
import '../../../providers/asset_provider.dart';
|
||||||
import '../../../providers/auth_provider.dart';
|
import '../../../providers/auth_provider.dart';
|
||||||
import '../../shared/ui_constants.dart';
|
import '../../shared/ui_constants.dart';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../core/constants/app_colors.dart';
|
||||||
import '../../../data/models/coin.dart';
|
import '../../../data/models/coin.dart';
|
||||||
import '../../../providers/market_provider.dart';
|
import '../../../providers/market_provider.dart';
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
|||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
height: 44,
|
height: 44,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: tabs.asMap().entries.map((entry) {
|
children: tabs.asMap().entries.map((entry) {
|
||||||
final index = entry.key;
|
final index = entry.key;
|
||||||
@@ -192,7 +193,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
|||||||
onRefresh: provider.refresh,
|
onRefresh: provider.refresh,
|
||||||
color: theme.colorScheme.primary,
|
color: theme.colorScheme.primary,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||||
itemCount: coins.length,
|
itemCount: coins.length,
|
||||||
itemBuilder: (context, index) => _buildCoinItem(coins[index]),
|
itemBuilder: (context, index) => _buildCoinItem(coins[index]),
|
||||||
),
|
),
|
||||||
@@ -201,8 +202,6 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
|||||||
|
|
||||||
Widget _buildCoinItem(Coin coin) {
|
Widget _buildCoinItem(Coin coin) {
|
||||||
final theme = ShadTheme.of(context);
|
final theme = ShadTheme.of(context);
|
||||||
final upColor = const Color(0xFF00C853);
|
|
||||||
final downColor = const Color(0xFFFF5252);
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 8),
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
@@ -245,13 +244,13 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: coin.isUp ? upColor.withValues(alpha: 0.2) : downColor.withValues(alpha: 0.2),
|
color: AppColors.getChangeBackgroundColor(coin.isUp),
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
coin.formattedChange,
|
coin.formattedChange,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: coin.isUp ? upColor : downColor,
|
color: AppColors.getChangeColor(coin.isUp),
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../core/constants/app_colors.dart';
|
||||||
import '../../../data/models/coin.dart';
|
import '../../../data/models/coin.dart';
|
||||||
import '../../../providers/market_provider.dart';
|
import '../../../providers/market_provider.dart';
|
||||||
import '../../../providers/asset_provider.dart';
|
import '../../../providers/asset_provider.dart';
|
||||||
|
|||||||
@@ -1,25 +1,21 @@
|
|||||||
import 'package:flutter/material.dart';
|
/// UI 常量整合导出
|
||||||
|
///
|
||||||
|
/// 统一导出所有设计 token,方便使用
|
||||||
|
/// 使用方式: import 'ui/shared/ui_constants.dart';
|
||||||
|
|
||||||
/// 应用颜色常量
|
// 导出颜色系统
|
||||||
class AppColors {
|
export '../../core/constants/app_colors.dart';
|
||||||
AppColors._();
|
|
||||||
|
|
||||||
static const Color up = Color(0xFF00C853);
|
// 导出主题配置 (包含 AppTextStyles, AppSpacing, AppRadius, AppBreakpoints)
|
||||||
static const Color down = Color(0xFFFF5252);
|
export '../../core/theme/app_theme.dart';
|
||||||
static const Color deposit = Color(0xFF00C853);
|
|
||||||
static const Color withdraw = Color(0xFFFF9800);
|
|
||||||
static const Color trade = Color(0xFF2196F3);
|
|
||||||
|
|
||||||
static const List<Color> gradientColors = [
|
|
||||||
Color(0xFF00D4AA),
|
|
||||||
Color(0xFF00B894),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 表单验证器
|
/// 表单验证器
|
||||||
|
///
|
||||||
|
/// 提供常用的表单验证方法
|
||||||
class Validators {
|
class Validators {
|
||||||
Validators._();
|
Validators._();
|
||||||
|
|
||||||
|
/// 金额验证
|
||||||
static String? amount(String? value) {
|
static String? amount(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return '请输入金额';
|
return '请输入金额';
|
||||||
@@ -31,6 +27,7 @@ class Validators {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 价格验证
|
||||||
static String? price(String? value) {
|
static String? price(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return '请输入价格';
|
return '请输入价格';
|
||||||
@@ -42,6 +39,7 @@ class Validators {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 数量验证
|
||||||
static String? quantity(String? value) {
|
static String? quantity(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return '请输入数量';
|
return '请输入数量';
|
||||||
@@ -53,10 +51,45 @@ class Validators {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 必填字段验证
|
||||||
static String? required(String? value, String fieldName) {
|
static String? required(String? value, String fieldName) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return '请输入$fieldName';
|
return '请输入$fieldName';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 用户名验证
|
||||||
|
static String? username(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return '请输入用户名';
|
||||||
|
}
|
||||||
|
if (value.length < 3) {
|
||||||
|
return '用户名至少 3 个字符';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 密码验证
|
||||||
|
static String? password(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return '请输入密码';
|
||||||
|
}
|
||||||
|
if (value.length < 6) {
|
||||||
|
return '密码至少 6 个字符';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 邮箱验证
|
||||||
|
static String? email(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return '请输入邮箱';
|
||||||
|
}
|
||||||
|
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
||||||
|
if (!emailRegex.hasMatch(value)) {
|
||||||
|
return '请输入有效的邮箱地址';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
237
flutter_monisuo/specs/theme-design.md
Normal file
237
flutter_monisuo/specs/theme-design.md
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
# 数字货币应用主题设计规范
|
||||||
|
|
||||||
|
## 设计原则
|
||||||
|
|
||||||
|
1. **一致性** - 所有页面使用统一的设计语言
|
||||||
|
2. **可读性** - 确保文字与背景对比度充足 (WCAG AA 标准)
|
||||||
|
3. **响应式** - 适配不同屏幕尺寸
|
||||||
|
4. **专业性** - 符合金融/交易类应用的专业感
|
||||||
|
5. **无障碍** - 避免颜色冲突,支持色盲用户
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 颜色系统
|
||||||
|
|
||||||
|
### 主色调 (Primary)
|
||||||
|
|
||||||
|
```
|
||||||
|
主色: #00D4AA (青绿色 - 代表增长、积极)
|
||||||
|
主色浅: #00E6B8
|
||||||
|
主色深: #00B894
|
||||||
|
```
|
||||||
|
|
||||||
|
### 涨跌色 (Trading Colors)
|
||||||
|
|
||||||
|
```
|
||||||
|
涨/买入: #00C853 (标准绿 - 国际通用)
|
||||||
|
跌/卖出: #FF5252 (标准红 - 国际通用)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 背景色 (Dark Theme)
|
||||||
|
|
||||||
|
```
|
||||||
|
背景主色: #0F0F1A (深蓝黑)
|
||||||
|
卡片背景: #1A1A2E (深蓝紫)
|
||||||
|
输入框背景: #16213E (深蓝)
|
||||||
|
模态框背景: #1E1E32
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文字颜色
|
||||||
|
|
||||||
|
```
|
||||||
|
主要文字: #FFFFFF (白色)
|
||||||
|
次要文字: #B0B0C0 (灰蓝)
|
||||||
|
提示文字: #6B6B80 (暗灰)
|
||||||
|
禁用文字: #4A4A5A
|
||||||
|
链接文字: #00D4AA
|
||||||
|
```
|
||||||
|
|
||||||
|
### 边框与分割线
|
||||||
|
|
||||||
|
```
|
||||||
|
边框: rgba(255, 255, 255, 0.08)
|
||||||
|
分割线: rgba(255, 255, 255, 0.06)
|
||||||
|
聚焦边框: #00D4AA
|
||||||
|
```
|
||||||
|
|
||||||
|
### 功能色
|
||||||
|
|
||||||
|
```
|
||||||
|
成功: #00C853
|
||||||
|
警告: #FF9800
|
||||||
|
错误: #FF5252
|
||||||
|
信息: #2196F3
|
||||||
|
充值: #00C853
|
||||||
|
提现: #FF9800
|
||||||
|
划转: #2196F3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 间距系统
|
||||||
|
|
||||||
|
```dart
|
||||||
|
static const double xs = 4.0;
|
||||||
|
static const double sm = 8.0;
|
||||||
|
static const double md = 16.0;
|
||||||
|
static const double lg = 24.0;
|
||||||
|
static const double xl = 32.0;
|
||||||
|
static const double xxl = 48.0;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 圆角系统
|
||||||
|
|
||||||
|
```dart
|
||||||
|
static const double sm = 8.0; // 小组件
|
||||||
|
static const double md = 12.0; // 按钮、输入框
|
||||||
|
static const double lg = 16.0; // 卡片
|
||||||
|
static const double xl = 24.0; // 大卡片
|
||||||
|
static const double full = 999.0; // 圆形
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文字排版
|
||||||
|
|
||||||
|
### 字号
|
||||||
|
|
||||||
|
```
|
||||||
|
h1: 28px - 页面大标题
|
||||||
|
h2: 24px - 区块标题
|
||||||
|
h3: 20px - 卡片标题
|
||||||
|
h4: 18px - 小标题
|
||||||
|
body1: 16px - 正文
|
||||||
|
body2: 14px - 次要正文
|
||||||
|
caption: 12px - 辅助文字
|
||||||
|
small: 11px - 极小文字
|
||||||
|
```
|
||||||
|
|
||||||
|
### 字重
|
||||||
|
|
||||||
|
```
|
||||||
|
bold: 700 (标题)
|
||||||
|
semibold: 600 (强调)
|
||||||
|
medium: 500 (正文)
|
||||||
|
regular: 400 (辅助)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 组件规范
|
||||||
|
|
||||||
|
### 按钮
|
||||||
|
|
||||||
|
1. **主按钮**
|
||||||
|
- 高度: 48px
|
||||||
|
- 圆角: 12px
|
||||||
|
- 背景: 主题色渐变
|
||||||
|
- 文字: 白色, 16px, semibold
|
||||||
|
|
||||||
|
2. **买入按钮**
|
||||||
|
- 背景: #00C853 渐变
|
||||||
|
- 文字: 白色
|
||||||
|
|
||||||
|
3. **卖出按钮**
|
||||||
|
- 背景: #FF5252 渐变
|
||||||
|
- 文字: 白色
|
||||||
|
|
||||||
|
4. **轮廓按钮**
|
||||||
|
- 边框: 1px solid border
|
||||||
|
- 背景: 透明
|
||||||
|
- 文字: 主题色
|
||||||
|
|
||||||
|
### 输入框
|
||||||
|
|
||||||
|
- 高度: 48px
|
||||||
|
- 圆角: 12px
|
||||||
|
- 背景: #16213E
|
||||||
|
- 边框: 1px solid rgba(255,255,255,0.1)
|
||||||
|
- 聚焦边框: #00D4AA
|
||||||
|
- 文字: 白色
|
||||||
|
- 提示: #6B6B80
|
||||||
|
|
||||||
|
### 卡片
|
||||||
|
|
||||||
|
- 圆角: 16px
|
||||||
|
- 背景: #1A1A2E
|
||||||
|
- 内边距: 16px-20px
|
||||||
|
- 阴影: 无 (扁平设计)
|
||||||
|
|
||||||
|
### 涨跌标签
|
||||||
|
|
||||||
|
- 圆角: 6px
|
||||||
|
- 内边距: 6px 10px
|
||||||
|
- 涨: 背景 rgba(0,200,83,0.15), 文字 #00C853
|
||||||
|
- 跌: 背景 rgba(255,82,82,0.15), 文字 #FF5252
|
||||||
|
|
||||||
|
### 底部导航
|
||||||
|
|
||||||
|
- 高度: 60px + safeArea
|
||||||
|
- 背景: #0F0F1A
|
||||||
|
- 边框: top 1px solid rgba(255,255,255,0.08)
|
||||||
|
- 选中色: #00D4AA
|
||||||
|
- 未选中色: #6B6B80
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 响应式断点
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 手机竖屏
|
||||||
|
const double mobile = 360;
|
||||||
|
|
||||||
|
// 手机横屏/小平板
|
||||||
|
const double tablet = 768;
|
||||||
|
|
||||||
|
// 平板/桌面
|
||||||
|
const double desktop = 1024;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 动画规范
|
||||||
|
|
||||||
|
- 标准时长: 200ms-300ms
|
||||||
|
- 缓动曲线: easeOutCubic
|
||||||
|
- 页面转场: 300ms
|
||||||
|
- 按钮反馈: 150ms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 无障碍设计
|
||||||
|
|
||||||
|
1. **对比度**: 所有文字与背景对比度 >= 4.5:1
|
||||||
|
2. **触摸目标**: 最小 44x44px
|
||||||
|
3. **状态反馈**: 不仅依赖颜色区分
|
||||||
|
4. **焦点指示**: 明显的焦点样式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 禁止事项
|
||||||
|
|
||||||
|
1. ❌ 文字与背景颜色相同
|
||||||
|
2. ❌ 纯黑色背景 (#000000)
|
||||||
|
3. ❌ 纯白色文字在浅色背景
|
||||||
|
4. ❌ 低对比度组合 (对比度 < 4.5)
|
||||||
|
5. ❌ 仅用颜色区分状态
|
||||||
|
6. ❌ 过小的触摸目标 (< 44px)
|
||||||
|
7. ❌ 不一致的组件样式
|
||||||
|
8. ❌ 硬编码颜色值
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实现清单
|
||||||
|
|
||||||
|
### 核心文件
|
||||||
|
|
||||||
|
1. `lib/core/theme/app_colors.dart` - 颜色定义
|
||||||
|
2. `lib/core/theme/app_theme.dart` - 主题配置
|
||||||
|
3. `lib/core/theme/app_text_styles.dart` - 文字样式
|
||||||
|
4. `lib/core/theme/app_spacing.dart` - 间距常量
|
||||||
|
5. `lib/ui/shared/ui_constants.dart` - 整合导出
|
||||||
|
|
||||||
|
### 需要优化的文件
|
||||||
|
|
||||||
|
- 所有 UI 页面文件
|
||||||
|
- 所有 UI 组件文件
|
||||||
|
- main.dart 主题配置
|
||||||
Reference in New Issue
Block a user