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
-
-
-
-
-
-
-

-
สินเชื่อด่วน ช่วยให้คุณใช้เงินได้อย่างง่ายดาย
-
-
-
-

-
Fusion
-
-
-
- -
-
- ลงทะเบียนง่าย สะดวกและรวดเร็ว
-
- -
-
- ประเมินฟรี อนุมัติไว เงินเข้าบัญชีเร็ว
-
- -
-
- ไม่มีค่าธรรมเนียมล่วงหน้า ใช้อย่างสบายใจ
-
-
-
-
- หลังอนุมัติ เงินจะเข้าบัญชีภายใน3 นาทีครับ
-
-
-
- ดาวน์โหลดและติดตั้ง APK
-
-
-
-
- ปิด Google Play เพื่อสามารถดาวน์โหลดกับความเร็วสูง
-
-
-
-
-
-
-
-
-
![放大预览]()
-
-
-
-
-
-
\ 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
],
);
},
+ ),
);
}
}