f975321b67
P3 计划 Task 2(apps/mobile):
- core/config.dart:API_BASE/VIEWER_BASE 经 --dart-define 覆盖,缺省
10.0.2.2 模拟器宿主回环;viewer 相册链接构造 {VIEWER_BASE}/a/{token}。
- core/error_codes.dart:errors.ts 17 码 1:1 镜像(含注释),另设 4 个
客户端本地伪码(NETWORK_ERROR/NETWORK_TIMEOUT/CANCELLED/HTTP_ERROR)。
- core/api_client.dart:dio 封装——Bearer 注入(登录端点豁免)、401
驱逐(清会话 + onUnauthorized 回调去重,App 壳注册跳 /login)、
DioException/错误体 {code,message,requestId} 归一 AppException、
通用游标分页助手;auth/albums/members/categories/admin/uploads/photos
全端点方法;riverpod provider 出口。
- core/session_store.dart:SessionStore 抽象 + flutter_secure_storage
实现(token/expiresAt/account 三键,encode/decode 纯函数可测)。
- features/{auth,albums,uploads,photos}/models.dart:手写 fromJson/
toJson,逐字段对齐 openapi.yaml(类注释标注契约 schema/operationId);
locale 按字符串透传(zh-CN 标识符不兼容),业务枚举 Dart 化并在
未知值 fail-fast。
- 测试 66 项:17 码表驱动 + 网络/超时/取消 + 兜底映射、游标边界
(含 CursorPageMeta 不变式违约容错)、模型往返(fixture 转写自
openapi.yaml schema 与 api e2e 断言,来源在测试头注释)、拦截器
行为(手写 FakeAdapter:Bearer 注入/401 驱逐/登录豁免/并发去重/
尽力而为 logout/refresh 滑动续期)。flutter analyze 零告警。
Co-Authored-By: Claude Code <noreply@anthropic.com>
36 lines
1.2 KiB
Dart
36 lines
1.2 KiB
Dart
import 'error_codes.dart';
|
||
|
||
/// 统一 API 异常:HTTP 错误响应体 `{code, message, requestId}`(契约
|
||
/// `components.schemas.Error`)与网络层失败一律归一为本类型,映射逻辑见
|
||
/// `ApiClient.mapDioException`。
|
||
///
|
||
/// UI 层按 [code]([ErrorCodes])解析本地化文案;[message] 为服务器/
|
||
/// 客户端生成的诊断消息,不作为展示文案依据。
|
||
class AppException implements Exception {
|
||
const AppException({
|
||
required this.code,
|
||
required this.message,
|
||
this.requestId,
|
||
this.statusCode,
|
||
});
|
||
|
||
/// 稳定错误码(契约码或客户端伪码,见 [ErrorCodes])。
|
||
final String code;
|
||
|
||
/// 可读消息(诊断用)。
|
||
final String message;
|
||
|
||
/// 请求追踪 ID(服务端错误体携带时非空)。
|
||
final String? requestId;
|
||
|
||
/// HTTP 状态码(网络层失败/取消时为 null)。
|
||
final int? statusCode;
|
||
|
||
/// 会话过期/未认证(401 语义:令牌失效需重新登录)。
|
||
bool get isAuthExpired => code == ErrorCodes.authTokenExpired;
|
||
|
||
@override
|
||
String toString() => 'AppException(code: $code, statusCode: $statusCode, '
|
||
'requestId: $requestId, message: $message)';
|
||
}
|