Files
pangolin/design/flutter/README.md
T
wangjia a642bf16a2 feat: 同步 design/ 设计系统(含 iPad tablet kit) + 架构任务拆分(todo/)
design/ 同步自最新设计导出,新增 ui_kits/tablet/ 平板分栏布局;todo/ 录入 18 个并行实施任务。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:57:57 +08:00

136 lines
7.7 KiB
Markdown
Raw 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.
# 穿山甲 VPN — Flutter 设计令牌
生产前端使用 **Flutter**。本目录提供与 `../colors_and_type.css` **一一对应**的 Dart 令牌,Flutter 可直接消费。`ui_kits/` 下的 React/HTML 是**视觉规范参考**(像素级还原 + 交互),Flutter 实现以它们为蓝本、以本文件为令牌来源。
## 快速开始
1. 新建 Flutter 工程,把本目录的 `pubspec.yaml` 覆盖到根目录(按需改 `name`)。
2. 拷贝:`pangolin_theme.dart``lib/`;`widgets/` 整个目录 → `lib/widgets/`;`main.dart``lib/`;`assets/*.svg` → 工程 `assets/`
3. 自备 4 款字体的 ttf 放 `fonts/`(或改用 `google_fonts` 包),族名须与 `pubspec.yaml` 一致。
4. `flutter pub get``flutter run``main.dart` 已串好「登录 → 引导 → 主框架」可直接跑。
## 文件
- `pubspec.yaml`**工程清单模板**:已配好 `flutter_svg` / `lucide_icons` 依赖、4 个 SVG 资产、4 款字体声明(族名对齐 `PangolinFonts`)。拷到工程根目录,补字体 ttf,`flutter pub get` 即可。
- `main.dart`**入口示例**:`runApp` + 明/暗主题 + 「登录 → 引导 → 主框架」`RootFlow` 串接,可直接跑通。
- `pangolin_theme.dart` — 全部令牌 + 明/暗 `ThemeData`:
- `PangolinColors` — clay / sand / 语义色阶(const `Color`)
- `PangolinScheme``ThemeExtension`)— 语义令牌(bg/surface/fg/accent/border/success…),含 `.light` / `.dark`
- `PangolinSpacing`(4px 基准)、`PangolinRadius``PangolinMotion`(时长 + 缓动曲线)
- `PangolinFonts``PangolinText`(字号阶)、`PangolinShadow`(暖色软阴影)
- `PangolinTheme.light` / `PangolinTheme.dark` — 开箱即用
- `widgets/`**核心组件 Dart 雏形**(纯样式,业务逻辑自接),全部读 `context.pangolin` 令牌:
- `pangolin_icons.dart`**Lucide 图标映射表**:`PangolinIcons.power` 等直用常量 + `PangolinIcons.byName('shield-check')` 查表(从 React `data-lucide` 名移植)。需 `lucide_icons` 包。
- `pangolin_button.dart``PangolinButton`(primary / secondary / ghost / danger,胶囊形)
- `country_code.dart``CountryCode`(2 字母国家码块)、`SignalBars`(延迟信号条)
- `status_pill.dart``StatusPill`(连接态 / PRO 等色点胶囊)
- `connect_button.dart``ConnectButton`(核心连接键三态:off 轨道环 / connecting 旋转弧 / on 满环 + 计时)
- `server_tile.dart``ServerTile` + `ServerInfo`(服务器列表行)
- `plan_card.dart``PlanCard`(套餐卡,专业版渐变高亮 + 「最受欢迎」浮标)
- `auth_screen.dart``AuthScreen`(登录 / 邮箱验证码注册,分屏式,带 `zh` 简单 i18n)
- `onboarding_screen.dart``OnboardingScreen`(首次引导 `PageView`,3 屏可滑动 + 进度点 + 跳过)
- `home_shell.dart``HomeShell`(主框架:底部 4 Tab 连接/节点/统计/账户 + 连接状态机 + 计时;各页骨架)
- `account_screens.dart` — 账户子页:`PlansScreen`(套餐选择)、`DevicesScreen`(设备管理 + 移除)、`RedeemScreen`(兑换码 + 购买渠道)、`ContactScreen`(联系渠道 + 服务时间);均为带返回栏的独立页,`HomeShell` 账户页已 `push` 接入
- `pangolin_logo.dart``PangolinMark` / `PangolinBrandLockup` / `PangolinWordmark` / `PangolinAppIcon`(`flutter_svg` 加载 `assets/` 矢量 logo,深色自动反白)
- `pangolin_widgets.dart` — 统一 `export`
> 这些是**视觉雏形**:对应 React UI Kit 的同名组件,Flutter 工程师可直接拷贝/微调,接上真实状态与导航。图标已走 `PangolinIcons`(Lucide),与设计一致。
## 接入
```dart
MaterialApp(
theme: PangolinTheme.light,
darkTheme: PangolinTheme.dark,
themeMode: ThemeMode.system, // 跟随系统;也可由设置里的开关控制
);
```
读语义色(随明暗自动切换):
```dart
final c = context.pangolin; // PangolinScheme
Container(color: c.surface);
Text('已连接', style: PangolinText.h3.copyWith(color: c.success));
```
令牌直取:
```dart
PangolinColors.clay500 // 品牌主色
PangolinSpacing.x4 // 16
BorderRadius.circular(PangolinRadius.lg)
AnimatedContainer(duration: PangolinMotion.base, curve: PangolinMotion.easeOut, ...)
```
组件雏形(组合示例):
```dart
import 'widgets/pangolin_widgets.dart';
// 连接键
ConnectButton(status: VpnStatus.on, elapsed: const Duration(seconds: 8048), onTap: toggle);
// 服务器行
ServerTile(
server: const ServerInfo(code: 'HK', name: '香港 · 流媒体', sub: 'Hong Kong', ping: 18),
active: true, onTap: () {},
);
// 套餐卡(专业版高亮)
PlanCard(
name: '专业版', price: '¥25', period: '/月', popularLabel: '最受欢迎', featured: true,
features: const ['80+ 全球节点', '无限流量 · 极速', '5 台设备同时在线'],
ctaLabel: '立即升级', onPressed: () {},
);
PangolinButton(label: '连接', icon: PangolinIcons.power, onPressed: () {});
StatusPill(label: '已连接', status: PangolinStatus.connected);
```
页面串接(登录 → 引导 → 主应用):
```dart
enum AppStage { auth, onboarding, app }
class _RootState extends State<Root> {
AppStage stage = AppStage.auth;
@override
Widget build(BuildContext context) => switch (stage) {
AppStage.auth => AuthScreen(onDone: () => setState(() => stage = AppStage.onboarding)),
AppStage.onboarding => OnboardingScreen(onDone: () => setState(() => stage = AppStage.app)),
AppStage.app => const HomeShell(), // 主框架:底部 4 Tab(连接/节点/统计/账户)
};
}
```
## 字体
`pubspec.yaml` 注册 **Sora**(display)、**Manrope**(正文/UI)、**Noto Sans SC**(中文)、**JetBrains Mono**(数据)。可用 `google_fonts` 包或打包本地字体;族名见 `PangolinFonts`
## 图标
UI Kit 用 Lucide(细线条)。Flutter 侧用 [`lucide_icons`](https://pub.dev/packages/lucide_icons) 包,经 `widgets/pangolin_icons.dart` 的映射表引用:`Icon(PangolinIcons.power)``pubspec.yaml``lucide_icons: ^0.x`。某常量名若在你的包版本缺失,按 IDE 提示替换为最接近名即可(文件内已注明 Lucide 原名)。
## Logo / 品牌标(SVG)
矢量 logo 在 `assets/`(`logo-mark.svg` clay 标、`logo-mark-white.svg` 反白标、`logo-wordmark.svg` 字标、`app-icon.svg` App 图标)。用 [`flutter_svg`](https://pub.dev/packages/flutter_svg) 加载,封装在 `widgets/pangolin_logo.dart`:
- `PangolinMark(size: 28)` — 仅标记,**深色主题自动用反白版**(可 `forceLight`/`forceDark`)
- `PangolinBrandLockup(zh: true)` — 标记 + 「穿山甲 / Pangolin」(随主题变色 + 双语,顶栏用)
- `PangolinWordmark(height: 28)` — 横版字标锁版(浅背景)
- `PangolinAppIcon(size: 64)` — App 图标(自动圆角)
接入步骤:
1. `pubspec.yaml` 加依赖与资产:
```yaml
dependencies:
flutter_svg: ^2.0.0
flutter:
assets:
- assets/logo-mark.svg
- assets/logo-mark-white.svg
- assets/logo-wordmark.svg
- assets/app-icon.svg
```
2. 把本目录的 `assets/*.svg` 拷进你工程的 `assets/`(若用别的前缀,改 `pangolin_logo.dart` 顶部的 `_base`)。
3. `AuthScreen` / `HomeShell` 顶栏已用 `PangolinMark` / `PangolinBrandLockup`,无需再改。
4. App 启动图标 / 桌面图标用 `app-icon.svg` 导出 PNG(`flutter_launcher_icons` 包)。
## 规则(务必遵守)
- 颜色只用语义令牌,组件天然适配明/暗,不要硬编码十六进制。
- 暖色基调:表面是暖白/暖 espresso,**不要纯白纯黑**大面积填充。
- 圆角偏大、阴影柔和暖调;状态用「色点 + 文字」,不用 emoji;国家用 2 字母码块,不用 emoji 国旗。
- 界面单语言显示(中文**或** EN),由设置切换;不要中英并排。
- App 内不放支付表单;走兑换码 + 外部渠道。
> ⚠️ 字体均为开源字体(Google Fonts),作为本品牌正式选定字体。若你已有授权品牌字体,替换族名与文件即可。