Files
flutterApp/lib/features/home/presentation/widgets/work_params_card.dart

364 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fpdart/fpdart.dart' hide State;
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
import 'package:maibu_satabot_v2/features/devices/domain/usecases/device_work_hostrirty_usecase.dart';
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_run_hostrity_entity.dart';
import 'package:maibu_satabot_v2/features/devices/domain/errors/device_failure.dart';
import '../../../../core/di/injection.dart';
import '../../../devices/presentation/bloc/devices_cubit.dart';
class WorkParamsCard extends StatefulWidget {
const WorkParamsCard({super.key});
@override
State<WorkParamsCard> createState() => _WorkParamsCardState();
}
class _WorkParamsCardState extends State<WorkParamsCard> {
List<DeviceRunStatisticsEntity>? _statistics;
String? _errorMessage;
bool _isLoading = false; // 默认不加载
@override
Widget build(BuildContext context) {
final deviceState = context.watch<DevicesCubit>().state;
final currentDevice = deviceState.selectedDevice;
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.02),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 4,
height: 16,
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(width: 8),
const Text(
'作业参数',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
],
),
GestureDetector(
onTap: () {
_handleInfoTap(currentDevice); // 包装在同步函数中
}, // 点击事件处理
child: Row(
children: [
Icon(Icons.info, size: 14, color: Colors.grey[400]),
const SizedBox(width: 4),
Text(
'查看详情',
style: TextStyle(fontSize: 12, color: Colors.grey[400]),
),
],
),
),
],
),
const SizedBox(height: 24),
IntrinsicHeight(
child: Row(
children: [
_buildParamItem('作业面积', '0', '亩'), // 默认值
_buildDivider(),
_buildParamItem('作业里程', '0', 'km'),
_buildDivider(),
_buildParamItem('作业时长', '0', 'h'),
],
),
),
],
),
);
}
// 点击事件处理
Future<void> _handleInfoTap(DeviceEntity? currentDevice) async {
print("点击触摸了历史作业");
setState(() {
_isLoading = true; // 开始加载
_errorMessage = null; // 清除错误信息
});
print("开始历史作业");
try {
final useCase = DeviceWorkHostrirty(sl());
print("发送获取历史作业记录开始");
//displayName
final deviceId = currentDevice?.deviceName.toString() ?? '';
final params = BindDeviceParams(deviceId, 'your_device_alias');
final result = await useCase(params);
print("发送获取历史作业记录结束");
result.fold(
(failure) {
setState(() {
_errorMessage = failure.message;
_isLoading = false;
});
},
(data) {
setState(() {
_statistics = data;
_isLoading = false;
});
_showDetailsDialog(context, _statistics!); // 展示弹窗
},
);
} catch (e) {
print("捕获异常: $e");
setState(() {
_errorMessage = '请求失败: $e';
_isLoading = false;
});
}
}
// 弹窗展示详情
// 弹窗展示详情(从底部弹出)
// 弹窗展示详情(从底部弹出,覆盖底部导航栏)
void _showDetailsDialog(
BuildContext context,
List<DeviceRunStatisticsEntity> data,
) {
showModalBottomSheet(
context: context,
isScrollControlled: true, // 支持全屏高度
useRootNavigator: true, // 覆盖底部导航栏
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)), // 顶部圆角
),
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height * 0.75, // 占据屏幕 75% 高度
padding: const EdgeInsets.all(20),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 顶部区域:拖拽指示器 + 标题 + 关闭按钮
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 顶部拖拽指示器(居中改左对齐,和关闭按钮形成布局)
Center(child: Container(width: 40, height: 4)),
const Text(
'历史记录详情',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
// 右上角关闭按钮(X号)
IconButton(
onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.close, color: Colors.grey, size: 24),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
),
],
),
const SizedBox(height: 10),
// 内容区域(增加无数据判断)
Expanded(
child: data.isEmpty
? // 无数据时显示占位
const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.description_outlined,
size: 60,
color: Colors.grey,
),
SizedBox(height: 16),
Text(
'暂无历史记录',
style: TextStyle(
fontSize: 16,
color: Colors.grey,
),
),
],
),
)
: // 有数据时显示列表
SingleChildScrollView(
child: Column(
children: data.map((item) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.05), // 浅蓝背景
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.blue.withOpacity(0.2),
width: 1,
),
),
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.directions_car,
'工作距离',
'${item.distance?.toStringAsFixed(2) ?? '未计算'} km',
),
_buildDetailRow(
Icons.timer,
'花费时间',
'${item.time} 小时',
),
],
),
);
}).toList(),
),
),
),
// 移除原有底部关闭按钮
],
),
);
},
);
}
// 构建详情行
Widget _buildDetailRow(IconData icon, String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
Icon(icon, size: 16, color: Colors.blue),
const SizedBox(width: 8),
Text(
'$label: ',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
Expanded(
child: Text(
value,
style: const TextStyle(fontSize: 14, color: Colors.black54),
),
),
],
),
);
}
// 构建单个参数项
Widget _buildParamItem(String label, String value, String unit) {
return Expanded(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
label == '作业面积'
? Icons.aspect_ratio
: label == '作业里程'
? Icons.local_shipping_outlined
: Icons.access_time,
size: 14,
color: Colors.black38,
),
const SizedBox(width: 4),
Text(
label,
style: const TextStyle(fontSize: 12, color: Colors.black38),
),
],
),
const SizedBox(height: 12),
RichText(
text: TextSpan(
children: [
TextSpan(
text: value,
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
color: Colors.black,
fontFamily: 'Inter',
),
),
TextSpan(
text: ' $unit',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: Colors.black54,
),
),
],
),
),
],
),
);
}
// 垂直分割线
Widget _buildDivider() {
return VerticalDivider(
color: Colors.black.withOpacity(0.05),
thickness: 1,
indent: 10,
endIndent: 10,
);
}
}