修复作业停止之后的bug 和远程遥控模式 默认前视角
This commit is contained in:
@@ -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 ? '登录中...' : '登 录',
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user