From e6e81e046f452205f053b609f8801c99e4519757 Mon Sep 17 00:00:00 2001 From: Cody Date: Tue, 10 Mar 2026 10:24:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=9E=B6=E6=9E=84=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Doc/IM_App_架构设计.html | 166 ++++++++++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 48 deletions(-) diff --git a/Doc/IM_App_架构设计.html b/Doc/IM_App_架构设计.html index 3b7bfa0..a4fc829 100644 --- a/Doc/IM_App_架构设计.html +++ b/Doc/IM_App_架构设计.html @@ -330,6 +330,20 @@ 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; + } @@ -2674,9 +2688,15 @@ final authRepositoryProvider = Provider<AuthRepository>((ref) { ); }); -/// 4. UseCase(按需) +/// 4. UseCase(登录有多步编排 — 校验 + 登录 + WS 连接 + DB 开库 + 用户持久化) final loginUseCaseProvider = Provider<LoginUseCase>((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), + ); }); @@ -2977,7 +2997,7 @@ flowchart TD style CoreUI fill:#fff4e6,stroke:#f57c00 -

2.2 整体目录图

+

2.2 整体目录图最后更新 2026-03-10-10-17

图表说明

@@ -2996,10 +3016,13 @@ flowchart TD │ │ └── guards/ │ │ └── auth_guard.dart # 登录守卫(switch AppRouteName,穷举防漏路由) │ │ -│ └── di/ # 全局 DI — 手动装配的 Provider -│ ├── network_provider.dart # NetworkMonitor + ApiConfig + NetworksSdkApi + SocketConfig + SocketClient + SocketManager -│ ├── db_provider.dart # StorageSdkApi(注入 AppDatabase factory) -│ └── app_providers.dart # AppInitializer + ThemeModeNotifier + AuthNotifier +│ ├── di/ # 全局 DI — 手动装配的 Provider +│ │ ├── network_provider.dart # NetworkMonitor + ApiConfig + NetworksSdkApi + SocketConfig + SocketClient + SocketManager +│ │ ├── db_provider.dart # storageSdkProvider + storageSdkLifecycleProvider +│ │ ├── 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 │ │ @@ -3012,18 +3035,33 @@ flowchart TD │ │ │ └── auth_providers.dart # authRepositoryProvider / loginUseCaseProvider │ │ ├── presentation/ │ │ │ ├── login_view_model.dart # @riverpod ViewModel(生成 login_view_model.g.dart) -│ │ │ └── login_state.dart # @freezed State(生成 login_state.freezed.dart) +│ │ │ └── login_state.dart # @freezed State(step / contact / isLoading / error) │ │ ├── usecases/ -│ │ │ └── login_usecase.dart # 格式校验 → Repository → User Entity +│ │ │ └── login_usecase.dart # 校验 → OTP → 登录 → WS 连接 → DB 开库 → 用户持久化 │ │ └── view/ -│ │ └── login_page.dart # 登录页 +│ │ ├── login_page.dart # 登录页(装配 + 控制器 + 回调) +│ │ └── widgets/ +│ │ ├── login_phone_step.dart # 手机号输入步骤(纯展示) +│ │ └── login_otp_step.dart # 验证码输入步骤(纯展示) │ │ │ ├── chat/ # 聊天 ── 开发中 +│ │ ├── di/ +│ │ │ └── chat_bot_provider.dart # chatBotRepositoryProvider / allChatBots / chatBot(id) +│ │ ├── call/ # 通话子模块 +│ │ │ └── di/ +│ │ │ └── call_log_provider.dart # callLogRepositoryProvider / allCallLogs / callLog(id) │ │ ├── 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 测试 ViewModel(startTest / loadMore) +│ │ ├── usecases/ +│ │ │ ├── insert_users_use_case.dart # 批量插入用户(200 条/批,去重) +│ │ │ ├── update_users_use_case.dart # 更新前 10 条用户昵称 +│ │ │ └── delete_users_use_case.dart # 删除前 10 条用户 │ │ └── view/ │ │ ├── chat_page.dart # 会话列表页(Tab 1) -│ │ └── chat_detail_page.dart # 聊天详情页 +│ │ ├── chat_detail_page.dart # 聊天详情页 +│ │ └── chat_db_test_page.dart # Drift DB 测试页 │ │ │ ├── contact/ # 通讯录 ── 骨架 │ │ └── view/ @@ -3031,12 +3069,12 @@ flowchart TD │ │ │ └── settings/ # 设置 ── 已实现(主题切换) │ ├── di/ -│ │ └── settings_providers.dart # settingsRepositoryProvider(待 storage_sdk 接入) +│ │ └── settings_providers.dart # setThemeUseCaseProvider │ ├── presentation/ │ │ ├── settings_view_model.dart # @riverpod ViewModel(设置页导航) -│ │ └── theme_view_model.dart # @riverpod ViewModel(生成 theme_view_model.g.dart) +│ │ └── theme_view_model.dart # @riverpod ViewModel(主题切换) │ ├── usecases/ -│ │ └── set_theme_usecase.dart # 主题切换用例 +│ │ └── set_theme_usecase.dart # 主题切换用例(幂等校验,防重复切换) │ └── view/ │ ├── settings_page.dart # 设置主页(Tab 3) │ ├── theme_view.dart # 主题选择页 @@ -3045,34 +3083,60 @@ flowchart TD │ └── theme_option_tile.dart │ ├── domain/ # Domain 层(纯 Dart,零 Flutter / 零网络依赖) -│ ├── entities/ -│ │ └── user.dart # 用户实体 -│ │ # message / conversation / contact 待开发 -│ └── repositories/ -│ └── auth_repository.dart # abstract interface -│ # message / chat / contact_repository 待开发 +│ ├── entities/ # 21 个实体(每实体一文件) +│ │ ├── user.dart # 用户 +│ │ ├── message.dart # 消息 +│ │ ├── chat.dart # 会话 +│ │ ├── call_log.dart # 通话记录 +│ │ ├── 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 接口) -│ ├── repositories/ -│ │ └── auth_repository_impl.dart # 认证仓库 -│ │ # message / chat / contact 待开发 +│ ├── repositories/ # 4 个实现类 +│ │ ├── auth_repository_impl.dart # 认证(登录 / 登出 / Token 回调) +│ │ ├── user_repository_impl.dart # 用户(Drift CRUD + Stream watch) +│ │ ├── call_log_repository_impl.dart # 通话记录 +│ │ └── chat_bot_repository_impl.dart # 聊天机器人 │ ├── local/ │ │ └── drift/ # Drift 本地数据库 -│ │ ├── app_database.dart # @DriftDatabase 定义 + onUpgrade 自动补列 -│ │ # database_connection.dart 已迁移至 storage_sdk(数据库生命周期统一在 SDK 层管理) +│ │ ├── app_database.dart # @DriftDatabase(19 张表)+ onUpgrade 自动补列 │ │ ├── mapper/ │ │ │ └── drift_path_mapper.dart # Drift 路径映射工具 -│ │ └── tables/ -│ │ └── users.dart # Users 表定义 +│ │ └── tables/ # 19 个表定义(每表一文件) +│ │ ├── 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 文件(一个端点一个文件) +│ │ ├── send_otp_request.dart # 发送验证码 +│ │ ├── verify_otp_request.dart # 校验验证码 │ │ ├── login_request.dart # 登录 │ │ ├── logout_request.dart # 登出 │ │ ├── get_profile_request.dart # 获取用户信息 │ │ └── upload_file_request.dart # 文件上传 -│ │ # send_message / 其他业务端点 待开发 -│ └── models/ # 持久化 DTO(@JsonSerializable) -│ └── user_dto.dart # 用户持久化 DTO -│ # message / conversation / contact_dto 待开发 +│ └── models/ # 持久化 DTO(17 个,与表一一对应) +│ ├── user_dto.dart / message_dto.dart / chat_dto.dart +│ ├── chat_bot_dto.dart / chat_category_dto.dart / group_dto.dart / workspace_dto.dart +│ ├── 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 ├── foundation/ # 基础配置(各为单独文件,非子目录) @@ -3097,7 +3161,7 @@ flowchart TD │ ├── icons.dart # 图标常量(AppIcons:导航 / 操作 / 聊天 / 用户 / 状态) │ ├── app_theme.dart # ThemeData 组装(Light / Dark) │ ├── 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)) ├── components/ # 原子组件 │ └── app_button.dart # 按钮 @@ -3106,7 +3170,7 @@ flowchart TD # app_dialog / app_toast / app_empty_state 等 -

