diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..f8b4888 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6b61141 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/mahjong_group.slnx/FileContentIndex/4e1cb05d-a98f-480e-8bd8-2f960369bf35.vsidx b/.vs/mahjong_group.slnx/FileContentIndex/4e1cb05d-a98f-480e-8bd8-2f960369bf35.vsidx new file mode 100644 index 0000000..c6ff033 Binary files /dev/null and b/.vs/mahjong_group.slnx/FileContentIndex/4e1cb05d-a98f-480e-8bd8-2f960369bf35.vsidx differ diff --git a/.vs/mahjong_group.slnx/v18/.wsuo b/.vs/mahjong_group.slnx/v18/.wsuo new file mode 100644 index 0000000..e53ebf0 Binary files /dev/null and b/.vs/mahjong_group.slnx/v18/.wsuo differ diff --git a/.vs/mahjong_group.slnx/v18/DocumentLayout.json b/.vs/mahjong_group.slnx/v18/DocumentLayout.json new file mode 100644 index 0000000..f1c3847 --- /dev/null +++ b/.vs/mahjong_group.slnx/v18/DocumentLayout.json @@ -0,0 +1,23 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\CodeManage\\Coreshop\\uniapp\\mahjong_group\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": -1, + "Children": [ + { + "$type": "Bookmark", + "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/.vs/mahjong_group/v18/workspaceFileList.bin b/.vs/mahjong_group/v18/workspaceFileList.bin new file mode 100644 index 0000000..48eae38 Binary files /dev/null and b/.vs/mahjong_group/v18/workspaceFileList.bin differ diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..32f3ee2 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/common/env.js b/common/env.js index 4c3b536..7886db2 100644 --- a/common/env.js +++ b/common/env.js @@ -8,8 +8,8 @@ const development = { // API基础URL baseUrl: 'https://sqqp.zpc-xy.com', host: ['https://sqqp.zpc-xy.com'], - // baseUrl: 'http://192.168.195.15:2401', - // host: ['http://192.168.195.15:2401'], + // baseUrl: 'http://192.168.1.21:2016', + // host: ['http://192.168.1.21:2016'], // baseUrl: 'http://192.168.1.24:2016', // host: ['http://192.168.1.24:2016'], imageUrl: 'https://guyu-1308826010.cos.ap-shanghai.myqcloud.com', diff --git a/pages/appointment/appointment-page.vue b/pages/appointment/appointment-page.vue index b6aeb8a..dc1dce4 100644 --- a/pages/appointment/appointment-page.vue +++ b/pages/appointment/appointment-page.vue @@ -14,23 +14,40 @@ - - - 加载时段信息中... - - - - 当前日期该房间暂无可预约时段 - + + + {{ startTime || '请选择开始时间' }} + - - - {{ getLatestDateTimeDisplayText() }} + + + + {{ endTime || '请选择结束时间' }} + + + 当天 + / + 次日 + - + + + + 预计时长: + {{ calculateDuration() }} + + + 跨越时段: + {{ calculateCrossSlots() }} + + + + + {{ timeError }} + + @@ -137,14 +154,9 @@ - - @@ -224,25 +236,19 @@ const lineHeight = ref("15rpx") // 房间页跳转相关 const selectedDate = ref(null) // 选中的日期时间戳(秒级) - const selectedTimeSlot = ref(null) // 选中的时段类型 0-3,null表示未选择 const roomDetail = ref(null) // 房间详情数据 const roomDetailLoading = ref(false) // 房间详情加载状态 - const timeSlotOptions = ref([]) // 时间段选项,从房间详情动态生成 + // 自由时间选择相关 + const startTime = ref('') // 开始时间 "HH:mm" + const endTime = ref('') // 结束时间 "HH:mm" + const timeError = ref('') // 时间错误提示 + const isNextDay = ref(false) // 结束时间是否为次日(用于通宵预约) // 日期选择器状态 const datePickerVisible = ref(false) const datePickerValue = ref(Date.now()) const datePickerMinDate = ref(Date.now()) // 最小日期为今天 // 最大日期为未来7天(今天+未来6天) const datePickerMaxDate = ref(new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).getTime()) - // 最晚到店时间选择器状态 - const latestDateTimePickerVisible = ref(false) - const latestDateTimePickerValue = ref('00:00') // 时间选择器值(HH:MM格式字符串) - const latestDateTime = ref(null) // 最晚到店时间(秒级时间戳) - // 时间选择器范围限制 - const latestDateTimeMinHour = ref(0) - const latestDateTimeMaxHour = ref(23) - const latestDateTimeMinMinute = ref(0) - const latestDateTimeMaxMinute = ref(59) //提交表单数据 const reservationInfo = ref({ room_id: 0, //房间id 非空 @@ -384,14 +390,15 @@ // 更新选中的日期 selectedDate.value = selectedTimestamp; - - // 重置时段选择 - selectedTimeSlot.value = null; + + // 重置时间选择 + startTime.value = ''; + endTime.value = ''; + timeError.value = ''; + isNextDay.value = false; // 重置跨天标记 reservationInfo.value.start_time = 0; reservationInfo.value.end_time = 0; - // 重置最晚到店时间 - latestDateTime.value = null; - + // 重新加载房间详情 if (reservationInfo.value.room_id) { console.log('重新加载房间详情, roomId:', reservationInfo.value.room_id, 'date:', selectedTimestamp); @@ -400,284 +407,204 @@ datePickerVisible.value = false; } + /** - * 获取最晚到店时间显示文本 + * 开始时间变更处理 */ - const getLatestDateTimeDisplayText = () => { - if (!latestDateTime.value) { - return '请选择最晚到店时间'; - } - const date = new Date(latestDateTime.value * 1000); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - return `${year}-${month}-${day} ${hours}:${minutes}`; + const onStartTimeChange = (e) => { + startTime.value = e.detail.value; + validateTimeRange(); + buildTimeFromPicker(); } + /** - * 获取时间段的时间范围限制 + * 结束时间变更处理 */ - const getTimeSlotRange = () => { - if (!selectedTimeSlot.value || selectedTimeSlot.value === null || selectedTimeSlot.value === undefined) { - return { minHour: 0, maxHour: 23, minMinute: 0, maxMinute: 59 }; - } - - let minHour = 0, maxHour = 23, minMinute = 0, maxMinute = 59; - - switch (selectedTimeSlot.value) { - case 0: // 凌晨 00:00-05:59 - minHour = 0; - maxHour = 5; - minMinute = 0; - maxMinute = 59; - break; - case 1: // 上午 06:00-11:59 - minHour = 6; - maxHour = 11; - minMinute = 0; - maxMinute = 59; - break; - case 2: // 下午 12:00-17:59 - minHour = 12; - maxHour = 17; - minMinute = 0; - maxMinute = 59; - break; - case 3: // 晚上 18:00-23:59 - minHour = 18; - maxHour = 23; - minMinute = 0; - maxMinute = 59; - break; - } - - return { minHour, maxHour, minMinute, maxMinute }; + const onEndTimeChange = (e) => { + endTime.value = e.detail.value; + // 自动判断是否需要切换到次日 + autoDetectNextDay(); + validateTimeRange(); + buildTimeFromPicker(); } - + /** - * 打开最晚到店时间选择器 + * 自动检测是否需要切换到次日(当结束时间小于开始时间时) */ - const openLatestDateTimePicker = () => { - if (!selectedDate.value) { - uni.showToast({ - title: '请先选择日期', - icon: 'none' - }); - return; + const autoDetectNextDay = () => { + if (!startTime.value || !endTime.value) return; + + const [startH, startM] = startTime.value.split(':').map(Number); + const [endH, endM] = endTime.value.split(':').map(Number); + const startMinutes = startH * 60 + startM; + const endMinutes = endH * 60 + endM; + + // 如果结束时间小于开始时间,自动切换到次日 + if (endMinutes <= startMinutes) { + isNextDay.value = true; } - - if (!selectedTimeSlot.value || selectedTimeSlot.value === null || selectedTimeSlot.value === undefined) { - uni.showToast({ - title: '请先选择时间段', - icon: 'none' - }); - return; - } - - // 设置时间段范围限制 - const timeRange = getTimeSlotRange(); - latestDateTimeMinHour.value = timeRange.minHour; - latestDateTimeMaxHour.value = timeRange.maxHour; - latestDateTimeMinMinute.value = timeRange.minMinute; - latestDateTimeMaxMinute.value = timeRange.maxMinute; - - // 如果有选择时间段,使用自动计算的时间 - updateLatestDateTimeFromSlot(); - - // 将时间戳转换为 HH:MM 格式字符串 - let timeString = null; - if (latestDateTime.value) { - const date = new Date(latestDateTime.value * 1000); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - timeString = `${hours}:${minutes}`; - } else { - // 默认使用时间段开始时间+30分钟 - const timeRangeForDefault = getTimeSlotRange(); - let defaultHour = timeRangeForDefault.minHour; - let defaultMinute = 30; - if (defaultMinute > timeRangeForDefault.maxMinute) { - defaultMinute = timeRangeForDefault.maxMinute; - } - timeString = `${String(defaultHour).padStart(2, '0')}:${String(defaultMinute).padStart(2, '0')}`; - } - - // 确保时间字符串格式正确(必须是 "HH:MM" 格式) - if (timeString && typeof timeString === 'string' && timeString.match(/^\d{2}:\d{2}$/)) { - latestDateTimePickerValue.value = timeString; - } else { - // 如果格式不正确,使用时间段开始时间作为默认值 - const timeRangeForFallback = getTimeSlotRange(); - latestDateTimePickerValue.value = `${String(timeRangeForFallback.minHour).padStart(2, '0')}:00`; - } - - // 确保值设置完成后再打开选择器 - nextTick(() => { - latestDateTimePickerVisible.value = true; - }); } + /** - * 最晚到店时间选择器确认 + * 设置结束时间是否为次日 */ - const onLatestDateTimePickerConfirm = async (e) => { - // up-datetime-picker mode="time" 时,v-model 绑定的值应该是 "HH:MM" 格式字符串 - // 事件参数 e 可能是对象 { value: "HH:MM", mode: 'time' } 或直接是字符串 "HH:MM" - let timeString = latestDateTimePickerValue.value; - - // 如果 v-model 的值无效,尝试从事件参数获取 - if (!timeString || typeof timeString !== 'string') { - if (e && typeof e === 'object' && e.value !== undefined) { - timeString = e.value; - } else if (typeof e === 'string') { - timeString = e; - } + const setNextDay = (value) => { + isNextDay.value = value; + validateTimeRange(); + buildTimeFromPicker(); + } + + /** + * 验证时间范围(支持跨天预约) + */ + const validateTimeRange = () => { + timeError.value = ''; + + if (!startTime.value || !endTime.value) { + return true; } - - // 验证时间字符串格式 - if (!timeString || typeof timeString !== 'string' || !timeString.includes(':')) { - console.error('时间选择器返回的值格式无效:', e, 'latestDateTimePickerValue:', latestDateTimePickerValue.value); - uni.showToast({ - title: '时间选择失败,请重试', - icon: 'none' - }); - latestDateTimePickerVisible.value = false; + + const [startH, startM] = startTime.value.split(':').map(Number); + const [endH, endM] = endTime.value.split(':').map(Number); + const startMinutes = startH * 60 + startM; + let endMinutes = endH * 60 + endM; + + // 如果是次日,结束时间加24小时 + if (isNextDay.value) { + endMinutes += 24 * 60; + } + + // 计算时长(分钟) + const durationMinutes = endMinutes - startMinutes; + + if (durationMinutes <= 0) { + timeError.value = '结束时间必须晚于开始时间'; + return false; + } + + if (durationMinutes < 60) { + timeError.value = '预约时长不能少于1小时'; + return false; + } + + if (durationMinutes > 720) { + timeError.value = '预约时长不能超过12小时'; + return false; + } + + return true; + } + + /** + * 构建时间戳(从时间选择器值,支持跨天预约) + */ + const buildTimeFromPicker = () => { + if (!selectedDate.value || !startTime.value || !endTime.value) { return; } - - // 解析时间字符串 "HH:MM" - const timeParts = timeString.split(':'); - if (timeParts.length !== 2) { - console.error('时间格式错误:', timeString); - uni.showToast({ - title: '时间格式错误', - icon: 'none' - }); - latestDateTimePickerVisible.value = false; + + if (!validateTimeRange()) { + // 清空时间戳 + reservationInfo.value.start_time = 0; + reservationInfo.value.end_time = 0; return; } - - const hours = parseInt(timeParts[0], 10); - const minutes = parseInt(timeParts[1], 10); - - if (isNaN(hours) || isNaN(minutes) || hours < 0 || hours > 23 || minutes < 0 || minutes > 59) { - console.error('时间值无效:', hours, minutes); - uni.showToast({ - title: '时间值无效', - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; - } - - // 验证选择的时间是否在时间段范围内 - if (selectedTimeSlot.value !== null && selectedTimeSlot.value !== undefined) { - const timeRange = getTimeSlotRange(); - if (hours < timeRange.minHour || hours > timeRange.maxHour) { - uni.showToast({ - title: `时间必须在 ${timeRange.minHour}:00-${timeRange.maxHour}:59 范围内`, - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; - } - if (hours === timeRange.minHour && minutes < timeRange.minMinute) { - uni.showToast({ - title: `时间必须在 ${timeRange.minHour}:${String(timeRange.minMinute).padStart(2, '0')}-${timeRange.maxHour}:59 范围内`, - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; - } - if (hours === timeRange.maxHour && minutes > timeRange.maxMinute) { - uni.showToast({ - title: `时间必须在 ${timeRange.minHour}:00-${timeRange.maxHour}:${String(timeRange.maxMinute).padStart(2, '0')} 范围内`, - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; - } - } - - // 如果没有选择日期,使用当前日期 - if (!selectedDate.value) { - uni.showToast({ - title: '请先选择日期', - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; - } - - // 将选择的日期和时间组合 + const date = new Date(selectedDate.value * 1000); - const year = date.getFullYear(); - const month = date.getMonth(); - const day = date.getDate(); - const dateTime = new Date(year, month, day, hours, minutes, 0); - - // 转换为秒级时间戳 - const selectedTimestamp = Math.floor(dateTime.getTime() / 1000); - - // 验证转换后的时间戳是否有效 - if (isNaN(selectedTimestamp) || selectedTimestamp <= 0) { - console.error('时间戳转换失败:', dateTime, selectedTimestamp); - uni.showToast({ - title: '时间处理失败', - icon: 'none' - }); - latestDateTimePickerVisible.value = false; - return; + const [startH, startM] = startTime.value.split(':').map(Number); + const [endH, endM] = endTime.value.split(':').map(Number); + + const startDateTime = new Date(date.getFullYear(), date.getMonth(), date.getDate(), startH, startM, 0); + + // 如果是次日,结束时间加1天 + let endDateTime; + if (isNextDay.value) { + const nextDay = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1, endH, endM, 0); + endDateTime = nextDay; + } else { + endDateTime = new Date(date.getFullYear(), date.getMonth(), date.getDate(), endH, endM, 0); } - - // 更新最晚到店时间 - latestDateTime.value = selectedTimestamp; - - latestDateTimePickerVisible.value = false; + + reservationInfo.value.start_time = Math.floor(startDateTime.getTime() / 1000); + reservationInfo.value.end_time = Math.floor(endDateTime.getTime() / 1000); } + /** - * 根据时间段自动更新最晚到店时间(时间段开始时间+30分钟) + * 计算时长显示(支持跨天预约) */ - const updateLatestDateTimeFromSlot = () => { - if (!selectedDate.value || selectedTimeSlot.value === null || selectedTimeSlot.value === undefined) { - return; + const calculateDuration = () => { + if (!startTime.value || !endTime.value) return '-'; + + const [startH, startM] = startTime.value.split(':').map(Number); + const [endH, endM] = endTime.value.split(':').map(Number); + let endMinutes = endH * 60 + endM; + + // 如果是次日,结束时间加24小时 + if (isNextDay.value) { + endMinutes += 24 * 60; } - - // 将日期时间戳转换为日期对象 - const date = new Date(selectedDate.value * 1000); - const year = date.getFullYear(); - const month = date.getMonth(); - const day = date.getDate(); - - // 根据时段类型设置开始时间 - let startHour = 0; - let startMinute = 30; // 默认加30分钟 - - switch (selectedTimeSlot.value) { - case 0: // 凌晨 00:00-05:59 - startHour = 0; - startMinute = 30; - break; - case 1: // 上午 06:00-11:59 - startHour = 6; - startMinute = 30; - break; - case 2: // 下午 12:00-17:59 - startHour = 12; - startMinute = 30; - break; - case 3: // 晚上 18:00-23:59 - startHour = 18; - startMinute = 30; - break; + + const diffMinutes = endMinutes - (startH * 60 + startM); + + if (diffMinutes <= 0) return '-'; + + const hours = Math.floor(diffMinutes / 60); + const mins = diffMinutes % 60; + + if (mins === 0) { + return `${hours}小时`; } - - // 创建最晚到店时间(开始时间+30分钟) - const latestDateTimeObj = new Date(year, month, day, startHour, startMinute, 0); - - // 转换为秒级时间戳 - latestDateTime.value = Math.floor(latestDateTimeObj.getTime() / 1000); + return `${hours}小时${mins}分钟`; } + + /** + * 计算跨越时段(支持跨天预约) + */ + const calculateCrossSlots = () => { + if (!startTime.value || !endTime.value) return '-'; + + const [startH] = startTime.value.split(':').map(Number); + const [endH] = endTime.value.split(':').map(Number); + + const slots = []; + const ranges = [ + { name: '凌晨', start: 0, end: 6 }, + { name: '上午', start: 6, end: 12 }, + { name: '下午', start: 12, end: 18 }, + { name: '晚上', start: 18, end: 24 } + ]; + + if (isNextDay.value) { + // 跨天预约:当天的时段 + 次日的时段 + // 当天:从开始时间到24点 + for (const r of ranges) { + if (startH < r.end && 24 > r.start) { + if (!slots.includes(r.name)) { + slots.push(r.name); + } + } + } + // 次日:从0点到结束时间 + for (const r of ranges) { + if (0 < r.end && endH > r.start) { + if (!slots.includes(r.name)) { + slots.push(r.name); + } + } + } + } else { + // 同一天:正常判断 + for (const r of ranges) { + // 重叠判断:预约开始 < 时段结束 AND 预约结束 > 时段开始 + if (startH < r.end && endH > r.start) { + slots.push(r.name); + } + } + } + + return slots.join('、') || '-'; + } + const tipsShow = () => { submitPopupRef.value.open() } @@ -807,38 +734,27 @@ const onCustomDepositInput = (val) => { return false } - // 检查是否选择了时段 - if (selectedTimeSlot.value === null || selectedTimeSlot.value === undefined) { + // 检查是否选择了时间 + if (!startTime.value || !endTime.value) { uni.showToast({ - title: '请选择时间段', + title: '请选择开始和结束时间', icon: 'none' }) return false } - - // 验证选择的时段是否仍然可预约 - if (roomDetail.value && roomDetail.value.time_slots) { - const selectedSlot = roomDetail.value.time_slots.find( - slot => slot.slot_type === selectedTimeSlot.value - ); - - if (!selectedSlot || selectedSlot.status !== 'available') { - uni.showToast({ - title: '该时段已不可预约,请重新选择', - icon: 'none', - duration: 2000 - }); - // 重新加载房间详情,更新可预约时段 - if (reservationInfo.value.room_id && selectedDate.value) { - await loadRoomDetailForReservation(reservationInfo.value.room_id, selectedDate.value); - } - return false; - } + + // 检查时间是否有效 + if (timeError.value) { + uni.showToast({ + title: timeError.value, + icon: 'none' + }) + return false } - + if (!info.start_time || info.start_time === 0) { uni.showToast({ - title: '请选择时间段', + title: '请选择开始时间', icon: 'none' }) return false @@ -846,7 +762,7 @@ const onCustomDepositInput = (val) => { if (!info.end_time || info.end_time === 0) { uni.showToast({ - title: '请选择时间段', + title: '请选择结束时间', icon: 'none' }) return false @@ -947,9 +863,7 @@ const onCustomDepositInput = (val) => { // 确保信誉限制同步 credit_limit: currentValue.value, deposit_fee: finalDeposit, - important_data: {}, - // 添加最晚到店时间参数 - latestDateTime: latestDateTime.value || null + important_data: {} } // 将玩法类型和具体规则从数字转换为字符串 @@ -1079,14 +993,15 @@ const onCustomDepositInput = (val) => { maxPlayerCount.value = savedMaxPlayerCount; peopleRange.value = savedPeopleRange; peopleText.value = savedPeopleText; - - // 重置时段选择 - selectedTimeSlot.value = null; + + // 重置时间选择 + startTime.value = ''; + endTime.value = ''; + timeError.value = ''; + isNextDay.value = false; // 重置跨天标记 reservationInfo.value.start_time = 0; reservationInfo.value.end_time = 0; - // 重置最晚到店时间 - latestDateTime.value = null; - + gameRuleText.value = "请先选择玩法类型" } @@ -1145,9 +1060,6 @@ const onCustomDepositInput = (val) => { } else { peopleText.value = "请选择游玩人数"; } - - // 从 time_slots 中过滤出可预约的时段,动态生成时间段选项 - generateTimeSlotOptions(detail.time_slots); } else { uni.showToast({ title: '获取房间详情失败', @@ -1164,103 +1076,7 @@ const onCustomDepositInput = (val) => { roomDetailLoading.value = false; } } - - /** - * 根据房间的 time_slots 动态生成时间段选项 - * 只显示可预约的时段(status === 'available') - */ - const generateTimeSlotOptions = (timeSlots) => { - if (!timeSlots || !Array.isArray(timeSlots)) { - timeSlotOptions.value = []; - return; - } - - // 时段时间范围映射 - const timeRangeMap = { - 0: { text: '凌晨', range: '00:00-05:59' }, - 1: { text: '上午', range: '06:00-11:59' }, - 2: { text: '下午', range: '12:00-17:59' }, - 3: { text: '晚上', range: '18:00-23:59' } - }; - - // 过滤出可预约的时段并生成选项 - const availableSlots = timeSlots.filter(slot => slot.status === 'available'); - - timeSlotOptions.value = availableSlots.map(slot => { - const slotInfo = timeRangeMap[slot.slot_type] || { text: slot.slot_name, range: '' }; - // 生成显示文本 - let displayText = slotInfo.text; - if (slotInfo.range) { - displayText += ` (${slotInfo.range})`; - } - // 如果有价格信息,可以追加显示 - if (slot.price_desc_standard) { - displayText += ` ${slot.price_desc_standard}`; - } - - return { - value: slot.slot_type, - text: displayText - }; - }); - } - - /** - * 时段选择改变事件 - */ - const onTimeSlotChange = (val) => { - if (!selectedDate.value) return; - selectedTimeSlot.value = val; - // 根据日期和时段计算开始时间和结束时间 - calculateTimeFromSlot(); - // 自动更新最晚到店时间(时间段开始时间+30分钟) - updateLatestDateTimeFromSlot(); - } - - /** - * 根据选择的日期和时段计算开始时间和结束时间 - */ - const calculateTimeFromSlot = () => { - if (!selectedDate.value || selectedTimeSlot.value === null || selectedTimeSlot.value === undefined) return; - - // 将日期时间戳转换为日期对象 - const date = new Date(selectedDate.value * 1000); - const year = date.getFullYear(); - const month = date.getMonth(); - const day = date.getDate(); - - // 根据时段类型设置开始时间 - let startHour = 0; - let endHour = 0; - - switch (selectedTimeSlot.value) { - case 0: // 凌晨 00:00-05:59 - startHour = 0; - endHour = 6; - break; - case 1: // 上午 06:00-11:59 - startHour = 6; - endHour = 12; - break; - case 2: // 下午 12:00-17:59 - startHour = 12; - endHour = 18; - break; - case 3: // 晚上 18:00-23:59 - startHour = 18; - endHour = 24; - break; - } - - // 创建开始时间和结束时间 - const startTime = new Date(year, month, day, startHour, 0, 0); - const endTime = new Date(year, month, day, endHour, 0, 0); - - // 转换为秒级时间戳 - reservationInfo.value.start_time = Math.floor(startTime.getTime() / 1000); - reservationInfo.value.end_time = Math.floor(endTime.getTime() / 1000); - } - + onLoad(async (options) => { const config = await getConfigData(); console.log('config', config); @@ -1416,6 +1232,92 @@ const onCustomDepositInput = (val) => { border-radius: 4px; } + /* 时间选择器样式 */ + .picker-value { + padding: 15rpx 20rpx; + background-color: #f5f5f5; + border-radius: 8rpx; + font-size: 28rpx; + color: #333; + } + + /* 结束时间行布局(时间选择器 + 当天/次日切换) */ + .end-time-row { + display: flex; + align-items: center; + gap: 20rpx; + } + + /* 当天/次日切换样式 */ + .next-day-toggle { + display: flex; + align-items: center; + background-color: #f0f0f0; + border-radius: 8rpx; + padding: 8rpx 16rpx; + } + + .next-day-label { + font-size: 24rpx; + color: #999; + padding: 4rpx 12rpx; + border-radius: 6rpx; + transition: all 0.2s; + + &.active { + color: #fff; + background-color: #00AC4E; + } + } + + .next-day-divider { + font-size: 24rpx; + color: #ccc; + margin: 0 4rpx; + } + + /* 时间信息显示 */ + .time-info { + margin: 20rpx 0; + padding: 20rpx; + background-color: #f8f8f8; + border-radius: 12rpx; + } + + .time-info-item { + display: flex; + justify-content: space-between; + margin-bottom: 10rpx; + + &:last-child { + margin-bottom: 0; + } + } + + .time-info-label { + font-size: 24rpx; + color: #999; + } + + .time-info-value { + font-size: 24rpx; + color: #333; + font-weight: 500; + } + + /* 时间错误提示 */ + .time-error { + margin: 16rpx 0; + padding: 16rpx; + background-color: #fff2f0; + border-radius: 8rpx; + + text { + font-size: 24rpx; + color: #ff4d4f; + } + } + /* 可点击的行(年龄范围显示) */ .clickable-row { font-size: 28rpx;