基本完成APP的所有页面中的语言切换支持的开发和设计
This commit is contained in:
@@ -18,6 +18,7 @@ import 'package:maibu_satabot_v2/components/toast.dart';
|
||||
import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
|
||||
import 'package:maibu_satabot_v2/core/consts/tcp_consts.dart';
|
||||
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
||||
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
|
||||
import 'package:maibu_satabot_v2/core/network/net_message_dispatcher.dart';
|
||||
import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart';
|
||||
import 'package:maibu_satabot_v2/core/router/route_paths.dart';
|
||||
@@ -167,9 +168,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// 所有可用的场站列表(根据你的实际瓦片目录配置)
|
||||
final List<DJIStation> _stationList = [
|
||||
const DJIStation(name: 'liaoning', displayName: '一号场站'),
|
||||
const DJIStation(name: 'station_b', displayName: '二号场站'),
|
||||
const DJIStation(name: 'station_c', displayName: '三号场站'),
|
||||
const DJIStation(name: 'liaoning', displayName: 'station_1'),
|
||||
const DJIStation(name: 'station_b', displayName: 'station_2'),
|
||||
const DJIStation(name: 'station_c', displayName: 'station_3'),
|
||||
// 新增场站只需在这里添加,无需修改其他逻辑
|
||||
];
|
||||
|
||||
@@ -591,20 +592,21 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
}
|
||||
|
||||
void _showSavePlotDialog() {
|
||||
final loc = AppLocalizations.of(context);
|
||||
showInputConfirmDialog(
|
||||
context: context,
|
||||
title: '保存地块', // 自定义标题
|
||||
hintText: '请输入地块名称(如:北地块、一号田)', // 自定义输入提示
|
||||
labelText: '地块名称', // 自定义输入框标签
|
||||
confirmText: '保存', // 确认按钮文字
|
||||
cancelText: '取消', // 取消按钮文字
|
||||
title: loc.translate('route_planning.save_plot'), // 自定义标题
|
||||
hintText: loc.translate('route_planning.plot_name_hint'), // 自定义输入提示
|
||||
labelText: loc.translate('route_planning.plot_name_label'), // 自定义输入框标签
|
||||
confirmText: loc.translate('route_planning.save'), // 确认按钮文字
|
||||
cancelText: loc.translate('route_planning.cancel'), // 取消按钮文字
|
||||
// 输入校验器(可选)
|
||||
inputValidator: (inputText) {
|
||||
if (inputText.isEmpty) {
|
||||
return '地块名称不能为空!';
|
||||
return loc.translate('route_planning.plot_name_empty');
|
||||
}
|
||||
if (inputText.length > 20) {
|
||||
return '地块名称不能超过20个字符!';
|
||||
return loc.translate('route_planning.plot_name_too_long');
|
||||
}
|
||||
return null; // 校验通过
|
||||
},
|
||||
@@ -629,7 +631,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
} else {
|
||||
// 截图失败时,允许空图片保存(可根据业务调整为强制失败)
|
||||
_savePlotData(plotName, null);
|
||||
_showPageToast(message: "地块保存成功,但地图截图生成失败!", type: ToastType.warn);
|
||||
_showPageToast(message: loc.translate('route_planning.save_success') + "," + "但地图截图生成失败!", type: ToastType.warn);
|
||||
|
||||
//ToastUtils.showWarn(context, '地块保存成功,但地图截图生成失败!');
|
||||
//ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('地块保存成功,但地图截图生成失败!'), backgroundColor: Colors.amber));
|
||||
@@ -683,10 +685,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
}
|
||||
|
||||
Future<void> _savePlotData(String plotName, String? imgBase64) async {
|
||||
final loc = AppLocalizations.of(context);
|
||||
// 1. 获取用户ID
|
||||
final userId = context.read<AppUserCubit>().state.user?.userId ?? "";
|
||||
if (userId.isEmpty) {
|
||||
_showPageToast(message: "用户ID为空,无法保存!", type: ToastType.error);
|
||||
_showPageToast(message: loc.translate('route_planning.user_id_empty'), type: ToastType.error);
|
||||
|
||||
//ToastUtils.showError(context, '用户ID为空,无法保存!');
|
||||
return;
|
||||
@@ -756,7 +759,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// 7. 发送请求
|
||||
try {
|
||||
_showPageToast(message: "正在保存地块「$plotName」...", type: ToastType.loading);
|
||||
_showPageToast(message: loc.translate('route_planning.saving') + "「$plotName」...", type: ToastType.loading);
|
||||
|
||||
//ToastUtils.showLoading(context, '正在保存地块「$plotName」...');
|
||||
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('正在保存地块...'), backgroundColor: Colors.blue));
|
||||
@@ -765,7 +768,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
final String responseBody = await response.stream.bytesToString();
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
_showPageToast(message: "地块「$plotName」保存成功!", type: ToastType.success);
|
||||
_showPageToast(message: loc.translate('route_planning.save_success') + "「$plotName」", type: ToastType.success);
|
||||
|
||||
//ToastUtils.showSuccess(context, '地块「$plotName」保存成功!');
|
||||
_clearLocalData();
|
||||
@@ -787,7 +790,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('保存失败: $e');
|
||||
_showPageToast(message: "保存失败: ${e.toString()}", type: ToastType.error);
|
||||
_showPageToast(message: loc.translate('route_planning.save_failed') + ": ${e.toString()}", type: ToastType.error);
|
||||
|
||||
//ToastUtils.showError(context, '保存失败: ${e.toString()}');
|
||||
//ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('保存失败: ${e.toString()}'), backgroundColor: Colors.red));
|
||||
@@ -822,7 +825,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
}
|
||||
_showPageToast(message: "已撤回作业区域最后一个点,剩余${_markedPoints.length}个点", type: ToastType.info);
|
||||
} else {
|
||||
_showPageToast(message: "暂无作业区域点可撤回", type: ToastType.info);
|
||||
final loc = AppLocalizations.of(context);
|
||||
_showPageToast(message: loc.translate('route_planning.no_work_points'), type: ToastType.info);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -884,7 +888,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_isWorkAreaCompleted = false;
|
||||
_saveBoxOpen = false;
|
||||
typedPathList.clear();
|
||||
_showPageToast(message: "已清空所有作业区域点和路径", type: ToastType.success);
|
||||
final loc = AppLocalizations.of(context);
|
||||
_showPageToast(message: loc.translate('route_planning.clear_work_area'), type: ToastType.success);
|
||||
//ToastUtils.showSuccess(context, '已清空所有作业区域点和路径');
|
||||
|
||||
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有作业区域点和路径')));
|
||||
@@ -892,7 +897,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
// 2. 空洞模式:清空所有空洞 + 恢复UI + 重新生成路径
|
||||
else if (_currentAreaMode == AreaMode.obstacle) {
|
||||
if (_obstacleHoles.isEmpty && _currentObstaclePoints.isEmpty) {
|
||||
_showPageToast(message: "暂无障碍物可删除", type: ToastType.info);
|
||||
final loc = AppLocalizations.of(context);
|
||||
_showPageToast(message: loc.translate('route_planning.no_obstacles'), type: ToastType.info);
|
||||
|
||||
//ToastUtils.showInfo(context, '暂无障碍物可删除');
|
||||
return;
|
||||
@@ -905,7 +911,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
if (_isWorkAreaCompleted) {
|
||||
_generatePath(showTips: false);
|
||||
}
|
||||
_showPageToast(message: "已清空所有障碍物", type: ToastType.success);
|
||||
final loc = AppLocalizations.of(context);
|
||||
_showPageToast(message: loc.translate('route_planning.clear_obstacles'), type: ToastType.success);
|
||||
//ToastUtils.showSuccess(context, '已清空所有障碍物');
|
||||
}
|
||||
});
|
||||
@@ -1032,11 +1039,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
await _saveDataToLocal();
|
||||
|
||||
if (mounted) {
|
||||
_showPageToast(message: "已清除所有缓存,恢复初始状态", type: ToastType.success);
|
||||
_showPageToast(message: AppLocalizations.of(context).translate('route_planning.clear_cache_success'), type: ToastType.success);
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
_showPageToast(message: "刷新失败:${e.toString().substring(0, 50)}", type: ToastType.error);
|
||||
_showPageToast(message: "${AppLocalizations.of(context).translate('route_planning.refresh_failed')}:${e.toString().substring(0, 50)}", type: ToastType.error);
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
@@ -1861,7 +1868,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text('作业模式:$workMode', style: const TextStyle(fontSize: 14, color: Colors.grey)),
|
||||
Text('${AppLocalizations.of(context).translate('route_planning.work_mode')}:$workMode', style: const TextStyle(fontSize: 14, color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1982,7 +1989,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
child: state.isLoading
|
||||
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white))
|
||||
: const Text('开始作业', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
: Text(AppLocalizations.of(context).translate('route_planning.start_work'), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
@@ -2638,6 +2645,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
child: RouteDirectionPanel(
|
||||
initialOptimalHeading: true,
|
||||
initialDirection: 0.0,
|
||||
titleText: AppLocalizations.of(context).translate('route_planning.route_direction'),
|
||||
optimalHeadingText: AppLocalizations.of(context).translate('route_planning.optimal_heading'),
|
||||
routeDirectionText: AppLocalizations.of(context).translate('route_planning.route_direction'),
|
||||
onValueChanged: (result) {
|
||||
_angle = result['optimalHeading'] == true ? -1 : result['direction'];
|
||||
|
||||
@@ -2687,7 +2697,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'地块列表(共${plotList.length}条)',
|
||||
AppLocalizations.of(context).translate('route_planning.plot_list_title').replaceAll('%d', plotList.length.toString()),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||
),
|
||||
IconButton(
|
||||
@@ -2704,13 +2714,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
const Divider(height: 1, color: Colors.grey),
|
||||
Expanded(
|
||||
child: plotList.isEmpty
|
||||
? const Center(
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.inbox_outlined, color: Colors.grey, size: 48),
|
||||
SizedBox(height: 16),
|
||||
Text('暂无地块数据', style: TextStyle(color: Colors.grey, fontSize: 16)),
|
||||
const Icon(Icons.inbox_outlined, color: Colors.grey, size: 48),
|
||||
const SizedBox(height: 16),
|
||||
Text(AppLocalizations.of(context).translate('route_planning.no_plot_data'), style: const TextStyle(color: Colors.grey, fontSize: 16)),
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -2750,12 +2760,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 4, offset: const Offset(0, 2))],
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.warning_amber_rounded, color: Colors.white, size: 20),
|
||||
SizedBox(width: 8),
|
||||
const Icon(Icons.warning_amber_rounded, color: Colors.white, size: 20),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text('航向角未初始化,无法开始作业', style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||
child: Text(AppLocalizations.of(context).translate('route_planning.heading_not_init'), style: const TextStyle(color: Colors.white, fontSize: 14)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -2775,12 +2785,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 4, offset: const Offset(0, 2))],
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.error_rounded, color: Colors.white, size: 20),
|
||||
SizedBox(width: 8),
|
||||
const Icon(Icons.error_rounded, color: Colors.white, size: 20),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text('请切换到远程模式后再开始作业', style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||
child: Text(AppLocalizations.of(context).translate('route_planning.switch_remote_mode'), style: const TextStyle(color: Colors.white, fontSize: 14)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user