2.3 整体分层图(MVVM + Riverpod 数据流)

+

2.3 整体分层图(MVVM + Riverpod 数据流)最后更新 2026-03-10-10-17

图表说明

@@ -3211,7 +3275,7 @@ flowchart LR
-

两大核心逻辑

+

三大核心逻辑

1. MVVM 分层职责:View(view/)只负责渲染和用户交互,ViewModel(presentation/)持有状态并处理业务逻辑,Model(model/ + entities/)定义数据结构 —— 三者通过 Riverpod Provider 连接,职责严格分离。

2. Riverpod 单向数据流:用户操作 → ref.read(vm.notifier).action() → ViewModel 处理逻辑 → state = newStateref.watch(vm) 检测变化 → View 自动 rebuild。数据永远单向流动,UI 永远是状态的函数。

3. Widget 纯展示原则build() 只做一件事——把 State 属性映射成 Widget 树,不允许出现任何计算或逻辑。

@@ -5178,19 +5242,19 @@ flowchart TD
flowchart TD - UI[UI Layer] -->|用户操作: vm.method()| VM[ViewModel] - VM -->|调用| Repo[Repository] - VM -.复杂场景.-> UC[UseCase(按需)] + UI["UI Layer"] -->|"用户操作 vm.method"| VM["ViewModel"] + VM -->|"调用"| Repo["Repository"] + VM -.->|"复杂场景"| UC["UseCase(按需)"] UC -.-> Repo - Repo -->|返回 Entity| VM - VM -->|state = newState| State[UI State] - State -->|ref.watch 自动刷新| UI + Repo -->|"返回 Entity"| VM + VM -->|"state = newState"| UIState["UI State"] + UIState -->|"ref.watch 自动刷新"| UI style UI fill:#e1f5ff,stroke:#0288d1 style VM fill:#fff4e6,stroke:#f57c00 style Repo fill:#e8f5e9,stroke:#388e3c - style UC fill:#f3e5f5,stroke:#7b1fa2,stroke-dasharray: 5 5 - style State fill:#fff4e6,stroke:#f57c00 + style UC fill:#f3e5f5,stroke:#7b1fa2 + style UIState fill:#fff4e6,stroke:#f57c00

