flutter_integrated_whb/lib/customWidget/BaiDuMap/Map_page.dart

206 lines
6.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/BaiDuMap/BaiduMapWebView.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/services/location_service.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:geolocator/geolocator.dart';
class MapPage extends StatefulWidget {
final String gson;
const MapPage({super.key, required this.gson});
@override
State<MapPage> createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
late final WebViewController _controller;
bool _isLoading = true;
String? _errorMessage;
double? _longitude;
double? _latitude;
List<dynamic> _gsonList = [];
late Map<String, dynamic> mapData = {};
@override
void initState() {
super.initState();
_initLocation();
}
/// 获取定位(并初始化 WebView 控制器)
Future<void> _initLocation() async {
setState(() {
_isLoading = true;
_errorMessage = null;
});
LoadingDialogHelper.show(message: '地图加载中');
try {
final LocationResult loc = await LocationService.getCurrentLocation(
timeout: const Duration(seconds: 10),
);
// 解析 gson
try {
final parsed = jsonDecode(widget.gson);
if (parsed is List) {
_gsonList = parsed;
} else {
_gsonList = [];
}
} catch (e) {
debugPrint('解析 gson 失败: $e');
_gsonList = [];
}
if (!mounted) return;
setState(() {
_longitude = loc.longitudeAsDouble;
_latitude = loc.latitudeAsDouble;
});
// 初始化 WebViewController 并加载本地页面
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
// 注册 JS 通道 'JS' —— 对应 HTML 中的 window.JS.postMessage(...)
..addJavaScriptChannel('JS', onMessageReceived: (dynamic message) {
// message 是动态对象,不在签名中引用具体类型以避免 "Undefined class" 问题
String payload;
try {
payload = message.message ?? message.toString();
} catch (e) {
payload = message.toString();
}
_onJsMessage(payload);
})
// 也保留一个备用通道 'Flutter'
..addJavaScriptChannel('Flutter', onMessageReceived: (dynamic message) {
String payload;
try {
payload = message.message ?? message.toString();
} catch (e) {
payload = message.toString();
}
_onJsMessage(payload);
})
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String url) async {
LoadingDialogHelper.hide();
debugPrint('网页加载完成: $url');
await _injectLocationParams();
},
onWebResourceError: (err) {
debugPrint('Web resource error: ${err.description}');
},
),
);
// 加载本地 assets 中的 HTML
// await _controller.loadFlutterAsset('assets/map/test_baidu_map.html');
await _controller.loadRequest(Uri.parse('http://47.92.102.56:7811/file/fluteightmap/index.html'));
setState(() {
_isLoading = false;
});
} catch (e, st) {
debugPrint('获取位置或初始化失败: $e\n$st');
if (!mounted) return;
setState(() {
_errorMessage = '获取位置失败: ${e.toString()}';
_isLoading = false;
});
}
}
/// 注入参数并调用页面初始化函数 window.initWithData(...)
Future<void> _injectLocationParams() async {
if (_longitude == null || _latitude == null) {
debugPrint('位置尚未准备好,跳过注入');
return;
}
final params = {
'longitude': _longitude,
'latitude': _latitude,
'GSON': _gsonList,
't': DateTime.now().millisecondsSinceEpoch,
};
final jsonParams = jsonEncode(params);
try {
await _controller.runJavaScript('''
(function(){
try {
if (typeof window.initWithData === 'function') {
window.initWithData($jsonParams);
} else if (typeof window.initMap === 'function') {
window.initMap($jsonParams);
} else {
console.error('initWithData / initMap function not found');
}
} catch(e) {
console.error('call initWithData error', e);
}
})();
''');
debugPrint('已注入地图初始化参数');
} catch (e) {
debugPrint('注入位置参数失败: $e');
}
}
/// 处理来自 Web 的消息(字符串或 JSON
void _onJsMessage(String message) {
debugPrint('收到来自 Web 的消息: $message');
if (message.isEmpty) return;
try {
Map<String,dynamic> data = jsonDecode(message);
if (FormUtils.hasValue(data, 'ok') && data['ok'] == true) {
}else{
if (FormUtils.hasValue(data, 'type') && data['type'] == 'converted') {
setState(() {
mapData = data;
});
}else{
ToastUtil.showNormal(context, '当前选择点位不在区域中');
setState(() {
mapData = {};
});
}
}
} catch (_) {
setState(() {
mapData = {};
});
ToastUtil.showNormal(context, '当前选择点位不在区域中');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: '地图选择', actions: [
if (mapData.isNotEmpty)
TextButton(onPressed: (){
Navigator.of(context).pop((mapData));
}, child: Text('确定', style: TextStyle(color: Colors.white, fontSize: 17),))
],),
body: SafeArea(
child: BaiduMapWebView(
controller: _isLoading || _errorMessage != null ? null : _controller,
isLoading: _isLoading,
errorMessage: _errorMessage,
onRetry: _initLocation,
),),
);
}
}