diff --git a/assets/images/carousel1.png b/assets/images/carousel1.png new file mode 100644 index 00000000..240bf11f Binary files /dev/null and b/assets/images/carousel1.png differ diff --git a/assets/images/carousel2.png b/assets/images/carousel2.png new file mode 100644 index 00000000..b8c1642a Binary files /dev/null and b/assets/images/carousel2.png differ diff --git a/assets/images/carousel3.jpg b/assets/images/carousel3.jpg new file mode 100644 index 00000000..dc82e835 Binary files /dev/null and b/assets/images/carousel3.jpg differ diff --git a/lib/components/BannerCarousel.dart b/lib/components/BannerCarousel.dart index db333bd3..395ca754 100644 --- a/lib/components/BannerCarousel.dart +++ b/lib/components/BannerCarousel.dart @@ -75,19 +75,10 @@ class _BannerCarouselState extends State { margin: EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), - image: DecorationImage(image: NetworkImage(item.image), fit: BoxFit.cover), + image: DecorationImage(image: AssetImage(item.image), fit: BoxFit.cover), ), child: Stack( children: [ - Positioned( - top: 12, - right: 12, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration(color: Colors.black.withOpacity(0.5), borderRadius: BorderRadius.circular(4)), - child: Text('了解我们', style: TextStyle(color: Colors.white, fontSize: 14)), - ), - ), Positioned( left: 12, bottom: 12, @@ -117,6 +108,15 @@ class _BannerCarouselState extends State { }), ), ), + Positioned( + top: 12, + right: 24, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration(color: Colors.black.withOpacity(0.5), borderRadius: BorderRadius.circular(4)), + child: Text('了解我们', style: TextStyle(color: Colors.white, fontSize: 14)), + ), + ), ], ), ); diff --git a/lib/core/network/net_message_dispatcher.dart b/lib/core/network/net_message_dispatcher.dart index 85ffab40..c3fc0cb7 100644 --- a/lib/core/network/net_message_dispatcher.dart +++ b/lib/core/network/net_message_dispatcher.dart @@ -18,14 +18,11 @@ class NetMessageDispatcher { // 🔥 修改:使用回调函数获取 AppState final Function? getAppState; - NetMessageDispatcher(this.tcpClient, this.routePlanningRepository, this._pathPlanningService, {this.getAppState}); - /// 过滤特定指令的流 Stream onCommand(int commandCode) { return tcpClient.packetStream.where((p) => p.command == commandCode); - } /// 示例解析方法:将 0x02 指令解析为 String @@ -42,7 +39,7 @@ class NetMessageDispatcher { return ''; // 返回空字符串,避免流中断 } }); - /* ///return onCommand(0x02).map((p) => utf8.decode(p.payload));*/ + /* ///return onCommand(0x02).map((p) => utf8.decode(p.payload));*/ } /// 示例解析方法:将 0x12 指令解析为 JSON 并转为模型 @@ -52,13 +49,13 @@ class NetMessageDispatcher { //监听路径规划的开始作业的指令的应答 -// if (data[0] == (byte) 0xAB && data[1] == (byte) 0xAA && data[2] == (byte) 0x01) { -// System.out.println("=====下位机回复成功=====" + data[0] + " " + data[1] + " " + data[2] + " " + data[3] + " " + -// data[4] + " " + data[5] + " " + data[6] + " " + data[7] + " " + data[8] + " " + data[9]); -// if (data[5] == (byte) 0x01) { -// Point point = new Point(); -// //发送下一个指令 -// } + // if (data[0] == (byte) 0xAB && data[1] == (byte) 0xAA && data[2] == (byte) 0x01) { + // System.out.println("=====下位机回复成功=====" + data[0] + " " + data[1] + " " + data[2] + " " + data[3] + " " + + // data[4] + " " + data[5] + " " + data[6] + " " + data[7] + " " + data[8] + " " + data[9]); + // if (data[5] == (byte) 0x01) { + // Point point = new Point(); + // //发送下一个指令 + // } /// 监听路径规划的开始作业指令的应答 (0x01 指令) /// 协议格式:AB AA 01 [DATA] CRC(2) AA AB @@ -83,39 +80,39 @@ class NetMessageDispatcher { 0xAB, 0xAA, 0x01, ...packet.payload, 0x00, 0x00, // CRC 占位 - 0xAA, 0xAB + 0xAA, 0xAB, ]; // 验证头部协议 - if (fullData[0] == 0xAB && - fullData[1] == 0xAA && - fullData[2] == 0x01) { - + if (fullData[0] == 0xAB && fullData[1] == 0xAA && fullData[2] == 0x01) { debugPrint('[Dispatcher] 下位机回复成功 - 完整数据包:${fullData.join(" ")}'); // 检查状态位 (索引 5 对应 payload 的第 2 个字节) if (fullData.length > 5 && fullData[5] == 0x01) { debugPrint('✅ [Dispatcher] 状态位验证通过:0x01 - 可以发送下一个指令'); + ///取全局的路径规划发送实体 queue /// 发送下一个指令 移除上一条数据 - var queue = _pathPlanningService.getQueue(); + var queue = _pathPlanningService.getQueue(); + ///更新完成jwd var deviceAddPathPointModel = queue.first; - devicesCubit.setArrivedLocation( - deviceAddPathPointModel.latitude, - deviceAddPathPointModel.longitude - ); + devicesCubit.setArrivedLocation(deviceAddPathPointModel.latitude, deviceAddPathPointModel.longitude); //去除上一条数据 queue.removeFirst(); - /// _pathPlanningService.updateQueue(queue as List); _pathPlanningService.updateQueue(queue.toList()); debugPrint('📡 [Dispatcher] 准备触发下一个路径点发送,队列剩余:${queue.length}'); + ///如果还剩0个数据 就停止发送 - if (queue.length==0) { + if (queue.length == 0) { debugPrint('⚠️ [Dispatcher] 队列已空,停止发送'); - // final devicesCubit = sl(); + // final devicesCubit = sl(); devicesCubit.finishWork(); + Future.delayed(Duration(seconds: 1), () { + devicesCubit.resetWorkStatus(); + }); + return false; } routePlanningRepository.startRoutePlanning(queue); @@ -135,11 +132,7 @@ class NetMessageDispatcher { /// [commandCode] 指令码 /// [statusIndex] 状态字节在 payload 中的索引 /// [expectedStatus] 期望的状态值 - Stream onStatusResponse({ - required int commandCode, - required int statusIndex, - required int expectedStatus, - }) { + Stream onStatusResponse({required int commandCode, required int statusIndex, required int expectedStatus}) { debugPrint('🔍 [Dispatcher] 监听指令应答 CMD: 0x${commandCode.toRadixString(16)}, 期望状态:0x${expectedStatus.toRadixString(16)}'); return onCommand(commandCode).where((packet) { diff --git a/lib/features/home/presentation/widgets/map/testmap_pages.dart b/lib/features/home/presentation/widgets/map/testmap_pages.dart index 4e22edfa..b679466f 100644 --- a/lib/features/home/presentation/widgets/map/testmap_pages.dart +++ b/lib/features/home/presentation/widgets/map/testmap_pages.dart @@ -85,6 +85,7 @@ class _MapPageEnterpriseState extends State { bool _isRefreshing = false; // 新增:页面刷新状态标志 bool _isVideoDialogOpen = false; // 控制视频弹窗显示 String _videoStreamUrl = ""; + bool isStopWork = false; //是否点击过停止 Offset _videoPopupPos = const Offset(0, 100); // 弹窗初始位置 // 🔥 关键修复:添加截图全局Key final GlobalKey _mapRepaintKey = GlobalKey(); @@ -381,23 +382,23 @@ class _MapPageEnterpriseState extends State { return; } - if (isStartWork && headingStatus == 0) { + if (isStartWork && headingStatus == 0 && !isStopWork) { if (!_showHeadingWarn) { // 仅状态变化时更新,避免重复刷新 setState(() => _showHeadingWarn = true); } return; - } else if (isStartWork && headingStatus == 1 && _showHeadingWarn) { + } else if (isStartWork && headingStatus == 1 && _showHeadingWarn && !isStopWork) { // 条件不满足时隐藏提示 setState(() => _showHeadingWarn = false); } - if (isStartWork && controlMode != "3") { + if (isStartWork && controlMode != "3" && !isStopWork) { if (!_showControlModeWarn) { // 仅状态变化时更新 setState(() => _showControlModeWarn = true); } - } else if (isStartWork && controlMode == "3" && _showControlModeWarn) { + } else if (isStartWork && controlMode == "3" && _showControlModeWarn && !isStopWork) { // 条件不满足时隐藏提示 setState(() => _showControlModeWarn = false); } @@ -815,6 +816,7 @@ class _MapPageEnterpriseState extends State { isDjMapShow = false; _workStatus = WorkStatus.idle; isStartWork = false; + isStopWork = false; }); _clearLocalData(); @@ -1461,8 +1463,8 @@ class _MapPageEnterpriseState extends State { for (int i = 0; i < gctracePoint!.length - 1; i++) Polyline( points: [gctracePoint![i], gctracePoint![i + 1]], - color: Colors.white, - strokeWidth: 1.5, + color: Colors.blueAccent, + strokeWidth: 3, isDotted: true, // 虚线区分作业区域 ), ], @@ -1473,11 +1475,11 @@ class _MapPageEnterpriseState extends State { /// 开始作业 void _startWork() async { + isStopWork = false; if (startWorkList.isEmpty) { ToastUtils.showInfo(context, '作业列表为空,请重新选择路径'); return; } - isStartWork = true; _traceManager.setMode(TPMode.NAVIGATION); setState(() { @@ -1490,7 +1492,6 @@ class _MapPageEnterpriseState extends State { // 🔥 延迟一下,确保状态已更新 await Future.delayed(const Duration(milliseconds: 100)); - //// 步骤1:将 List 转换为 List //final List pathModels = gcjPathPoints.map((latLng) { // return work_area_model.DeviceAddPathPointModel( @@ -1508,6 +1509,7 @@ class _MapPageEnterpriseState extends State { // 步骤 3:调用 Cubit 方法(类型匹配) await context.read().startRoutePlanning(pathQueue); + ///context.read().updateAppState(AppState.routePlanning); // 可选:显示作业提示 ToastUtils.showSuccess(context, '作业已开始'); @@ -1530,6 +1532,7 @@ class _MapPageEnterpriseState extends State { _workStatus = WorkStatus.idle; _showHeadingWarn = false; _showControlModeWarn = false; + isStopWork = true; //已经点击过停止 }); _traceManager.setMode(TPMode.LOCATION); context.read().updateAppState(AppState.none); @@ -1630,6 +1633,7 @@ class _MapPageEnterpriseState extends State { _showControlModeWarn = false; isStartWork = false; }); + if (isStopWork) return; _stopWork(); }, icon: const Icon(Icons.close, color: Colors.grey, size: 20), @@ -1642,30 +1646,30 @@ class _MapPageEnterpriseState extends State { const SizedBox(height: 16), // 2. 错误提示(如果加载失败) - if (state.errorMessage != null) - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.red[50], - borderRadius: BorderRadius.circular(6), - border: Border.all(color: Colors.red[200]!), - ), - child: Row( - children: [ - const Icon(Icons.error_outline, color: Colors.redAccent, size: 16), - const SizedBox(width: 8), - Expanded( - child: Text( - state.errorMessage!, - style: const TextStyle(fontSize: 14, color: Colors.redAccent), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), + //if (state.errorMessage != null) + // Container( + // padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + // margin: const EdgeInsets.only(bottom: 12), + // decoration: BoxDecoration( + // color: Colors.red[50], + // borderRadius: BorderRadius.circular(6), + // border: Border.all(color: Colors.red[200]!), + // ), + // child: Row( + // children: [ + // const Icon(Icons.error_outline, color: Colors.redAccent, size: 16), + // const SizedBox(width: 8), + // Expanded( + // child: Text( + // state.errorMessage!, + // style: const TextStyle(fontSize: 14, color: Colors.redAccent), + // maxLines: 2, + // overflow: TextOverflow.ellipsis, + // ), + // ), + // ], + // ), + // ), // 3. 开始作业按钮(加载中禁用) // 放在 Column/Row 的 children: [ ... ] 内部 @@ -2034,6 +2038,7 @@ class _MapPageEnterpriseState extends State { LatLng? targetLatLng; if (arriLatitude != null && arriLongitude != null) { targetLatLng = LatLng(arriLatitude, arriLongitude); + debugPrint("${targetLatLng}收到完成点gctracePoint"); _traceManager.upsert(targetLatLng, TPAction.ADD); } @@ -2043,11 +2048,12 @@ class _MapPageEnterpriseState extends State { int headingStatus = 0; String controlMode = "0"; DeviceStatusUpdated? updatedState; + //有停止信号 if (isFinishWork) { _workStatus = WorkStatus.idle; ToastUtils.showError(context, '作业已停止'); - isStartWork = false; _traceManager.setMode(TPMode.LOCATION); + isStopWork = true; } if (state is DeviceStatusUpdated) { diff --git a/lib/features/my/presentation/pages/my_page.dart b/lib/features/my/presentation/pages/my_page.dart index 61aefb58..f55641b3 100644 --- a/lib/features/my/presentation/pages/my_page.dart +++ b/lib/features/my/presentation/pages/my_page.dart @@ -71,9 +71,9 @@ class MyPage extends StatelessWidget { // 添加 context 参数 return BannerCarousel( items: [ - BannerItem(image: 'https://c.53326.com/d/file/lan20221010/fyhj0ibovbp.jpg', title: 'AI赋能农业', url: 'https://www.satabot.com/'), - BannerItem(image: 'https://picsum.photos/800/400?1', title: '智能农机上新', url: 'https://www.satabot.com/'), - BannerItem(image: 'https://picsum.photos/800/400?2', title: '科技改变生活', url: 'https://www.satabot.com/'), + BannerItem(image: 'assets/images/carousel3.jpg', title: 'AI赋能农业', url: 'https://www.satabot.com/'), + BannerItem(image: 'assets/images/carousel1.png', title: '智能农机上新', url: 'https://www.satabot.com/'), + BannerItem(image: 'assets/images/carousel2.png', title: '科技改变生活', url: 'https://www.satabot.com/'), ], ); }