修复作业停止之后的bug 和远程遥控模式 默认前视角

This commit is contained in:
mmc
2026-03-25 09:48:05 +08:00
parent c4d085cb45
commit d6ad53a1ed
3 changed files with 90 additions and 62 deletions

View File

@@ -96,20 +96,21 @@ class _LoginPageState extends State<LoginPage> {
width: double.infinity,
child: BlocBuilder<LoginCubit, LoginState>(
builder: (context, state) {
bool isLoading = state is LoginLoading; // 假设你有 Loading 状态
// 关键:判断是否正在 Loading
bool isLoading = state is LoginLoading;
return CCPrimaryButton(
onPressed: () {
if (!_isAgreed) {
// 如果没有勾选协议,弹出提示
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请先阅读并同意用户协议')));
return;
}
if (state is! LoginLoading) {
_handleLogin();
}
},
text: state is LoginLoading ? '登录中...' : '登 录',
// 核心修复:正在加载时 → onPressed 为 null,按钮禁用
onPressed: isLoading
? null
: () {
if (!_isAgreed) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请先阅读并同意用户协议')));
return;
}
_handleLogin();
},
text: isLoading ? '登录中...' : '登 录',
);
},
),

View File

@@ -65,6 +65,7 @@ const String kSavedIsStartWork = 'saved_is_start_work'; // 是否开始作业
const String kSavedIsStopWork = 'saved_is_stop_work'; // 是否点击过停止
const String kSavedTPMode = "saved_tp_mode";
const String kSavedCurrentRobotMode = "kSavedCurrentRobotMode";
const String kSavedIsPanelOpen = "kSavedIsPanelOpen";
// 保持 PlotData 类不变
class PlotData {
@@ -256,6 +257,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
await prefs.remove(kSavedWorkMode);
await prefs.remove(kSavedStartWorkList);
await prefs.remove(kSavedSelectedPlot);
await prefs.remove(kSavedIsPanelOpen);
} catch (e) {
debugPrint('清空本地数据失败:$e');
}
@@ -296,6 +298,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// 3. 恢复是否点击过停止
isStopWork = prefs.getBool(kSavedIsStopWork) ?? false;
_isPanelOpen = prefs.getBool(kSavedIsPanelOpen) ?? false;
// 加载路径点
final pathJson = prefs.getString(kSavedGcjPathPoints);
if (pathJson != null) {
@@ -411,6 +415,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// 保存作业区域完成状态
prefs.setBool(kSavedIsWorkAreaCompleted, _isWorkAreaCompleted);
prefs.setBool(kSavedIsPanelOpen, _isPanelOpen);
// 1. 保存作业面板显示状态
prefs.setBool(kSavedIsWorkPanelOpen, _isWorkPanelOpen);
@@ -682,7 +688,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
debugPrint(typedPathList[i].toString());
}
debugPrint("===打印生成的路径结束");
debugPrint("$_robotModeWgsPoints $gcjOuterPoints $_currentRobotMode _robotModeWgsPointsgcjOuterPoints ");
// 2. 构造 SavePath 数据 (严格对应你的 JS 结构)
final Map<String, dynamic> savePath = {
//'img': imgBase64 ?? '', // 截图的 Base64 字符串
@@ -1044,6 +1049,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
_markedPoints.add(_mapCenter);
debugPrint('新增作业区域打点:第${_markedPoints.length}个点,经纬度:${_mapCenter.latitude}, ${_mapCenter.longitude}');
} else {
if (_markedPoints.isEmpty) {
_showPageToast(message: "请先完成作业区域打点!", type: ToastType.info);
return;
}
// 障碍物模式:添加到当前障碍物打点
_currentObstaclePoints.add(_mapCenter);
_isObstacleEditing = true; // 标记进入障碍物编辑状态
@@ -1062,6 +1071,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
_robotModeWgsPoints.add(_currentWgsLatLng!);
debugPrint('Robot模式新增作业打点:第${_markedPoints.length}个点,经纬度:${_currentLatLng!.latitude}, ${_currentLatLng!.longitude}');
} else {
if (_markedPoints.isEmpty || _robotModeWgsPoints.isEmpty) {
_showPageToast(message: "请先完成作业区域打点!", type: ToastType.info);
return;
}
// 3. Robot模式-障碍物打点
_currentObstaclePoints.add(_currentLatLng!);
_robotModeObsWgsPoints.add(_currentWgsLatLng!);
@@ -1560,6 +1573,28 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
],
),
if (gctracePoint!.isNotEmpty)
PolylineLayer(
polylines: [Polyline(points: gctracePoint!, color: Color.fromARGB(255, 6, 187, 232), strokeWidth: 3, isDotted: false)],
),
/// 当前定位 Marker
if (_currentLatLng != null && __isValidLatLng(_currentLatLng))
MarkerLayer(
markers: [
Marker(
point: _currentLatLng!,
width: 40,
height: 40,
child: CustomPaint(
size: const Size(40, 40),
painter: HeadingMarkerPainter(headingAngle: _headingAngle),
),
),
],
),
if (!_isWorkAreaCompleted)
/// 历史打点的绿色标记
MarkerLayer(
@@ -1580,7 +1615,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
width: 16,
height: 16,
decoration: const BoxDecoration(
color: Color(0xFF00C853), // 绿色主题色
color: Color.fromARGB(255, 10, 218, 55), // 绿色主题色
shape: BoxShape.circle,
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 2)],
),
@@ -1596,26 +1631,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
);
}).toList(),
),
if (gctracePoint!.isNotEmpty)
PolylineLayer(
polylines: [Polyline(points: gctracePoint!, color: Color(0xFF00C853), strokeWidth: 3, isDotted: false)],
),
/// 当前定位 Marker
if (_currentLatLng != null && __isValidLatLng(_currentLatLng))
MarkerLayer(
markers: [
Marker(
point: _currentLatLng!,
width: 40,
height: 40,
child: CustomPaint(
size: const Size(40, 40),
painter: HeadingMarkerPainter(headingAngle: _headingAngle),
),
),
],
),
],
);
}
@@ -2189,28 +2204,32 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// 只在当前页面显示安全 Toast,退出自动消失
void _showPageToast({required String message, required ToastType type}) {
_cancelAllToast();
// 🔥 延迟执行 Overlay 操作,避开构建阶段
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
OverlayEntry entry = OverlayEntry(
builder: (context) => SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 30),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(color: _getToastColor(type), borderRadius: BorderRadius.circular(8)),
child: Text(message, style: const TextStyle(color: Colors.white, fontSize: 14)),
OverlayEntry entry = OverlayEntry(
builder: (context) => SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 30),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(color: _getToastColor(type), borderRadius: BorderRadius.circular(8)),
child: Text(message, style: const TextStyle(color: Colors.white, fontSize: 14)),
),
),
),
),
);
);
_toastEntries.add(entry);
Overlay.of(context)?.insert(entry);
_toastEntries.add(entry);
Overlay.of(context)?.insert(entry);
// 2秒后自动关闭
Future.delayed(const Duration(seconds: 2), () {
if (entry.mounted) entry.remove();
_toastEntries.remove(entry);
// 2秒后自动关闭
Future.delayed(const Duration(seconds: 2), () {
if (entry.mounted) entry.remove();
_toastEntries.remove(entry);
});
});
}
@@ -2270,19 +2289,25 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
DeviceStatusUpdated? updatedState;
//有停止信号
if (isFinishWork) {
_workStatus = WorkStatus.idle;
_showPageToast(message: "作业已停止", type: ToastType.error);
//ToastUtils.showError(context, '作业已停止');
// 👇 延迟 1 秒钟再执行 reset(不会阻塞UI,安全)
Future.delayed(const Duration(seconds: 1), () {
// 🔥 关键:用微任务延迟执行状态更新,避开构建阶段
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
_traceManager.reset();
_traceManager.setMode(TPMode.LOCATION);
setState(() {
_workStatus = WorkStatus.idle;
isStopWork = true;
isreceiveFirstCompletePoint = false;
});
_showPageToast(message: "作业已停止", type: ToastType.error);
// 延迟重置轨迹管理器
Future.delayed(const Duration(seconds: 1), () {
if (mounted) {
_traceManager.reset();
_traceManager.setMode(TPMode.LOCATION);
}
});
}
});
isStopWork = true;
isreceiveFirstCompletePoint = false;
}
if (state is DeviceStatusUpdated) {

View File

@@ -76,13 +76,15 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
} else {
_videoStreamUrl = '';
}
final int originY = context.watch<RemoteControlCubit>().state.controlEntity.originY;
debugPrint("${originY},originY");
return WebRTCLocalPlayer(
// 这里的 URL 拼接根据你的后端规则
// streamUrl: "webrtc://${TCPConsts.TCP_IP}/live/livestream/${currentDevice.deviceName}?token=${userState.user!.token}",
streamUrl: _videoStreamUrl,
showLeftPip: state.showLeftPip, // 从 Cubit 状态中读取
showRightPip: state.showRightPip, // 从 Cubit 状态中读取
isFrontMain: context.watch<RemoteControlCubit>().state.controlEntity.originY>= 0.5,
isFrontMain: context.watch<RemoteControlCubit>().state.controlEntity.originY >= 0,
);
},
),