周睿 2 年之前
父節點
當前提交
a1e6299835

+ 17 - 0
app_business/lib/model/game_map.dart

@@ -0,0 +1,17 @@
+import 'dart:typed_data';
+
+import 'package:app_business/service/api.dart';
+import 'package:track_common/model.dart';
+
+import '../generated/base.pb.dart' as pb;
+
+extension PBGameMap on pb.NetImage {
+  GameMap toGameMap() {
+    final md5Data = Uint8List.fromList(md5);
+
+    return GameMap()
+      ..url = url
+      ..md5 = md5Data
+      ..readerBuilder = () => Get.find<ApiService>().getBinReaderByMd5(md5Data);
+  }
+}

+ 3 - 0
app_business/lib/service/all_init.dart

@@ -1,5 +1,7 @@
 import 'package:app_business/service/api.dart';
 import 'package:app_business/service/app.dart';
+import 'package:app_business/service/map_watch.dart';
+import 'package:track_common/service/map_watch.dart';
 import 'package:track_common/track_common.dart';
 
 import 'abase.dart';
@@ -17,5 +19,6 @@ Future<void> allInit() async {
     await service.init();
   }
 
+  Get.put<MapWatchService>(MapWatchServiceImpl(), permanent: true);
   info('初始化完成');
 }

+ 10 - 3
app_business/lib/service/api.dart

@@ -5,14 +5,21 @@ import 'package:app_business/app_config.dart';
 import 'package:app_business/generated/base.pb.dart' as pb;
 import 'package:app_business/generated/track_offical.pbgrpc.dart' as pb;
 import 'package:app_business/service/app.dart';
+import 'package:common_pub/model.dart';
 import 'package:grpc/grpc.dart';
+import 'package:track_common/model/map_info.dart';
 import 'package:track_common/track_common.dart';
-import 'package:track_common/view/home/map/map_page.dart';
 
 import 'abase.dart';
 
 typedef SmsType = pb.SmsType;
 
+extension _ImageExt on pb.NetImage {
+  NetImage toModel() {
+    return NetImage(url, md5);
+  }
+}
+
 class ApiService extends IService {
   ClientChannel? channel;
 
@@ -106,8 +113,8 @@ class ApiService extends IService {
       ..offset = offset);
 
     return r.list
-        .map((e) => MapInfo(e.mapId, e.name, e.distance.meter, e.image.url,
-            e.description, e.mapScaleNumber, e.image.md5))
+        .map((e) => MapInfo(e.mapId, e.name, e.distance.meter, e.description,
+            e.mapScaleNumber, e.image.toModel()))
         .toList();
   }
 

+ 34 - 0
app_business/lib/service/map_watch.dart

@@ -0,0 +1,34 @@
+import 'package:app_business/service/api.dart';
+import 'package:fixnum/fixnum.dart';
+import 'package:get/get.dart';
+import 'package:track_common/model/event.dart';
+import 'package:track_common/model/map_info.dart';
+import 'package:track_common/service/map_watch.dart';
+
+import '../generated/base.pb.dart' as pb;
+import '../model/game_map.dart';
+
+class MapWatchImpl extends MapWatch {
+  MapWatchImpl({required super.id});
+
+  ApiService get _api => Get.find();
+  @override
+  Future<List<EventInfo>> getEventList(int mapId) async {
+    return [];
+  }
+}
+
+class MapWatchServiceImpl extends MapWatchService {
+  ApiService get _api => Get.find();
+  @override
+  Future<MapWatch> newInstanceByMap(MapInfo info) async {
+    final r =
+        await _api.stub.toMapDetailV2(pb.IdRequest()..id = Int64(info.id));
+
+    final instance = MapWatchImpl(id: info.id)
+      ..name = r.mapName
+      ..plugMap.gameMap = r.zipImage.toGameMap();
+
+    return instance;
+  }
+}

+ 1 - 3
app_business/lib/view/home/maplist.dart

@@ -1,5 +1,6 @@
 import 'package:app_business/service/abase.dart';
 import 'package:app_business/service/api.dart';
+import 'package:track_common/model/map_info.dart';
 import 'package:track_common/view.dart';
 import 'package:track_common/view/home/map/map_page.dart';
 
@@ -16,7 +17,4 @@ class MapPageControllerImpl extends MapPageController {
   set selectedMap(MapInfo map) {
     home.selectMapName.value = map.name;
   }
-
-  @override
-  int get selectedMapId => 0;
 }

+ 2 - 0
app_business/macos/Flutter/GeneratedPluginRegistrant.swift

@@ -9,10 +9,12 @@ import common_pub
 import package_info_plus
 import path_provider_foundation
 import rive_common
