feat: 源码提交
Build Windows / build (push) Has been cancelled

This commit is contained in:
2025-10-19 23:30:54 -07:00
parent 54e7df78db
commit 75d4c48e41
6076 changed files with 64655 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
import 'dart:convert';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/common/app_config.dart';
import 'package:kaer_with_panels/app/mixins/kr_app_bar_opacity_mixin.dart';
import 'package:kaer_with_panels/app/model/entity_from_json_util.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import '../utils/kr_aes_util.dart';
import '../utils/kr_log_util.dart';
/// 接口返回基础类
class BaseResponse<T> {
late int retCode; //状态码
late String retMsg; //返回的信息
late Map<String, dynamic> body; // 返回的数据
late T model;
List<T> list = []; // 初始化为空列表
bool isSuccess = true; // 是否返回正确数据
BaseResponse.fromJson(Map<String, dynamic> json) {
retCode = json['code'];
final dataMap = json['data'] ?? Map<String, dynamic>();
final cipherText = dataMap['data'] ?? "";
final nonce = dataMap['time'] ?? "";
// 判断是否需要解密:根据站点配置的 enable_security 字段
final shouldDecrypt = KRSiteConfigService().isDeviceSecurityEnabled();
if (shouldDecrypt && cipherText.isNotEmpty && nonce.isNotEmpty) {
try {
KRLogUtil.kr_i('🔓 开始解密响应数据', tag: 'BaseResponse');
final decrypted = KRAesUtil.decryptData(cipherText, nonce, AppConfig.kr_encryptionKey);
body = jsonDecode(decrypted);
KRLogUtil.kr_i('✅ 解密成功', tag: 'BaseResponse');
// 打印完整的解密后数据,方便调试
final bodyStr = jsonEncode(body);
KRLogUtil.kr_i('📦 解密后数据(完整): $bodyStr', tag: 'BaseResponse');
} catch (e) {
KRLogUtil.kr_e('❌ 解密失败: $e,使用原始数据', tag: 'BaseResponse');
body = dataMap;
}
}
else
{
body = dataMap;
}
if (retCode == 40004 || retCode == 40005 || retCode == 40002 || retCode == 40003) {
KRAppRunData().kr_loginOut();
}
if (retCode != 200) {
isSuccess = false;
}
retMsg = json['msg'];
// 获取错误信息
final msg = "error.${retCode.toString()}".tr;
if (msg.isNotEmpty && msg != "error.${retCode.toString()}") {
retMsg = msg;
}
if (body.isNotEmpty) {
if (body is List) {
list = (json['data'] as List<dynamic>)
.map((e) => EntityFromJsonUtil.parseJsonToEntity<T>(e))
.toList();
} else {
if (T == dynamic) {
model = body as T;
} else {
model = EntityFromJsonUtil.parseJsonToEntity<T>(body);
}
}
} else {
// 当body为空时,设置默认model值
}
}
// 获取泛型T的默认值
T _getDefaultValue<T>() {
if (T == String) return '' as T;
if (T == int) return 0 as T;
if (T == double) return 0.0 as T;
if (T == bool) return false as T;
if (T == Map) return {} as T;
if (T == List) return [] as T;
return null as T;
}
}
+10
View File
@@ -0,0 +1,10 @@
/// 接口返回的 -999等错误
class HttpError implements Exception {
int code;
String msg;
HttpError({required this.msg, required this.code});
@override
String toString() => 'ChatError(code: $code, msg: $msg)';
}
+310
View File
@@ -0,0 +1,310 @@
import 'dart:convert';
import 'dart:io' show Platform;
import 'package:dio/dio.dart';
// import 'package:flutter_easyloading/flutter_easyloading.dart'; // 已替换为自定义组件
import 'package:flutter_loggy_dio/flutter_loggy_dio.dart';
import 'package:kaer_with_panels/app/common/app_config.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/network/base_response.dart';
import 'package:kaer_with_panels/app/localization/kr_language_utils.dart';
import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
// import 'package:crypto/crypto.dart';
// import 'package:encrypt/encrypt.dart';
import 'package:loggy/loggy.dart';
import '../utils/kr_aes_util.dart';
import '../utils/kr_log_util.dart';
// import 'package:video/app/utils/common_util.dart';
// import 'package:video/app/utils/log_util.dart';
/// 定义请求方法的枚举
enum HttpMethod { GET, POST, DELETE, PUT }
/// 封装请求
class HttpUtil {
final Dio _dio = Dio();
static final HttpUtil _instance = HttpUtil._internal();
HttpUtil._internal() {
initDio();
}
factory HttpUtil() => _instance;
static HttpUtil getInstance() {
return _instance;
}
/// 对dio进行配置
void initDio() {
// 不使用 Loggy,改用自定义简洁拦截器
_dio.interceptors.add(_KRSimpleHttpInterceptor());
_dio.options.baseUrl = AppConfig.getInstance().baseUrl;
// 设置连接超时时间
_dio.options.connectTimeout = const Duration(seconds: 60);
_dio.options.receiveTimeout = const Duration(seconds: 60);
_dio.options.sendTimeout = const Duration(seconds: 60);
// 设置请求头
_dio.options.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8',
// 移除固定的UserAgent,使用动态的
};
// 设置响应类型
_dio.options.responseType = ResponseType.json;
// 设置验证状态
_dio.options.validateStatus = (status) {
return status != null && status >= 200 && status < 500;
};
}
/// 更新baseUrl
void updateBaseUrl() {
String newBaseUrl = AppConfig.getInstance().baseUrl;
if (_dio.options.baseUrl != newBaseUrl) {
KRLogUtil.kr_i('🔄 更新baseUrl: ${_dio.options.baseUrl} -> $newBaseUrl', tag: 'HttpUtil');
_dio.options.baseUrl = newBaseUrl;
}
}
/// 初始化请求头 signature签名字符串
Map<String, dynamic> _initHeader(
String signature, String? userId, String? token) {
Map<String, dynamic> map = <String, dynamic>{};
if (KRAppRunData().kr_isLogin.value == true) {
map["Authorization"] = KRAppRunData().kr_token;
}
// 添加语言请求头
map["lang"] = KRLanguageUtils.getCurrentLanguageCode();
// 添加动态UserAgent头
map["User-Agent"] = _kr_getUserAgent();
return map;
}
/// 获取当前系统的 user_agent
String _kr_getUserAgent() {
if (Platform.isAndroid) {
return 'android';
} else if (Platform.isIOS) {
return 'ios';
} else if (Platform.isMacOS) {
return 'mac';
} else if (Platform.isWindows) {
return 'windows';
} else if (Platform.isLinux) {
return 'linux';
} else if (Platform.isFuchsia) {
return 'harmony';
} else {
return 'unknown';
}
}
/// request请求:T为转换的实体类, path:请求地址,query:请求参数, method: 请求方法, isShowLoading(可选): 是否显示加载中的状态,默认true显示, false为不显示
Future<BaseResponse<T>> request<T>(String path, Map<String, dynamic> params,
{HttpMethod method = HttpMethod.POST, bool isShowLoading = true}) async {
try {
// 每次请求前更新baseUrl,确保使用最新的域名
updateBaseUrl();
if (isShowLoading) {
KRCommonUtil.kr_showLoading();
}
var map = <String, dynamic>{};
// 判断是否需要加密:根据站点配置的 enable_security 字段
final shouldEncrypt = KRSiteConfigService().isDeviceSecurityEnabled();
if (shouldEncrypt && path.contains("app")) {
KRLogUtil.kr_i('🔐 需要加密请求数据', tag: 'HttpUtil');
final plainText = jsonEncode(params);
map = KRAesUtil.encryptData(plainText, AppConfig.kr_encryptionKey);
} else {
map = params;
}
// 初始化请求头
final headers = _initHeader('signature', 'userId', 'token');
// 调试:打印请求头
KRLogUtil.kr_i('🔍 请求头: $headers', tag: 'HttpUtil');
Response<Map<String, dynamic>> responseTemp;
if (method == HttpMethod.GET) {
responseTemp = await _dio.get<Map<String, dynamic>>(
path,
queryParameters: map,
options: Options(
contentType: "application/json",
headers: headers, // 添加请求头
),
);
} else if (method == HttpMethod.DELETE) {
responseTemp = await _dio.delete<Map<String, dynamic>>(
path,
data: map,
options: Options(
contentType: "application/json",
headers: headers, // 添加请求头
),
);
} else if (method == HttpMethod.PUT) {
responseTemp = await _dio.put<Map<String, dynamic>>(
path,
data: map,
options: Options(
contentType: "application/json",
headers: headers, // 添加请求头
),
);
} else {
responseTemp = await _dio.post<Map<String, dynamic>>(
path,
data: map,
options: Options(
contentType: "application/json",
headers: headers, // 添加请求头
),
);
}
if (isShowLoading) {
KRCommonUtil.kr_hideLoading();
}
return BaseResponse<T>.fromJson(responseTemp.data!);
} on DioException catch (err) {
if (isShowLoading) {
KRCommonUtil.kr_hideLoading();
}
int code = -90000;
String msg = "";
msg = err.message ?? err.type.toString();
switch (err.type) {
case DioExceptionType.connectionTimeout:
code = -90001;
break;
case DioExceptionType.sendTimeout:
code = -90002;
break;
case DioExceptionType.receiveTimeout:
code = -90003;
break;
case DioExceptionType.badResponse:
code = err.response?.statusCode ?? -90004;
break;
case DioExceptionType.cancel:
break;
case DioExceptionType.connectionError:
code = -90006;
break;
case DioExceptionType.badCertificate:
code = -90007;
break;
default:
if (err.error != null) {
if (err.error.toString().contains("Connection reset by peer")) {
code = -90008;
}
}
}
return BaseResponse<T>.fromJson({
'code': code,
'msg': msg,
'data': <String, dynamic>{}
});
} catch (e) {
if (isShowLoading) {
KRCommonUtil.kr_hideLoading();
}
return BaseResponse<T>.fromJson({
'code': -90000,
'msg': e.toString(),
'data': <String, dynamic>{}
});
}
}
}
/// 拦截器(简洁格式,无边框)
class MyInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
print('>>> Request │ ${options.method}${options.uri}');
if (options.data != null) {
print('Body: ${options.data}');
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
print('<<< Response │ ${response.requestOptions.method}${response.statusCode} ${response.statusMessage}${response.requestOptions.uri}');
if (response.data != null) {
print('Body: ${response.data}');
}
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
print('<<< Error │ ${err.requestOptions.method}${err.requestOptions.uri}');
print('Error Type: ${err.type}');
if (err.message != null) {
print('Error Message: ${err.message}');
}
if (err.response?.data != null) {
print('Response Data: ${err.response?.data}');
}
handler.next(err);
}
}
/// 自定义简洁 HTTP 拦截器(无边框符号)
class _KRSimpleHttpInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
print('>>> Request │ ${options.method}${options.uri}');
if (options.data != null) {
print('Body: ${options.data}');
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
print('<<< Response │ ${response.requestOptions.method}${response.statusCode} ${response.statusMessage}${response.requestOptions.uri}');
if (response.data != null) {
print('Body: ${response.data}');
}
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
print('<<< Error │ ${err.requestOptions.method}${err.requestOptions.uri}');
print('Error Type: ${err.type}');
if (err.message != null) {
print('Error Message: ${err.message}');
}
if (err.response?.data != null) {
print('Response Data: ${err.response?.data}');
}
handler.next(err);
}
}