外观
API Client 与数据流
本页记录 Flutter 前端如何访问 backend,以及数据如何在 Screen -> BLoC -> API Client -> Backend -> BLoC -> Screen 闭环里流动。
API Client 清单
| API Client | 当前技术栈 | 负责范围 | 典型消费者 |
|---|---|---|---|
AuthApiClient | Dio | 发送验证码、注册、密码登录、健康信息完成标记 | AuthBloc |
ChatApiClient | Dio + Interceptor + secure storage | 发消息、拉历史、会话列表、创建/删除/切换会话 | ChatBloc |
AssessmentApiClient | http.Client + secure storage | 安全检查、完整评估提交、上次评估、症状列表 | assessment / safety 相关 BLoC |
UserApiClient | http.Client + secure storage + multipart factory | 档案、疾病史、手术史、头像、基础资料 | OnboardingBloc、ProfileOverviewBloc、ExerciseBloc |
SportApiClient | 运动相关请求 | MET、运动日志、当前活动记录、日历、统计 | ExerciseBloc、CalendarBloc、ExerciseHistoryBloc |
PrescriptionApiClient | 处方相关请求 | 当前处方、处方生成相关数据 | PrescriptionBloc、ExerciseBloc |
FeedbackApiClient | 反馈相关请求 | 运动反馈提交 | ExerciseBloc |
CompanionApiClient | Dio + secure storage | 健康总览、陪伴状态 | CompanionBloc、HealthOverviewBloc |
ExerciseHistoryApiClient | 历史记录访问 | 运动历史列表与分页 | ExerciseHistoryBloc |
网络配置
EnvironmentConfig
- 负责环境选择:
development / staging / production - 支持
--dart-define=API_BASE_URL - 基础 URL 默认为
http://115.29.202.237/api - 视频资源默认走
https://lechengzhikang.com/static/videos
NetworkConfig
- 为
Dioclient 提供统一BaseOptions - 统一设置:
- connect / receive / send timeout
- logging interceptor
- retry interceptor
- error interceptor
- 当前
Dio层已经具备较完整的网络错误归一化
认证与 token 传递
当前机制
- token 存储:
flutter_secure_storage - 常见 key:
jwt_tokenuser_idcached_avatar_url
传递方式
| client | token 注入方式 |
|---|---|
ChatApiClient | Dio Interceptor 读 secure storage 注入 Authorization |
AuthApiClient | 登录成功后由 AuthBloc 写入 token |
UserApiClient | 每次请求前读 token 组装 headers |
AssessmentApiClient | 每次请求前读 token 组装 headers |
ExerciseBloc | 可显式 setAuthToken(),否则回退读取 secure storage |
数据流模板
mermaid
flowchart LR
Screen["页面交互\nScreen / Widget"]
Bloc["状态编排\nBLoC"]
Client["请求客户端\nAPI Client"]
Backend["后端接口\nFastAPI API"]
State["状态回流\nBLoC State"]
Screen --> Bloc
Bloc --> Client
Client --> Backend
Backend --> Client
Client --> State
State --> Screen典型链路
1. 登录链路
mermaid
sequenceDiagram
participant Screen as PasswordLoginScreen
participant Bloc as AuthBloc
participant Client as AuthApiClient
participant Storage as SecureStorage
participant API as Backend Auth API
Screen->>Bloc: PasswordLoginRequested
Bloc->>Client: loginWithPassword(phone, password)
Client->>API: POST /api/auth/login-password
API-->>Client: token + userId + healthInfoCompleted
Client-->>Bloc: PasswordLoginResponse
Bloc->>Storage: write(jwt_token, user_id)
Bloc-->>Screen: AuthAuthenticatedAuthApiClient 的 base URL 已经指向 /api/auth,代码里调用的是相对路径 /login-password。文档使用完整路径,便于读者和后端 API surface 对齐。
2. Chat 链路
mermaid
sequenceDiagram
participant Screen as ChatScreen
participant Bloc as ChatBloc
participant Client as ChatApiClient
participant Storage as SecureStorage
participant API as Backend Chat API
Screen->>Bloc: ChatSendMessage
Bloc->>Client: sendMessage(...)
Client->>Storage: read(jwt_token)
Client->>API: POST /api/chat/message
API-->>Client: message + sessionId + ragContext
Client-->>Bloc: ChatResponse
Bloc-->>Screen: ChatMessagesLoaded3. 运动执行链路
| 阶段 | 前端行为 |
|---|---|
| 进入运动中心 | ExerciseBloc 加载当前处方与动作分类 |
| 开始运动 | 创建 active sport log |
| 执行中 | 基于用户资料与 MET 值计算实时卡路里 |
| 完成 | 保存本次运动日志,跳反馈页 |
| 提交反馈 | FeedbackApiClient 提交完成情况与感受 |
关键技术事实
1. client 技术风格混用
AuthApiClient/ChatApiClient/CompanionApiClient走DioUserApiClient/AssessmentApiClient走http.Client
这会带来两类后果:
- 错误处理和日志风格不完全统一
- 替换点接口也分成
Dio注入与http.Client注入两种模式
2. UserApiClient 是当前最重的 client 之一
- 既负责 profile CRUD
- 又负责 avatar 上传、OSS policy、confirm、cache avatar URL
- 还有
multipartRequestFactory作为测试替换点
3. 前端存在“真实后端 + mock 数据”混用
ExerciseBloc的动作分类当前仍可来自本地 mock- 所以前端文档不能把所有列表都描述成已完全后端化
4. 网络配置已经有统一基础,但客户端实现风格仍待收敛
NetworkConfig已经在Dio侧统一了 timeout、retry、logging 和错误归一化。http.Client系列 client 仍各自维护 request、header 和异常逻辑。- 这意味着前端的数据访问已经有统一雏形,但还没有完全收敛为单一风格。
联调检查点
| 检查点 | 说明 |
|---|---|
| base URL | EnvironmentConfig 默认已带 /api,具体 client 是否再拼模块前缀需要逐个确认 |
| token 来源 | flutter_secure_storage 是主要来源,但部分 BLoC 支持显式注入 token |
| 错误归一化 | Dio client 更集中,http.Client client 更分散,前端提示效果可能不同 |
| mock/static 数据 | ExerciseBloc 动作分类、首页部分卡片等不能直接当作后端返回结果 |
| 隐藏入口 client | CompanionApiClient 与健康总览相关 BLoC 保留,不代表对应 Flutter 页面当前可达 |
| 测试替换 | 新 client 或重构 client 时,应保留 dio/http/secureStorage 等替换点 |
来源锚点
apps/flutter_app/lib/api/auth_api_client.dartapps/flutter_app/lib/api/chat_api_client.dartapps/flutter_app/lib/api/user_api_client.dartapps/flutter_app/lib/api/assessment_api_client.dartapps/flutter_app/lib/config/environment_config.dartapps/flutter_app/lib/config/network_config.dart