调整预约时间格式
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||||
<title>导航规划</title>
|
<title>路径规划</title>
|
||||||
<style>
|
<style>
|
||||||
html, body, #container { width: 100%; height: 100%; margin: 0; }
|
html, body, #container { width: 100%; height: 100%; margin: 0; }
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ class B_BaseWidgetsPage extends GetView<B_BaseWidgetsController> {
|
|||||||
label: '加氢预约',
|
label: '加氢预约',
|
||||||
icon: AntdIcon.orderedlist,
|
icon: AntdIcon.orderedlist,
|
||||||
selectedIcon: AntdIcon.calendar_fill,
|
selectedIcon: AntdIcon.calendar_fill,
|
||||||
badge: '99+',
|
|
||||||
dot: true,
|
|
||||||
),
|
),
|
||||||
NavigationItemModel(
|
NavigationItemModel(
|
||||||
label: '站点信息',
|
label: '站点信息',
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
_buildHeaderStat(controller.costPrice, '氢气价格'),
|
_buildHeaderStat(controller.customerPrice, '氢气价格'),
|
||||||
_buildHeaderStat(controller.timeStr, '营业时间'),
|
_buildHeaderStat(controller.timeStr, '营业时间'),
|
||||||
_buildHeaderStat('98%', '设备状态'),
|
_buildHeaderStat('98%', '设备状态'),
|
||||||
],
|
],
|
||||||
@@ -119,7 +119,7 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
|
|
||||||
// --- 价格信息 ---
|
// --- 价格信息 ---
|
||||||
_buildSectionTitle('价格信息'),
|
_buildSectionTitle('价格信息'),
|
||||||
_buildDisplayField(label: '氢气价格 (元/kg)', value: controller.costPrice),
|
// _buildDisplayField(label: '氢气价格 (元/kg)', value: controller.costPrice),
|
||||||
_buildDisplayField(label: '官方价格 (元/kg)', value: controller.customerPrice),
|
_buildDisplayField(label: '官方价格 (元/kg)', value: controller.customerPrice),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
|||||||
@@ -51,14 +51,11 @@ class BaseWidgetsPage extends GetView<BaseWidgetsController> {
|
|||||||
label: '地图',
|
label: '地图',
|
||||||
icon: AntdIcon.location,
|
icon: AntdIcon.location,
|
||||||
selectedIcon: AntdIcon.location_fill,
|
selectedIcon: AntdIcon.location_fill,
|
||||||
dot: false,
|
|
||||||
),
|
),
|
||||||
NavigationItemModel(
|
NavigationItemModel(
|
||||||
label: '加氢预约',
|
label: '加氢预约',
|
||||||
icon: AntdIcon.orderedlist,
|
icon: AntdIcon.orderedlist,
|
||||||
selectedIcon: AntdIcon.calendar_fill,
|
selectedIcon: AntdIcon.calendar_fill,
|
||||||
badge: '99+',
|
|
||||||
dot: true,
|
|
||||||
),
|
),
|
||||||
NavigationItemModel(
|
NavigationItemModel(
|
||||||
label: '车辆信息',
|
label: '车辆信息',
|
||||||
|
|||||||
@@ -119,68 +119,55 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pickTime(BuildContext context, bool isStartTime) {
|
void pickTime(BuildContext context, bool isStartTime) {
|
||||||
// 确定当前操作的时间和初始值
|
// 1. 确定当前操作的时间和初始值
|
||||||
TimeOfDay initialTime = isStartTime ? startTime.value : endTime.value;
|
TimeOfDay initialTime = isStartTime ? startTime.value : endTime.value;
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
|
|
||||||
// 计算最小可选时间
|
// 2. 准备小时和分钟的数据源
|
||||||
DateTime? minimumDateTime; // 默认为 null,即可选任意时间
|
List<int> hours = List<int>.generate(24, (index) => index);
|
||||||
|
List<int> minutes = [0, 30];
|
||||||
|
|
||||||
// 获取当前选择的日期(年月日)
|
// 3. 计算初始选中的索引
|
||||||
final selectedDay = DateTime(
|
int initialHour = initialTime.hour;
|
||||||
selectedDate.value.year,
|
// 将初始分钟校准到0或30,并找到对应的索引
|
||||||
selectedDate.value.month,
|
int initialMinute = initialTime.minute;
|
||||||
selectedDate.value.day,
|
int minuteIndex = initialMinute < 30 ? 0 : 1;
|
||||||
);
|
initialMinute = minutes[minuteIndex]; // 校准后的分钟
|
||||||
|
|
||||||
// 获取今天的日期(年月日)
|
// 如果校准后导致时间早于当前时间,需要向上调整
|
||||||
|
final selectedDay = DateTime(selectedDate.value.year, selectedDate.value.month, selectedDate.value.day);
|
||||||
final today = DateTime(now.year, now.month, now.day);
|
final today = DateTime(now.year, now.month, now.day);
|
||||||
|
if (selectedDay.isAtSameMomentAs(today)) {
|
||||||
if (isStartTime) {
|
if (initialHour < now.hour || (initialHour == now.hour && initialMinute < now.minute)) {
|
||||||
// 如果是选择开始时间并且日期是 今天
|
initialHour = now.hour;
|
||||||
if (selectedDay.isAtSameMomentAs(today)) {
|
if (now.minute > 30) {
|
||||||
minimumDateTime = now; // 最小可选时间就是现在
|
// 如果当前分钟>30, 则进位到下一小时的0分
|
||||||
}
|
initialHour = (now.hour + 1) % 24;
|
||||||
} else {
|
initialMinute = 0;
|
||||||
// 如果是选择结束时间
|
} else {
|
||||||
// 将开始时间转换为 DateTime 对象
|
// 否则,取30分
|
||||||
final startDateTime = DateTime(
|
initialMinute = 30;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始显示时间
|
// 重新获取校准后的索引
|
||||||
DateTime initialDateTime = DateTime(
|
minuteIndex = minutes.indexOf(initialMinute);
|
||||||
selectedDate.value.year,
|
|
||||||
selectedDate.value.month,
|
|
||||||
selectedDate.value.day,
|
|
||||||
initialTime.hour,
|
|
||||||
initialTime.minute,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 确保初始时间不早于最小时间
|
|
||||||
if (minimumDateTime != null && initialDateTime.isBefore(minimumDateTime)) {
|
|
||||||
initialDateTime = minimumDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime tempTime = initialDateTime;
|
// 4. 创建 FixedExtentScrollController 来控制滚轮的初始位置
|
||||||
|
final FixedExtentScrollController hourController =
|
||||||
|
FixedExtentScrollController(initialItem: hours.indexOf(initialHour));
|
||||||
|
final FixedExtentScrollController minuteController =
|
||||||
|
FixedExtentScrollController(initialItem: minuteIndex);
|
||||||
|
|
||||||
|
// 5. 存储临时选择的值
|
||||||
|
int tempHour = initialHour;
|
||||||
|
int tempMinute = initialMinute;
|
||||||
|
|
||||||
Get.bottomSheet(
|
Get.bottomSheet(
|
||||||
Container(
|
Container(
|
||||||
height: 300,
|
height: 300,
|
||||||
padding: const EdgeInsets.only(top: 6.0),
|
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
@@ -197,75 +184,55 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
children: [
|
children: [
|
||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
onPressed: () => Get.back(),
|
onPressed: () => Get.back(),
|
||||||
child: const Text(
|
child: const Text('取消', style: TextStyle(color: CupertinoColors.systemGrey)),
|
||||||
'取消',
|
|
||||||
style: TextStyle(color: CupertinoColors.systemGrey),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final pickedTempTime = TimeOfDay.fromDateTime(tempTime);
|
final pickedTempTime = TimeOfDay(hour: tempHour, minute: tempMinute);
|
||||||
|
final now = DateTime.now();
|
||||||
|
|
||||||
// 验证条件1:不能选择过去的时间
|
// --- 合并和简化校验逻辑 ---
|
||||||
// 这个验证只在选择【今天】的【开始时间】或【结束时间】时有意义
|
final selectedDateTime = DateTime(
|
||||||
final selectedDay = DateTime(
|
|
||||||
selectedDate.value.year,
|
selectedDate.value.year,
|
||||||
selectedDate.value.month,
|
selectedDate.value.month,
|
||||||
selectedDate.value.day,
|
selectedDate.value.day,
|
||||||
);
|
pickedTempTime.hour,
|
||||||
final today = DateTime(
|
pickedTempTime.minute,
|
||||||
DateTime.now().year,
|
|
||||||
DateTime.now().month,
|
|
||||||
DateTime.now().day,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedDay.isAtSameMomentAs(today) &&
|
// 验证1: 不能选择过去的时间(留出一分钟缓冲)
|
||||||
tempTime.isBefore(DateTime.now())) {
|
if (selectedDateTime.isBefore(now.subtract(const Duration(minutes: 1)))) {
|
||||||
showToast('不能选择过去的时间');
|
showToast('不能选择过去的时间');
|
||||||
return; // 中断执行,不关闭弹窗
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//结束时间必须晚于开始时间
|
// 验证2: 结束时间必须晚于开始时间
|
||||||
if (isStartTime) {
|
if (isStartTime) {
|
||||||
// 已有的结束时间 比较
|
startTime.value = pickedTempTime;
|
||||||
final pickedStartInMinutes =
|
final startInMinutes = pickedTempTime.hour * 60 + pickedTempTime.minute;
|
||||||
pickedTempTime.hour * 60 + pickedTempTime.minute;
|
final endInMinutes = endTime.value.hour * 60 + endTime.value.minute;
|
||||||
final endInMinutes =
|
|
||||||
endTime.value.hour * 60 + endTime.value.minute;
|
|
||||||
|
|
||||||
if (pickedStartInMinutes >= endInMinutes) {
|
// 如果新的开始时间大于等于结束时间,自动将结束时间设置为开始时间+30分钟
|
||||||
// 整结束时间
|
if (startInMinutes >= endInMinutes) {
|
||||||
startTime.value = pickedTempTime;
|
final newEndDateTime = selectedDateTime.add(const Duration(minutes: 30));
|
||||||
final newEndDateTime = tempTime.add(
|
|
||||||
const Duration(minutes: 30),
|
|
||||||
);
|
|
||||||
endTime.value = TimeOfDay.fromDateTime(newEndDateTime);
|
endTime.value = TimeOfDay.fromDateTime(newEndDateTime);
|
||||||
} else {
|
|
||||||
//设置开始时间
|
|
||||||
startTime.value = pickedTempTime;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else { // 正在设置结束时间
|
||||||
// 如果当前正在设置结束时间,我们来和已有的开始时间比较
|
final startInMinutes = startTime.value.hour * 60 + startTime.value.minute;
|
||||||
final pickedEndInMinutes =
|
final endInMinutes = pickedTempTime.hour * 60 + pickedTempTime.minute;
|
||||||
pickedTempTime.hour * 60 + pickedTempTime.minute;
|
|
||||||
final startInMinutes =
|
|
||||||
startTime.value.hour * 60 + startTime.value.minute;
|
|
||||||
|
|
||||||
if (pickedEndInMinutes <= startInMinutes) {
|
if (endInMinutes <= startInMinutes) {
|
||||||
showToast('结束时间必须晚于开始时间');
|
showToast('结束时间必须晚于开始时间');
|
||||||
return; // 中断执行,不关闭弹窗
|
return;
|
||||||
} else {
|
|
||||||
endTime.value = pickedTempTime;
|
|
||||||
}
|
}
|
||||||
|
endTime.value = pickedTempTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.back();
|
Get.back();
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'确认',
|
'确认',
|
||||||
style: TextStyle(
|
style: TextStyle(color: AppTheme.themeColor, fontWeight: FontWeight.bold),
|
||||||
color: AppTheme.themeColor,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -273,14 +240,36 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
),
|
),
|
||||||
const Divider(height: 1, color: Color(0xFFE5E5E5)),
|
const Divider(height: 1, color: Color(0xFFE5E5E5)),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CupertinoDatePicker(
|
child: Row(
|
||||||
mode: CupertinoDatePickerMode.time,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
use24hFormat: true,
|
children: [
|
||||||
initialDateTime: initialDateTime,
|
// 小时选择器
|
||||||
minimumDate: minimumDateTime,
|
Expanded(
|
||||||
onDateTimeChanged: (DateTime newTime) {
|
child: CupertinoPicker(
|
||||||
tempTime = newTime;
|
scrollController: hourController,
|
||||||
},
|
itemExtent: 32.0,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
tempHour = hours[index];
|
||||||
|
},
|
||||||
|
children: hours
|
||||||
|
.map((h) => Center(child: Text(h.toString().padLeft(2, '0'))))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 分钟选择器
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
scrollController: minuteController,
|
||||||
|
itemExtent: 32.0,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
tempMinute = minutes[index];
|
||||||
|
},
|
||||||
|
children: minutes
|
||||||
|
.map((m) => Center(child: Text(m.toString().padLeft(2, '0'))))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -290,6 +279,8 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 用于存储上一次成功预约的信息
|
// 用于存储上一次成功预约的信息
|
||||||
ReservationModel? lastSuccessfulReservation;
|
ReservationModel? lastSuccessfulReservation;
|
||||||
|
|
||||||
@@ -323,7 +314,6 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
|||||||
final startTimeStr = '$dateStr ${formattedStartTime}:00';
|
final startTimeStr = '$dateStr ${formattedStartTime}:00';
|
||||||
if (lastSuccessfulReservation != null &&
|
if (lastSuccessfulReservation != null &&
|
||||||
lastSuccessfulReservation!.id == selectedStationId.value &&
|
lastSuccessfulReservation!.id == selectedStationId.value &&
|
||||||
lastSuccessfulReservation!.hydAmount == ampuntStr &&
|
|
||||||
lastSuccessfulReservation!.startTime == startTimeStr) {
|
lastSuccessfulReservation!.startTime == startTimeStr) {
|
||||||
showToast("请勿重复提交相同的预约");
|
showToast("请勿重复提交相同的预约");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user