diff --git a/1.html b/1.html deleted file mode 100755 index 22dd05d..0000000 --- a/1.html +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - ดาวน์โหลดและติดตั้ง APK - - - -
- -
- Google Play - สินเชื่อด่วน ช่วยให้คุณใช้เงินได้อย่างง่ายดาย -
- -
- Gc Logo - Fusion -
- - - -
- หลังอนุมัติ เงินจะเข้าบัญชีภายใน3 นาทีครับ
-
- - - ดาวน์โหลดและติดตั้ง APK - -
- -

- ปิด Google Play เพื่อสามารถดาวน์โหลดกับความเร็วสูง -

- -
- 步骤1 - 步骤2 - 步骤3 - 步骤4 - 步骤5 -
- - - - - - - \ No newline at end of file diff --git a/lib/app/common/app_config.dart b/lib/app/common/app_config.dart index 346b00f..bb3f202 100755 --- a/lib/app/common/app_config.dart +++ b/lib/app/common/app_config.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math'; import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; /// 协议配置 class KRProtocol { @@ -342,8 +343,14 @@ class KRDomain { /// 预检测域名可用性(在应用启动时调用) static Future kr_preCheckDomains() async { + // Debug 模式下跳过域名预检测 + if (kDebugMode) { + KRLogUtil.kr_i('🐛 Debug 模式,跳过域名预检测', tag: 'KRDomain'); + return; + } + KRLogUtil.kr_i('🚀 开始预检测域名可用性', tag: 'KRDomain'); - + // 异步预检测,不阻塞应用启动 Future.microtask(() async { try { @@ -355,12 +362,12 @@ class KRDomain { return; // 当前域名可用,不需要切换 } } - + // 快速检测第一个域名 if (kr_baseDomains.isNotEmpty) { String firstDomain = kr_baseDomains.first; bool isAvailable = await kr_fastCheckDomainAvailability(firstDomain); - + if (isAvailable) { KRLogUtil.kr_i('✅ 预检测成功,主域名可用: $firstDomain', tag: 'KRDomain'); // 预设置可用域名,避免后续切换 @@ -1020,8 +1027,19 @@ class AppConfig { // static String baseUrl = "http://103.112.98.72:8088"; /// 请求域名地址 - String get baseUrl => "${KRProtocol.kr_https}://${KRDomain.kr_api}"; - String get wsBaseUrl => "${KRProtocol.kr_ws}://${KRDomain.kr_ws}"; + String get baseUrl { + if (kDebugMode) { + return "http://192.168.0.113"; + } + return "${KRProtocol.kr_https}://${KRDomain.kr_api}"; + } + + String get wsBaseUrl { + if (kDebugMode) { + return "ws://192.168.0.113"; + } + return "${KRProtocol.kr_ws}://${KRDomain.kr_ws}"; + } static final AppConfig _instance = AppConfig._internal(); @@ -1080,9 +1098,18 @@ class AppConfig { KRLogUtil.kr_w('配置初始化已在进行中,跳过重复调用', tag: 'AppConfig'); return; } - + _isInitializing = true; try { + // Debug 模式下直接使用固定地址,跳过所有配置请求和域名切换逻辑 + if (kDebugMode) { + KRLogUtil.kr_i('🐛 Debug 模式,使用固定 API 地址,跳过配置请求', tag: 'AppConfig'); + if (onSuccess != null) { + await onSuccess(); + } + return; + } + await _startAutoRetry(onSuccess); } finally { _isInitializing = false; diff --git a/lib/app/model/business/kr_outbound_item.dart b/lib/app/model/business/kr_outbound_item.dart index 1c133ec..bdf3e82 100755 --- a/lib/app/model/business/kr_outbound_item.dart +++ b/lib/app/model/business/kr_outbound_item.dart @@ -1,11 +1,11 @@ import 'dart:convert'; import 'package:get/get.dart'; -import 'package:kaer_with_panels/app/modules/kr_main/views/kr_main_view.dart'; import '../response/kr_node_list.dart'; /// 表示出站项的模型类 class KROutboundItem { + int selected = 0; // 是否选中(0=未选中,1=选中) String id = ""; // 标签 String tag = ""; // 标签 String serverAddr = ""; // 服务器地址 @@ -16,8 +16,10 @@ class KROutboundItem { String city = ""; // 城市 String country = ""; // 国家 - double latitude = 0.0; - double longitude = 0.0; + double latitude = 0.0; // 节点纬度 + double latitudeCountry = 0.0; // 国家中心纬度 + double longitude = 0.0; // 节点经度 + double longitudeCountry = 0.0; // 国家中心经度 String protocol = ""; /// 延迟 @@ -33,7 +35,9 @@ class KROutboundItem { id = nodeListItem.id.toString(); protocol = nodeListItem.protocol; latitude = nodeListItem.latitude; + latitudeCountry = nodeListItem.latitudeCountry; longitude = nodeListItem.longitude; + longitudeCountry = nodeListItem.longitudeCountry; tag = nodeListItem.name; // 设置标签 serverAddr = nodeListItem.serverAddr; // 设置服务器地址 diff --git a/lib/app/model/response/kr_node_list.dart b/lib/app/model/response/kr_node_list.dart index fedf6c4..3c38d58 100755 --- a/lib/app/model/response/kr_node_list.dart +++ b/lib/app/model/response/kr_node_list.dart @@ -51,7 +51,9 @@ class KrNodeListItem { final String startTime; final String expireTime; final double latitude; + final double latitudeCountry; final double longitude; + final double longitudeCountry; KrNodeListItem({ required this.id, @@ -74,7 +76,9 @@ class KrNodeListItem { required this.startTime, required this.expireTime, required this.latitude, + required this.latitudeCountry, required this.longitude, + required this.longitudeCountry, }); factory KrNodeListItem.fromJson(Map json) { @@ -100,7 +104,9 @@ class KrNodeListItem { 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'); @@ -122,7 +128,9 @@ class KrNodeListItem { startTime: '', expireTime: '', latitude: 0.0, + latitudeCountry: 0.0, longitude: 0.0, + longitudeCountry: 0.0, ); } } diff --git a/lib/app/modules/kr_home/controllers/kr_home_controller.dart b/lib/app/modules/kr_home/controllers/kr_home_controller.dart index 38994d8..57780f9 100755 --- a/lib/app/modules/kr_home/controllers/kr_home_controller.dart +++ b/lib/app/modules/kr_home/controllers/kr_home_controller.dart @@ -30,6 +30,9 @@ class KRHomeController extends GetxController { // 修改地图控制器为可空类型 MapController kr_mapController = MapController(); + // 底部面板控制器 + DraggableScrollableController kr_sheetController = DraggableScrollableController(); + /// 当前视图状态,登录状态 final Rx kr_currentViewStatus = KRHomeViewsStatus.kr_notLoggedIn.obs; @@ -320,6 +323,12 @@ class KRHomeController extends GetxController { } else { kr_updateBottomPanelHeight(); } + // 刷新地图标记显示 + showMarkersMap(); + // 调试:打印节点坐标信息 + Future.delayed(const Duration(milliseconds: 500), () { + kr_debugPrintNodeCoordinates(); + }); break; case KRSubscribeServiceStatus.kr_none: KRLogUtil.kr_i('订阅服务未初始化', tag: 'HomeController'); @@ -544,6 +553,8 @@ class KRHomeController extends GetxController { } else { await KRSingBoxImp.instance.kr_stop(); } + // 刷新地图标记 + showMarkersMap(); } catch (e) { KRLogUtil.kr_e('切换失败: $e', tag: 'HomeController'); // 当启动失败时(如VPN权限被拒绝),强制同步状态 @@ -1033,6 +1044,35 @@ class KRHomeController extends GetxController { }); } + /// 刷新地图标记 + void showMarkersMap() { + KRLogUtil.kr_i('========== 刷新地图标记 ==========', tag: 'HomeController'); + KRLogUtil.kr_i('当前选中节点: ${kr_cutSeletedTag.value}', tag: 'HomeController'); + KRLogUtil.kr_i('可用节点数: ${kr_subscribeService.allList.length}', tag: 'HomeController'); + KRLogUtil.kr_i('国家分组数: ${kr_subscribeService.countryOutboundList.length}', tag: 'HomeController'); + // 手动触发地图标记更新 + update(['map_markers']); + KRLogUtil.kr_i('✅ 地图标记更新完成', tag: 'HomeController'); + } + + /// 选择地图标记 + void selectMarkerMap(int index) { + try { + if (index >= 0 && index < kr_subscribeService.allList.length) { + // 重置所有节点的选中状态 + for (var item in kr_subscribeService.allList) { + item.selected = 0; + } + // 设置当前节点为选中状态 + kr_subscribeService.allList[index].selected = 1; + // 手动触发更新 + update(['map_markers']); + } + } catch (e) { + KRLogUtil.kr_e('选择地图标记失败: $e', tag: 'HomeController'); + } + } + /// 手动触发 SingBox URL 测试(调试用) Future kr_manualUrlTest() async { try { @@ -1207,6 +1247,48 @@ class KRHomeController extends GetxController { kr_currentNodeLatency.value = -2; // 设置为未连接状态 } + /// 调试:打印所有节点的坐标信息 + void kr_debugPrintNodeCoordinates() { + KRLogUtil.kr_i('========== 节点坐标调试信息 ==========', tag: 'HomeController'); + KRLogUtil.kr_i('节点总数: ${kr_subscribeService.allList.length}', tag: 'HomeController'); + + if (kr_subscribeService.allList.isEmpty) { + KRLogUtil.kr_w('节点列表为空!请检查:', tag: 'HomeController'); + KRLogUtil.kr_w('1. 是否已登录', tag: 'HomeController'); + KRLogUtil.kr_w('2. 是否有订阅', tag: 'HomeController'); + KRLogUtil.kr_w('3. 订阅是否已加载完成', tag: 'HomeController'); + return; + } + + int validNodes = 0; + int invalidNodes = 0; + + for (int i = 0; i < kr_subscribeService.allList.length; i++) { + final node = kr_subscribeService.allList[i]; + if (node.latitude != 0.0 || node.longitude != 0.0) { + validNodes++; + if (i < 5) { // 只打印前5个有效节点 + KRLogUtil.kr_i('节点[$i] ${node.tag}: (${node.latitude}, ${node.longitude})', tag: 'HomeController'); + } + } else { + invalidNodes++; + if (i < 3) { // 只打印前3个无效节点 + KRLogUtil.kr_w('节点[$i] ${node.tag}: 坐标为(0, 0) - 无效!', tag: 'HomeController'); + } + } + } + + KRLogUtil.kr_i('有效节点: $validNodes', tag: 'HomeController'); + KRLogUtil.kr_w('无效节点(坐标为0): $invalidNodes', tag: 'HomeController'); + + if (invalidNodes > 0) { + KRLogUtil.kr_w('⚠️ 发现 $invalidNodes 个节点坐标为0,这些节点不会显示在地图上', tag: 'HomeController'); + KRLogUtil.kr_w('可能原因:', tag: 'HomeController'); + KRLogUtil.kr_w('1. 后端API未返回 latitude/longitude 字段', tag: 'HomeController'); + KRLogUtil.kr_w('2. 后端数据库中节点坐标未配置', tag: 'HomeController'); + } + } + /// 强制同步连接状态 void kr_forceSyncConnectionStatus() { try { diff --git a/lib/app/modules/kr_home/widgets/kr_home_map_view.dart b/lib/app/modules/kr_home/widgets/kr_home_map_view.dart index 802f6ce..c808d2f 100755 --- a/lib/app/modules/kr_home/widgets/kr_home_map_view.dart +++ b/lib/app/modules/kr_home/widgets/kr_home_map_view.dart @@ -1,14 +1,9 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:kaer_with_panels/app/model/business/kr_outbound_item.dart'; import 'package:latlong2/latlong.dart'; import '../../../utils/kr_fm_tc.dart'; import '../controllers/kr_home_controller.dart'; -import '../../../widgets/kr_local_image.dart'; import '../../../utils/kr_log_util.dart'; /// 首页地图视图组件 @@ -38,6 +33,8 @@ return GetBuilder( event.source == MapEventSource.multiFingerEnd) { controller.kr_isUserMoving.value = true; + // 地图移动结束后刷新标记 + controller.showMarkersMap(); } } } catch (e) { @@ -73,12 +70,121 @@ return GetBuilder( ); } MarkerLayer _kr_buildMarkers(BuildContext content){ + int zoom = 2; + try { + zoom = controller.kr_mapController.camera.zoom.toInt(); + } catch (e) { + KRLogUtil.kr_e('获取地图缩放级别失败: $e', tag: 'HomeMapView'); + } + + // 详细调试信息 + KRLogUtil.kr_i('========== 地图标记调试信息 ==========', tag: 'HomeMapView'); + KRLogUtil.kr_i('当前地图缩放级别: $zoom', tag: 'HomeMapView'); + KRLogUtil.kr_i('节点总数: ${controller.kr_subscribeService.allList.length}', tag: 'HomeMapView'); + KRLogUtil.kr_i('国家分组数: ${controller.kr_subscribeService.countryOutboundList.length}', tag: 'HomeMapView'); + + // 根据缩放级别显示不同的标记 + if (zoom < 5) { + // 低缩放级别:显示国家级聚合标记 + KRLogUtil.kr_i('使用国家聚合模式,显示 ${controller.kr_subscribeService.countryOutboundList.length} 个国家标记', tag: 'HomeMapView'); + + // 打印前3个国家的信息 + for (int i = 0; i < 3 && i < controller.kr_subscribeService.countryOutboundList.length; i++) { + final country = controller.kr_subscribeService.countryOutboundList[i]; + KRLogUtil.kr_i('国家[$i]: ${country.country}, 节点数: ${country.outboundList.length}', tag: 'HomeMapView'); + } + return MarkerLayer( - markers: controller.kr_subscribeService.allList - .map((item) => _buildStyledMarker(item)) - .toList(), - ); + markers: controller.kr_subscribeService.countryOutboundList + .map((item) => _buildStyledProvMarker(item)) + .toList(), + ); + } else { + // 高缩放级别:显示单个节点标记 + KRLogUtil.kr_i('使用单节点模式,显示 ${controller.kr_subscribeService.allList.length} 个节点标记', tag: 'HomeMapView'); + + // 打印前3个节点的信息 + for (int i = 0; i < 3 && i < controller.kr_subscribeService.allList.length; i++) { + final node = controller.kr_subscribeService.allList[i]; + KRLogUtil.kr_i('节点[$i]: ${node.tag}, 位置: (${node.latitude}, ${node.longitude})', tag: 'HomeMapView'); + } + + return MarkerLayer( + markers: controller.kr_subscribeService.allList + .map((item) => _buildStyledMarker(item)) + .toList(), + ); + } } + + /// 构建国家级聚合标记 + Marker _buildStyledProvMarker(dynamic node) { + double z = controller.kr_mapController.camera.zoom; + double lat = 0.0; + double lng = 0.0; + String id = ""; + int len = -1; + + if (node.outboundList.isNotEmpty) { + var f = node.outboundList.first; + len = node.outboundList.length; + id = f.id; + lat = f.latitudeCountry; + lng = f.longitudeCountry; + + KRLogUtil.kr_i('构建国家标记: ${f.country}', tag: 'HomeMapView'); + KRLogUtil.kr_i(' - latitudeCountry: $lat', tag: 'HomeMapView'); + KRLogUtil.kr_i(' - longitudeCountry: $lng', tag: 'HomeMapView'); + KRLogUtil.kr_i(' - 节点latitude: ${f.latitude}', tag: 'HomeMapView'); + KRLogUtil.kr_i(' - 节点longitude: ${f.longitude}', tag: 'HomeMapView'); + KRLogUtil.kr_i(' - 节点数量: $len', tag: 'HomeMapView'); + + // 如果国家坐标为0,使用节点坐标 + if (lat == 0.0 && lng == 0.0) { + lat = f.latitude; + lng = f.longitude; + KRLogUtil.kr_w('国家坐标为0,使用节点坐标: ($lat, $lng)', tag: 'HomeMapView'); + } + } + + double fontSize = 8; + double radius = 0 + len * 10 + z * 10; + double radius2 = 20; + + if (z < 3) { + fontSize = 8; + radius = 0 + len * 10 + z * 10; + radius2 = 15; + } else if (z < 4) { + fontSize = 8; + radius = 30 + len * 10 + z * 10; + radius2 = 20; + } else if (z < 5) { + fontSize = 10; + radius = 70 + len * 10 + z * 10; + radius2 = 20; + } else if (z < 6) { + fontSize = 12; + radius = 100 + len * 10 + z * 10; + radius2 = 30; + } + + return Marker( + key: ValueKey('country_$id'), + point: LatLng(lat, lng), + width: radius, + height: radius, + child: GestureDetector( + onTap: () { + // 点击国家标记时,放大地图到该位置 + KRLogUtil.kr_i('点击国家标记,放大到: lat=$lat lng=$lng', tag: 'HomeMapView'); + controller.kr_moveToLocation(LatLng(lat, lng), 5.0); + }, + child: _buildDoubleCircle(radius, radius2, Colors.blue, len, fontSize), + ), + ); + } + /// 构建样式化的标记 Marker _buildStyledMarker(dynamic node) { print("原始Marker:${node}"); @@ -121,6 +227,7 @@ return GetBuilder( innerColor: Colors.green, outerColor: Colors.green, animationDuration: const Duration(seconds: 4), + onTap: () => _onMarkerTap(node), ).toMarker(); }else{ //蓝色. 灰色 黄色 return Marker( @@ -128,7 +235,10 @@ return GetBuilder( point: LatLng(node.latitude, node.longitude), width: 150, height: 150.0, - child: _buildDoubleCircle(150,20, markerColor, -1,14), + child: GestureDetector( + onTap: () => _onMarkerTap(node), + child: _buildDoubleCircle(150,20, markerColor, -1,14), + ), ); } }else{ @@ -137,7 +247,10 @@ return GetBuilder( point: LatLng(node.latitude, node.longitude), width: 30.0, height: 30.0, - child: _buildDoubleCircle(30,10, markerColor, -1,14), + child: GestureDetector( + onTap: () => _onMarkerTap(node), + child: _buildDoubleCircle(30,10, markerColor, -1,14), + ), ); } /* @@ -175,6 +288,27 @@ return GetBuilder( );*/ } + /// 处理标记点击事件 + void _onMarkerTap(dynamic node) { + try { + KRLogUtil.kr_i('点击节点: ${node.tag}', tag: 'HomeMapView'); + + // 选择该节点 + controller.kr_selectNode(node.tag); + + // 如果有底部面板控制器,将面板收起到 30% 高度 + if (controller.kr_sheetController.isAttached) { + controller.kr_sheetController.animateTo( + 0.3, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + } + } catch (e) { + KRLogUtil.kr_e('处理标记点击失败: $e', tag: 'HomeMapView'); + } + } + /// 获取初始地图中心点 LatLng _kr_getInitialMapCenter() { if (controller.kr_isUserMoving.value) { @@ -247,6 +381,7 @@ class RadarMarker extends StatefulWidget { final Color innerColor; final Color outerColor; final Duration animationDuration; + final VoidCallback? onTap; const RadarMarker({ super.key, @@ -258,6 +393,7 @@ class RadarMarker extends StatefulWidget { this.outerColor = Colors.blue, //this.animationDuration = const Duration(seconds: 1), this.animationDuration = const Duration(milliseconds: 500), + this.onTap, }); @override @@ -296,12 +432,14 @@ class _RadarMarkerState extends State @override Widget build(BuildContext context) { - return AnimatedBuilder( - animation: _controller, - builder: (context, child) { - return Stack( - alignment: Alignment.center, - children: [ + return GestureDetector( + onTap: widget.onTap, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Stack( + alignment: Alignment.center, + children: [ // 第一层外圈雷达波纹 Transform.scale( scale: _scaleAnimation.value, @@ -365,6 +503,7 @@ class _RadarMarkerState extends State ], ); }, + ), ); } }