Browse Source

[new]增加轨迹行为总结分享报告

zk 5 months ago
parent
commit
73289e120b

+ 8 - 1
lib/module/track/track_day_detail/track_day_detail_controller.dart

@@ -12,8 +12,8 @@ import 'package:location/handler/error_handler.dart';
 import 'package:location/module/track/track_controller.dart';
 import 'package:location/module/track/track_day_detail/time_proportion/pie_chat_data.dart';
 import 'package:location/resource/string.gen.dart';
+import 'package:location/sdk/wechat/wechat_share_util.dart';
 import 'package:location/utils/async_util.dart';
-import 'package:location/utils/atmob_log.dart';
 import 'package:location/utils/common_expand.dart';
 import 'package:location/utils/pair.dart';
 import 'package:location/utils/toast_util.dart';
@@ -21,6 +21,7 @@ import 'package:url_launcher/url_launcher.dart';
 import '../../../data/api/response/track_daily_summary_response.dart';
 import '../../../data/bean/stream_chat_origin_data.dart';
 import '../../../data/bean/track_days.dart';
+import '../../../utils/capture_util.dart';
 import '../../../utils/http_handler.dart';
 import '../../../widget/gradually_print_text.dart';
 import '../track_status.dart';
@@ -69,6 +70,8 @@ class TrackDayDetailController extends BaseController {
 
   String? get summaryError => _summaryError.value;
 
+  final GlobalKey shareGlobalKey = GlobalKey();
+
   CancelableFuture? summaryFuture;
 
   TrackDayDetailController(this.days, bool isExpand) {
@@ -275,6 +278,10 @@ class TrackDayDetailController extends BaseController {
     }
   }
 
+  void onShareClick() async {
+    WechatShareUtil.shareWidgetToWeChat(shareGlobalKey);
+  }
+
   @override
   void onClose() {
     super.onClose();

+ 40 - 29
lib/module/track/track_day_detail/track_day_detail_view.dart

@@ -70,7 +70,12 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
             ),
             SliverToBoxAdapter(
               child: buildTrackDailySummaryView(),
-            )
+            ),
+            SliverToBoxAdapter(
+                child: Container(
+              height: 80.w,
+              color: '#F8F5FF'.color,
+            )),
           ],
         ),
         _buildFoldBtn(),
@@ -79,26 +84,29 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
   }
 
   Widget buildTrackDailySummaryView() {
-    return Column(
-      children: [
-        buildDailySummaryTitle(),
-        SizedBox(height: 8.w),
-        Obx(() {
-          return _buildSituationItem(StringName.trackDailySummaryPhone,
-              controller.trackDailySummary?.phoneSituation);
-        }),
-        Obx(() {
-          return _buildSituationItem(StringName.trackDailySummaryStay,
-              controller.trackDailySummary?.stayLongest);
-        }),
-        //轨迹情况
-        Obx(() {
-          return _buildDailyTrack(
-              controller.trackDailySummary?.showTrackSituation,
-              controller.trackDailySummary?.trackSituation);
-        }),
-        SizedBox(height: 100.w)
-      ],
+    return RepaintBoundary(
+      key: controller.shareGlobalKey,
+      child: Column(
+        children: [
+          buildDailySummaryTitle(),
+          SizedBox(height: 8.w),
+          Obx(() {
+            return _buildSituationItem(StringName.trackDailySummaryPhone,
+                controller.trackDailySummary?.phoneSituation);
+          }),
+          Obx(() {
+            return _buildSituationItem(StringName.trackDailySummaryStay,
+                controller.trackDailySummary?.stayLongest);
+          }),
+          //轨迹情况
+          Obx(() {
+            return _buildDailyTrack(
+                controller.trackDailySummary?.showTrackSituation,
+                controller.trackDailySummary?.trackSituation);
+          }),
+          SizedBox(height: 10.w)
+        ],
+      ),
     );
   }
 
@@ -210,14 +218,17 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
                 fontSize: 14.sp,
                 color: '#333333'.color)),
         Spacer(),
-        Container(
-          padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 12.w),
-          child: Row(
-            children: [
-              Text(StringName.trackDetailDailySummaryShare,
-                  style: TextStyle(fontSize: 12.sp, color: '#666666'.color)),
-              Assets.images.iconTrackDailySummaryArrow.image(height: 11.w)
-            ],
+        GestureDetector(
+          onTap: controller.onShareClick,
+          child: Container(
+            padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 12.w),
+            child: Row(
+              children: [
+                Text(StringName.trackDetailDailySummaryShare,
+                    style: TextStyle(fontSize: 12.sp, color: '#666666'.color)),
+                Assets.images.iconTrackDailySummaryArrow.image(height: 11.w)
+              ],
+            ),
           ),
         ),
         SizedBox(width: 10.w),

