import 'package:kaer_with_panels/app/utils/kr_log_util.dart'; class KRNodeList { final List list; 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 json) { try { // 新的 API 返回格式: {"list": [{"id": 24, "is_try_out": true, "nodes": [...]}]} final List? listData = json['list'] as List?; if (listData == null || listData.isEmpty) { KRLogUtil.kr_w('节点列表为空', tag: 'NodeList'); return const KRNodeList(list: []); } // 获取第一个订阅对象 final subscribeData = listData[0] as Map; final bool isTryOut = subscribeData['is_try_out'] as bool? ?? false; final List? nodesData = subscribeData['nodes'] as List?; KRLogUtil.kr_i('节点列表解析: is_try_out=$isTryOut, 节点数=${nodesData?.length ?? 0}', tag: 'NodeList'); return KRNodeList( list: nodesData?.map((e) => KrNodeListItem.fromJson(e as Map)).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'); return const KRNodeList(list: []); } } } class KrNodeListItem { final int id; String name; final String uuid; final String protocol; final String relayMode; final String relayNode; final String serverAddr; final int port; // 新增:端口字段 final int speedLimit; final List tags; final int traffic; final double trafficRatio; final int upload; final String city; final String config; final String country; final int createdAt; final int download; final String startTime; final String expireTime; final double latitude; final double latitudeCountry; final double longitude; final double longitudeCountry; KrNodeListItem({ required this.id, required this.name, required this.uuid, required this.protocol, this.relayMode = '', this.relayNode = '', required this.serverAddr, this.port = 0, // 默认值 required this.speedLimit, required this.tags, required this.traffic, required this.trafficRatio, required this.upload, required this.city, required this.config, required this.country, this.createdAt = 0, required this.download, required this.startTime, required this.expireTime, required this.latitude, required this.latitudeCountry, required this.longitude, required this.longitudeCountry, }); factory KrNodeListItem.fromJson(Map 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() ?? '', uuid: json['uuid']?.toString() ?? '', protocol: json['protocol']?.toString() ?? '', relayMode: json['relay_mode']?.toString() ?? '', relayNode: json['relay_node']?.toString() ?? '', serverAddr: serverAddr, port: port, speedLimit: _parseIntSafely(json['speed_limit']), tags: _parseStringList(json['tags']), traffic: _parseIntSafely(json['traffic']), trafficRatio: _parseDoubleSafely(json['traffic_ratio']), upload: _parseIntSafely(json['upload']), city: json['city']?.toString() ?? '', config: json['config']?.toString() ?? '', country: json['country']?.toString() ?? '', createdAt: _parseIntSafely(json['created_at']), download: _parseIntSafely(json['download']), startTime: json['start_time']?.toString() ?? '', expireTime: json['expire_time']?.toString() ?? '', latitude: _parseDoubleSafely(json['latitude']), latitudeCountry: _parseDoubleSafely(json['latitude_country']), longitude: _parseDoubleSafely(json['longitude']), longitudeCountry: _parseDoubleSafely(json['longitude_country']), ); } catch (err) { KRLogUtil.kr_e('KrNodeListItem解析错误: $err', tag: 'NodeList'); return KrNodeListItem( id: 0, name: '', uuid: '', protocol: '', serverAddr: '', port: 0, speedLimit: 0, tags: [], traffic: 0, trafficRatio: 0, upload: 0, city: '', config: '', country: '', download: 0, startTime: '', expireTime: '', latitude: 0.0, latitudeCountry: 0.0, longitude: 0.0, longitudeCountry: 0.0, ); } } // 添加安全解析工具方法 static int _parseIntSafely(dynamic value) { if (value == null) return 0; if (value is int) return value; if (value is String) return int.tryParse(value) ?? 0; return 0; } static double _parseDoubleSafely(dynamic value) { if (value == null) return 0.0; if (value is double) return value; if (value is int) return value.toDouble(); if (value is String) return double.tryParse(value) ?? 0.0; return 0.0; } static List _parseStringList(dynamic value) { if (value == null) return []; if (value is List) { return value.map((e) => e?.toString() ?? '').toList(); } return []; } }