import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:ln_jq_app/common/login_util.dart'; import 'package:ln_jq_app/pages/b_page/reservation/controller.dart'; import 'package:ln_jq_app/pages/c_page/message/view.dart'; class ReservationPage extends GetView { const ReservationPage({super.key}); // 定义主题色 static const kPrimaryColor = Color(0xFF006D35); // 效果图深绿色 static const kBgColor = Color(0xFFF5F7F9); // 背景灰 @override Widget build(BuildContext context) { return GetBuilder( init: ReservationController(), id: 'b_reservation', builder: (_) { return Scaffold( backgroundColor: kBgColor, body: SingleChildScrollView( child: Column( children: [ _buildTopSection(context), Padding( padding: EdgeInsets.symmetric(horizontal: 20.w), child: Column( children: [ SizedBox(height: 16), _buildBasicInfoCard(), SizedBox(height: 16), _buildOperationContentCard(context), SizedBox(height: 16.h), _buildSystemTips(), SizedBox(height: 24), _buildLogoutButton(), SizedBox(height: 75.h), ], ), ), ], ), ), ); }, ); } /// 1. 顶部个人信息及统计栏 Widget _buildTopSection(BuildContext context) { return Container( width: double.infinity, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(bottom: Radius.circular(30)), ), 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( controller.name, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), _buildStatusTag(), ], ), const SizedBox(height: 4), Text( "站点:${controller.address}", style: TextStyle(color: Colors.grey[500], fontSize: 13), ), ], ), ), IconButton( onPressed: () async{ var scanResult = await Get.to(() => const MessagePage()); if (scanResult == null) { controller.msgNotice(); } }, 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("氢气价格", "Hydrogen price", controller.customerPrice, "/kg"), SizedBox(width: 4.w), _buildStatBox("营业时间", "Opening time", controller.timeStr, ""), SizedBox(width: 4.w), _buildStatBox("设备状态", "Anlagenzustand", "98", "%"), ], ), ], ), ); } Widget _buildStatusTag() { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: const Color(0xFFE1F5FE), borderRadius: BorderRadius.circular(10), ), child: Text( controller.selectedOperationStatus, style: TextStyle( color: Color(0xFF03A9F4), fontSize: 12.sp, fontWeight: FontWeight.w600, ), ), ); } 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: kBgColor, 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)), ], ), ], ), ), ); } /// 2. 站点基本信息 Widget _buildBasicInfoCard() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "站点基本信息", style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.bold), ), SizedBox(height: 15), _buildInfoRow("站点名称", controller.name), _buildInfoRow("运营企业", controller.operatingEnterprise), _buildInfoRow("站点地址", controller.address), ], ), ); } Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: TextStyle(color: Colors.grey, fontSize: 11.sp), ), Text( value, style: TextStyle( color: Color(0xFF333333), fontSize: 12.sp, fontWeight: FontWeight.bold, ), ), ], ), ); } /// 3. 运营信息/站点广播 Tab 及内容 Widget _buildOperationContentCard(BuildContext context) { return GestureDetector( onTap: hideKeyboard, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Column( children: [ // 自定义 TabBar Obx( () => Padding( padding: const EdgeInsets.only(left: 16, top: 16), child: Row( children: [ _buildTabTitle(0, "运营信息"), const SizedBox(width: 30), _buildTabTitle(1, "站点广播"), ], ), ), ), Obx( () => controller.selectedTabIndex.value == 0 ? _buildOperatingForm(context) : _buildBroadcastForm(), ), ], ), ), ); } Widget _buildTabTitle(int index, String title) { bool isSelected = controller.selectedTabIndex.value == index; return GestureDetector( onTap: () => controller.selectedTabIndex.value = index, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: isSelected ? Colors.black87 : Colors.grey, ), ), if (isSelected) Container( margin: const EdgeInsets.only(top: 4), width: 25, height: 3, decoration: BoxDecoration( color: const Color(0xFF00A870), // 效果图中的亮绿色横线 borderRadius: BorderRadius.circular(2), ), ), ], ), ); } Widget _buildOperatingForm(BuildContext context) { return Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '运营状态', style: TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontSize: 12.sp, fontWeight: FontWeight.bold, ), ), //加氢站未执行的状态修改任务 if (controller.jobTipStr.isNotEmpty) GestureDetector( onTap: controller.showJob, child: Row( children: [ Text( controller.jobTipStr, style: TextStyle(color: Colors.yellow[800], fontSize: 14), ), SizedBox(width: 2.w), Icon(AntdIcon.info_circle, size: 14, color: Colors.yellow[800]), ], ), ), ], ), const SizedBox(height: 12), // 状态网格选择 Wrap( spacing: 4, runSpacing: 4, children: controller.operationStatusOptions.map((status) { bool isSelected = controller.selectedOperationStatus == status; return GestureDetector( onTap: () => controller.onOperationStatusChanged(status), child: Container( width: (Get.width - 80) / 2, padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: isSelected ? kPrimaryColor : const Color(0xFFEBEBEB), borderRadius: BorderRadius.circular(8), ), alignment: Alignment.center, child: Text( status, style: TextStyle( fontSize: 13.sp, color: isSelected ? Colors.white : Color.fromRGBO(51, 51, 51, 1), fontWeight: FontWeight.w500, ), ), ), ); }).toList(), ), SizedBox(height: 12.h), if (controller.selectedOperationStatus == "营运中") _buildDisplayField(label: '营业时间', value: controller.timeStr) else Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildInputLabel("开始时间"), _buildDateTimePicker( controller.customStartTimeStr, () => controller.pickDateTime(context, true), ), const SizedBox(height: 15), _buildInputLabel("结束时间"), _buildDateTimePicker( controller.customEndTimeStr, () => controller.pickDateTime(context, false), ), const SizedBox(height: 15), ], ), _buildDisplayField(label: '联系电话', value: controller.phone), const SizedBox(height: 25), Row( children: [ Expanded( flex: 1, child: OutlinedButton( onPressed: () { controller.renderData(); }, // 重置逻辑 style: OutlinedButton.styleFrom( side: const BorderSide(color: kPrimaryColor), padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), child: const Text("重置", style: TextStyle(color: kPrimaryColor)), ), ), const SizedBox(width: 15), Expanded( flex: 2, child: ElevatedButton( onPressed: controller.saveInfo, style: ElevatedButton.styleFrom( backgroundColor: kPrimaryColor, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), child: const Text("保存设置", style: TextStyle(color: Colors.white)), ), ), ], ), ], ), ); } Widget _buildDisplayField({required String label, required String value}) { return Padding( padding: const EdgeInsets.only(bottom: 12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontSize: 12.sp, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8.0), border: Border.all(color: Colors.grey[300]!), ), child: Text( value, style: const TextStyle(fontSize: 14, color: Colors.black87), ), ), ], ), ); } Widget _buildBroadcastForm() { return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildInputLabel("通知标题"), TextField( controller: controller.broadcastTitleController, decoration: _inputDecoration("例如:临时闭站通知"), ), const SizedBox(height: 15), _buildInputLabel("通知内容"), TextField( controller: controller.broadcastContentController, maxLines: 4, decoration: _inputDecoration("请输入通知内容..."), ), const SizedBox(height: 20), Row( children: [ Expanded( flex: 1, child: OutlinedButton( onPressed: () { controller.broadcastTitleController.clear(); controller.broadcastContentController.clear(); }, // 重置逻辑 style: OutlinedButton.styleFrom( side: const BorderSide(color: kPrimaryColor), padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), child: const Text("重置", style: TextStyle(color: kPrimaryColor)), ), ), const SizedBox(width: 15), Expanded( flex: 2, child: ElevatedButton( onPressed: controller.sendBroadcast, style: ElevatedButton.styleFrom( backgroundColor: kPrimaryColor, minimumSize: const Size(double.infinity, 50), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), child: const Text("发送广播", style: TextStyle(color: Colors.white)), ), ), ], ), ], ), ); } Widget _buildInputLabel(String label) { return Padding( padding: const EdgeInsets.only(left: 0, bottom: 8), child: Text( label, style: TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontSize: 12.sp, fontWeight: FontWeight.bold, ), ), ); } Widget _buildDateTimePicker(String value, VoidCallback onTap) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 12), decoration: BoxDecoration( border: Border.all(color: const Color(0xFF00A870).withOpacity(0.5)), borderRadius: BorderRadius.circular(10), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(value, style: const TextStyle(color: Colors.black87)), const Icon(Icons.calendar_today_outlined, size: 18, color: Color(0xFF00A870)), ], ), ), ); } InputDecoration _inputDecoration(String hint) { return InputDecoration( hintText: hint, hintStyle: const TextStyle(color: Colors.grey, fontSize: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFFE0E0E0)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFFE0E0E0)), ), contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 12), ); } /// 4. 系统提醒 Widget _buildSystemTips() { return 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( "请您确保所提供的信息准确无误,价格信息也将实时\n更新至用户端", 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), ), ], ), ], ), ); } /// 5. 退出登录按钮 Widget _buildLogoutButton() { return SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: controller.logout, style: ElevatedButton.styleFrom( backgroundColor: Color.fromRGBO(204, 52, 46, 1), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)), elevation: 0, ), child: const Text( "退出登录", style: TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ); } }