+import sqflite
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   CommonPubPlugin.register(with: registry.registrar(forPlugin: "CommonPubPlugin"))
   FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
   RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
+  SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
 }

+ 81 - 1
app_business/pubspec.lock

@@ -49,6 +49,30 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
+  cached_network_image:
+    dependency: transitive
+    description:
+      name: cached_network_image
+      sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "3.3.0"
+  cached_network_image_platform_interface:
+    dependency: transitive
+    description:
+      name: cached_network_image_platform_interface
+      sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "3.0.0"
+  cached_network_image_web:
+    dependency: transitive
+    description:
+      name: cached_network_image_web
+      sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.1.0"
   characters:
     dependency: transitive
     description:
@@ -136,8 +160,16 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
-  fixnum:
+  file:
     dependency: transitive
+    description:
+      name: file
+      sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "7.0.0"
+  fixnum:
+    dependency: "direct main"
     description:
       name: fixnum
       sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
@@ -157,6 +189,14 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_cache_manager:
+    dependency: transitive
+    description:
+      name: flutter_cache_manager
+      sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "3.3.1"
   flutter_lints:
     dependency: "direct dev"
     description:
@@ -324,6 +364,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.0.4"
+  octo_image:
+    dependency: transitive
+    description:
+      name: octo_image
+      sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.0.0"
   package_info_plus:
     dependency: "direct main"
     description:
@@ -468,6 +516,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.2.8"
+  rxdart:
+    dependency: transitive
+    description:
+      name: rxdart
+      sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.27.7"
   shelf:
     dependency: transitive
     description:
@@ -513,6 +569,22 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "7.0.0"
+  sqflite:
+    dependency: transitive
+    description:
+      name: sqflite
+      sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.3.0"
+  sqflite_common:
+    dependency: transitive
+    description:
+      name: sqflite_common
+      sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.5.0+2"
   stack_trace:
     dependency: transitive
     description:
@@ -537,6 +609,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.2.0"
+  synchronized:
+    dependency: transitive
+    description:
+      name: synchronized
+      sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "3.1.0"
   term_glyph:
     dependency: transitive
     description:

+ 1 - 0
app_business/pubspec.yaml

@@ -46,6 +46,7 @@ dependencies:
   grpc: ^3.2.4
   get_storage: ^2.1.1
   package_info_plus: ^4.2.0
+  fixnum: ^1.1.0
 
 dev_dependencies:
   flutter_test:

+ 1 - 1
libs/common_pub

@@ -1 +1 @@
-Subproject commit eecbc6cd1b9972d35d0daaa8e3a12f9a63b2c7d1
+Subproject commit 1ea47cad737263a7a7633002e8ce819c50ed9e56

+ 7 - 0
libs/track_common/lib/model.dart

@@ -0,0 +1,7 @@
+export 'package:common_pub/model.dart';
+
+export 'model/event.dart';
+export 'model/game.dart';
+export 'model/map_info.dart';
+export 'model/route.dart';
+export 'model/user.dart';

+ 6 - 0
libs/track_common/lib/model/event.dart

@@ -0,0 +1,6 @@
+/// 活动信息
+class EventInfo {
+  var id = 0;
+  var name = '';
+  var cpAllCount = 0;
+}

+ 1 - 0
libs/track_common/lib/model/game.dart

@@ -0,0 +1 @@
+class GameInfo {}

+ 13 - 0
libs/track_common/lib/model/map_info.dart

@@ -0,0 +1,13 @@
+import 'package:common_pub/model.dart';
+
+class MapInfo {
+  const MapInfo(this.id, this.name, this.distance, this.description,
+      this.mapScaleNumber, this.image);
+
+  final int id;
+  final String name;
+  final Distance? distance;
+  final NetImage image;
+  final String description;
+  final int mapScaleNumber;
+}

+ 4 - 0
libs/track_common/lib/model/route.dart

@@ -0,0 +1,4 @@
+/// 路线信息
+class RouteInfo {
+  String name = '';
+}

+ 4 - 0
libs/track_common/lib/model/user.dart

@@ -0,0 +1,4 @@
+class UserInfo {
+  int id = 0;
+  String name = '';
+}

+ 82 - 0
libs/track_common/lib/service/map_watch.dart

