Merge remote-tracking branch 'origin/feature/my' into feature/my
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:maibu_satabot_v2/core/router/route_paths.dart';
|
||||
import 'package:maibu_satabot_v2/features/ai/presentation/routes/ai_routes.dart';
|
||||
import 'package:maibu_satabot_v2/features/auth/presentation/pages/login_page.dart';
|
||||
import 'package:maibu_satabot_v2/features/auth/presentation/routes/auth_routes.dart';
|
||||
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
|
||||
import 'package:maibu_satabot_v2/features/home/presentation/routes/home_routes.dart';
|
||||
import 'package:maibu_satabot_v2/features/my/presentation/routes/my_routes.dart';
|
||||
|
||||
@@ -14,7 +15,6 @@ import 'go_router_refresh_stream.dart';
|
||||
|
||||
GoRouter createRouter(AuthCubit authCubit) {
|
||||
return GoRouter(
|
||||
|
||||
initialLocation: RoutePaths.login,
|
||||
refreshListenable: GoRouterRefreshStream(authCubit.stream),
|
||||
redirect: (context, state) {
|
||||
@@ -33,7 +33,14 @@ GoRouter createRouter(AuthCubit authCubit) {
|
||||
// 注册 machineDetails 路由
|
||||
GoRoute(
|
||||
path: RoutePaths.machineDetails,
|
||||
builder: (context, state) => const MachineDetailsPage(), // 替换为实际页面
|
||||
name: 'machineDetails', // 建议加 name,方便跳转
|
||||
builder: (context, state) {
|
||||
// 从 extra 中取出设备数据(核心)
|
||||
final DeviceEntity? device = state.extra as DeviceEntity?;
|
||||
|
||||
// 跳转到详情页组件,并传入设备数据
|
||||
return MachineDetailsPage(device: device);
|
||||
},
|
||||
),
|
||||
|
||||
// 注册登录注册 路由
|
||||
|
||||
@@ -355,7 +355,9 @@ class ImmersionHeader extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
device.deviceAlias ?? '未知设备',
|
||||
(device.deviceAlias?.trim() ?? '').isEmpty
|
||||
? '未知设备'
|
||||
: device.deviceAlias!,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
@@ -393,8 +395,11 @@ class ImmersionHeader extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
CCPrimaryButton(
|
||||
onPressed: () {
|
||||
context.push(RoutePaths.machineDetails);
|
||||
print("通过按钮进入详情");
|
||||
context.push(
|
||||
RoutePaths.machineDetails,
|
||||
extra: device,
|
||||
); // 把当前点击的这个设备对象传过去
|
||||
print("通过按钮进入详情,设备名称:$device");
|
||||
},
|
||||
|
||||
text: "详情",
|
||||
|
||||
@@ -354,13 +354,20 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
);
|
||||
}
|
||||
|
||||
// ========== 新增:返回上一级页面的方法 ==========
|
||||
void _navigateBack() {
|
||||
// 关闭当前页面,返回上一级
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_positionSub?.cancel();
|
||||
_traceManager.reset();
|
||||
_mapController.dispose();
|
||||
_sub?.cancel();
|
||||
|
||||
// 修复:_sub 是 non-null 类型,直接 cancel 无需 ?
|
||||
_sub.cancel();
|
||||
_plotNameController.dispose(); // 新增:释放文本控制器资源
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -673,8 +680,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
|
||||
/// ========== 新增:中心标与历史打点的虚线连线 ==========
|
||||
///
|
||||
/// if (_markedPoints.length >= 2)
|
||||
PolylineLayer(
|
||||
polylines: [
|
||||
for (int i = 0; i < _markedPoints.length - 1; i++)
|
||||
@@ -771,6 +776,53 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
],
|
||||
),
|
||||
|
||||
// ========== 悬浮返回按钮(核心修改) ==========
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 10,
|
||||
child: GestureDetector(
|
||||
// 自定义点击事件
|
||||
onTap: _navigateBack,
|
||||
// 自定义点击反馈(替代 IconButton 的高亮/水波纹)
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
blurRadius: 3,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
// 核心:用 Stack 实现点击高亮层 + 图标层
|
||||
child: Stack(
|
||||
alignment: Alignment.center, // 所有子组件居中
|
||||
children: [
|
||||
// 1. 点击高亮层(默认隐藏,点击时显示)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent, // 默认透明
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 2. 图标层(绝对居中)
|
||||
const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: Colors.black87,
|
||||
size: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// ========== 核心:地图正中心固定定位标 ==========
|
||||
Positioned(
|
||||
left: 0,
|
||||
@@ -788,45 +840,37 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
//保存按钮
|
||||
if (_saveBoxOpen)
|
||||
Positioned(
|
||||
left: 16,
|
||||
right: 80,
|
||||
top: maxTop > 10 ? 11 : maxTop,
|
||||
child: // 改用小尺寸按钮容器,替代默认大尺寸FloatingActionButton
|
||||
Container(
|
||||
width: 40, // 按钮宽度(默认FAB是56,改为40更小巧)
|
||||
height: 40, // 按钮高度
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF00C853), // 保留绿色主题
|
||||
shape: BoxShape.circle, // 圆形
|
||||
color: const Color(0xFF00C853),
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
blurRadius: 4, // 对应elevation:4的阴影效果
|
||||
offset: const Offset(0, 2), // 阴影偏移
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
_showSavePlotDialog();
|
||||
//// 点击保存按钮的逻辑
|
||||
//// 1. 可以直接调用保存方法
|
||||
//_saveCurrentPath();
|
||||
//// 2. 也可以弹出输入框让用户输入路径名称(推荐)
|
||||
//_showSavePathDialog();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.save,
|
||||
color: Colors.white,
|
||||
size: 18, // 图标尺寸缩小(原20→18)
|
||||
),
|
||||
padding: EdgeInsets.zero, // 移除IconButton默认内边距
|
||||
constraints: const BoxConstraints(), // 解除IconButton尺寸限制
|
||||
icon: const Icon(Icons.save, color: Colors.white, size: 18),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 右侧悬浮菜单
|
||||
Positioned(
|
||||
height: 336,
|
||||
@@ -852,7 +896,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
),
|
||||
),
|
||||
//开始作业面板
|
||||
|
||||
// 底部操作面板
|
||||
if (_isPanelOpen)
|
||||
@@ -879,13 +922,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
setState(() => _currentAreaMode = mode);
|
||||
debugPrint('外部收到区域模式:$mode');
|
||||
},
|
||||
// ========== 绑定加号打点事件 ==========
|
||||
onAddTap: () {
|
||||
_addMarkedPoint(); // 点击加号打点
|
||||
_addMarkedPoint();
|
||||
debugPrint('外部处理加号按钮点击,已添加打点');
|
||||
},
|
||||
onDistanceTap: (distance) {
|
||||
_workDistance = distance; // 更新距离状态
|
||||
_workDistance = distance;
|
||||
debugPrint(
|
||||
'外部处理作业行距距离设置,当前距离:${distance.toStringAsFixed(1)}米',
|
||||
);
|
||||
@@ -920,7 +962,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
);
|
||||
_angle = result['optimalHeading'] == true
|
||||
? -1
|
||||
: result['direction']; // 更新航线方向角状态
|
||||
: result['direction'];
|
||||
debugPrint('外部处理航线方向设置,当前角度:${_angle}');
|
||||
setState(() => _directionBoxOpen = false);
|
||||
},
|
||||
@@ -929,14 +971,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
},
|
||||
),
|
||||
),
|
||||
// 在build方法的Stack中添加抽屉组件
|
||||
|
||||
// 列表面板
|
||||
if (_isListBoxOpen)
|
||||
// 半透明背景 + 底部抽屉
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
// 1. 半透明遮罩(点击关闭抽屉)
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
@@ -947,14 +988,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
child: Container(color: Colors.black.withOpacity(0.3)),
|
||||
),
|
||||
),
|
||||
|
||||
// 2. 底部抽屉主体
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(16), // 顶部圆角
|
||||
top: Radius.circular(16),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
@@ -964,14 +1003,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
],
|
||||
),
|
||||
// 限制抽屉高度(可自定义)
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 600,
|
||||
minHeight: 200,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// 顶部标题栏
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
@@ -980,7 +1017,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
// 标题:显示数据总数
|
||||
Text(
|
||||
'地块列表(共${_plotList.length}条)',
|
||||
style: const TextStyle(
|
||||
@@ -989,8 +1025,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
|
||||
// 关闭按钮
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -1006,14 +1040,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const Divider(height: 1, color: Colors.grey),
|
||||
|
||||
// 列表内容(可滚动)
|
||||
Expanded(
|
||||
child: _plotList.isEmpty
|
||||
? // 空数据提示
|
||||
const Center(
|
||||
? const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
@@ -1034,8 +1064,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
],
|
||||
),
|
||||
)
|
||||
: // 列表项
|
||||
ListView.builder(
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
),
|
||||
|
||||
@@ -117,13 +117,13 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
final result = await useCase(params);
|
||||
print("发送获取历史作业记录结束");
|
||||
result.fold(
|
||||
(failure) {
|
||||
(failure) {
|
||||
setState(() {
|
||||
_errorMessage = failure.message;
|
||||
_isLoading = false;
|
||||
});
|
||||
},
|
||||
(data) {
|
||||
(data) {
|
||||
setState(() {
|
||||
_statistics = data;
|
||||
_isLoading = false;
|
||||
@@ -141,9 +141,12 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
}
|
||||
|
||||
// 弹窗展示详情
|
||||
// 弹窗展示详情(从底部弹出)
|
||||
// 弹窗展示详情(从底部弹出,覆盖底部导航栏)
|
||||
void _showDetailsDialog(BuildContext context, List<DeviceRunStatisticsEntity> data) {
|
||||
// 弹窗展示详情(从底部弹出)
|
||||
// 弹窗展示详情(从底部弹出,覆盖底部导航栏)
|
||||
void _showDetailsDialog(
|
||||
BuildContext context,
|
||||
List<DeviceRunStatisticsEntity> data,
|
||||
) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true, // 支持全屏高度
|
||||
@@ -203,15 +206,31 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildDetailRow(Icons.calendar_today, '开始时间', item.startTime),
|
||||
_buildDetailRow(Icons.calendar_today_outlined, '结束时间', item.endTime),
|
||||
_buildDetailRow(Icons.square_foot, '工作面积', '${item.workArea} 亩'),
|
||||
_buildDetailRow(
|
||||
Icons.calendar_today,
|
||||
'开始时间',
|
||||
item.startTime,
|
||||
),
|
||||
_buildDetailRow(
|
||||
Icons.calendar_today_outlined,
|
||||
'结束时间',
|
||||
item.endTime,
|
||||
),
|
||||
_buildDetailRow(
|
||||
Icons.square_foot,
|
||||
'工作面积',
|
||||
'${item.workArea} 亩',
|
||||
),
|
||||
_buildDetailRow(
|
||||
Icons.directions_car,
|
||||
'工作距离',
|
||||
'${item.distance?.toStringAsFixed(2) ?? '未计算'} km',
|
||||
),
|
||||
_buildDetailRow(Icons.timer, '花费时间', '${item.time} 小时'),
|
||||
_buildDetailRow(
|
||||
Icons.timer,
|
||||
'花费时间',
|
||||
'${item.time} 小时',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -244,9 +263,7 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 构建详情行
|
||||
// 构建详情行
|
||||
Widget _buildDetailRow(IconData icon, String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
@@ -265,10 +282,7 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black54,
|
||||
),
|
||||
style: const TextStyle(fontSize: 14, color: Colors.black54),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -276,9 +290,6 @@ class _WorkParamsCardState extends State<WorkParamsCard> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 构建单个参数项
|
||||
Widget _buildParamItem(String label, String value, String unit) {
|
||||
return Expanded(
|
||||
|
||||
@@ -1,30 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
|
||||
|
||||
class MachineDetailsPage extends StatelessWidget {
|
||||
const MachineDetailsPage({super.key});
|
||||
final DeviceEntity? device; // 接收传过来的设备数据
|
||||
|
||||
const MachineDetailsPage({super.key, this.device});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 移除 MaterialApp,直接返回 Scaffold
|
||||
return const DeviceDetailPage();
|
||||
// 把 device 参数传递给 DeviceDetailPage
|
||||
return DeviceDetailPage(device: device);
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceDetailPage extends StatelessWidget {
|
||||
const DeviceDetailPage({super.key});
|
||||
final DeviceEntity? device; // 定义参数接收设备数据
|
||||
|
||||
// 构造函数接收 device 参数
|
||||
const DeviceDetailPage({super.key, this.device});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 空值校验:无设备数据时显示提示
|
||||
if (device == null) {
|
||||
return const Scaffold(body: Center(child: Text("未获取到设备信息")));
|
||||
}
|
||||
|
||||
// 非空断言:已经校验过 device 非空,放心使用
|
||||
final currentDevice = device!;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFF5F5F5),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: const Text(
|
||||
'设备详情',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios),
|
||||
@@ -35,9 +47,9 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildDeviceStatusCard(),
|
||||
_buildDeviceStatusCard(currentDevice), // 传递设备数据
|
||||
const SizedBox(height: 16),
|
||||
_buildBasicInfoCard(),
|
||||
_buildBasicInfoCard(context, currentDevice), // 传递context和设备数据
|
||||
const SizedBox(height: 16),
|
||||
_buildResourceCenterCard(),
|
||||
const SizedBox(height: 24),
|
||||
@@ -48,8 +60,8 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// 设备状态卡片
|
||||
Widget _buildDeviceStatusCard() {
|
||||
// 设备状态卡片(接收设备数据参数)
|
||||
Widget _buildDeviceStatusCard(DeviceEntity device) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
@@ -58,17 +70,16 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/car.png',
|
||||
width: 380,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
Image.asset('assets/images/car.png', width: 380, fit: BoxFit.contain),
|
||||
const SizedBox(height: 12),
|
||||
const Text(
|
||||
'离线',
|
||||
// 使用设备真实在线状态
|
||||
Text(
|
||||
device.isOnline ? '在线' : '离线',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF999999),
|
||||
color: device.isOnline
|
||||
? const Color(0xFF00C853)
|
||||
: const Color(0xFF999999),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -76,8 +87,17 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// 基本信息卡片
|
||||
Widget _buildBasicInfoCard() {
|
||||
// 基本信息卡片(接收context和设备数据参数)
|
||||
Widget _buildBasicInfoCard(BuildContext context, DeviceEntity device) {
|
||||
// 处理设备名称(空值兜底)
|
||||
final deviceName = (device.deviceAlias?.trim() ?? '').isEmpty
|
||||
? '未知设备'
|
||||
: device.deviceAlias!;
|
||||
// 处理设备ID(空值兜底)
|
||||
final deviceId = device.deviceName ?? '未知ID';
|
||||
//print('激活时间:$device'); // 调试输出激活时间
|
||||
|
||||
//final activeTime = device.activeTime != null ? device.activeTime : '未知时间';
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
@@ -91,47 +111,114 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
padding: EdgeInsets.only(bottom: 16),
|
||||
child: Text(
|
||||
'基本信息',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
style: TextStyle(fontSize: 14, color: Color(0xFF999999)),
|
||||
),
|
||||
),
|
||||
// 设备名称行 - 传递context参数
|
||||
_buildInfoRow(
|
||||
context: context, // 关键:补上必填的context参数
|
||||
icon: Icons.info_outline,
|
||||
label: '设备名称',
|
||||
trailing: Row(
|
||||
children: const [
|
||||
Text(''),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.edit, size: 16, color: Color(0xFF007AFF)),
|
||||
mainAxisSize: MainAxisSize.min, // 防止Row撑满宽度
|
||||
children: [
|
||||
// 显示真实设备名称
|
||||
Text(deviceName),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.edit, size: 16, color: Color(0xFF007AFF)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 32, color: Color(0xFFF0F0F0)),
|
||||
// 设备ID行 - 传递context参数
|
||||
// 设备ID行 - 传递context参数
|
||||
_buildInfoRow(
|
||||
context: context,
|
||||
icon: Icons.shield_outlined,
|
||||
label: '设备ID',
|
||||
trailing: Row(
|
||||
children: const [
|
||||
Text('undefined'),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.copy, size: 16, color: Color(0xFF999999)),
|
||||
trailing: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end, // 右对齐
|
||||
mainAxisSize: MainAxisSize.min, // 只占必要高度
|
||||
children: [
|
||||
// 核心修改:去掉宽度限制,允许换行显示全部ID
|
||||
SizedBox(
|
||||
// 取消固定宽度,让文本自适应(也可设置最大宽度适配屏幕)
|
||||
width:
|
||||
MediaQuery.of(context).size.width - 180, // 适配屏幕宽度(避免超出)
|
||||
child: GestureDetector(
|
||||
onLongPress: () {
|
||||
// 长按文本复制
|
||||
Clipboard.setData(ClipboardData(text: deviceId));
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('设备ID已复制'),
|
||||
duration: Duration(seconds: 1),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
deviceId,
|
||||
textAlign: TextAlign.right, // 右对齐更美观
|
||||
softWrap: true, // 允许换行
|
||||
overflow: TextOverflow.visible, // 显示全部内容(无省略号)
|
||||
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4), // 文本和复制图标间距
|
||||
// 复制图标单独一行
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: deviceId));
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('设备ID已复制到剪贴板'),
|
||||
duration: Duration(seconds: 1),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.copy,
|
||||
size: 16,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
),
|
||||
|
||||
//_buildInfoRow(
|
||||
// context: context, // 关键:补上必填的context参数
|
||||
// icon: Icons.info_outline,
|
||||
// label: '激活时间',
|
||||
// trailing: Row(
|
||||
// mainAxisSize: MainAxisSize.min, // 防止Row撑满宽度
|
||||
// children: [
|
||||
// // 显示真实设备名称
|
||||
// Text(activeTime),
|
||||
// const SizedBox(width: 8),
|
||||
// const Icon(
|
||||
// Icons.edit,
|
||||
// size: 16,
|
||||
// color: Color(0xFF007AFF),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
//),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 32, color: Color(0xFFF0F0F0)),
|
||||
_buildInfoRow(
|
||||
icon: Icons.date_range_outlined,
|
||||
label: '激活时间',
|
||||
trailing: const Text(''),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 资源中心卡片
|
||||
// 资源中心卡片(无设备数据依赖)
|
||||
Widget _buildResourceCenterCard() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -146,10 +233,7 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
padding: EdgeInsets.only(bottom: 16),
|
||||
child: Text(
|
||||
'资源中心',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
style: TextStyle(fontSize: 14, color: Color(0xFF999999)),
|
||||
),
|
||||
),
|
||||
_buildResourceItem('使用说明', Icons.description_outlined),
|
||||
@@ -160,8 +244,9 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// 信息行组件
|
||||
// 信息行组件(添加context必填参数)
|
||||
Widget _buildInfoRow({
|
||||
required BuildContext context, // 必填的context参数
|
||||
required IconData icon,
|
||||
required String label,
|
||||
required Widget trailing,
|
||||
@@ -170,10 +255,7 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
children: [
|
||||
Icon(icon, size: 18, color: const Color(0xFF999999)),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
Text(label, style: const TextStyle(fontSize: 16)),
|
||||
const Spacer(),
|
||||
trailing,
|
||||
],
|
||||
@@ -186,10 +268,7 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
children: [
|
||||
Icon(icon, size: 18, color: const Color(0xFF007AFF)),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
Text(title, style: const TextStyle(fontSize: 16)),
|
||||
const Spacer(),
|
||||
const Icon(Icons.arrow_forward_ios, size: 16, color: Color(0xFF999999)),
|
||||
],
|
||||
@@ -213,18 +292,19 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
// 实现解绑逻辑
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: const Text('确认解绑'),
|
||||
content: const Text('确定要解绑该设备吗?'),
|
||||
content: Text('确定要解绑【${device?.deviceAlias ?? '该设备'}】吗?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.pop(dialogContext),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
// 执行解绑操作
|
||||
Navigator.pop(dialogContext);
|
||||
// 执行解绑操作(传入设备ID)
|
||||
// _unbindDevice(device?.deviceName ?? '');
|
||||
},
|
||||
child: const Text('确认'),
|
||||
),
|
||||
@@ -237,13 +317,15 @@ class DeviceDetailPage extends StatelessWidget {
|
||||
children: [
|
||||
Icon(Icons.unarchive_outlined, size: 18),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
'解绑设备',
|
||||
style: TextStyle(fontSize: 12),
|
||||
),
|
||||
Text('解绑设备', style: TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 可选:解绑设备的方法(根据你的业务实现)
|
||||
// void _unbindDevice(String deviceId) {
|
||||
// // 调用解绑接口的逻辑
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user