补充地图的演示功能
This commit is contained in:
@@ -10,4 +10,10 @@ Ln123456.
|
|||||||
|
|
||||||
高德key
|
高德key
|
||||||
安卓 92495660f7bc990cb475426c47c03b65
|
安卓 92495660f7bc990cb475426c47c03b65
|
||||||
苹果:3ac08e5e14df9d7a52e98d40e21a0189
|
苹果:3ac08e5e14df9d7a52e98d40e21a0189
|
||||||
|
|
||||||
|
key:2cc1d822e313307fe311c3127a1deeb5
|
||||||
|
秘钥:0529b72df6bf0c577ff2182cb8b1d970
|
||||||
|
|
||||||
|
安卓包名:com.lingniu.driver
|
||||||
|
iOS包名:com.lnkj.ln_jq_app
|
||||||
|
|||||||
@@ -11,6 +11,10 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
|
<!--定位权限-->
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="小羚羚"
|
android:label="小羚羚"
|
||||||
@@ -43,6 +47,8 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
|
|||||||
224
ln_jq_app/assets/html/map.html
Normal file
224
ln_jq_app/assets/html/map.html
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||||
|
<title>导航规划</title>
|
||||||
|
<style>
|
||||||
|
html, body, #container { width: 100%; height: 100%; margin: 0; }
|
||||||
|
|
||||||
|
/* 搜索栏样式 */
|
||||||
|
#search-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 100;
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.input-row { display: flex; gap: 5px; }
|
||||||
|
input { flex: 1; padding: 8px; border: 1px solid #eee; border-radius: 4px; }
|
||||||
|
button { padding: 0 15px; background: #3366FF; color: #fff; border: none; border-radius: 4px; font-weight: bold; }
|
||||||
|
|
||||||
|
/* 导航结果面板 (仿高德原生) */
|
||||||
|
#panel {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 30%; /* 占据底部30% */
|
||||||
|
background-color: white;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
z-index: 99;
|
||||||
|
display: none; /* 默认隐藏,规划成功后显示 */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- 1. 必须最先配置安全密钥 -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
window._AMapSecurityConfig = {
|
||||||
|
securityJsCode: '0529b72df6bf0c577ff2182cb8b1d970',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- 2. 加载地图和插件 -->
|
||||||
|
<!-- 注意:如果你要货车规划,需要在plugin里加上 AMap.TruckDriving -->
|
||||||
|
<script src="https://webapi.amap.com/maps?v=2.0&key=2cc1d822e313307fe311c3127a1deeb5&plugin=AMap.MoveAnimation,AMap.Driving,AMap.TruckDriving,AMap.AutoComplete"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="search-box">
|
||||||
|
<div class="input-row">
|
||||||
|
<input id="startInput" placeholder="起点: 默认使用当前位置" />
|
||||||
|
</div>
|
||||||
|
<div class="input-row">
|
||||||
|
<input id="endInput" placeholder="终点: 请输入目的地" />
|
||||||
|
<button onclick="startRouteSearch()">路径规划</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="container"></div>
|
||||||
|
<div id="panel"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var map, marker, driving, truckDriving;
|
||||||
|
var currentLat, currentLng;
|
||||||
|
|
||||||
|
// 标记是否使用货车模式 (true: 货车, false: 轿车)
|
||||||
|
var isTruckMode = false;
|
||||||
|
|
||||||
|
function initMap() {
|
||||||
|
map = new AMap.Map('container', {
|
||||||
|
resizeEnable: true,
|
||||||
|
zoom: 15,
|
||||||
|
viewMode: '3D'
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- 初始化轿车规划 ---
|
||||||
|
driving = new AMap.Driving({
|
||||||
|
map: map,
|
||||||
|
panel: "panel", // 结果显示在 panel div 中
|
||||||
|
policy: AMap.DrivingPolicy.LEAST_TIME
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- 初始化货车规划 (按需开启) ---
|
||||||
|
// 货车需要设置 size (1:微型, 2:轻型, 3:中型, 4:重型)
|
||||||
|
if(AMap.TruckDriving) {
|
||||||
|
truckDriving = new AMap.TruckDriving({
|
||||||
|
map: map,
|
||||||
|
panel: "panel",
|
||||||
|
size: 2,
|
||||||
|
policy: 0, // 0: 躲避拥堵
|
||||||
|
width: 2.5,
|
||||||
|
height: 2,
|
||||||
|
load: 1,
|
||||||
|
weight: 10,
|
||||||
|
axlesNum: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 输入提示 (自动补全) ---
|
||||||
|
new AMap.AutoComplete({ input: "startInput" });
|
||||||
|
new AMap.AutoComplete({ input: "endInput" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 被动接收 Flutter 传来的定位 ---
|
||||||
|
function updateMyLocation(lat, lng, angle) {
|
||||||
|
currentLat = lat;
|
||||||
|
currentLng = lng;
|
||||||
|
var position = [lng, lat];
|
||||||
|
|
||||||
|
if (!marker) {
|
||||||
|
marker = new AMap.Marker({
|
||||||
|
map: map,
|
||||||
|
position: position,
|
||||||
|
icon: "https://webapi.amap.com/images/car.png",
|
||||||
|
offset: new AMap.Pixel(-26, -13),
|
||||||
|
autoRotation: true,
|
||||||
|
angle: angle || 0,
|
||||||
|
});
|
||||||
|
// 第一次定位移动中心
|
||||||
|
map.setCenter(position);
|
||||||
|
} else {
|
||||||
|
marker.setPosition(position);
|
||||||
|
if (angle) marker.setAngle(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 核心:规划路线 ---
|
||||||
|
function startRouteSearch() {
|
||||||
|
var startKw = document.getElementById('startInput').value;
|
||||||
|
var endKw = document.getElementById('endInput').value;
|
||||||
|
|
||||||
|
if(!endKw) {
|
||||||
|
console.log("FlutterLog: 终点不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("FlutterLog: 开始规划..." + (isTruckMode ? "货车" : "轿车"));
|
||||||
|
|
||||||
|
// 清除之前的路线
|
||||||
|
if(driving) driving.clear();
|
||||||
|
if(truckDriving) truckDriving.clear();
|
||||||
|
|
||||||
|
// 构造起点和终点参数
|
||||||
|
// 高德API Search方法支持点对象数组:[{keyword: '名字', city: '城市'}, {keyword: '...'}]
|
||||||
|
var points = [];
|
||||||
|
|
||||||
|
// 1. 处理起点
|
||||||
|
if (startKw) {
|
||||||
|
// 如果用户输入了文字
|
||||||
|
points.push({ keyword: startKw });
|
||||||
|
} else {
|
||||||
|
// 如果用户没输入,使用当前定位
|
||||||
|
if (currentLng && currentLat) {
|
||||||
|
// 关键点:当混合使用坐标和关键字时,必须构建 LngLat 对象
|
||||||
|
points.push({
|
||||||
|
keyword: '我的位置',
|
||||||
|
location: new AMap.LngLat(currentLng, currentLat)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("FlutterLog: 无定位数据且无输入");
|
||||||
|
alert("未获取到定位,请输入起点");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 处理终点
|
||||||
|
points.push({ keyword: endKw });
|
||||||
|
|
||||||
|
// 显示底部面板
|
||||||
|
document.getElementById('panel').style.display = 'block';
|
||||||
|
|
||||||
|
// 3. 发起请求
|
||||||
|
if (isTruckMode && truckDriving) {
|
||||||
|
// 货车接口略有不同,需要传入 path 数组
|
||||||
|
// truckDriving.search(path, callback)
|
||||||
|
// 这里为了简化,我们先演示轿车。货车通常需要具体的经纬度,建议先通过 Geocoder 把 endKw 转成经纬度再传给货车接口
|
||||||
|
console.log("FlutterLog: 货车API需要更严格的经纬度参数,建议先使用轿车演示");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认使用轿车规划 (支持 keyword + location 混合)
|
||||||
|
driving.search(points, function(status, result) {
|
||||||
|
if (status === 'complete') {
|
||||||
|
console.log('FlutterLog: 规划成功');
|
||||||
|
} else {
|
||||||
|
console.log('FlutterLog: 规划失败: ' + result);
|
||||||
|
// 常见错误: "USER_DAILY_QUERY_OVER_LIMIT" (Key额度超限)
|
||||||
|
// "INVALID_USER_KEY" (Key错误)
|
||||||
|
// "no_data" (地点没找到)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 绘制自定义路径 (保持原有功能) ---
|
||||||
|
function drawCustomRoute(pointsJsonString) {
|
||||||
|
// 如果是从Flutter传来的JSON字符串,需要Parse,如果是对象则直接用
|
||||||
|
var path = typeof pointsJsonString === 'string' ? JSON.parse(pointsJsonString) : pointsJsonString;
|
||||||
|
|
||||||
|
if (driving) driving.clear();
|
||||||
|
|
||||||
|
var polyline = new AMap.Polyline({
|
||||||
|
path: path,
|
||||||
|
isOutline: true,
|
||||||
|
outlineColor: '#ffeeee',
|
||||||
|
borderWeight: 3,
|
||||||
|
strokeColor: "#3366FF",
|
||||||
|
strokeWeight: 6,
|
||||||
|
lineJoin: 'round'
|
||||||
|
});
|
||||||
|
map.add(polyline);
|
||||||
|
map.setFitView([polyline]);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = initMap;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -38,6 +38,33 @@ end
|
|||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
|
# Flutter 默认配置
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# 1. Geolocator 配置 (你原来的代码)
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
if target.name == "geolocator_apple"
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'BYPASS_PERMISSION_LOCATION_ALWAYS=1']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# 2. PermissionHandler 配置 (这是缺少的关键部分!!!)
|
||||||
|
# 必须显式开启 'PERMISSION_LOCATION=1'
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
# 确保 GCC_PREPROCESSOR_DEFINITIONS 存在
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
|
||||||
|
|
||||||
|
# 开启定位权限支持
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_LOCATION=1'
|
||||||
|
|
||||||
|
# 如果你需要其他权限,也在这里加,比如相机:
|
||||||
|
# config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CAMERA=1'
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,24 @@ PODS:
|
|||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_inappwebview_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- flutter_inappwebview_ios/Core (= 0.0.1)
|
||||||
|
- OrderedSet (~> 6.0.3)
|
||||||
|
- flutter_inappwebview_ios/Core (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- OrderedSet (~> 6.0.3)
|
||||||
- flutter_native_splash (2.4.3):
|
- flutter_native_splash (2.4.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_pdfview (1.0.2):
|
- flutter_pdfview (1.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- geolocator_apple (1.2.0):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- image_picker_ios (0.0.1):
|
- image_picker_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- MTBBarcodeScanner (5.0.11)
|
- MTBBarcodeScanner (5.0.11)
|
||||||
|
- OrderedSet (6.0.3)
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider_foundation (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
@@ -31,8 +42,10 @@ DEPENDENCIES:
|
|||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_pdfview (from `.symlinks/plugins/flutter_pdfview/ios`)
|
- flutter_pdfview (from `.symlinks/plugins/flutter_pdfview/ios`)
|
||||||
|
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
@@ -44,6 +57,7 @@ DEPENDENCIES:
|
|||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- MTBBarcodeScanner
|
- MTBBarcodeScanner
|
||||||
|
- OrderedSet
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
@@ -52,10 +66,14 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_inappwebview_ios:
|
||||||
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_pdfview:
|
flutter_pdfview:
|
||||||
:path: ".symlinks/plugins/flutter_pdfview/ios"
|
:path: ".symlinks/plugins/flutter_pdfview/ios"
|
||||||
|
geolocator_apple:
|
||||||
|
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
||||||
image_picker_ios:
|
image_picker_ios:
|
||||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
@@ -75,10 +93,13 @@ SPEC CHECKSUMS:
|
|||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_pdfview: 54e283d5851b0b247b3cc57877d35f1a05a204de
|
flutter_pdfview: 54e283d5851b0b247b3cc57877d35f1a05a204de
|
||||||
|
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
||||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||||
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||||
@@ -86,6 +107,6 @@ SPEC CHECKSUMS:
|
|||||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
PODFILE CHECKSUM: c2b648820a58f7013d9d17db812a119f8affaf6f
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key></key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string>需要您的位置信息以在地图上展示</string>
|
||||||
|
<!-- 建议添加:即使你只申请WhenInUse,有些插件逻辑可能会检查这个key -->
|
||||||
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
|
<string>我们需要您的位置来规划路线</string>
|
||||||
|
<!-- 建议添加:旧版本iOS兼容 -->
|
||||||
|
<key>NSLocationAlwaysUsageDescription</key>
|
||||||
|
<string>我们需要您的位置来规划路线</string>
|
||||||
|
|
||||||
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
|
|||||||
@@ -59,7 +59,13 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
} else {
|
} else {
|
||||||
costPrice = "暂无价格";
|
costPrice = "暂无价格";
|
||||||
}
|
}
|
||||||
customerPrice = result.data["customerPrice"] ?? "暂无价格";
|
var customerPriceTemp = result.data["customerPrice"];
|
||||||
|
if (customerPriceTemp != null && customerPriceTemp.toString().isNotEmpty) {
|
||||||
|
customerPrice = "$customerPriceTemp";
|
||||||
|
} else {
|
||||||
|
customerPrice = "暂无价格";
|
||||||
|
}
|
||||||
|
|
||||||
phone = result.data["phone"];
|
phone = result.data["phone"];
|
||||||
startBusiness = result.data["startBusiness"];
|
startBusiness = result.data["startBusiness"];
|
||||||
endBusiness = result.data["endBusiness"];
|
endBusiness = result.data["endBusiness"];
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class BaseWidgetsPage extends GetView<BaseWidgetsController> {
|
|||||||
Widget _buildView() {
|
Widget _buildView() {
|
||||||
return PageView(
|
return PageView(
|
||||||
controller: _pageController,
|
controller: _pageController,
|
||||||
|
physics: const NeverScrollableScrollPhysics(), // 禁止滑动
|
||||||
onPageChanged: (index) {
|
onPageChanged: (index) {
|
||||||
jumpTabAndPage(index);
|
jumpTabAndPage(index);
|
||||||
},
|
},
|
||||||
@@ -31,7 +32,7 @@ class BaseWidgetsPage extends GetView<BaseWidgetsController> {
|
|||||||
// 对应的页面
|
// 对应的页面
|
||||||
List<Widget> _buildPages() {
|
List<Widget> _buildPages() {
|
||||||
return [
|
return [
|
||||||
// MapPage(),
|
MapPage(),
|
||||||
ReservationPage(),
|
ReservationPage(),
|
||||||
CarInfoPage(),
|
CarInfoPage(),
|
||||||
MinePage(),
|
MinePage(),
|
||||||
@@ -46,12 +47,12 @@ class BaseWidgetsPage extends GetView<BaseWidgetsController> {
|
|||||||
jumpTabAndPage(index);
|
jumpTabAndPage(index);
|
||||||
}, // 切换tab事件
|
}, // 切换tab事件
|
||||||
items: [
|
items: [
|
||||||
/*NavigationItemModel(
|
NavigationItemModel(
|
||||||
label: '地图',
|
label: '地图',
|
||||||
icon: AntdIcon.location,
|
icon: AntdIcon.location,
|
||||||
selectedIcon: AntdIcon.location_fill,
|
selectedIcon: AntdIcon.location_fill,
|
||||||
dot: false,
|
dot: false,
|
||||||
),*/
|
),
|
||||||
NavigationItemModel(
|
NavigationItemModel(
|
||||||
label: '加氢预约',
|
label: '加氢预约',
|
||||||
icon: AntdIcon.orderedlist,
|
icon: AntdIcon.orderedlist,
|
||||||
|
|||||||
@@ -1,18 +1,127 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart'; // 确保引用这个做权限请求
|
||||||
|
|
||||||
class MapController extends GetxController with BaseControllerMixin {
|
class MapController extends GetxController with BaseControllerMixin {
|
||||||
@override
|
@override
|
||||||
String get builderId => 'map';
|
String get builderId => 'map';
|
||||||
|
|
||||||
MapController();
|
InAppWebViewController? webViewController;
|
||||||
|
StreamSubscription<Position>? positionStream;
|
||||||
|
final RxBool isLocationPermissionGranted = false.obs;
|
||||||
|
|
||||||
|
// 缓存最后一次的位置,防止 WebView 加载慢于定位
|
||||||
|
Position? _lastKnownPosition;
|
||||||
|
// 是否已经初始化过地图中心
|
||||||
|
bool _hasInitializedMapCenter = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
requestLocationPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
|
positionStream?.cancel();
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 请求权限
|
||||||
|
void requestLocationPermission() async {
|
||||||
|
var status = await Permission.locationWhenInUse.request();
|
||||||
|
|
||||||
|
print("权限状态: $status"); // 在控制台看这个输出
|
||||||
|
|
||||||
|
if (status.isGranted) {
|
||||||
|
isLocationPermissionGranted.value = true;
|
||||||
|
showToast('定位权限已获取');
|
||||||
|
_startLocationTracking();
|
||||||
|
}
|
||||||
|
else if (status.isPermanentlyDenied) {
|
||||||
|
// iOS 特性:如果你之前点过“不允许”,之后再请求都会直接进这里
|
||||||
|
isLocationPermissionGranted.value = false;
|
||||||
|
// 引导用户去设置页面开启
|
||||||
|
openAppSettings();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 第一次被拒绝,或者其他情况
|
||||||
|
isLocationPermissionGranted.value = false;
|
||||||
|
showErrorToast('需要定位权限才能显示您的位置');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启定位监听
|
||||||
|
void _startLocationTracking() async {
|
||||||
|
// 再次检查服务是否开启
|
||||||
|
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||||
|
if (!serviceEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LocationSettings locationSettings = LocationSettings(
|
||||||
|
accuracy: LocationAccuracy.high,
|
||||||
|
distanceFilter: 50, // 移动更新范围
|
||||||
|
);
|
||||||
|
|
||||||
|
// 先获取一次当前位置,用于快速初始化中心
|
||||||
|
Geolocator.getCurrentPosition().then((position) {
|
||||||
|
_lastKnownPosition = position;
|
||||||
|
_syncLocationToMap(position, isInit: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 持续监听
|
||||||
|
positionStream = Geolocator.getPositionStream(locationSettings: locationSettings)
|
||||||
|
.listen((Position position) {
|
||||||
|
_lastKnownPosition = position;
|
||||||
|
_syncLocationToMap(position, isInit: false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将位置同步给 JS
|
||||||
|
void _syncLocationToMap(Position position, {required bool isInit}) {
|
||||||
|
if (webViewController == null) return;
|
||||||
|
|
||||||
|
// 如果是第一次定位,或者 WebView 刚加载完且从未设置过中心
|
||||||
|
if (isInit || !_hasInitializedMapCenter) {
|
||||||
|
webViewController!.evaluateJavascript(
|
||||||
|
source: "initLocation(${position.latitude}, ${position.longitude})"
|
||||||
|
);
|
||||||
|
_hasInitializedMapCenter = true;
|
||||||
|
} else {
|
||||||
|
// 后续只更新图标位置,不强行移动地图中心(防止用户拖动地图看别处时被拉回)
|
||||||
|
webViewController!.evaluateJavascript(
|
||||||
|
source: "updateMyLocation(${position.latitude}, ${position.longitude}, ${position.heading})"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebView 加载完成回调
|
||||||
|
void onWebViewLoadStop() {
|
||||||
|
// 页面加载完了,如果我们已经拿到了定位数据,立刻设置地图中心
|
||||||
|
if (_lastKnownPosition != null) {
|
||||||
|
_syncLocationToMap(_lastKnownPosition!, isInit: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果业务需要,可以在这里加载默认的推荐路径
|
||||||
|
// loadRecommendedRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟:获取你的后台推荐路径
|
||||||
|
void loadRecommendedRoute() {
|
||||||
|
// 示例数据
|
||||||
|
List<List<double>> routePoints = [
|
||||||
|
[116.397428, 39.90923],
|
||||||
|
[116.398000, 39.90950],
|
||||||
|
[116.400000, 39.91000],
|
||||||
|
];
|
||||||
|
|
||||||
|
String jsonPoints = jsonEncode(routePoints);
|
||||||
|
webViewController?.evaluateJavascript(source: "drawCustomRoute($jsonPoints)");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||||
|
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
@@ -6,11 +6,32 @@ import 'controller.dart';
|
|||||||
class MapPage extends GetView<MapController> {
|
class MapPage extends GetView<MapController> {
|
||||||
const MapPage({super.key});
|
const MapPage({super.key});
|
||||||
|
|
||||||
// 主视图
|
|
||||||
Widget _buildView() {
|
Widget _buildView() {
|
||||||
return <Widget>[
|
return Stack(
|
||||||
TextX.titleLarge('地图'),
|
children: [
|
||||||
].toColumn(mainAxisSize: MainAxisSize.min).center();
|
InAppWebView(
|
||||||
|
// 确保 pubspec.yaml 中声明了 assets/html/map.html
|
||||||
|
initialFile: 'assets/html/map.html',
|
||||||
|
initialSettings: InAppWebViewSettings(
|
||||||
|
isInspectable: true,
|
||||||
|
geolocationEnabled: true,
|
||||||
|
// 允许 JS 弹窗 (Alert) 用于调试
|
||||||
|
javaScriptCanOpenWindowsAutomatically: true,
|
||||||
|
),
|
||||||
|
onWebViewCreated: (c) {
|
||||||
|
controller.webViewController = c;
|
||||||
|
},
|
||||||
|
onLoadStop: (c, url) {
|
||||||
|
// 通知 Controller 页面加载完毕
|
||||||
|
controller.onWebViewLoadStop();
|
||||||
|
},
|
||||||
|
onConsoleMessage: (controller, consoleMessage) {
|
||||||
|
// 方便在 Flutter 控制台看 JS 日志
|
||||||
|
print("JS Log: ${consoleMessage.message}");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -289,6 +289,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.3+4"
|
version: "0.9.3+4"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -302,6 +310,70 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.5"
|
||||||
|
flutter_inappwebview:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview
|
||||||
|
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.5"
|
||||||
|
flutter_inappwebview_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_android
|
||||||
|
sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
|
flutter_inappwebview_internal_annotations:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_internal_annotations
|
||||||
|
sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
flutter_inappwebview_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_ios
|
||||||
|
sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
flutter_inappwebview_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_macos
|
||||||
|
sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
flutter_inappwebview_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_platform_interface
|
||||||
|
sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0+1"
|
||||||
|
flutter_inappwebview_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_web
|
||||||
|
sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
flutter_inappwebview_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_inappwebview_windows
|
||||||
|
sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.0"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -373,6 +445,70 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
geoclue:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geoclue
|
||||||
|
sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.1"
|
||||||
|
geolocator:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: geolocator
|
||||||
|
sha256: "79939537046c9025be47ec645f35c8090ecadb6fe98eba146a0d25e8c1357516"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "14.0.2"
|
||||||
|
geolocator_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_android
|
||||||
|
sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.2"
|
||||||
|
geolocator_apple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_apple
|
||||||
|
sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.13"
|
||||||
|
geolocator_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_linux
|
||||||
|
sha256: c4e966f0a7a87e70049eac7a2617f9e16fd4c585a26e4330bdfc3a71e6a721f3
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.3"
|
||||||
|
geolocator_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_platform_interface
|
||||||
|
sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.6"
|
||||||
|
geolocator_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_web
|
||||||
|
sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.3"
|
||||||
|
geolocator_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geolocator_windows
|
||||||
|
sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.5"
|
||||||
get:
|
get:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -397,6 +533,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.2"
|
version: "0.2.2"
|
||||||
|
gsettings:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: gsettings
|
||||||
|
sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.8"
|
||||||
html:
|
html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -994,6 +1138,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.4"
|
version: "3.1.4"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.2"
|
||||||
vector_graphics:
|
vector_graphics:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ dependencies:
|
|||||||
zxing_lib: ^1.1.4
|
zxing_lib: ^1.1.4
|
||||||
flutter_pdfview: 1.3.2 #显示pdf
|
flutter_pdfview: 1.3.2 #显示pdf
|
||||||
photo_view: ^0.15.0 #操作图片
|
photo_view: ^0.15.0 #操作图片
|
||||||
|
flutter_inappwebview: ^6.1.5 # WebView插件
|
||||||
|
geolocator: ^14.0.2 # 获取精确定位
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -67,4 +68,5 @@ flutter:
|
|||||||
|
|
||||||
assets:
|
assets:
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
- assets/html/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user