chore: 初始化脚手架 — sunny_mochi 企业级 Flutter 模板

Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库
7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系
5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter

通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
This commit is contained in:
SkyJourney
2026-05-14 12:51:05 +08:00
commit 61017f1c39
204 changed files with 15386 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
import 'package:sunny_mochi/core/error/exception_mapper.dart'
show ExceptionMapper;
/// 应用层统一失败模型。
///
/// 所有数据/网络/缓存层的异常通过 [ExceptionMapper] 转换为 [Failure] 子类,
/// presentation 层只面对 Failure,避免散落 try-catch DioException / DriftException。
///
/// **实现 [Exception]**:让 datasource/repository 可以直接 `throw failure;`
/// 不触发 `only_throw_errors` lint。
///
/// 详见 docs/flutter-architecture-design.md §四.2。
sealed class Failure implements Exception {
const Failure({required this.message, this.cause, this.stackTrace});
final String message;
final Object? cause;
final StackTrace? stackTrace;
/// 子类自我描述前缀(避免直接用 [Object.runtimeType]Release 混淆友好)。
String get _typeName;
/// 适合展示给用户的文案(区别于 [message],后者含技术细节,供 Sentry/Talker 日志使用)。
String get userMessage;
@override
String toString() => '$_typeName: $message';
}
/// 网络层失败:超时 / 无网 / DNS 解析失败 / 证书绑定失败 / 连接断开。
class NetworkFailure extends Failure {
const NetworkFailure({
required super.message,
this.kind = NetworkFailureKind.unknown,
super.cause,
super.stackTrace,
});
final NetworkFailureKind kind;
@override
String get _typeName => 'NetworkFailure';
@override
String get userMessage => message;
}
enum NetworkFailureKind {
timeout,
noNetwork,
badCertificate,
cancelled,
unknown,
}
/// 鉴权失败:未登录 / Token 过期 / refresh 失败 → 应跳登录。
class AuthFailure extends Failure {
const AuthFailure({
required super.message,
this.kind = AuthFailureKind.unauthorized,
super.cause,
super.stackTrace,
});
final AuthFailureKind kind;
@override
String get _typeName => 'AuthFailure';
@override
String get userMessage => message;
}
enum AuthFailureKind {
unauthorized, // A0401
forbidden, // 403
refreshFailed,
cryptoFailed, // 客户端加密失败(如登录密码 RSA 加密前置错)
}
/// 服务端业务失败:500/501 / 业务校验失败 / 参数错误。
class ServerFailure extends Failure {
const ServerFailure({
required super.message,
this.code,
this.statusCode,
super.cause,
super.stackTrace,
});
final String? code; // 业务错误码(如 A0500 / A0400 / A0404
final int? statusCode; // HTTP 状态码
@override
String get _typeName => 'ServerFailure';
@override
String get userMessage {
// HTTP 5xx:服务端内部错误,后端 message 可能含技术细节(SQL/堆栈),统一遮蔽
if (statusCode != null && statusCode! >= 500) return '服务器开小差了,请稍后再试';
// 业务码 / 4xxmessage 已经过 ResponseCode.friendlyMessage 映射,安全展示
return message;
}
}
/// 本地缓存/数据库失败:Drift 异常 / SQLCipher 解密失败 / 文件 IO 错误。
class CacheFailure extends Failure {
const CacheFailure({
required super.message,
super.cause,
super.stackTrace,
});
@override
String get _typeName => 'CacheFailure';
@override
String get userMessage => '本地数据异常,请重启应用试试';
}
/// 兜底未知错误。
class UnknownFailure extends Failure {
const UnknownFailure({
required super.message,
super.cause,
super.stackTrace,
});
@override
String get _typeName => 'UnknownFailure';
@override
String get userMessage => '遇到了点问题,已自动上报';
}