diff --git a/ln_jq_app/lib/pages/c_page/reservation/controller.dart b/ln_jq_app/lib/pages/c_page/reservation/controller.dart index 0361370..62f66b5 100644 --- a/ln_jq_app/lib/pages/c_page/reservation/controller.dart +++ b/ln_jq_app/lib/pages/c_page/reservation/controller.dart @@ -434,7 +434,7 @@ class C_ReservationController extends GetxController with BaseControllerMixin { //打开预约列表 Future.delayed(const Duration(milliseconds: 500), () { - getReservationList(); + getReservationList(showPopup: true, addStatus: ''); }); } else { showToast(result.error); @@ -446,16 +446,16 @@ class C_ReservationController extends GetxController with BaseControllerMixin { } /// 状态变量:是否有预约数据 - bool hasReservationData = false; - + final RxBool hasReservationData = false.obs; // 新增预约数据列表 - List reservationList = []; - + final RxList reservationList = [].obs; + final RxBool shouldShowReservationList = false.obs; // --- 用于防抖的 Timer --- Timer? _debounce; //查看预约列表 - void getReservationList() async { + void getReservationList({bool showPopup = false, String? addStatus}) async { + // 增加 addStatus 参数 if (_debounce?.isActive ?? false) { return; } @@ -464,19 +464,26 @@ class C_ReservationController extends GetxController with BaseControllerMixin { showLoading("加载中"); try { + + final Map requestData = { + 'phone': StorageService.to.phone, + 'pageNum': 1, + 'pageSize': 50, + }; + // 将 addStatus 参数添加到请求中 + if (addStatus != null && addStatus.isNotEmpty) { + requestData['addStatus'] = addStatus; + } + var response = await HttpService.to.post( "appointment/orderAddHyd/driverOrderPage", - data: { - 'phone': StorageService.to.phone, // 使用从 renderData 中获取到的 name - 'pageNum': 1, - 'pageSize': 50, // 暂时不考虑分页,一次获取30条 - }, + data: requestData, ); if (response == null || response.data == null) { showToast('暂时无法获取预约数据'); - hasReservationData = false; - reservationList = []; + hasReservationData.value = false; + reservationList.clear(); return; } @@ -485,13 +492,13 @@ class C_ReservationController extends GetxController with BaseControllerMixin { if (baseModel.code == 0 && baseModel.data != null) { final dataMap = baseModel.data as Map; final List listFromServer = dataMap['records'] ?? []; - reservationList = listFromServer.map((item) { + + // 使用 .value 来更新响应式列表 + reservationList.value = listFromServer.map((item) { return ReservationModel.fromJson(item as Map); }).toList(); - // 根据列表是否为空来更新 hasReservationData 状态 - hasReservationData = reservationList.isNotEmpty; - + // 更新 hasEdit 状态 for (var reservation in reservationList) { try { // 获取当前时间和预约的结束时间 @@ -510,206 +517,27 @@ class C_ReservationController extends GetxController with BaseControllerMixin { reservation.hasEdit = false; } } + + hasReservationData.value = reservationList.isNotEmpty; + + if (showPopup) { + shouldShowReservationList.value = true; + } + } else { showToast(baseModel.message); - hasReservationData = false; - reservationList = []; // 清空列表 + hasReservationData.value = false; + reservationList.clear(); } } catch (e) { showToast('获取预约数据失败'); - hasReservationData = false; - reservationList = []; // 清空列表 + hasReservationData.value = false; + reservationList.clear(); } finally { dismissLoading(); } - - Get.bottomSheet( - Container( - height: Get.height * 0.55, - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - ), - ), - child: Column( - children: [ - //标题 - Container( - padding: const EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - '我的预约', - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: Colors.black87, - ), - ), - ElevatedButton( - onPressed: () => Get.back(), - style: ElevatedButton.styleFrom( - elevation: 0, - backgroundColor: Colors.grey[200], - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - ), - ), - child: const Text('关闭', style: TextStyle(color: Colors.black54)), - ), - ], - ), - ), - const Divider(height: 1), - Expanded( - child: !hasReservationData - ? Container( - margin: EdgeInsets.only(top: 40), - child: TextX.bodyLarge('暂无预约', weight: FontWeight.w500), - ) - : ListView.builder( - padding: const EdgeInsets.all(16), - itemCount: reservationList.length, - itemBuilder: (context, index) { - final ReservationModel reservation = reservationList[index]; - return Card( - color: Colors.white, - margin: const EdgeInsets.only(bottom: 12.0), - elevation: 1, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Padding( - padding: EdgeInsets.all(10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - decoration: BoxDecoration( - color: const Color( - 0xFFE6F7FF, - ), // Light blue background - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: const Color(0xFF91D5FF), - ), // Blue border - ), - child: Text( - reservation.stateName + - "-" + - reservation.addStatusName, - style: const TextStyle( - color: Color(0xFF1890FF), - fontWeight: FontWeight.bold, - ), - ), - ), - !reservation.hasEdit - ? SizedBox() - : GestureDetector( - onTap: () async { - var result = await Get.to( - () => ReservationEditPage(), - arguments: { - 'reservation': reservation, - 'difference': difference, - }, - binding: BindingsBuilder(() { - Get.put(ReservationEditController()); - }), - preventDuplicates: false, - ); - if (result == true) { - Get.back(); - getReservationList(); - } - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 4, - ), - decoration: BoxDecoration( - color: const Color( - 0xFFFFF7E6, - ), // Light orange background - borderRadius: BorderRadius.circular(12), - ), - child: Text( - "修改", - style: const TextStyle( - color: Color(0xFFFA8C16), - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - ), - ), - ], - ), - const SizedBox(height: 12), - _buildDetailRow('车牌号:', reservation.plateNumber), - _buildDetailRow('预约日期:', reservation.date), - _buildDetailRow('预约氢量:', reservation.hydAmount), - _buildDetailRow('加氢站:', reservation.stationName), - _buildDetailRow('开始时间:', reservation.startTime), - _buildDetailRow('结束时间:', reservation.endTime), - _buildDetailRow('联系人:', reservation.contacts), - _buildDetailRow('联系电话:', reservation.phone), - reservation.addStatus == "5" - ? _buildDetailRow('拒绝原因:', reservation.rejectReason) - : SizedBox(), - ], - ), - ), - ); - }, - ), - ), - ], - ), - ), - isScrollControlled: true, - backgroundColor: - Colors.transparent, // Make background transparent to see the rounded corners - ); } - Widget _buildDetailRow(String label, String value) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 6.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 85, - child: Text(label, style: TextStyle(color: Colors.grey[600], fontSize: 14)), - ), - Expanded( - child: Text( - value, - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Colors.black87, - ), - ), - ), - ], - ), - ); - } String workEfficiency = "0"; String fillingWeight = "0"; diff --git a/ln_jq_app/lib/pages/c_page/reservation/reservation_list_bottomsheet.dart b/ln_jq_app/lib/pages/c_page/reservation/reservation_list_bottomsheet.dart new file mode 100644 index 0000000..2cad37b --- /dev/null +++ b/ln_jq_app/lib/pages/c_page/reservation/reservation_list_bottomsheet.dart @@ -0,0 +1,245 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:getx_scaffold/common/index.dart'; +import 'package:ln_jq_app/pages/c_page/reservation/controller.dart'; +import 'package:ln_jq_app/pages/c_page/reservation_edit/controller.dart'; +import 'package:ln_jq_app/pages/c_page/reservation_edit/view.dart'; + +//加氢预约列表 +class ReservationListBottomSheet extends StatefulWidget { + const ReservationListBottomSheet({super.key}); + + @override + State createState() => _ReservationListBottomSheetState(); +} + +class _ReservationListBottomSheetState extends State { + final C_ReservationController _controller = Get.find(); + + final Map _statusOptions = { + '': '所有状态', // 增加一个“所有状态”的选项 + '0': '待加氢', + '1': '加氢完成', + '2': '未加氢', + '5': '拒绝加氢', + }; + String _selectedStatus = ''; // 默认选中 '0' (待加氢) + + @override + void initState() { + super.initState(); + // Widget 初始化时,立即调用接口加载默认状态(待加氢)的数据 + _controller.getReservationList(addStatus: _selectedStatus); + } + + @override + Widget build(BuildContext context) { + return Container( + height: Get.height * 0.55, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), + child: Column( + children: [ + // 构建标题和下拉框 + _buildHeader(), + const Divider(height: 1), + // 下拉筛选框 + _buildChoice(), + // 构建列表(使用 Obx 监听数据变化) + _buildList(), + ], + ), + ); + } + + Container _buildChoice() { + return Container( + padding: const EdgeInsets.fromLTRB(20, 8, 0, 0), + alignment: AlignmentGeometry.centerLeft, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(8), + ), + child: DropdownButton( + value: _selectedStatus, + underline: const SizedBox.shrink(), // 隐藏下划线 + items: _statusOptions.entries.map((entry) { + return DropdownMenuItem( + value: entry.key, + child: Text(entry.value), + ); + }).toList(), + onChanged: (newValue) { + if (newValue != null) { + setState(() { + _selectedStatus = newValue; + }); + // 当选择新状态时,调用接口刷新数据 + _controller.getReservationList(addStatus: _selectedStatus); + } + }, + ), + ), + ); + } + + /// 构建标题、关闭按钮和下拉筛选框 + Widget _buildHeader() { + return Container( + padding: const EdgeInsets.fromLTRB(20, 8, 8, 8), + child: Stack( + alignment: Alignment.center, + children: [ + Center(child: const Text('我的预约', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),), + Align( + alignment: Alignment.centerRight, + child: ElevatedButton( + onPressed: () => Get.back(), + style: ElevatedButton.styleFrom( + elevation: 0, + backgroundColor: Colors.grey[200], + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), + ), + child: const Text('关闭', style: TextStyle(color: Colors.black54)), + ), + ), + ], + ), + ); + } + + /// 构建预约列表 + Widget _buildList() { + return Expanded( + child: Obx(() { + if (!_controller.hasReservationData.value) { + return Container( + margin: const EdgeInsets.only(top: 40), + child: TextX.bodyLarge('暂无该状态下的预约', weight: FontWeight.w500), + ); + } + return ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: _controller.reservationList.length, + itemBuilder: (context, index) { + final reservation = _controller.reservationList[index]; + return Card( + color: Colors.white, + margin: const EdgeInsets.only(bottom: 12.0), + elevation: 1, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 状态标签 + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + decoration: BoxDecoration( + color: const Color(0xFFE6F7FF), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: const Color(0xFF91D5FF)), + ), + child: Text( + "${reservation.stateName}-${reservation.addStatusName}", + style: const TextStyle( + color: Color(0xFF1890FF), + fontWeight: FontWeight.bold, + ), + ), + ), + // 修改按钮 (仅在 hasEdit 为 true 时显示) + if (reservation.hasEdit) + GestureDetector( + onTap: () async { + var result = await Get.to( + () => ReservationEditPage(), + arguments: { + 'reservation': reservation, + 'difference': _controller.difference, + }, + binding: BindingsBuilder(() { + Get.put(ReservationEditController()); + }), + preventDuplicates: false, + ); + if (result == true) { + _controller.getReservationList( + addStatus: _selectedStatus, + ); + } + }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 4, + ), + decoration: BoxDecoration( + color: const Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(12), + ), + child: const Text( + "修改", + style: TextStyle( + color: Color(0xFFFA8C16), + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + ), + ), + ], + ), + const SizedBox(height: 12), + _buildDetailRow('车牌号:', reservation.plateNumber), + _buildDetailRow('预约日期:', reservation.date), + _buildDetailRow('预约氢量:', reservation.hydAmount), + _buildDetailRow('加氢站:', reservation.stationName), + _buildDetailRow('开始时间:', reservation.startTime), + _buildDetailRow('结束时间:', reservation.endTime), + _buildDetailRow('联系人:', reservation.contacts), + _buildDetailRow('联系电话:', reservation.phone), + reservation.addStatus == "5" + ? _buildDetailRow('拒绝原因:', reservation.rejectReason) + : SizedBox(), + ], + ), + ), + ); + }, + ); + }), + ); + } + + /// 构建详情行 (这是一个辅助Widget) + Widget _buildDetailRow(String label, String value) { + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + Text(label, style: const TextStyle(color: Colors.grey)), + const SizedBox(width: 8), + Expanded( + child: Text(value, style: const TextStyle(fontWeight: FontWeight.w500)), + ), + ], + ), + ); + } +} diff --git a/ln_jq_app/lib/pages/c_page/reservation/view.dart b/ln_jq_app/lib/pages/c_page/reservation/view.dart index f364712..0d95a51 100644 --- a/ln_jq_app/lib/pages/c_page/reservation/view.dart +++ b/ln_jq_app/lib/pages/c_page/reservation/view.dart @@ -7,10 +7,13 @@ import 'package:ln_jq_app/pages/qr_code/view.dart'; import 'package:ln_jq_app/storage_service.dart'; import 'controller.dart'; +import 'reservation_list_bottomsheet.dart'; ///加氢预约 class ReservationPage extends GetView { - const ReservationPage({super.key}); + ReservationPage({super.key}); + + bool init = false; @override Widget build(BuildContext context) { @@ -18,6 +21,10 @@ class ReservationPage extends GetView { init: C_ReservationController(), id: 'reservation', builder: (_) { + if (!init) { + _setupListener(context); + init = true; + } return Scaffold( backgroundColor: Colors.grey[100], body: GestureDetector( @@ -299,7 +306,9 @@ class ReservationPage extends GetView { const SizedBox(width: 16), Expanded( child: OutlinedButton( - onPressed: controller.getReservationList, + onPressed: () { + controller.getReservationList(showPopup: true, addStatus: ''); + }, style: OutlinedButton.styleFrom( minimumSize: const Size(double.infinity, 38), // 高度与另一个按钮保持一致 side: const BorderSide(color: Colors.blue), @@ -326,6 +335,21 @@ class ReservationPage extends GetView { ); } + void _setupListener(BuildContext context) { + ever(controller.shouldShowReservationList, (bool shouldShow) { + if (shouldShow) { + Get.bottomSheet( + const ReservationListBottomSheet(), + isScrollControlled: true, // 允许弹窗使用更多屏幕高度 + backgroundColor: Colors.transparent, + ); + + // 重要:显示后立即将信号重置为 false,防止不必要的重复弹出 + controller.shouldShowReservationList.value = false; + } + }); + } + // 表单中的可点击行 (用于日期和时间选择) Widget _buildPickerRow({ required String label,