Riverpod ViewModel 实现方式

@@ -6206,9 +6270,15 @@ final authRepositoryProvider = Provider<AuthRepository>((ref) { ); }); -// UseCase(按需 — 登录有多步编排,所以需要 UseCase) +// UseCase(登录有多步编排 — 校验 + 登录 + WS 连接 + DB 开库 + 用户持久化) final loginUseCaseProvider = Provider<LoginUseCase>((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), + ); }); @@ -6877,7 +6947,7 @@ final user = await db.selectFirst(appDb.users, (t) => t.uid.equals(uid));

为什么独立 Package:国际化服务于 core/ui(组件内置文案)和 Feature 层(页面文案、错误提示展示),作为独立 SDK 可跨项目复用翻译基础设施。注意:foundation 本身不依赖 l10n_sdk —— 错误映射仅产出错误码/错误键,由 Presentation / UI 层通过 l10n_sdk 转为本地化文案,从而避免 foundation ↔ l10n 双向依赖。

-

7.5 Core UI(core/ui/)

+

7.5 Core UI(core/ui/)最后更新 2026-03-10-10-17

UI 基础设施,为所有 Feature 提供统一的视觉规范和可复用组件。三层结构自底向上构建:

@@ -9836,7 +9906,7 @@ flowchart TD

本章定义颜色、字体、组件、弹框、图标的命名与使用规则,明确设计与研发的协作约定。Figma 按此命名,代码按此封装,两端名称一一对应。

-

8.0 核心约定

+

8.0 核心约定最后更新 2026-03-10-10-17

全局只有一份

@@ -9863,7 +9933,7 @@ flowchart TD 图片和组件是重灾区:没有统一来源时,不同研发各自导出同一张图,文件名不同、尺寸不同,最终项目里堆满重复文件。Figma 统一命名、代码统一注册,才能从源头堵住。
-

8.1 颜色体系

+

8.1 颜色体系最后更新 2026-03-10-10-17

颜色采用 5 层架构:ColorBases(颜色常量)→ AppColors(语义接口)→ LightColors/DarkColors(亮暗实现)→ AppTheme._build(AppColors c)(主题组装)→ context.colors(Widget 消费)。AppTheme 内部零 isDark 分支,亮暗差异完全由实现类决定。