基本完成APP的所有页面中的语言切换支持的开发和设计

This commit is contained in:
2026-04-24 15:24:43 +08:00
parent ba4519125e
commit 2e241cb9f5
26 changed files with 649 additions and 416 deletions

View File

@@ -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)),
),
],
),