+ 22 - 0
lib/sdk/wechat/wechat_helper.dart

@@ -20,6 +20,28 @@ class WechatHelper {
     });
   }
 
+  static Future<void> shareImageToWechat({
+    required int scene,
+    Uint8List? imageData,
+    Uri? imageUri,
+  }) async {
+    return WechatKitPlatform.instance.shareImage(
+      scene: scene,
+      imageData: imageData,
+      imageUri: imageUri,
+    );
+  }
+
+  static Future<void> shareTextToWechat({
+    required int scene,
+    required String text,
+  }) async {
+    return WechatKitPlatform.instance.shareText(
+      scene: scene,
+      text: text,
+    );
+  }
+
   static Future<void> shareUrlToWechat({
     required int scene,
     required String webpageUrl,

+ 52 - 0
lib/sdk/wechat/wechat_share_util.dart

@@ -1,3 +1,4 @@
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/services.dart';
 import 'package:location/sdk/wechat/wechat_helper.dart';
@@ -5,6 +6,8 @@ import 'package:wechat_kit/wechat_kit.dart';
 import '../../data/consts/web_url.dart';
 import '../../resource/assets.gen.dart';
 import '../../resource/string.gen.dart';
+import '../../utils/capture_util.dart';
+import 'package:image/image.dart' as img;
 
 class WechatShareUtil {
   WechatShareUtil._();
@@ -25,4 +28,53 @@ class WechatShareUtil {
     final ByteData byteData = await rootBundle.load(assetPath);
     return byteData.buffer.asUint8List();
   }
+
+  static Future<void> shareWidgetToWeChat(
+    GlobalKey repaintKey, {
+    int scene = WechatScene.kSession,
+    double pixelRatio = 2.5,
+    int maxBytes = 1024 * 1024,
+  }) async {
+    try {
+      final isInstall = await WechatHelper.isInstalled();
+      if (!isInstall) {
+        throw Exception(StringName.wechatNoInstall);
+      }
+
+      final captured = await CaptureUtil.captureWidgetToImage(repaintKey);
+      if (captured == null) {
+        throw Exception('截图失败');
+      }
+
+      final compressed =
+          await _compressImageToLimit(captured, maxBytes: maxBytes);
+      if (compressed == null) {
+        debugPrint("图片压缩失败");
+        return;
+      }
+
+      await WechatHelper.shareImageToWechat(
+        scene: scene,
+        imageData: compressed,
+      );
+    } catch (e) {
+      throw Exception('分享失败');
+    }
+  }
+
+  static Future<Uint8List?> _compressImageToLimit(Uint8List data,
+      {required int maxBytes}) async {
+    final decoded = img.decodeImage(data);
+    if (decoded == null) return null;
+
+    int quality = 95;
+    late Uint8List result;
+
+    do {
+      result = Uint8List.fromList(img.encodeJpg(decoded, quality: quality));
+      quality -= 5;
+    } while (result.lengthInBytes > maxBytes && quality > 10);
+
+    return result.lengthInBytes <= maxBytes ? result : null;
+  }
 }

+ 24 - 0
lib/utils/capture_util.dart

@@ -0,0 +1,24 @@
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/rendering.dart';
+
+class CaptureUtil {
+  CaptureUtil._();
+
+  static Future<Uint8List?> captureWidgetToImage(GlobalKey key,
+      {double pixelRatio = 2.5}) async {
+    try {
+      RenderRepaintBoundary boundary =
+          key.currentContext!.findRenderObject() as RenderRepaintBoundary;
+
+      final ui.Image image = await boundary.toImage(pixelRatio: pixelRatio);
+      final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
+      return byteData?.buffer.asUint8List();
+    } catch (e) {
+      debugPrint("截图失败: $e");
+      return null;
+    }
+  }
+}

+ 3 - 0
pubspec.yaml

@@ -139,6 +139,9 @@ dependencies:
   #跳转评价
   in_app_review: ^2.0.10
 
+  #图片压缩
+  image: ^4.5.4
+
   ######################地图########################
   flutter_map:
     path: plugins/map