import 'package:flutter/material.dart'; import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:ln_jq_app/common/login_util.dart'; import 'package:ln_jq_app/common/styles/theme.dart'; import 'package:ln_jq_app/pages/b_page/history/view.dart'; import 'package:ln_jq_app/pages/c_page/message/view.dart'; import 'controller.dart'; ///加氢预约 class SitePage extends GetView { const SitePage({super.key}); @override Widget build(BuildContext context) { return GetBuilder( init: SiteController(), id: 'site', builder: (_) { return Scaffold( backgroundColor: Color(0xFFF5F7F9), body: SingleChildScrollView(child: _buildView(context)), ); }, ); } // 主视图 Widget _buildView(BuildContext context) { return Column( children: [ // 第一个卡片: 今日预约统计 _buildTopSection(context), Padding( padding: EdgeInsets.only(left: 20.w, right: 20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Padding( padding: EdgeInsets.only(top: 17.h, bottom: 10.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "预约信息", style: TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontWeight: FontWeight.w600, fontSize: 14.sp, ), ), GestureDetector( onTap: () { Get.to( () => HistoryPage(), arguments: {'stationName': controller.name}, ); }, child: Text( '历史记录', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w500, color: Color.fromRGBO(156, 163, 175, 1), ), ), ), ], ), ), // 第二个卡片: 预约信息 Column( children: [ _buildSearchView(), controller.hasReservationData ? _buildReservationListView() : _buildEmptyReservationView(), ], ), //第三部分 Container( padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: const Color(0xFFF1F9F6), // 极浅绿色背景 borderRadius: BorderRadius.circular(10), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( Icons.info_outline, color: Color.fromRGBO(1, 113, 55, 1), size: 20, ), SizedBox(width: 8.w), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "系统提醒", style: TextStyle( color: Color.fromRGBO(1, 113, 55, 1), fontWeight: FontWeight.bold, fontSize: 14.sp, ), ), SizedBox(height: 6.h), Text( "数据每五分钟自动刷新,如需实时更新请下拉页面", style: TextStyle( color: Color.fromRGBO(1, 113, 55, 0.8), fontSize: 12.sp, ), ), SizedBox(height: 6.h), Text( "如有疑问请联系客服:400-021-1773", style: TextStyle( color: Color.fromRGBO(1, 113, 55, 0.8), fontSize: 12.sp, ), ), ], ), ], ), ), ], ), ), ], ); } Widget _buildTopSection(BuildContext context) { return Container( width: double.infinity, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(bottom: Radius.circular(20)), ), padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + 10, left: 20, right: 20, bottom: 25, ), child: Column( children: [ Row( children: [ CircleAvatar( radius: 25, backgroundColor: Colors.white, child: LoginUtil.getAssImg('ic_user_logo@2x'), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( "今日预约统计", style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w400), ), const SizedBox(width: 8), ], ), const SizedBox(height: 4), Text( "Today's Reservation Statistics", style: TextStyle(color: Colors.grey[500], fontSize: 13), ), ], ), ), IconButton( onPressed: () { Get.to(() => const MessagePage()); }, style: IconButton.styleFrom( backgroundColor: Colors.grey[100], padding: const EdgeInsets.all(8), ), icon: Badge( smallSize: 8, backgroundColor: controller.isNotice ? Colors.red : Colors.transparent, child: const Icon( Icons.notifications_outlined, color: Colors.black87, size: 30, ), ), ), ], ), const SizedBox(height: 25), Row( children: [ _buildStatBox("剩余氢量", "remaining quantity", controller.leftHydrogen, "kg"), SizedBox(width: 4.w), _buildStatBox( "今日加氢量", "Have been added", controller.orderTotalAmount, "kg", ), SizedBox(width: 4.w), _buildStatBox( "未加氢总量", "No quantity added", controller.orderUnfinishedAmount, "kg", ), ], ), ], ), ); } Widget _buildStatBox(String title, String enTitle, String value, String unit) { return Expanded( child: Container( padding: EdgeInsets.only(left: 12.w, top: 4.h, bottom: 4.h), decoration: BoxDecoration( color: Color(0xFFF5F7F9), borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 12.sp, color: Color.fromRGBO(51, 51, 51, 0.8), fontWeight: FontWeight.w400, ), ), Text(enTitle, style: const TextStyle(fontSize: 9, color: Colors.grey)), const SizedBox(height: 8), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( value, style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w500, color: Color(0xFF333333), ), ), const SizedBox(width: 2), Text(unit, style: const TextStyle(fontSize: 11, color: Colors.grey)), ], ), ], ), ), ); } //搜索输入框,提示可以输入车牌或者手机 Widget _buildSearchView() { return Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 0), child: Row( children: [ Expanded( child: SizedBox( height: 44, child: TextField( controller: controller.searchController, // 绑定控制器 decoration: InputDecoration( hintText: '输入车牌号或完整手机号查询', contentPadding: const EdgeInsets.symmetric(horizontal: 16), border: OutlineInputBorder( borderRadius: BorderRadius.circular(22), borderSide: BorderSide(color: Colors.grey.shade300), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(22), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(22), borderSide: BorderSide(color: Get.theme.primaryColor, width: 1.5), ), // 清除按钮 suffixIcon: IconButton( icon: const Icon(Icons.clear, size: 20), onPressed: () { controller.searchController.clear(); controller.fetchReservationData(); // 清除后也刷新一次 }, ), ), onSubmitted: (value) { // 用户在键盘上点击“完成”或“搜索”时触发 controller.fetchReservationData(); }, ), ), ), const SizedBox(width: 10), ElevatedButton( onPressed: () { // 点击“搜索”按钮时触发 FocusScope.of(Get.context!).unfocus(); // 收起键盘 controller.fetchReservationData(); }, style: ElevatedButton.styleFrom( shape: const CircleBorder(), padding: const EdgeInsets.all(8), ), child: const Icon(Icons.search_rounded), ), ], ), ); } /// 构建单个统计项 Widget _buildStatItem(String value, String label, {Color valueColor = Colors.blue}) { return Expanded( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( value, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: valueColor, ), ), const SizedBox(height: 4), Text(label, style: const TextStyle(fontSize: 14, color: Colors.grey)), ], ), ); } /// 构建“暂无预约数据”的视图 Widget _buildEmptyReservationView() { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 48.0), color: Colors.white, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.inventory_2_outlined, size: 80, color: Colors.grey[300]), const SizedBox(height: 16), const Text('暂无预约数据', style: TextStyle(fontSize: 16, color: Colors.black54)), const SizedBox(height: 8), const Text( '点击右上角刷新按钮获取最新数据', style: TextStyle(fontSize: 14, color: Colors.grey), ), ], ), ); } /// 构建“有预约数据”的列表视图 Widget _buildReservationListView() { return Container( color: Colors.white, child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), // 因为外层已有滚动,这里禁用内部滚动 itemCount: controller.reservationList.length, padding: const EdgeInsets.all(12.0), itemBuilder: (context, index) { final item = controller.reservationList[index]; // 调用新的方法来构建每一项 return _buildReservationItem(index, item); }, separatorBuilder: (context, index) => const SizedBox(height: 12), // 列表项之间的间距 ), ); } Widget _buildReservationItem(int index, ReservationModel item) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8.0), border: Border.all(color: Colors.grey[200]!, width: 1.0), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), spreadRadius: 1, blurRadius: 3, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // 顶部:序号、车牌号、状态 Padding( padding: const EdgeInsets.fromLTRB(8, 12, 16, 12), child: Row( children: [ // 序号 Container( width: 24, height: 24, alignment: Alignment.center, decoration: const BoxDecoration( color: Colors.blue, shape: BoxShape.circle, ), child: Text( "${index + 1}", style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 8), const Icon(Icons.directions_car, color: Colors.black54), const SizedBox(width: 4), // 车牌号 Expanded( child: Text( item.plateNumber, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: AppTheme.themeColor, ), ), ), // 状态标签 _buildStatusChip(item.status), ], ), ), const Divider(height: 1), // 中部:详细信息 Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), child: Column( children: [ _buildDetailRow( Icons.local_gas_station, '加氢量', item.amount, valueColor: Colors.red, ), const SizedBox(height: 8), _buildDetailRow(Icons.access_time, '预约时间', item.time), const SizedBox(height: 8), _buildDetailRow(Icons.person, '联系人', item.contactPerson), const SizedBox(height: 8), _buildDetailRow( Icons.phone, '联系电话', item.contactPhone, valueColor: AppTheme.themeColor, ), ], ), ), // 底部:操作按钮 (仅在待处理时显示) if (item.status == ReservationStatus.pending) Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 12), child: Row( children: [ Expanded( child: ElevatedButton( onPressed: () => controller.confirmReservation(item.id), style: ElevatedButton.styleFrom(backgroundColor: Colors.blue), child: const Text('确认'), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton( onPressed: () => controller.rejectReservation(item.id), style: ElevatedButton.styleFrom(backgroundColor: Colors.red), child: const Text('拒绝'), ), ), ], ), ), ], ), ); } /// 构建状态标签 Widget _buildStatusChip(ReservationStatus status) { String text; Color color; switch (status) { case ReservationStatus.pending: text = '待加氢'; color = Colors.orange; break; case ReservationStatus.completed: text = '已加氢'; color = Colors.greenAccent; break; case ReservationStatus.rejected: text = '拒绝加氢'; color = Colors.red; break; case ReservationStatus.unadded: text = '未加氢'; color = Colors.red; break; default: text = '未知状态'; color = Colors.grey; break; } return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.circle, color: color, size: 8), const SizedBox(width: 4), Text( text, style: TextStyle(color: color, fontSize: 12, fontWeight: FontWeight.bold), ), ], ), ); } /// 构建信息详情行 Widget _buildDetailRow( IconData icon, String label, String value, { Color valueColor = Colors.black87, }) { return Row( children: [ Icon(icon, color: Colors.grey, size: 20), const SizedBox(width: 8), Text('$label: ', style: const TextStyle(fontSize: 14, color: Colors.grey)), Expanded( child: Text( value, style: TextStyle( fontSize: 14, color: valueColor, fontWeight: FontWeight.w500, ), ), ), ], ); } /// 底部构建带图标的提示信息行 Widget _buildInfoItem(IconData icon, String text) { return Row( children: [ Icon(icon, color: Colors.blue, size: 20), const SizedBox(width: 8), Text(text, style: const TextStyle(fontSize: 14, color: Colors.black54)), ], ); } }