补充选择器逻辑
This commit is contained in:
@@ -6,6 +6,9 @@ PODS:
|
||||
- Flutter (1.0.0)
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- MTBBarcodeScanner (5.0.11)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
@@ -13,6 +16,9 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- qr_code_scanner_plus (0.2.6):
|
||||
- Flutter
|
||||
- MTBBarcodeScanner
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -24,12 +30,18 @@ DEPENDENCIES:
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- qr_code_scanner_plus (from `.symlinks/plugins/qr_code_scanner_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- MTBBarcodeScanner
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
@@ -39,12 +51,16 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
qr_code_scanner_plus:
|
||||
:path: ".symlinks/plugins/qr_code_scanner_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
url_launcher_ios:
|
||||
@@ -55,9 +71,12 @@ SPEC CHECKSUMS:
|
||||
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||
qr_code_scanner_plus: 7e087021bc69873140e0754750eb87d867bed755
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
@@ -12,7 +13,11 @@ import 'pages/login/view.dart';
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
WidgetsBinding widgetsBinding = await init(isDebug: true, logTag: '小羚羚');
|
||||
WidgetsBinding widgetsBinding = await init(
|
||||
isDebug: true,
|
||||
logTag: '小羚羚',
|
||||
supportedLocales: [Locale('zh', 'CN')],
|
||||
);
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
|
||||
await GetStorage.init();
|
||||
@@ -38,9 +43,14 @@ void main() async {
|
||||
title: '小羚羚',
|
||||
// 首页入口
|
||||
home: HomePage(),
|
||||
// 推荐使用命名路由,如果配置好了可以取消下面两行的注释
|
||||
// initialRoute: AppPages.INITIAL,
|
||||
// getPages: AppPages.routes,
|
||||
//组件国际化
|
||||
fallbackLocale: Locale('zh', 'CN'),
|
||||
supportedLocales: [Locale('zh', 'CN')],
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
|
||||
// Builder
|
||||
builder: (context, widget) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:getx_scaffold/common/common.dart';
|
||||
@@ -9,117 +10,283 @@ import 'package:ln_jq_app/common/model/vehicle_info.dart';
|
||||
import 'package:ln_jq_app/pages/b_page/site/controller.dart';
|
||||
import 'package:ln_jq_app/storage_service.dart';
|
||||
|
||||
import '../../../common/styles/theme.dart'; // 用于日期格式化
|
||||
import '../../../common/styles/theme.dart';
|
||||
|
||||
class ReservationController extends GetxController with BaseControllerMixin {
|
||||
@override
|
||||
String get builderId => 'reservation';
|
||||
|
||||
// 【修改】使用 Rx 变量,让 GetX 的 Obx/GetX 能够自动监听变化,UI更新更简单
|
||||
// 日期,默认为今天
|
||||
final Rx<DateTime> selectedDate = DateTime.now().obs;
|
||||
|
||||
// 开始时间,默认为当前时分
|
||||
final Rx<TimeOfDay> startTime = TimeOfDay.now().obs;
|
||||
|
||||
// 结束时间,默认为开始时间后30分钟
|
||||
final Rx<TimeOfDay> endTime = TimeOfDay.fromDateTime(
|
||||
DateTime.now().add(const Duration(minutes: 30)),
|
||||
).obs;
|
||||
|
||||
// 预约氢量
|
||||
final TextEditingController amountController = TextEditingController();
|
||||
|
||||
// 车牌号
|
||||
TextEditingController plateNumberController = TextEditingController();
|
||||
|
||||
// 加氢站
|
||||
final List<String> stationOptions = [
|
||||
'诚志AP银河路加氢站',
|
||||
'站点B',
|
||||
'站点C',
|
||||
'站点C',
|
||||
'站点C',
|
||||
'站点C',
|
||||
'站点C',
|
||||
];
|
||||
final List<String> stationOptions = ['诚志AP银河路加氢站', '站点B', '站点C'];
|
||||
final Rx<String> selectedStation = '诚志AP银河路加氢站'.obs;
|
||||
|
||||
// --- 用于UI显示的格式化字符串 (Getters) ---
|
||||
String get formattedDate => DateFormat('yyyy-MM-dd').format(selectedDate.value);
|
||||
|
||||
// 使用 context-aware 的 format 方法
|
||||
String get formattedStartTime => startTime.value.format(Get.context!);
|
||||
String get formattedStartTime => _formatTimeOfDay(startTime.value);
|
||||
|
||||
String get formattedEndTime => endTime.value.format(Get.context!);
|
||||
String get formattedEndTime => _formatTimeOfDay(endTime.value);
|
||||
|
||||
/// --- 交互方法 ---
|
||||
void pickDate(BuildContext context) {
|
||||
DateTime tempDate = selectedDate.value;
|
||||
|
||||
/// 【修改】显示 Flutter 内置的日期选择器
|
||||
void pickDate(BuildContext context) async {
|
||||
// 改为 async
|
||||
final DateTime? pickedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: selectedDate.value,
|
||||
firstDate: DateTime.now(),
|
||||
// 只能从今天开始选
|
||||
lastDate: DateTime.now().add(const Duration(days: 365)),
|
||||
// 假设最多预约一年内
|
||||
helpText: '选择预约日期',
|
||||
confirmText: '确定',
|
||||
cancelText: '取消',
|
||||
Get.bottomSheet(
|
||||
Container(
|
||||
height: 300,
|
||||
padding: const EdgeInsets.only(top: 6.0),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
CupertinoButton(
|
||||
onPressed: () => Get.back(),
|
||||
child: const Text(
|
||||
'取消',
|
||||
style: TextStyle(color: CupertinoColors.systemGrey),
|
||||
),
|
||||
),
|
||||
CupertinoButton(
|
||||
onPressed: () {
|
||||
selectedDate.value = tempDate;
|
||||
Get.back();
|
||||
},
|
||||
child: const Text(
|
||||
'确认',
|
||||
style: TextStyle(
|
||||
color: AppTheme.themeColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1, color: Color(0xFFE5E5E5)),
|
||||
Expanded(
|
||||
child: CupertinoDatePicker(
|
||||
mode: CupertinoDatePickerMode.date,
|
||||
initialDateTime:
|
||||
selectedDate.value.isBefore(
|
||||
DateTime(
|
||||
DateTime.now().year,
|
||||
DateTime.now().month,
|
||||
DateTime.now().day,
|
||||
),
|
||||
)
|
||||
? DateTime(
|
||||
DateTime.now().year,
|
||||
DateTime.now().month,
|
||||
DateTime.now().day,
|
||||
)
|
||||
: selectedDate.value,
|
||||
|
||||
// 【核心】设置最小可选日期为“今天凌晨0点”
|
||||
minimumDate: DateTime(
|
||||
DateTime.now().year,
|
||||
DateTime.now().month,
|
||||
DateTime.now().day,
|
||||
),
|
||||
maximumDate: DateTime.now().add(const Duration(days: 365)),
|
||||
onDateTimeChanged: (DateTime newDate) {
|
||||
tempDate = newDate;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
|
||||
if (pickedDate != null && pickedDate != selectedDate.value) {
|
||||
selectedDate.value = pickedDate;
|
||||
}
|
||||
}
|
||||
|
||||
/// 【修改】显示 Flutter 内置的时间选择器
|
||||
void pickTime(BuildContext context, bool isStartTime) async {
|
||||
// 改为 async
|
||||
void pickTime(BuildContext context, bool isStartTime) {
|
||||
// 1. 确定当前操作的时间和初始值
|
||||
TimeOfDay initialTime = isStartTime ? startTime.value : endTime.value;
|
||||
DateTime now = DateTime.now();
|
||||
|
||||
final TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: initialTime,
|
||||
helpText: isStartTime ? '选择开始时间' : '选择结束时间',
|
||||
confirmText: '确定',
|
||||
cancelText: '取消',
|
||||
// 2.【核心】计算最小可选时间 (Minimum Date)
|
||||
DateTime? minimumDateTime; // 默认为 null,即可选任意时间
|
||||
|
||||
// 获取当前选择的日期(年月日)
|
||||
final selectedDay = DateTime(
|
||||
selectedDate.value.year,
|
||||
selectedDate.value.month,
|
||||
selectedDate.value.day,
|
||||
);
|
||||
|
||||
if (pickedTime != null) {
|
||||
if (isStartTime) {
|
||||
startTime.value = pickedTime;
|
||||
// 如果新的开始时间晚于或等于结束时间,自动将结束时间设置为开始时间后30分钟
|
||||
if ((pickedTime.hour * 60 + pickedTime.minute) >=
|
||||
(endTime.value.hour * 60 + endTime.value.minute)) {
|
||||
final newDateTime = DateTime(
|
||||
selectedDate.value.year,
|
||||
selectedDate.value.month,
|
||||
selectedDate.value.day,
|
||||
pickedTime.hour,
|
||||
pickedTime.minute,
|
||||
).add(const Duration(minutes: 30));
|
||||
endTime.value = TimeOfDay.fromDateTime(newDateTime);
|
||||
}
|
||||
} else {
|
||||
// 确保结束时间不早于开始时间
|
||||
if ((pickedTime.hour * 60 + pickedTime.minute) >
|
||||
(startTime.value.hour * 60 + startTime.value.minute)) {
|
||||
endTime.value = pickedTime;
|
||||
} else {
|
||||
// 如果选择了更早的时间,给出提示
|
||||
Get.snackbar(
|
||||
'时间选择错误',
|
||||
'结束时间必须晚于开始时间',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
}
|
||||
// 获取今天的日期(年月日)
|
||||
final today = DateTime(now.year, now.month, now.day);
|
||||
|
||||
if (isStartTime) {
|
||||
// 如果是选择【开始时间】并且日期是【今天】
|
||||
if (selectedDay.isAtSameMomentAs(today)) {
|
||||
minimumDateTime = now; // 最小可选时间就是现在
|
||||
}
|
||||
} else {
|
||||
// 如果是选择【结束时间】
|
||||
// 将开始时间转换为 DateTime 对象
|
||||
final startDateTime = DateTime(
|
||||
selectedDate.value.year,
|
||||
selectedDate.value.month,
|
||||
selectedDate.value.day,
|
||||
startTime.value.hour,
|
||||
startTime.value.minute,
|
||||
);
|
||||
|
||||
// 结束时间的最小值必须晚于开始时间
|
||||
minimumDateTime = startDateTime;
|
||||
|
||||
// 如果日期是今天,并且开始时间早于现在,那么结束时间的最小值也应该是现在
|
||||
if (selectedDay.isAtSameMomentAs(today) && startDateTime.isBefore(now)) {
|
||||
minimumDateTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 准备 DatePicker 的初始显示时间
|
||||
DateTime initialDateTime = DateTime(
|
||||
selectedDate.value.year,
|
||||
selectedDate.value.month,
|
||||
selectedDate.value.day,
|
||||
initialTime.hour,
|
||||
initialTime.minute,
|
||||
);
|
||||
|
||||
// 确保初始时间不早于最小时间
|
||||
if (minimumDateTime != null && initialDateTime.isBefore(minimumDateTime)) {
|
||||
initialDateTime = minimumDateTime;
|
||||
}
|
||||
|
||||
DateTime tempTime = initialDateTime;
|
||||
|
||||
Get.bottomSheet(
|
||||
Container(
|
||||
height: 300,
|
||||
padding: const EdgeInsets.only(top: 6.0),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
CupertinoButton(
|
||||
onPressed: () => Get.back(),
|
||||
child: const Text(
|
||||
'取消',
|
||||
style: TextStyle(color: CupertinoColors.systemGrey),
|
||||
),
|
||||
),
|
||||
CupertinoButton(
|
||||
onPressed: () {
|
||||
final pickedTempTime = TimeOfDay.fromDateTime(tempTime);
|
||||
|
||||
// 验证条件1:不能选择过去的时间
|
||||
// 这个验证只在选择【今天】的【开始时间】或【结束时间】时有意义
|
||||
final selectedDay = DateTime(
|
||||
selectedDate.value.year,
|
||||
selectedDate.value.month,
|
||||
selectedDate.value.day,
|
||||
);
|
||||
final today = DateTime(
|
||||
DateTime.now().year,
|
||||
DateTime.now().month,
|
||||
DateTime.now().day,
|
||||
);
|
||||
|
||||
if (selectedDay.isAtSameMomentAs(today) &&
|
||||
tempTime.isBefore(DateTime.now())) {
|
||||
showToast('不能选择过去的时间');
|
||||
return; // 中断执行,不关闭弹窗
|
||||
}
|
||||
|
||||
//结束时间必须晚于开始时间
|
||||
if (isStartTime) {
|
||||
// 和【已有的结束时间】比较
|
||||
final pickedStartInMinutes =
|
||||
pickedTempTime.hour * 60 + pickedTempTime.minute;
|
||||
final endInMinutes =
|
||||
endTime.value.hour * 60 + endTime.value.minute;
|
||||
|
||||
if (pickedStartInMinutes >= endInMinutes) {
|
||||
// 在这里,我们不提示错误,而是智能地调整结束时间
|
||||
startTime.value = pickedTempTime;
|
||||
final newEndDateTime = tempTime.add(
|
||||
const Duration(minutes: 30),
|
||||
);
|
||||
endTime.value = TimeOfDay.fromDateTime(newEndDateTime);
|
||||
} else {
|
||||
// 合法,直接设置开始时间
|
||||
startTime.value = pickedTempTime;
|
||||
}
|
||||
} else {
|
||||
// 如果当前正在设置【结束时间】,我们来和【已有的开始时间】比较
|
||||
final pickedEndInMinutes =
|
||||
pickedTempTime.hour * 60 + pickedTempTime.minute;
|
||||
final startInMinutes =
|
||||
startTime.value.hour * 60 + startTime.value.minute;
|
||||
|
||||
if (pickedEndInMinutes <= startInMinutes) {
|
||||
showToast('结束时间必须晚于开始时间');
|
||||
return; // 中断执行,不关闭弹窗
|
||||
} else {
|
||||
// 合法,直接设置结束时间
|
||||
endTime.value = pickedTempTime;
|
||||
}
|
||||
}
|
||||
Get.back();
|
||||
},
|
||||
child: const Text(
|
||||
'确认',
|
||||
style: TextStyle(
|
||||
color: AppTheme.themeColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1, color: Color(0xFFE5E5E5)),
|
||||
Expanded(
|
||||
child: CupertinoDatePicker(
|
||||
mode: CupertinoDatePickerMode.time,
|
||||
use24hFormat: true,
|
||||
initialDateTime: initialDateTime,
|
||||
minimumDate: minimumDateTime,
|
||||
onDateTimeChanged: (DateTime newTime) {
|
||||
tempTime = newTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
|
||||
/// 提交预约
|
||||
@@ -150,7 +317,7 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
var response = await HttpService.to.post(
|
||||
"appointment/orderAddHyd/driverOrderPage",
|
||||
data: {
|
||||
'phone': StorageService.to.userId, // 使用从 renderData 中获取到的 name
|
||||
'phone': StorageService.to.phone, // 使用从 renderData 中获取到的 name
|
||||
'pageNum': 1,
|
||||
'pageSize': 30, // 暂时不考虑分页,一次获取30条
|
||||
},
|
||||
@@ -189,7 +356,7 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
|
||||
Get.bottomSheet(
|
||||
Container(
|
||||
height: Get.height * 0.45,
|
||||
height: Get.height * 0.55,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
@@ -199,6 +366,7 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
//标题
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
|
||||
child: Row(
|
||||
@@ -207,7 +375,7 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
const Text(
|
||||
'我的预约',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
@@ -228,83 +396,91 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: reservationList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final ReservationModel reservation = reservationList[index];
|
||||
return Card(
|
||||
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,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF1890FF),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(
|
||||
0xFFFFF7E6,
|
||||
), // Light orange background
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
reservation.addStatusName,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFFA8C16),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
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: Color.fromARGB(255, 246, 248, 250),
|
||||
margin: const EdgeInsets.only(bottom: 12.0),
|
||||
elevation: 1,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
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,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF1890FF),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(
|
||||
0xFFFFF7E6,
|
||||
), // Light orange background
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
reservation.addStatusName,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFFA8C16),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -344,8 +520,6 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
String name = "";
|
||||
String leftHydrogen = "0";
|
||||
String workEfficiency = "0";
|
||||
|
||||
//累计数据
|
||||
String fillingWeight = "0";
|
||||
String fillingTimes = "0";
|
||||
String plateNumber = "";
|
||||
@@ -355,7 +529,6 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
void onInit() {
|
||||
phone = StorageService.to.phone ?? "";
|
||||
name = StorageService.to.name ?? "";
|
||||
|
||||
getUserBindCarInfo();
|
||||
getSiteList();
|
||||
super.onInit();
|
||||
@@ -457,6 +630,12 @@ class ReservationController extends GetxController with BaseControllerMixin {
|
||||
}
|
||||
}
|
||||
|
||||
String _formatTimeOfDay(TimeOfDay time) {
|
||||
final hour = time.hour.toString().padLeft(2, '0');
|
||||
final minute = time.minute.toString().padLeft(2, '0');
|
||||
return '$hour:$minute';
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
amountController.dispose();
|
||||
|
||||
@@ -310,6 +310,11 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_native_splash:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -489,7 +494,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
name: intl
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
|
||||
@@ -35,6 +35,9 @@ dependencies:
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
getx_scaffold: ^0.2.2
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
|
||||
encrypt: ^5.0.3
|
||||
get_storage: ^2.1.1
|
||||
|
||||
@@ -45,6 +48,8 @@ dependencies:
|
||||
image: ^4.5.4
|
||||
zxing_lib: ^1.1.4
|
||||
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
@@ -52,6 +57,9 @@ dev_dependencies:
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
|
||||
dependency_overrides:
|
||||
intl: 0.19.0
|
||||
|
||||
flutter:
|
||||
|
||||
uses-material-design: true
|
||||
|
||||
Reference in New Issue
Block a user