4 changed files with 170 additions and 142 deletions
@ -1,10 +1,12 @@ |
|||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||
import '../controllers/meeting_details_controller.dart'; |
import '../controllers/meeting_details_controller.dart'; |
||||
|
import '../controllers/mind_map_controller.dart'; |
||||
|
|
||||
class MeetingDetailsBinding extends Bindings { |
class MeetingDetailsBinding extends Bindings { |
||||
@override |
@override |
||||
void dependencies() { |
void dependencies() { |
||||
// 注册控制器 |
// 注册控制器 |
||||
Get.lazyPut<MeetingDetailsController>(() => MeetingDetailsController()); |
Get.lazyPut<MeetingDetailsController>(() => MeetingDetailsController()); |
||||
|
Get.lazyPut<MindMapController>(() => MindMapController()); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,155 @@ |
|||||
|
import 'dart:convert'; |
||||
|
import 'dart:io'; |
||||
|
import 'dart:typed_data'; |
||||
|
|
||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
import 'package:path_provider/path_provider.dart'; |
||||
|
import 'package:share_plus/share_plus.dart'; |
||||
|
import 'package:webview_flutter/webview_flutter.dart'; |
||||
|
|
||||
|
import 'meeting_details_controller.dart'; |
||||
|
|
||||
|
class MindMapController extends GetxController { |
||||
|
late final WebViewController webViewController; |
||||
|
final _meetingDetailsController = Get.find<MeetingDetailsController>(); |
||||
|
|
||||
|
@override |
||||
|
void onInit() { |
||||
|
super.onInit(); |
||||
|
String html = ''' |
||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<title>MindMap</title> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/markmap-lib"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/markmap-view"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/markmap-toolbar"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/save-svg-as-png@1.4.17/lib/saveSvgAsPng.min.js"></script> |
||||
|
<style> |
||||
|
html, |
||||
|
body { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.mind-map { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.mind-map #markmap { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.mind-map .mm-toolbar { |
||||
|
height: 30px; |
||||
|
background: #fff; |
||||
|
border: 1px solid #d0d5dd; |
||||
|
border-radius: 8px; |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
align-items: center; |
||||
|
position: absolute; |
||||
|
top: 20px; |
||||
|
right: 20px; |
||||
|
} |
||||
|
|
||||
|
.mind-map .mm-toolbar-item { |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
border-radius: 6px; |
||||
|
cursor: pointer; |
||||
|
color: #101828; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.mind-map .mm-toolbar-item.active { |
||||
|
background-color: #d4d4d8; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div class="mind-map"> |
||||
|
<svg id="markmap"></svg> |
||||
|
<div id="toolbar"></div> |
||||
|
</div> |
||||
|
<script> |
||||
|
const { Transformer, Markmap, Toolbar } = window.markmap; |
||||
|
const transformer = new Transformer(); |
||||
|
const { root } = transformer.transform(`${_meetingDetailsController.meetingDetails.value.summary}`); |
||||
|
let mm = Markmap.create('#markmap', { |
||||
|
maxWidth: 300, |
||||
|
initialExpandLevel: 3, |
||||
|
}, root); |
||||
|
const toolbar = Toolbar.create(mm); |
||||
|
toolbar.showBrand = false |
||||
|
toolbar.render(); |
||||
|
const el = toolbar.el; |
||||
|
const toolbarElement = document.getElementById('toolbar'); |
||||
|
toolbarElement.append(el); |
||||
|
|
||||
|
async function captureImage() { |
||||
|
const markmapElement = document.getElementById('markmap'); |
||||
|
markmapElement.style.height = `${1.sw}px`; |
||||
|
await mm.fit(); |
||||
|
const options = { |
||||
|
scale: 2, |
||||
|
backgroundColor: '#FFFFFF', |
||||
|
encoderOptions: 1, |
||||
|
}; |
||||
|
const uri = await svgAsPngUri(markmapElement, options); |
||||
|
markmapElement.style.height = '100%'; |
||||
|
mm.fit(); |
||||
|
if (window.ImageChannel) { |
||||
|
window.ImageChannel.postMessage(uri); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
|
'''; |
||||
|
webViewController = WebViewController() |
||||
|
..setJavaScriptMode(JavaScriptMode.unrestricted) |
||||
|
..addJavaScriptChannel( |
||||
|
'ImageChannel', |
||||
|
onMessageReceived: _messageReceived, |
||||
|
) |
||||
|
..setBackgroundColor(Colors.transparent) |
||||
|
..loadHtmlString(html); |
||||
|
} |
||||
|
|
||||
|
void _messageReceived(message) async { |
||||
|
final String dataUrl = message.message; |
||||
|
final String base64Str = dataUrl.split(',').last; |
||||
|
final Uint8List bytes = base64.decode(base64Str); |
||||
|
final String fileName = |
||||
|
'${_meetingDetailsController.meetingData.value.title} mindmap.png'; |
||||
|
final tempDir = await getTemporaryDirectory(); |
||||
|
final File file = File('${tempDir.path}/$fileName'); |
||||
|
await file.writeAsBytes(bytes); |
||||
|
final result = await SharePlus.instance.share(ShareParams( |
||||
|
text: '分享思维导图', |
||||
|
files: [XFile(file.path)], |
||||
|
)); |
||||
|
if (result.status == ShareResultStatus.success) { |
||||
|
EasyLoading.showToast('分享完成!'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue