QinGang_interested/lib/pages/WebViewInteractionPage.dart

167 lines
5.0 KiB
Dart

import 'dart:convert';
import 'dart:typed_data';
import 'package:dart_sm/dart_sm.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewMediaBridgePage extends StatefulWidget {
const WebViewMediaBridgePage({super.key, required this.userId});
final String userId;
@override
State<WebViewMediaBridgePage> createState() => _WebViewMediaBridgePageState();
}
class _WebViewMediaBridgePageState extends State<WebViewMediaBridgePage> {
static const _jsChannelName = 'WebViewBridge';
static const _publicKey =
'049818e94f1abefab63d7193dd71b16241b5e721ab936eb1d4abb84f5024cb5d5b503a1776163cce4dd0f0ffdc612329f3497da3ac9b643306d5bfbe844459d186';
static const _baseUrl =
'http://121.22.11.43:8091/emisApp/#/pages/index?user=';
final ImagePicker _imagePicker = ImagePicker();
late final WebViewController _controller;
@override
void initState() {
super.initState();
final encryptedUser = SM2.encrypt(widget.userId, _publicKey);
final targetUrl = '$_baseUrl$encryptedUser';
_controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.white)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (_) => _injectBridge(),
onWebResourceError: (error) {
debugPrint('设备管理 WebView 加载错误: ${error.description}');
},
),
)
..addJavaScriptChannel(
_jsChannelName,
onMessageReceived: (message) => _handleWebMessage(message.message),
)
..loadRequest(Uri.parse(targetUrl));
}
Future<void> _injectBridge() {
return _controller.runJavaScript('''
window.flutterSendToDart = function(message) {
if (window.$_jsChannelName && window.$_jsChannelName.postMessage) {
window.$_jsChannelName.postMessage(String(message));
}
};
''');
}
Future<void> _handleWebMessage(String raw) async {
Map<String, dynamic> data;
try {
data = jsonDecode(raw) as Map<String, dynamic>;
} catch (_) {
data = {'action': raw};
}
final action = data['action']?.toString();
final callbackId = data['callbackId']?.toString();
switch (action) {
case 'camera':
await _pickImageAndCallback(ImageSource.camera, callbackId);
return;
case 'gallery':
await _pickImageAndCallback(ImageSource.gallery, callbackId);
return;
case 'back':
if (mounted) Navigator.of(context).pop();
return;
case 'ping':
await _replyToWeb(callbackId, {
'ok': true,
'message': 'pong from flutter',
'time': DateTime.now().toIso8601String(),
});
return;
default:
debugPrint('设备管理 WebView 未知 action: $action');
}
}
Future<void> _pickImageAndCallback(
ImageSource source,
String? callbackId,
) async {
try {
final file = await _imagePicker.pickImage(
source: source,
imageQuality: 85,
);
if (file == null) {
await _replyToWeb(callbackId, {
'ok': false,
'cancelled': true,
'message': '用户取消选择',
});
return;
}
final Uint8List bytes = await file.readAsBytes();
final base64Data = base64Encode(bytes);
final mimeType = _guessMimeType(file.path);
await _replyToWeb(callbackId, {
'ok': true,
'name': file.name,
'path': file.path,
'mimeType': mimeType,
'base64': base64Data,
'dataUrl': 'data:$mimeType;base64,$base64Data',
});
} catch (error) {
debugPrint('设备管理图片选择失败: $error');
await _replyToWeb(callbackId, {'ok': false, 'message': error.toString()});
}
}
String _guessMimeType(String path) {
final lower = path.toLowerCase();
if (lower.endsWith('.png')) return 'image/png';
if (lower.endsWith('.webp')) return 'image/webp';
if (lower.endsWith('.gif')) return 'image/gif';
if (lower.endsWith('.heic')) return 'image/heic';
return 'image/jpeg';
}
Future<void> _replyToWeb(String? callbackId, Map<String, dynamic> payload) {
final jsonText = jsonEncode(payload);
if (callbackId == null || callbackId.isEmpty) {
return _controller.runJavaScript('''
if (window.onFlutterResult) window.onFlutterResult($jsonText);
''');
}
return _controller.runJavaScript('''
if (window.WebViewCallbacks && window.WebViewCallbacks['$callbackId']) {
window.WebViewCallbacks['$callbackId']($jsonText);
delete window.WebViewCallbacks['$callbackId'];
} else if (window.onFlutterResult) {
window.onFlutterResult($jsonText);
}
''');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: false,
bottom: false,
child: WebViewWidget(controller: _controller),
),
);
}
}