@@ -0,0 +1,82 @@
+import 'package:common_pub/logger.dart';
+import 'package:common_pub/service/controller.dart';
+import 'package:common_pub/ui/map_view/map_view.dart';
+import 'package:track_common/model/event.dart';
+
+import '../model/map_info.dart';
+
+class Flag {
+  Flag(this.value);
+
+  int value;
+
+  Color get color => Color(value);
+
+  @override
+  bool operator ==(Object other) {
+    if (other is Flag) {
+      return value == other.value;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => value.hashCode;
+
+  static final red = Flag(0xffff0000);
+  static final yellow = Flag(0xffffcb00);
+  static final blue = Flag(0xff00a0ff);
+
+  static List<Flag> get values => [red, yellow, blue];
+}
+
+abstract class MapWatchService extends GetxService {
+  final Rx<MapWatch?> _instance = Rx(null);
+
+  MapWatch? get instance => _instance.value;
+
+  @protected
+  Future<MapWatch> newInstanceByMap(MapInfo info);
+
+  Future<void> setMap(MapInfo mapInfo) async {
+    final thisInstance = await newInstanceByMap(mapInfo);
+
+    thisInstance.addPlugs([thisInstance.plugMap]);
+
+    _instance.value = thisInstance;
+    thisInstance.init();
+    thisInstance.workFlushData();
+  }
+}
+
+abstract class MapWatch extends PlugController {
+  Future<void> workFlushData() async {
+    while (isActive) {
+      try {
+        // await flushData();
+      } catch (e) {
+        error(e);
+      }
+      await 1.seconds.delay();
+    }
+  }
+
+  EventInfo? getEventById(int id) {
+    for (final one in eventList) {
+      if (one.id == id) {
+        return one;
+      }
+    }
+    return null;
+  }
+
+  MapWatch({required this.id});
+
+  final int id;
+  String name = '';
+  final plugMap = PlugMap();
+  final eventList = <EventInfo>[].obs;
+
+  @protected
+  Future<List<EventInfo>> getEventList(int mapId);
+}

+ 26 - 31
libs/track_common/lib/utils.dart

@@ -1,12 +1,7 @@
-import 'dart:io';
-
 import 'package:common_pub/common_pub.dart';
-import 'package:common_pub/pb.dart' as pb;
-import 'package:f_cache/manager.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:grpc/grpc.dart';
-import 'package:http/http.dart' as http;
 
 import 'styles/color_schemes.g.dart';
 import 'view/login/login_view.dart';
@@ -55,33 +50,33 @@ class Preview extends StatelessWidget {
   }
 }
 
-typedef NetImage = pb.NetImage;
+// typedef NetImage = pb.NetImage;
 
-extension NetImageExt on NetImage {
-  String? get md5Hex {
-    if (md5.isEmpty) {
-      return null;
-    } else {
-      return md5.toHexString();
-    }
-  }
-
-  Future<Reader> readerBuilder() async {
-    final url = Uri.parse(this.url);
-    var request = http.Request('GET', url);
-    var response = await request.send();
-    if (response.statusCode != 200) {
-      throw HttpException('state: ${response.statusCode}', uri: url);
-    }
-    final length = response.contentLength ?? 0;
-    return Reader(response.stream, length);
-  }
-
-  Future<void> preload() async {
-    await CacheManager()
-        .getCached(id: md5Hex ?? '', readerBuilder: readerBuilder);
-  }
-}
+// extension NetImageExt on NetImage {
+//   String? get md5Hex {
+//     if (md5.isEmpty) {
+//       return null;
+//     } else {
+//       return md5.toHexString();
+//     }
+//   }
+//
+//   Future<Reader> readerBuilder() async {
+//     final url = Uri.parse(this.url);
+//     var request = http.Request('GET', url);
+//     var response = await request.send();
+//     if (response.statusCode != 200) {
+//       throw HttpException('state: ${response.statusCode}', uri: url);
+//     }
+//     final length = response.contentLength ?? 0;
+//     return Reader(response.stream, length);
+//   }
+//
+//   Future<void> preload() async {
+//     await CacheManager()
+//         .getCached(id: md5Hex ?? '', readerBuilder: readerBuilder);
+//   }
+// }
 
 void runPreview(Widget child) {
   runApp(GetMaterialApp(

+ 16 - 24
libs/track_common/lib/view/home/map/map_page.dart

@@ -1,24 +1,12 @@
-import 'package:common_pub/model/distance.dart';
+import 'package:common_pub/model.dart';
 import 'package:common_pub/model/position.dart' as m;
+import 'package:common_pub/ui/app_net_image.dart';
+import 'package:track_common/service/map_watch.dart';
 import 'package:track_common/widget/prelude.dart';
 
+import '../../../model/map_info.dart';
 import '../../../utils.dart';
 import '../../../widget.dart';
-import '../../../widget/app_net_image.dart';
-
-export 'package:common_pub/model/distance.dart';
-
-class MapInfo {
-  const MapInfo(this.id, this.name, this.distance, this.url, this.description,
-      this.mapScaleNumber, this.md5);
-  final int id;
-  final String name;
-  final Distance? distance;
-  final String url;
-  final String description;
-  final int mapScaleNumber;
-  final List<int> md5;
-}
 
 abstract class MapPageController extends GetxController {
   @override
@@ -29,10 +17,17 @@ abstract class MapPageController extends GetxController {
 
   Future<List<MapInfo>> getMapList(int limit, int offset);
 
-  int get selectedMapId;
+  int get selectedMapId {
+    return Get.find<MapWatchService>().instance?.id ?? 0;
+  }
 
   set selectedMap(MapInfo map);
 
+  void onTapMap(MapInfo info) {
+    selectedMap = info;
+    Get.find<MapWatchService>().setMap(info);
+  }
+
   Future<void> mapGetMore() async {
     if (isMapGetMoreLoading.value) {
       return;
@@ -122,7 +117,7 @@ class GalleryCardWidget extends GetView<MapPageController> {
       required this.isSelected});
 
   void onTap(MapInfo mapInfo) {
-    controller.selectedMap = mapInfo;
+    controller.onTapMap(mapInfo);
   }
 
   @override
@@ -147,9 +142,8 @@ class GalleryCardWidget extends GetView<MapPageController> {
           children: [
             AspectRatio(
                 aspectRatio: 1.1,
-                child: AppNetImage(
-                    netImage: NetImage(url: data.url, md5: data.md5),
-                    fit: BoxFit.fitHeight)),
+                child:
+                    AppNetImage(netImage: data.image, fit: BoxFit.fitHeight)),
             Expanded(
                 child: Padding(
                     padding: const EdgeInsets.all(6),
@@ -207,9 +201,7 @@ class GalleryCardWidget extends GetView<MapPageController> {
       children: [
         SizedBox(
             height: double.infinity,
-            child: AppNetImage(
-                netImage: NetImage(url: data.url, md5: data.md5),
-                fit: BoxFit.fitHeight)),
+            child: AppNetImage(netImage: data.image, fit: BoxFit.fitHeight)),
       ],
     );
   }

+ 0 - 97
libs/track_common/lib/widget/app_net_image.dart

@@ -1,97 +0,0 @@
-import 'package:common_pub/logger.dart';
-import 'package:f_cache/f_cache.dart';
-
-import '../utils.dart';
-import 'prelude.dart';
-
-class AppNetImage extends StatefulWidget {
-  const AppNetImage(
-      {super.key,
-      required this.netImage,
-      this.fit,
-      this.onWidgetOk,
-      this.width,
-      this.height});
-
-  final NetImage netImage;
-  final BoxFit? fit;
-  final VoidCallback? onWidgetOk;
-  final double? width;
-  final double? height;
-
-  @override
-  State<StatefulWidget> createState() {
-    return _AppNetImageState();
-  }
-}
-
-CachedReaderImage cachedProvider(NetImage image) {
-  return CachedReaderImage(image.md5Hex ?? '', image.readerBuilder);
-}
-
-class _AppNetImageState extends State<AppNetImage> {
-  late CachedReaderImage provider;
-
-  @override
-  void initState() {
-    super.initState();
-    final image = widget.netImage;
-    provider = cachedProvider(image);
-  }
-
-  @override
-  void didUpdateWidget(covariant AppNetImage oldWidget) {
-    super.didUpdateWidget(oldWidget);
-    final image = widget.netImage;
-    provider = cachedProvider(image);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Image(
-      image: provider,
-      loadingBuilder: (BuildContext context, Widget child,
-          ImageChunkEvent? loadingProgress) {
-        if (loadingProgress != null) {
-          var p = 0.0;
-          final all = loadingProgress.expectedTotalBytes ?? 0;
-          if (all > 0) {
-            p = loadingProgress.cumulativeBytesLoaded.toDouble() /
-                all.toDouble();
-          }
-          return ImageLoading(value: p);
-        } else {
-          return child;
-        }
-      },
-      errorBuilder: (ctx, e, trace) {
-        warn('图片加载失败: ${widget.netImage.url}  md5: ${widget.netImage.md5Hex}',
-            e);
-        return Container(
-            color: Colors.white,
-            child: const Center(child: Icon(Icons.broken_image_outlined)));
-      },
-      width: widget.width,
-      height: widget.height,
-      fit: widget.fit,
-    );
-  }
-}
-
-class ImageLoading extends StatelessWidget {
-  final double? value;
-  const ImageLoading({super.key, this.value});
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      decoration: BoxDecoration(color: Colors.grey.withAlpha(20)),
-      child: Center(
-        child: SizedBox(
-            width: 48,
-            height: 48,
-            child: CircularProgressIndicator(value: value)),
-      ),
-    );
-  }
-}