优化轮播图 发送完成信号
This commit is contained in:
BIN
assets/images/carousel1.png
Normal file
BIN
assets/images/carousel1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
assets/images/carousel2.png
Normal file
BIN
assets/images/carousel2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/images/carousel3.jpg
Normal file
BIN
assets/images/carousel3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 MiB |
@@ -75,19 +75,10 @@ class _BannerCarouselState extends State<BannerCarousel> {
|
||||
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<BannerCarousel> {
|
||||
}),
|
||||
),
|
||||
),
|
||||
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)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -18,14 +18,11 @@ class NetMessageDispatcher {
|
||||
// 🔥 修改:使用回调函数获取 AppState
|
||||
final Function? getAppState;
|
||||
|
||||
|
||||
NetMessageDispatcher(this.tcpClient, this.routePlanningRepository, this._pathPlanningService, {this.getAppState});
|
||||
|
||||
|
||||
/// 过滤特定指令的流
|
||||
Stream<RawPacket> 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<DeviceAddPathPointModel>);
|
||||
_pathPlanningService.updateQueue(queue.toList());
|
||||
debugPrint('📡 [Dispatcher] 准备触发下一个路径点发送,队列剩余:${queue.length}');
|
||||
|
||||
///如果还剩0个数据 就停止发送
|
||||
if (queue.length==0) {
|
||||
if (queue.length == 0) {
|
||||
debugPrint('⚠️ [Dispatcher] 队列已空,停止发送');
|
||||
// final devicesCubit = sl<DevicesCubit>();
|
||||
// final devicesCubit = sl<DevicesCubit>();
|
||||
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<RawPacket> onStatusResponse({
|
||||
required int commandCode,
|
||||
required int statusIndex,
|
||||
required int expectedStatus,
|
||||
}) {
|
||||
Stream<RawPacket> 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) {
|
||||
|
||||
@@ -85,6 +85,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
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<MapPageEnterprise> {
|
||||
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<MapPageEnterprise> {
|
||||
isDjMapShow = false;
|
||||
_workStatus = WorkStatus.idle;
|
||||
isStartWork = false;
|
||||
isStopWork = false;
|
||||
});
|
||||
_clearLocalData();
|
||||
|
||||
@@ -1461,8 +1463,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
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<MapPageEnterprise> {
|
||||
|
||||
/// 开始作业
|
||||
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<MapPageEnterprise> {
|
||||
// 🔥 延迟一下,确保状态已更新
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
|
||||
//// 步骤1:将 List<LatLng> 转换为 List<DeviceAddPathPointModel>
|
||||
//final List<work_area_model.DeviceAddPathPointModel> pathModels = gcjPathPoints.map((latLng) {
|
||||
// return work_area_model.DeviceAddPathPointModel(
|
||||
@@ -1508,6 +1509,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// 步骤 3:调用 Cubit 方法(类型匹配)
|
||||
await context.read<DevicesCubit>().startRoutePlanning(pathQueue);
|
||||
|
||||
///context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
|
||||
// 可选:显示作业提示
|
||||
ToastUtils.showSuccess(context, '作业已开始');
|
||||
@@ -1530,6 +1532,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_workStatus = WorkStatus.idle;
|
||||
_showHeadingWarn = false;
|
||||
_showControlModeWarn = false;
|
||||
isStopWork = true; //已经点击过停止
|
||||
});
|
||||
_traceManager.setMode(TPMode.LOCATION);
|
||||
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
@@ -1630,6 +1633,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_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<MapPageEnterprise> {
|
||||
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<MapPageEnterprise> {
|
||||
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<MapPageEnterprise> {
|
||||
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) {
|
||||
|
||||
@@ -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/'),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user