完善移动端错误提示中文化
This commit is contained in:
@@ -1,7 +1,78 @@
|
||||
// 功能描述:封装用户端 HTTP 请求,并将服务端错误转换为安全、可读的中文提示。
|
||||
// 版本:1.1.0
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
const Map<int, String> _apiErrorMessages = {
|
||||
404: '记录不存在',
|
||||
1001: '请求标识缺失',
|
||||
1002: '登录信息缺失,请重新登录',
|
||||
1003: '接口密钥缺失',
|
||||
1004: '请求头参数缺失',
|
||||
1101: '暂无数据',
|
||||
1102: '请求解析失败',
|
||||
1103: '请填写必填参数',
|
||||
1104: '无权执行此操作',
|
||||
1105: '服务端数据处理失败',
|
||||
1106: '服务端数据处理失败',
|
||||
1107: '服务内部错误,请稍后重试',
|
||||
1108: '密码错误',
|
||||
1110: '账号已禁用',
|
||||
1111: '当前记录已停用',
|
||||
1112: '记录不存在',
|
||||
1301: '登录状态已失效,请重新登录',
|
||||
1302: '登录状态已失效,请重新登录',
|
||||
1303: '登录状态已失效,请重新登录',
|
||||
1304: '登录状态已失效,请重新登录',
|
||||
1305: '登录状态已失效,请重新登录',
|
||||
1306: '登录状态已失效,请重新登录',
|
||||
1307: '登录状态已变更,请重新登录',
|
||||
1308: '登录已过期,请重新登录',
|
||||
1309: '登录状态已失效,请重新登录',
|
||||
1310: '登录状态已失效,请重新登录',
|
||||
1311: '登录状态已失效,请重新登录',
|
||||
1312: '登录状态已失效,请重新登录',
|
||||
1313: '登录失败,请稍后重试',
|
||||
1314: '登录状态已失效,请重新登录',
|
||||
1501: '服务暂时不可用,请稍后重试',
|
||||
1502: '服务暂时不可用,请稍后重试',
|
||||
1503: '服务暂时不可用,请稍后重试',
|
||||
1504: '服务暂时不可用,请稍后重试',
|
||||
1505: '服务暂时不可用,请稍后重试',
|
||||
1506: '服务暂时不可用,请稍后重试',
|
||||
1507: '服务暂时不可用,请稍后重试',
|
||||
1702: '操作已取消',
|
||||
1703: '操作失败,请稍后重试',
|
||||
1704: '请求参数错误',
|
||||
1705: '请求超时,请稍后重试',
|
||||
1706: '记录已存在',
|
||||
1707: '无权执行此操作',
|
||||
1708: '系统繁忙,请稍后重试',
|
||||
1709: '当前状态不支持此操作',
|
||||
1710: '操作已中止',
|
||||
1711: '输入内容超出允许范围',
|
||||
1712: '当前功能暂不支持',
|
||||
1713: '服务暂时不可用,请稍后重试',
|
||||
1714: '服务数据异常,请稍后重试',
|
||||
1715: '请先登录',
|
||||
};
|
||||
|
||||
final RegExp _chineseCharacterPattern = RegExp(r'[\u3400-\u9fff]');
|
||||
|
||||
/// 将服务端错误转换为中文用户提示。
|
||||
///
|
||||
/// [code] 是稳定错误码,[message] 是服务端原始消息;返回值不会透传未知英文技术信息。
|
||||
String localizeApiErrorMessage(int code, String? message) {
|
||||
final mappedMessage = _apiErrorMessages[code];
|
||||
if (mappedMessage != null) return mappedMessage;
|
||||
|
||||
final originalMessage = message?.trim() ?? '';
|
||||
if (_chineseCharacterPattern.hasMatch(originalMessage)) return originalMessage;
|
||||
return '操作失败,请稍后重试';
|
||||
}
|
||||
|
||||
/// 表示客户端可识别并可安全展示的接口异常。
|
||||
class ApiException implements Exception {
|
||||
const ApiException(this.code, this.message);
|
||||
|
||||
@@ -12,6 +83,7 @@ class ApiException implements Exception {
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
/// 负责用户端统一 HTTP 请求、鉴权头和响应解析。
|
||||
class ApiClient {
|
||||
ApiClient(
|
||||
this._tokenProvider, {
|
||||
@@ -59,18 +131,39 @@ class ApiClient {
|
||||
request.headers['content-type'] = 'application/json; charset=UTF-8';
|
||||
request.body = jsonEncode(body);
|
||||
}
|
||||
final streamed = await _client.send(request);
|
||||
final response = await http.Response.fromStream(streamed);
|
||||
final response = await _sendRequest(request);
|
||||
return _decode(response);
|
||||
}
|
||||
|
||||
/// 发送请求并统一处理网络连接异常。
|
||||
Future<http.Response> _sendRequest(http.BaseRequest request) async {
|
||||
try {
|
||||
return await http.Response.fromStream(await _client.send(request));
|
||||
} catch (_) {
|
||||
throw const ApiException(500, '网络连接失败,请稍后重试');
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析统一响应结构,并按错误码生成中文提示。
|
||||
Object? _decode(http.Response response) {
|
||||
if (response.statusCode < 200 || response.statusCode >= 300) {
|
||||
throw ApiException(response.statusCode, '网络请求失败(${response.statusCode})');
|
||||
}
|
||||
final decoded = jsonDecode(response.body);
|
||||
Object? decoded;
|
||||
try {
|
||||
decoded = jsonDecode(response.body);
|
||||
} on FormatException {
|
||||
throw const ApiException(500, '服务端响应格式错误');
|
||||
}
|
||||
if (decoded is! Map<String, Object?>) {
|
||||
throw const ApiException(500, '服务端响应格式错误');
|
||||
}
|
||||
final code = (decoded['code'] as num?)?.toInt() ?? 500;
|
||||
if (code != 0) {
|
||||
throw ApiException(code, decoded['message'] as String? ?? '操作失败');
|
||||
throw ApiException(
|
||||
code,
|
||||
localizeApiErrorMessage(code, decoded['message'] as String?),
|
||||
);
|
||||
}
|
||||
return decoded['details'];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user