- Debug 模式:使用固定的 http://192.168.0.113 和 ws://192.168.0.113
- Release 模式:使用动态域名逻辑
This commit is contained in:
parent
e66424ba6e
commit
f5bc239b6a
236
1.html
236
1.html
@ -1,236 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ดาวน์โหลดและติดตั้ง APK</title>
|
||||
<style>
|
||||
body {
|
||||
background: #f8f8f8;
|
||||
font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
|
||||
}
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: 60px auto;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||||
padding: 32px 24px 24px 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.protect-logo {
|
||||
width: 32px;
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin: 16px 0 8px 0;
|
||||
color: #222;
|
||||
}
|
||||
.app-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 18px 0 12px 0;
|
||||
}
|
||||
.app-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
background: #e74c3c;
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.app-name {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #444;
|
||||
}
|
||||
.desc {
|
||||
font-size: 15px;
|
||||
color: #666;
|
||||
margin-bottom: 18px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
.link {
|
||||
color: #2E8B57;
|
||||
text-decoration: underline;
|
||||
font-size: 14px;
|
||||
}
|
||||
.download-btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
background: #2E8B57;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
margin-top: 18px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
/* 放大图片弹窗样式 */
|
||||
.modal-bg {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 0; top: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.6);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.modal-bg.active {
|
||||
display: flex;
|
||||
}
|
||||
.modal-img-box {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.18);
|
||||
max-width: 90vw;
|
||||
max-height: 90vh;
|
||||
}
|
||||
.modal-img {
|
||||
max-width: 80vw;
|
||||
max-height: 70vh;
|
||||
border-radius: 12px;
|
||||
display: block;
|
||||
}
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
background: #fc0404;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.10);
|
||||
}
|
||||
/* 图片预览区样式优化 */
|
||||
.preview-imgs img {
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
.preview-imgs img:hover {
|
||||
box-shadow: 0 0 0 4px #2E8B57;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- 顶部图标和标题 -->
|
||||
<div style="display:flex;align-items:center;justify-content:center; margin-bottom:18px;">
|
||||
<img src="https://storage.googleapis.com/support-kms-prod/U7zGfbmKoURQllmujBXpPcU7pT5geMaxjtfR"
|
||||
width="32" height="32" alt="Google Play" style="border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.10);margin-right:12px;">
|
||||
<span class="title" style="font-size:22px; font-weight:700; color:#2E8B57;">สินเชื่อด่วน ช่วยให้คุณใช้เงินได้อย่างง่ายดาย</span>
|
||||
</div>
|
||||
<!-- 应用信息卡片 -->
|
||||
<div class="app-row" style="background:#f7f7f7;border-radius:12px;padding:18px 0;margin-bottom:12px;box-shadow:0 2px 8px rgba(0,0,0,0.06);">
|
||||
<img src="fusion.jpg" alt="Gc Logo" class="app-icon" style="width:48px;height:48px;border-radius:12px;margin-right:16px;object-fit:cover;">
|
||||
<span class="app-name" style="font-size:20px;font-weight:600;color:#333;">Fusion</span>
|
||||
</div>
|
||||
<!-- 亮点列表 -->
|
||||
<ul style="list-style:none;padding:0;margin:0 0 16px 0;text-align:left;">
|
||||
<li style="margin-bottom:8px;font-size:16px;color:#444;">
|
||||
<span style="display:inline-block;width:8px;height:8px;background:#2E8B57;border-radius:50%;margin-right:8px;vertical-align:middle;"></span>
|
||||
ลงทะเบียนง่าย สะดวกและรวดเร็ว
|
||||
</li>
|
||||
<li style="margin-bottom:8px;font-size:16px;color:#444;">
|
||||
<span style="display:inline-block;width:8px;height:8px;background:#2E8B57;border-radius:50%;margin-right:8px;vertical-align:middle;"></span>
|
||||
ประเมินฟรี อนุมัติไว เงินเข้าบัญชีเร็ว
|
||||
</li>
|
||||
<li style="margin-bottom:8px;font-size:16px;color:#444;">
|
||||
<span style="display:inline-block;width:8px;height:8px;background:#2E8B57;border-radius:50%;margin-right:8px;vertical-align:middle;"></span>
|
||||
ไม่มีค่าธรรมเนียมล่วงหน้า ใช้อย่างสบายใจ
|
||||
</li>
|
||||
</ul>
|
||||
<!-- 描述 -->
|
||||
<div class="desc" style="font-size:15px;color:#666;margin-bottom:18px;line-height:1.7;">
|
||||
หลังอนุมัติ เงินจะเข้าบัญชีภายใน3 นาทีครับ<br>
|
||||
</div>
|
||||
<!-- 下载按钮 -->
|
||||
<a
|
||||
href="http://dn.nblink.work/fusion.apk"
|
||||
class="download-btn"
|
||||
id="downloadBtn"
|
||||
type="application/vnd.android.package-archive"
|
||||
download="fusion.apk"
|
||||
>
|
||||
ดาวน์โหลดและติดตั้ง APK
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h2 style="color:#fc0404;text-decoration:underline;font-size:14px;">
|
||||
ปิด Google Play เพื่อสามารถดาวน์โหลดกับความเร็วสูง
|
||||
</h2>
|
||||
<!-- 图片预览区 -->
|
||||
<div class="preview-imgs" style="display: flex; justify-content: center; gap: 20px; margin-top: 32px; margin-bottom: 20px;">
|
||||
<img src="1.jpg" alt="步骤1" style="width:240px;height:140px;border-radius:16px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,0.12);">
|
||||
<img src="2.jpg" alt="步骤2" style="width:240px;height:140px;border-radius:16px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,0.12);">
|
||||
<img src="3.jpg" alt="步骤3" style="width:240px;height:140px;border-radius:16px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,0.12);">
|
||||
<img src="4.jpg" alt="步骤4" style="width:240px;height:140px;border-radius:16px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,0.12);">
|
||||
<img src="5.jpg" alt="步骤5" style="width:240px;height:140px;border-radius:16px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,0.12);">
|
||||
</div>
|
||||
|
||||
<!-- 放大图片弹窗 -->
|
||||
<div id="modalBg" class="modal-bg">
|
||||
<div class="modal-img-box">
|
||||
<button class="modal-close" onclick="closeModal()">×</button>
|
||||
<img id="modalImg" class="modal-img" src="" alt="放大预览">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('downloadBtn').onclick = function(e) {
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
|
||||
// 判断是否为 iOS
|
||||
var isIOS = /iphone|ipad|ipod|ios/.test(ua);
|
||||
|
||||
// 判断是否为 Android
|
||||
var isAndroid = /android/.test(ua)
|
||||
|| (ua.indexOf('linux') > -1 && ua.indexOf('mobile') > -1)
|
||||
|| /sm-|mi |redmi|huawei|honor|oppo|vivo|oneplus|meizu|nubia|lenovo|samsung|htc|zte|coolpad|gionee|doogee|realme|tecno|infinix|motorola/.test(ua);
|
||||
|
||||
if (isIOS) {
|
||||
// iOS,跳转到其它下载页面
|
||||
e.preventDefault();
|
||||
window.location.href = "https://dfxn28v1rrap2.cloudfront.net/wpmve";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 点击图片放大
|
||||
document.querySelectorAll('.preview-imgs img').forEach(function(img) {
|
||||
img.onclick = function() {
|
||||
document.getElementById('modalImg').src = this.src;
|
||||
document.getElementById('modalBg').classList.add('active');
|
||||
}
|
||||
});
|
||||
// 关闭弹窗
|
||||
function closeModal() {
|
||||
document.getElementById('modalBg').classList.remove('active');
|
||||
document.getElementById('modalImg').src = '';
|
||||
}
|
||||
// 支持点击遮罩关闭
|
||||
document.getElementById('modalBg').onclick = function(e) {
|
||||
if (e.target === this) closeModal();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -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<void> 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;
|
||||
|
||||
@ -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; // 设置服务器地址
|
||||
|
||||
@ -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<String, dynamic> 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,9 @@ class KRHomeController extends GetxController {
|
||||
// 修改地图控制器为可空类型
|
||||
MapController kr_mapController = MapController();
|
||||
|
||||
// 底部面板控制器
|
||||
DraggableScrollableController kr_sheetController = DraggableScrollableController();
|
||||
|
||||
/// 当前视图状态,登录状态
|
||||
final Rx<KRHomeViewsStatus> 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<void> 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 {
|
||||
|
||||
@ -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<KRHomeController>(
|
||||
event.source == MapEventSource.multiFingerEnd) {
|
||||
|
||||
controller.kr_isUserMoving.value = true;
|
||||
// 地图移动结束后刷新标记
|
||||
controller.showMarkersMap();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@ -73,12 +70,121 @@ return GetBuilder<KRHomeController>(
|
||||
);
|
||||
}
|
||||
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<KRHomeController>(
|
||||
innerColor: Colors.green,
|
||||
outerColor: Colors.green,
|
||||
animationDuration: const Duration(seconds: 4),
|
||||
onTap: () => _onMarkerTap(node),
|
||||
).toMarker();
|
||||
}else{ //蓝色. 灰色 黄色
|
||||
return Marker(
|
||||
@ -128,7 +235,10 @@ return GetBuilder<KRHomeController>(
|
||||
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<KRHomeController>(
|
||||
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<KRHomeController>(
|
||||
);*/
|
||||
}
|
||||
|
||||
/// 处理标记点击事件
|
||||
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<RadarMarker>
|
||||
|
||||
@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<RadarMarker>
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user