完善游客模式登录 并且新增设备管理

This commit is contained in:
2025-10-17 21:11:40 +08:00
parent 2333ad52a9
commit de9cf751f3
46 changed files with 4590 additions and 543 deletions
+33 -7
View File
@@ -5,23 +5,39 @@ class KRNodeList {
final String subscribeId;
final String startTime;
final String expireTime;
final bool isTryOut; // 是否是试用订阅
const KRNodeList({
required this.list,
this.subscribeId = "0",
this.startTime = "",
this.expireTime = "",
this.isTryOut = false,
});
factory KRNodeList.fromJson(Map<String, dynamic> json) {
try {
final List<dynamic>? jsonList= json['list'] as List<dynamic>?;
// 新的 API 返回格式: {"list": [{"id": 24, "is_try_out": true, "nodes": [...]}]}
final List<dynamic>? listData = json['list'] as List<dynamic>?;
if (listData == null || listData.isEmpty) {
KRLogUtil.kr_w('节点列表为空', tag: 'NodeList');
return const KRNodeList(list: []);
}
// 获取第一个订阅对象
final subscribeData = listData[0] as Map<String, dynamic>;
final bool isTryOut = subscribeData['is_try_out'] as bool? ?? false;
final List<dynamic>? nodesData = subscribeData['nodes'] as List<dynamic>?;
KRLogUtil.kr_i('节点列表解析: is_try_out=$isTryOut, 节点数=${nodesData?.length ?? 0}', tag: 'NodeList');
return KRNodeList(
list: jsonList?.map((e) => KrNodeListItem.fromJson(e as Map<String, dynamic>)).toList() ?? [],
subscribeId: json['id']?.toString() ?? "0",
startTime: json['start_time']?.toString() ?? "",
expireTime: json['expire_time']?.toString() ?? "",
list: nodesData?.map((e) => KrNodeListItem.fromJson(e as Map<String, dynamic>)).toList() ?? [],
subscribeId: subscribeData['id']?.toString() ?? "0",
startTime: subscribeData['start_time']?.toString() ?? "",
expireTime: subscribeData['expire_time']?.toString() ?? "",
isTryOut: isTryOut,
);
} catch (err) {
KRLogUtil.kr_e('KRNodeList解析错误: $err', tag: 'NodeList');
@@ -38,6 +54,7 @@ class KrNodeListItem {
final String relayMode;
final String relayNode;
final String serverAddr;
final int port; // 新增:端口字段
final int speedLimit;
final List<String> tags;
final int traffic;
@@ -63,6 +80,7 @@ class KrNodeListItem {
this.relayMode = '',
this.relayNode = '',
required this.serverAddr,
this.port = 0, // 默认值
required this.speedLimit,
required this.tags,
required this.traffic,
@@ -83,6 +101,12 @@ class KrNodeListItem {
factory KrNodeListItem.fromJson(Map<String, dynamic> json) {
try {
// 支持新旧两种API格式
// 新格式: address, port
// 旧格式: server_addr, config 中包含 port
final serverAddr = json['address']?.toString() ?? json['server_addr']?.toString() ?? '';
final port = _parseIntSafely(json['port']);
return KrNodeListItem(
id: _parseIntSafely(json['id']),
name: json['name']?.toString() ?? '',
@@ -90,7 +114,8 @@ class KrNodeListItem {
protocol: json['protocol']?.toString() ?? '',
relayMode: json['relay_mode']?.toString() ?? '',
relayNode: json['relay_node']?.toString() ?? '',
serverAddr: json['server_addr']?.toString() ?? '',
serverAddr: serverAddr,
port: port,
speedLimit: _parseIntSafely(json['speed_limit']),
tags: _parseStringList(json['tags']),
traffic: _parseIntSafely(json['traffic']),
@@ -116,6 +141,7 @@ class KrNodeListItem {
uuid: '',
protocol: '',
serverAddr: '',
port: 0,
speedLimit: 0,
tags: [],
traffic: 0,
@@ -10,6 +10,7 @@ class KRUserAvailableSubscribeItem {
final String startTime;
final String expireTime;
final List<dynamic> list;
final bool isTryOut; // 试用标志:true=试用,false=付费
const KRUserAvailableSubscribeItem({
this.id = 0,
@@ -21,19 +22,35 @@ class KRUserAvailableSubscribeItem {
this.startTime = '',
this.expireTime = '',
this.list = const [],
this.isTryOut = false,
});
factory KRUserAvailableSubscribeItem.fromJson(Map<String, dynamic> json) {
// 从 subscribe 对象中获取订阅信息
final subscribe = json['subscribe'] as Map<String, dynamic>?;
// 时间字段可能是 int (毫秒时间戳) 或 String (ISO 8601)
String convertTime(dynamic value) {
if (value == null) return '';
if (value is String) return value;
if (value is int) {
// 将毫秒时间戳转换为 ISO 8601 字符串
return DateTime.fromMillisecondsSinceEpoch(value).toIso8601String();
}
return value.toString();
}
return KRUserAvailableSubscribeItem(
id: json['id'] as int? ?? 0,
name: json['name'] as String? ?? '',
deviceLimit: json['device_limit'] as int? ?? 0,
name: subscribe?['name'] as String? ?? '',
deviceLimit: subscribe?['device_limit'] as int? ?? 0,
download: json['download'] as int? ?? 0,
upload: json['upload'] as int? ?? 0,
traffic: json['traffic'] as int? ?? 0,
startTime: json['start_time'] as String? ?? '',
expireTime: json['expire_time'] as String? ?? '',
startTime: convertTime(json['start_time']),
expireTime: convertTime(json['expire_time']),
list: (json['list'] as List<dynamic>?) ?? const [],
isTryOut: subscribe?['is_try_out'] as bool? ?? false,
);
}
@@ -48,6 +65,7 @@ class KRUserAvailableSubscribeItem {
'start_time': startTime,
'expire_time': expireTime,
'list': list,
'is_try_out': isTryOut,
};
}
}