# Flutter 项目规范

> 严格遵循本文档定义的架构模式、状态管理标准和代码风格。未经授权不得引入新的第三方包或架构模式。优先组合而非继承，业务逻辑不进入 UI 组件。

---

## 1. 技术栈

- **语言：** Dart（SDK >=3.0.0，严格空安全）
- **框架：** Flutter（最新稳定通道）
- **状态管理：** `flutter_riverpod`（v2.x，注解 + 代码生成）
- **路由：** `go_router`
- **网络请求：** `dio`（配合 `json_annotation` + `freezed` 进行 JSON 序列化）
- **数据模型：** `freezed` + `build_runner`
- **本地存储：** `shared_preferences`（非敏感偏好）+ `flutter_secure_storage`（令牌）
- **依赖注入：** Riverpod Providers（不使用 GetIt）
- **国际化：** `flutter_localizations`（l10n / ARB 格式）

---

## 2. 目录结构

采用 **特性优先架构（Feature-First）**，特性内部结合 **整洁架构（Clean Architecture）** 分层：

```text
lib/
├── main.dart                 # 应用程序入口（ProviderScope + runApp）
├── app/                      # 全局应用配置
│   ├── app.dart              # CupertinoApp.router 入口
│   ├── router/               # 路由定义（GoRouter）
│   ├── theme/                # 主题、颜色、排版
│   └── constants/            # 全局常量、API 端点、ICE 配置
├── core/                     # 跨特性共享代码
│   ├── network/              # dio 客户端、错误处理
│   ├── proto/                # Protobuf 生成代码（控制指令协议）
│   ├── storage/              # 本地存储辅助工具
│   ├── utils/                # 辅助函数、扩展方法
│   └── widgets/              # 共享 UI 组件（触摸层）
├── features/                 # 特性模块
│   ├── auth/                 # 登录 / 令牌 / 绑定列表
│   │   ├── data/             # Repository 实现（dio）
│   │   ├── domain/           # 仓库接口、状态模型（freezed）
│   │   └── presentation/     # 控制器、登录对话框
│   └── connection/           # 信令 / WebRTC / 控制面板
│       ├── data/             # 信令客户端、WebRTC、编排器、解码器、录制器
│       ├── domain/           # 信令消息、会话状态（freezed）
│       └── presentation/     # 控制器、设置页、控制页、鉴权对话框
└── l10n/                     # 国际化（.arb 文件）
```

---

## 3. 分层职责

### 表示层（`presentation/`）

UI 组件 + Riverpod Notifier / AsyncNotifier 控制器。

- 只能通过 `ref.watch` 或 `ref.listen` 消费状态。
- 禁止在 `onPressed` 或 `build()` 中直接调用 API 或编写业务逻辑。
- 一次性提示通过状态中的 `alert` 字段传递，UI 展示后调用 `consumeAlert()` 消费。

### 领域层（`domain/`）

纯 Dart 实体（`freezed`）和仓库接口定义。

- 零 Flutter/UI 依赖（协议模型除外）。
- 状态类命名避免与 Flutter SDK 冲突（如用 `ConnectionSessionState` 而非 `ConnectionState`）。

### 数据层（`data/`）

实现仓库接口，通过 dio 处理 API 请求，将 JSON DTO 映射为领域实体。

---

## 4. 编码规范

### 状态管理（Riverpod）

- 使用 `@riverpod` 注解 + `build_runner` 代码生成。
- 会话级控制器（如登录、连接）使用 `@Riverpod(keepAlive: true)`，避免页面切换时销毁。
- 异步操作优先使用 `AsyncNotifierProvider`，配合 `AsyncValue`（Loading / Data / Error）。
- 业务回调（信令/WebRTC 事件）统一在控制器内映射到状态，不在 UI 层直接持有控制器实例。

### 数据建模（freezed）

所有数据类/实体必须用 `freezed` 实现不可变，并配置 JSON 序列化：

```dart
@freezed
class SignalMessage with _$SignalMessage {
  const SignalMessage._();

  const factory SignalMessage({
    String? type,
    String? payload,
  }) = _SignalMessage;

  factory SignalMessage.fromJson(Map<String, dynamic> json) =>
      _$SignalMessageFromJson(json);

  @override
  String toString() => jsonEncode(toJson());
}
```

### UI 组件

- 尽可能使用 `const` 构造函数，避免不必要的重建。
- 复杂子树提取为独立私有/公有无状态组件，不要写冗长的内联辅助方法。
- 响应式适配使用 `LayoutBuilder` / `MediaQuery` 或项目统一的屏幕适配工具。

---

## 5. 命名约定

| 类别 | 规范 | 示例 |
|---|---|---|
| 文件/文件夹 | `snake_case.dart` | `connection_controller.dart` |
| 类/枚举 | `PascalCase` | `ConnectionSessionState` |
| 变量/方法 | `camelCase` | `sendResolutionChange()` |
| Provider | 以 `Provider` 结尾 | `authRepositoryProvider` |
| 私有成员 | `_` 前缀 | `_handleSignalMessage()` |

---

## 6. 代码生成

修改或新增带代码生成的模型/控制器后，运行：

```bash
# 一次性生成（freezed / json_serializable / riverpod_generator）
dart run build_runner build --delete-conflicting-outputs

# 监听模式
dart run build_runner watch --delete-conflicting-outputs

# 生成国际化（l10n.yaml 已配置）
flutter gen-l10n
```

---

## 7. 完成标准

- 新文件遵循特性优先结构（app / core / features / l10n）。
- 代码为空安全、完全类型化，并进行 `const` 优化。
- 对应创建数据层、领域层和表示层组件。
- 提交前 `flutter analyze` 无 issue；`flutter test` 通过。
- 协议（`.proto` / 信令 JSON）变更需同步 Android / iOS / Web 各端。
