更新架构文档

This commit is contained in:
Cody
2026-03-10 10:24:34 +08:00
parent ed93d556d6
commit e6e81e046f

View File

@@ -330,6 +330,20 @@
font-size: 28px; font-size: 28px;
} }
} }
/* 章节最后更新时间标签 */
.updated-tag {
font-size: 11px;
font-weight: 400;
color: #999;
background: #f3f4f6;
border: 1px solid #e0e3e8;
padding: 1px 8px;
border-radius: 20px;
margin-left: 10px;
vertical-align: middle;
letter-spacing: 0;
}
</style> </style>
</head> </head>
</head> </head>
@@ -2674,9 +2688,15 @@ final authRepositoryProvider = Provider&lt;AuthRepository&gt;((ref) {
); );
}); });
/// 4. UseCase按需 /// 4. UseCase登录有多步编排 — 校验 + 登录 + WS 连接 + DB 开库 + 用户持久化
final loginUseCaseProvider = Provider&lt;LoginUseCase&gt;((ref) { final loginUseCaseProvider = Provider&lt;LoginUseCase&gt;((ref) {
return LoginUseCase(authRepository: ref.read(authRepositoryProvider)); return LoginUseCase(
authRepository: ref.read(authRepositoryProvider),
socketManager: ref.read(socketManagerProvider),
apiConfig: ref.read(apiConfigProvider),
storageApi: ref.read(storageSdkProvider),
userRepository: ref.read(userRepositoryProvider),
);
}); });
</code></pre> </code></pre>
@@ -2977,7 +2997,7 @@ flowchart TD
style CoreUI fill:#fff4e6,stroke:#f57c00 style CoreUI fill:#fff4e6,stroke:#f57c00
</div> </div>
<h3 id="2-2-整体目录图">2.2 整体目录图</h3> <h3 id="2-2-整体目录图">2.2 整体目录图<span class="updated-tag">最后更新 2026-03-10-10-17</span></h3>
<h4>图表说明</h4> <h4>图表说明</h4>
@@ -2996,10 +3016,13 @@ flowchart TD
│ │ └── guards/ │ │ └── guards/
│ │ └── auth_guard.dart # 登录守卫switch AppRouteName穷举防漏路由 │ │ └── auth_guard.dart # 登录守卫switch AppRouteName穷举防漏路由
│ │ │ │
── di/ # 全局 DI — 手动装配的 Provider ── di/ # 全局 DI — 手动装配的 Provider
├── network_provider.dart # NetworkMonitor + ApiConfig + NetworksSdkApi + SocketConfig + SocketClient + SocketManager ├── network_provider.dart # NetworkMonitor + ApiConfig + NetworksSdkApi + SocketConfig + SocketClient + SocketManager
├── db_provider.dart # StorageSdkApi注入 AppDatabase factory ├── db_provider.dart # storageSdkProvider + storageSdkLifecycleProvider
── app_providers.dart # AppInitializer + ThemeModeNotifier + AuthNotifier ── app_providers.dart # AppInitializer + ThemeModeNotifier + AuthNotifier
│ │ └── user_provider.dart # userRepositoryProvider / CRUD UseCase Providers / users + allUsers Stream
│ └── notifiers/ # 全局 Notifier@riverpod跨模块共用
│ └── user_notifier.dart # UserNotifier — 单用户状态family per-uid含 watch + CRUD
├── features/ # 功能模块垂直切片Feature 间禁止直接 import ├── features/ # 功能模块垂直切片Feature 间禁止直接 import
│ │ │ │
@@ -3012,18 +3035,33 @@ flowchart TD
│ │ │ └── auth_providers.dart # authRepositoryProvider / loginUseCaseProvider │ │ │ └── auth_providers.dart # authRepositoryProvider / loginUseCaseProvider
│ │ ├── presentation/ │ │ ├── presentation/
│ │ │ ├── login_view_model.dart # @riverpod ViewModel生成 login_view_model.g.dart │ │ │ ├── login_view_model.dart # @riverpod ViewModel生成 login_view_model.g.dart
│ │ │ └── login_state.dart # @freezed State生成 login_state.freezed.dart │ │ │ └── login_state.dart # @freezed Statestep / contact / isLoading / error
│ │ ├── usecases/ │ │ ├── usecases/
│ │ │ └── login_usecase.dart # 格式校验 → Repository → User Entity │ │ │ └── login_usecase.dart # 校验 → OTP → 登录 → WS 连接 → DB 开库 → 用户持久化
│ │ └── view/ │ │ └── view/
│ │ ── login_page.dart # 登录页 │ │ ── login_page.dart # 登录页(装配 + 控制器 + 回调)
│ │ └── widgets/
│ │ ├── login_phone_step.dart # 手机号输入步骤(纯展示)
│ │ └── login_otp_step.dart # 验证码输入步骤(纯展示)
│ │ │ │
│ ├── chat/ # 聊天 ── 开发中 │ ├── chat/ # 聊天 ── 开发中
│ │ ├── di/
│ │ │ └── chat_bot_provider.dart # chatBotRepositoryProvider / allChatBots / chatBot(id)
│ │ ├── call/ # 通话子模块
│ │ │ └── di/
│ │ │ └── call_log_provider.dart # callLogRepositoryProvider / allCallLogs / callLog(id)
│ │ ├── presentation/ │ │ ├── presentation/
│ │ │ ── chat_view_model.dart # @riverpod ViewModel │ │ │ ── chat_view_model.dart # @riverpod ViewModel(会话列表)
│ │ │ ├── chat_db_test_state.dart # Drift DB 测试 State手写含分页字段
│ │ │ └── chat_db_test_view_model.dart # Drift DB 测试 ViewModelstartTest / loadMore
│ │ ├── usecases/
│ │ │ ├── insert_users_use_case.dart # 批量插入用户200 条/批,去重)
│ │ │ ├── update_users_use_case.dart # 更新前 10 条用户昵称
│ │ │ └── delete_users_use_case.dart # 删除前 10 条用户
│ │ └── view/ │ │ └── view/
│ │ ├── chat_page.dart # 会话列表页Tab 1 │ │ ├── chat_page.dart # 会话列表页Tab 1
│ │ ── chat_detail_page.dart # 聊天详情页 │ │ ── chat_detail_page.dart # 聊天详情页
│ │ └── chat_db_test_page.dart # Drift DB 测试页
│ │ │ │
│ ├── contact/ # 通讯录 ── 骨架 │ ├── contact/ # 通讯录 ── 骨架
│ │ └── view/ │ │ └── view/
@@ -3031,12 +3069,12 @@ flowchart TD
│ │ │ │
│ └── settings/ # 设置 ── 已实现(主题切换) │ └── settings/ # 设置 ── 已实现(主题切换)
│ ├── di/ │ ├── di/
│ │ └── settings_providers.dart # settingsRepositoryProvider待 storage_sdk 接入) │ │ └── settings_providers.dart # setThemeUseCaseProvider
│ ├── presentation/ │ ├── presentation/
│ │ ├── settings_view_model.dart # @riverpod ViewModel设置页导航 │ │ ├── settings_view_model.dart # @riverpod ViewModel设置页导航
│ │ └── theme_view_model.dart # @riverpod ViewModel生成 theme_view_model.g.dart │ │ └── theme_view_model.dart # @riverpod ViewModel主题切换
│ ├── usecases/ │ ├── usecases/
│ │ └── set_theme_usecase.dart # 主题切换用例 │ │ └── set_theme_usecase.dart # 主题切换用例(幂等校验,防重复切换)
│ └── view/ │ └── view/
│ ├── settings_page.dart # 设置主页Tab 3 │ ├── settings_page.dart # 设置主页Tab 3
│ ├── theme_view.dart # 主题选择页 │ ├── theme_view.dart # 主题选择页
@@ -3045,34 +3083,60 @@ flowchart TD
│ └── theme_option_tile.dart │ └── theme_option_tile.dart
├── domain/ # Domain 层(纯 Dart零 Flutter / 零网络依赖) ├── domain/ # Domain 层(纯 Dart零 Flutter / 零网络依赖)
│ ├── entities/ │ ├── entities/ # 21 个实体(每实体一文件)
│ │ ── user.dart # 用户实体 │ │ ── user.dart # 用户
│ │ # message / conversation / contact 待开发 │ │ ├── message.dart # 消息
└── repositories/ │ ├── chat.dart # 会话
── auth_repository.dart # abstract interface ── call_log.dart # 通话记录
# message / chat / contact_repository 待开发 │ ├── chat_bot.dart # 聊天机器人
│ │ ├── chat_category.dart # 会话分类
│ │ ├── group.dart # 群组
│ │ ├── group_member.dart # 群成员
│ │ ├── workspace.dart # 工作区
│ │ ├── company_member.dart # 企业成员
│ │ ├── favourite.dart / favourite_detail.dart
│ │ ├── sound.dart / tag.dart / retry.dart
│ │ ├── pending_friend_request_history.dart
│ │ ├── user_request_history.dart
│ │ └── {discover,explore,favorite,recent}_mini_app.dart
│ └── repositories/ # 4 个抽象接口
│ ├── auth_repository.dart # sendOtp / verifyOtp / login / logout
│ ├── user_repository.dart # watch / get / insert / update / upsert / delete
│ ├── call_log_repository.dart # 通话记录 CRUD + watch
│ └── chat_bot_repository.dart # 聊天机器人 CRUD + watch
├── data/ # Data 层implements domain 接口) ├── data/ # Data 层implements domain 接口)
│ ├── repositories/ │ ├── repositories/ # 4 个实现类
│ │ ── auth_repository_impl.dart # 认证仓库 │ │ ── auth_repository_impl.dart # 认证(登录 / 登出 / Token 回调)
│ │ # message / chat / contact 待开发 │ │ ├── user_repository_impl.dart # 用户Drift CRUD + Stream watch
│ │ ├── call_log_repository_impl.dart # 通话记录
│ │ └── chat_bot_repository_impl.dart # 聊天机器人
│ ├── local/ │ ├── local/
│ │ └── drift/ # Drift 本地数据库 │ │ └── drift/ # Drift 本地数据库
│ │ ├── app_database.dart # @DriftDatabase 定义 + onUpgrade 自动补列 │ │ ├── app_database.dart # @DriftDatabase19 张表)+ onUpgrade 自动补列
│ │ # database_connection.dart 已迁移至 storage_sdk数据库生命周期统一在 SDK 层管理)
│ │ ├── mapper/ │ │ ├── mapper/
│ │ │ └── drift_path_mapper.dart # Drift 路径映射工具 │ │ │ └── drift_path_mapper.dart # Drift 路径映射工具
│ │ └── tables/ │ │ └── tables/ # 19 个表定义(每表一文件)
│ │ ── users.dart # Users 表定义 │ │ ── users.dart / messages.dart / chats.dart / call_logs.dart
│ │ ├── chat_bots.dart / chat_categories.dart / groups.dart / workspaces.dart
│ │ ├── favourites.dart / favourite_details.dart
│ │ ├── sounds.dart / tags.dart / retries.dart
│ │ ├── pending_friend_request_histories.dart / user_request_histories.dart
│ │ └── {discover,explore,favorite,recent}_mini_apps.dart
│ ├── remote/ # Request 文件(一个端点一个文件) │ ├── remote/ # Request 文件(一个端点一个文件)
│ │ ├── send_otp_request.dart # 发送验证码
│ │ ├── verify_otp_request.dart # 校验验证码
│ │ ├── login_request.dart # 登录 │ │ ├── login_request.dart # 登录
│ │ ├── logout_request.dart # 登出 │ │ ├── logout_request.dart # 登出
│ │ ├── get_profile_request.dart # 获取用户信息 │ │ ├── get_profile_request.dart # 获取用户信息
│ │ └── upload_file_request.dart # 文件上传 │ │ └── upload_file_request.dart # 文件上传
│ # send_message / 其他业务端点 待开发 └── models/ # 持久化 DTO17 个,与表一一对应)
└── models/ # 持久化 DTO@JsonSerializable ├── user_dto.dart / message_dto.dart / chat_dto.dart
── user_dto.dart # 用户持久化 DTO ── chat_bot_dto.dart / chat_category_dto.dart / group_dto.dart / workspace_dto.dart
# message / conversation / contact_dto 待开发 ├── favourite_dto.dart / favourite_detail_dto.dart
│ ├── sound_dto.dart / tag_dto.dart / retry_dto.dart
│ ├── pending_friend_request_history_dto.dart / user_request_history_dto.dart
│ └── {discover,explore,favorite,recent}_mini_app_dto.dart
└── core/ # Core 层:零业务逻辑,禁止反向依赖 features / domain / data └── core/ # Core 层:零业务逻辑,禁止反向依赖 features / domain / data
├── foundation/ # 基础配置(各为单独文件,非子目录) ├── foundation/ # 基础配置(各为单独文件,非子目录)
@@ -3097,7 +3161,7 @@ flowchart TD
│ ├── icons.dart # 图标常量AppIcons导航 / 操作 / 聊天 / 用户 / 状态) │ ├── icons.dart # 图标常量AppIcons导航 / 操作 / 聊天 / 用户 / 状态)
│ ├── app_theme.dart # ThemeData 组装Light / Dark │ ├── app_theme.dart # ThemeData 组装Light / Dark
│ ├── colors.dart # 颜色体系(品牌色 / 语义色 / 灰阶) │ ├── colors.dart # 颜色体系(品牌色 / 语义色 / 灰阶)
│ ├── context_theme_ext.dart # BuildContext 主题扩展context.theme / context.colors │ ├── context_theme_ext.dart # BuildContext 扩展context.colors / context.styles / context.shadows
│ └── font.dart # 字体TextStyle 定义 + textTheme(brightness) │ └── font.dart # 字体TextStyle 定义 + textTheme(brightness)
├── components/ # 原子组件 ├── components/ # 原子组件
│ └── app_button.dart # 按钮 │ └── app_button.dart # 按钮
@@ -3106,7 +3170,7 @@ flowchart TD
# app_dialog / app_toast / app_empty_state 等 # app_dialog / app_toast / app_empty_state 等
</code></pre> </code></pre>
<h3 id="2-3-整体分层图">2.3 整体分层图MVVM + Riverpod 数据流)</h3> <h3 id="2-3-整体分层图">2.3 整体分层图MVVM + Riverpod 数据流)<span class="updated-tag">最后更新 2026-03-10-10-17</span></h3>
<h4>图表说明</h4> <h4>图表说明</h4>
@@ -3211,7 +3275,7 @@ flowchart LR
</div> </div>
<blockquote> <blockquote>
<p><strong>大核心逻辑</strong></p> <p><strong>大核心逻辑</strong></p>
<p>1. <strong>MVVM 分层职责</strong>Viewview/只负责渲染和用户交互ViewModelpresentation/持有状态并处理业务逻辑Modelmodel/ + entities/)定义数据结构 —— 三者通过 Riverpod Provider 连接,职责严格分离。</p> <p>1. <strong>MVVM 分层职责</strong>Viewview/只负责渲染和用户交互ViewModelpresentation/持有状态并处理业务逻辑Modelmodel/ + entities/)定义数据结构 —— 三者通过 Riverpod Provider 连接,职责严格分离。</p>
<p>2. <strong>Riverpod 单向数据流</strong>:用户操作 → <code>ref.read(vm.notifier).action()</code> → ViewModel 处理逻辑 → <code>state = newState</code><code>ref.watch(vm)</code> 检测变化 → View 自动 rebuild。数据永远单向流动UI 永远是状态的函数。</p> <p>2. <strong>Riverpod 单向数据流</strong>:用户操作 → <code>ref.read(vm.notifier).action()</code> → ViewModel 处理逻辑 → <code>state = newState</code><code>ref.watch(vm)</code> 检测变化 → View 自动 rebuild。数据永远单向流动UI 永远是状态的函数。</p>
<p>3. <strong>Widget 纯展示原则</strong><code>build()</code> 只做一件事——把 State 属性映射成 Widget 树,不允许出现任何计算或逻辑。</p> <p>3. <strong>Widget 纯展示原则</strong><code>build()</code> 只做一件事——把 State 属性映射成 Widget 树,不允许出现任何计算或逻辑。</p>
@@ -5178,19 +5242,19 @@ flowchart TD
<div class="mermaid"> <div class="mermaid">
flowchart TD flowchart TD
UI[UI Layer] -->|用户操作: vm.method()| VM[ViewModel] UI["UI Layer"] -->|"用户操作 vm.method"| VM["ViewModel"]
VM -->|调用| Repo[Repository] VM -->|"调用"| Repo["Repository"]
VM -.复杂场景.-> UC[UseCase按需] VM -.->|"复杂场景"| UC["UseCase按需"]
UC -.-> Repo UC -.-> Repo
Repo -->|返回 Entity| VM Repo -->|"返回 Entity"| VM
VM -->|state = newState| State[UI State] VM -->|"state = newState"| UIState["UI State"]
State -->|ref.watch 自动刷新| UI UIState -->|"ref.watch 自动刷新"| UI
style UI fill:#e1f5ff,stroke:#0288d1 style UI fill:#e1f5ff,stroke:#0288d1
style VM fill:#fff4e6,stroke:#f57c00 style VM fill:#fff4e6,stroke:#f57c00
style Repo fill:#e8f5e9,stroke:#388e3c style Repo fill:#e8f5e9,stroke:#388e3c
style UC fill:#f3e5f5,stroke:#7b1fa2,stroke-dasharray: 5 5 style UC fill:#f3e5f5,stroke:#7b1fa2
style State fill:#fff4e6,stroke:#f57c00 style UIState fill:#fff4e6,stroke:#f57c00
</div> </div>
<h4>Riverpod ViewModel 实现方式</h4> <h4>Riverpod ViewModel 实现方式</h4>
@@ -6206,9 +6270,15 @@ final authRepositoryProvider = Provider&lt;AuthRepository&gt;((ref) {
); );
}); });
// UseCase按需 — 登录有多步编排,所以需要 UseCase // UseCase登录有多步编排 — 校验 + 登录 + WS 连接 + DB 开库 + 用户持久化
final loginUseCaseProvider = Provider&lt;LoginUseCase&gt;((ref) { final loginUseCaseProvider = Provider&lt;LoginUseCase&gt;((ref) {
return LoginUseCase(authRepository: ref.read(authRepositoryProvider)); return LoginUseCase(
authRepository: ref.read(authRepositoryProvider),
socketManager: ref.read(socketManagerProvider),
apiConfig: ref.read(apiConfigProvider),
storageApi: ref.read(storageSdkProvider),
userRepository: ref.read(userRepositoryProvider),
);
}); });
</code></pre> </code></pre>
@@ -6877,7 +6947,7 @@ final user = await db.selectFirst(appDb.users, (t) =&gt; t.uid.equals(uid));
<p><strong>为什么独立 Package</strong>:国际化服务于 core/ui组件内置文案和 Feature 层(页面文案、错误提示展示),作为独立 SDK 可跨项目复用翻译基础设施。<strong>注意</strong>foundation 本身不依赖 l10n_sdk —— 错误映射仅产出错误码/错误键,由 Presentation / UI 层通过 l10n_sdk 转为本地化文案,从而避免 foundation ↔ l10n 双向依赖。</p> <p><strong>为什么独立 Package</strong>:国际化服务于 core/ui组件内置文案和 Feature 层(页面文案、错误提示展示),作为独立 SDK 可跨项目复用翻译基础设施。<strong>注意</strong>foundation 本身不依赖 l10n_sdk —— 错误映射仅产出错误码/错误键,由 Presentation / UI 层通过 l10n_sdk 转为本地化文案,从而避免 foundation ↔ l10n 双向依赖。</p>
</blockquote> </blockquote>
<h3 id="7-5-core-ui">7.5 Core UIcore/ui/</h3> <h3 id="7-5-core-ui">7.5 Core UIcore/ui/<span class="updated-tag">最后更新 2026-03-10-10-17</span></h3>
<p>UI 基础设施,为所有 Feature 提供统一的视觉规范和可复用组件。三层结构自底向上构建:</p> <p>UI 基础设施,为所有 Feature 提供统一的视觉规范和可复用组件。三层结构自底向上构建:</p>
@@ -9836,7 +9906,7 @@ flowchart TD
<p>本章定义颜色、字体、组件、弹框、图标的命名与使用规则明确设计与研发的协作约定。Figma 按此命名,代码按此封装,两端名称一一对应。</p> <p>本章定义颜色、字体、组件、弹框、图标的命名与使用规则明确设计与研发的协作约定。Figma 按此命名,代码按此封装,两端名称一一对应。</p>
<h3 id="8-0-核心约定">8.0 核心约定</h3> <h3 id="8-0-核心约定">8.0 核心约定<span class="updated-tag">最后更新 2026-03-10-10-17</span></h3>
<div style="background: #e3f2fd; padding: 20px; border-radius: 8px; border-left: 4px solid #1565c0; margin: 20px 0;"> <div style="background: #e3f2fd; padding: 20px; border-radius: 8px; border-left: 4px solid #1565c0; margin: 20px 0;">
<p style="margin-top: 0; font-weight: 700; color: #1565c0;">全局只有一份</p> <p style="margin-top: 0; font-weight: 700; color: #1565c0;">全局只有一份</p>
@@ -9863,7 +9933,7 @@ flowchart TD
<strong>图片和组件是重灾区:</strong>没有统一来源时不同研发各自导出同一张图文件名不同、尺寸不同最终项目里堆满重复文件。Figma 统一命名、代码统一注册,才能从源头堵住。 <strong>图片和组件是重灾区:</strong>没有统一来源时不同研发各自导出同一张图文件名不同、尺寸不同最终项目里堆满重复文件。Figma 统一命名、代码统一注册,才能从源头堵住。
</div> </div>
<h3 id="8-1-颜色体系">8.1 颜色体系</h3> <h3 id="8-1-颜色体系">8.1 颜色体系<span class="updated-tag">最后更新 2026-03-10-10-17</span></h3>
<p>颜色采用 5 层架构:<strong>ColorBases颜色常量→ AppColors语义接口→ LightColors/DarkColors亮暗实现→ AppTheme._build(AppColors c)(主题组装)→ context.colorsWidget 消费)</strong>。AppTheme 内部零 isDark 分支,亮暗差异完全由实现类决定。</p> <p>颜色采用 5 层架构:<strong>ColorBases颜色常量→ AppColors语义接口→ LightColors/DarkColors亮暗实现→ AppTheme._build(AppColors c)(主题组装)→ context.colorsWidget 消费)</strong>。AppTheme 内部零 isDark 分支,亮暗差异完全由实现类决定。</p>