ui调整 # Conflicts: # ln_jq_app/lib/pages/b_page/reservation/controller.dart # ln_jq_app/lib/pages/b_page/site/controller.dart # ln_jq_app/lib/pages/b_page/site/view.dart # ln_jq_app/lib/pages/c_page/mine/view.dart # ln_jq_app/lib/pages/c_page/reservation/controller.dart # ln_jq_app/lib/pages/c_page/reservation/view.dart # ln_jq_app/lib/pages/login/view.dart
642 lines
21 KiB
Dart
642 lines
21 KiB
Dart
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<ReservationController> {
|
||
const ReservationPage({super.key});
|
||
|
||
// 定义主题色
|
||
static const kPrimaryColor = Color(0xFF006D35); // 效果图深绿色
|
||
static const kBgColor = Color(0xFFF5F7F9); // 背景灰
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return GetBuilder<ReservationController>(
|
||
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: 40),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
/// 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: () {
|
||
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("氢气价格", "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: 11.sp,
|
||
color: isSelected ? Colors.white : Color.fromRGBO(51, 51, 51, 1),
|
||
fontWeight: FontWeight.w400,
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}).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,
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|