import PageContainerBehavior from "../../../../core/behavior/page-container.behavior"; import DictionariesBehavior from "../../../../core/behavior/dictionaries.behavior"; import tickleBehavior from "../../../../core/behavior/tickle.behavior"; import { patientOfflineTreatmentAppointmentMethod ,updateAppointmentMethod} from "../../request"; // module/order/pages/appointment/appointment.ts Page({ behaviors: [PageContainerBehavior, DictionariesBehavior, tickleBehavior], data: { goodsInfo: { appointmentTime: '' }, dateList: [] as Array<{ label: string; dateStr: string; date: string; isSelected: boolean; }>, timeSlots: [] as Array<{ time: string; isSelected: boolean; isDisabled: boolean; }>, selectedDate: "", selectedTime: "", show: false, date: '', offlineId: "", // 是否为修改预约模式,以及原始预约时间(用于高亮和对比是否有改动) isEditMode: false, originalAppointmentTime: "", }, onLoad(options: any) { const goodsInfoFromStorage = wx.getStorageSync('goodsInfo'); let parsedGoodsInfo: any = null; if ( goodsInfoFromStorage) { try { parsedGoodsInfo = JSON.parse(goodsInfoFromStorage || '{}'); } catch (e) { console.error("解析 goodsInfo 失败", e); } } const originalAppointmentTime = (options.arrangeTime && decodeURIComponent(options.arrangeTime)) || parsedGoodsInfo?.arrangeTime || parsedGoodsInfo?.appointmentTime || ""; const isEditMode = options.mode === "edit" || !!originalAppointmentTime; // 如果有原始预约时间,则围绕该日期初始化列表;否则从今天开始 5 天 if (originalAppointmentTime) { const [datePart] = originalAppointmentTime.split(" "); const baseDate = datePart ? new Date(datePart) : new Date(); this.initDateList(baseDate); } else { this.initDateList(); } if (parsedGoodsInfo) { this.setData({ goodsInfo: parsedGoodsInfo, offlineId: parsedGoodsInfo.offlineId || "", isEditMode, originalAppointmentTime, }); } else { this.setData({ isEditMode, originalAppointmentTime, }); } // 修改预约场景:根据原始预约时间高亮默认选中项 if (originalAppointmentTime) { this.highlightOriginalAppointmentTime(originalAppointmentTime); } }, // 初始化日期列表 initDateList(startDate?: Date) { const dateList: Array<{ label: string; dateStr: string; date: string; isSelected: boolean; }> = []; const baseDate = startDate || new Date(); // 设置时间为0点,避免时区问题 baseDate.setHours(0, 0, 0, 0); const today = new Date(); today.setHours(0, 0, 0, 0); const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; for (let i = 0; i < 5; i++) { const date = new Date(baseDate); date.setDate(baseDate.getDate() + i); const month = date.getMonth() + 1; const day = date.getDate(); const weekDay = weekDays[date.getDay()]; // 判断相对今天的位置 const diffDays = Math.floor((date.getTime() - today.getTime()) / (1000 * 60 * 60 * 24)); let label = ''; if (diffDays === 0) { label = '今天'; } else if (diffDays === 1) { label = '明天'; } else { label = weekDay; } const dateStr = `${month}月${day}日`; const dateValue = `${date.getFullYear()}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; dateList.push({ label, dateStr, date: dateValue, isSelected: i === 0, // 默认选中第一个 }); } this.setData({ dateList, selectedDate: dateList[0].date, // 默认选中第一个日期 }); // 初始化时间列表,传入默认选中的日期 this.initTimeSlots(dateList[0].date); }, // 初始化时间列表 - 固定8:00-20:00 // 可选传入 preSelectedTime,在初始化时高亮该时间段 initTimeSlots(selectedDate?: string, preSelectedTime?: string) { const timeSlots: Array<{ time: string; isSelected: boolean; isDisabled: boolean; }> = []; const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const selectedDateObj = selectedDate ? new Date(selectedDate) : today; const selectedDateOnly = new Date(selectedDateObj.getFullYear(), selectedDateObj.getMonth(), selectedDateObj.getDate()); // 判断选中的日期是否是今天 const isToday = selectedDateOnly.getTime() === today.getTime(); const currentHour = now.getHours(); const currentMinute = now.getMinutes(); // 从08:00到20:00,每30分钟一个时间段 for (let hour = 8; hour <= 20; hour++) { for (let minute = 0; minute < 60; minute += 30) { if (timeSlots.length >= 25) break; // 限制为25个时间段 const timeStr = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`; // 如果是今天,需要判断时间是否已过去 let isDisabled = false; if (isToday) { // 如果时间已过去,禁用 if (hour < currentHour || (hour === currentHour && minute <= currentMinute)) { isDisabled = true; } } timeSlots.push({ time: timeStr, isSelected: preSelectedTime ? timeStr === preSelectedTime : false, isDisabled, }); } } this.setData({ timeSlots }); }, // 根据原始预约时间高亮日期和时间 highlightOriginalAppointmentTime(appointmentTime: string) { if (!appointmentTime) return; const [rawDatePart, rawTimePart] = appointmentTime.split(" "); if (!rawDatePart || !rawTimePart) return; // 兼容不同格式:2025-03-13 / 2025/03/13 以及带秒的时间 14:30:00 const datePart = rawDatePart.replace(/\//g, "-").substring(0, 10); const timePart = rawTimePart.substring(0, 5); // 只取 HH:mm // 高亮日期 const dateList = this.data.dateList.map((item) => ({ ...item, isSelected: item.date === datePart, })); // 如果当前 5 天中没有该日期,则直接返回(保持已有逻辑);更复杂的滚动可后续再优化 const hasTargetDate = dateList.some((item) => item.isSelected); if (!hasTargetDate) { return; } this.setData({ dateList, selectedDate: datePart, selectedTime: timePart, }); // 按该日期重新初始化时间段,并选中对应时间 this.initTimeSlots(datePart, timePart); }, // 选择日期 onDateSelect(e: any) { const index = e.currentTarget.dataset.index; const dateList = this.data.dateList.map((item, i) => ({ ...item, isSelected: i === index, })); const selectedDate = dateList[index].date; // 重新初始化时间列表,根据选中的日期禁用已过去的时间 this.initTimeSlots(selectedDate); this.setData({ dateList, selectedDate, // 切换日期时清空已选时间 selectedTime: "", }); }, // 选择时间 onTimeSelect(e: any) { const index = e.currentTarget.dataset.index; const time = e.currentTarget.dataset.time; const timeSlot = this.data.timeSlots[index]; // 如果时间段被禁用,不处理 if (timeSlot && timeSlot.isDisabled) { return; } // 每次只能选择一个时间段,点击新的会取消之前的选择 const timeSlots = this.data.timeSlots.map((item, i) => ({ ...item, isSelected: i === index, // 只有当前点击的为选中状态 })); this.setData({ timeSlots, selectedTime: time, }); }, // 提交预约 async onSubmit() { if (!this.data.selectedDate) { wx.showToast({ title: "请选择日期", icon: "none", }); return; } if (!this.data.selectedTime) { wx.showToast({ title: "请选择时间", icon: "none", }); return; } const appointmentTime = `${this.data.selectedDate} ${this.data.selectedTime}`; // 归一化原始预约时间为 "YYYY-MM-DD HH:mm" 用于对比 let normalizedOriginal = ""; if (this.data.originalAppointmentTime) { const [rawDatePart, rawTimePart] = this.data.originalAppointmentTime.split(" "); if (rawDatePart && rawTimePart) { const datePart = rawDatePart.replace(/\//g, "-").substring(0, 10); const timePart = rawTimePart.substring(0, 5); // HH:mm normalizedOriginal = `${datePart} ${timePart}`; } } // 修改预约模式下,如果时间未变化,则提示修改失败,不调接口 if (this.data.isEditMode && normalizedOriginal && appointmentTime === normalizedOriginal) { wx.showToast({ title: "预约时间未修改", icon: "none", }); return; } this.setData({ goodsInfo: { ...this.data.goodsInfo, appointmentTime: `${this.data.selectedDate} ${this.data.selectedTime}`, }, }); try { if (this.data.isEditMode) { await updateAppointmentMethod(this.data.offlineId, appointmentTime); } else { await patientOfflineTreatmentAppointmentMethod( this.data.offlineId, appointmentTime ); } wx.showToast({ title: '预约成功', icon: 'success', }); setTimeout(() => { wx.redirectTo({ url: `/module/order/pages/appointment-success/appointment-success?goodsInfo=${encodeURIComponent(JSON.stringify(this.data.goodsInfo))}`, }); }, 1000); } catch (error: any) { wx.showToast({ title: error.errMsg || "预约失败", icon: "none", }); } }, // 打开日历弹窗 onOpenCalendar() { this.setData({ show: true }); }, // 关闭日历弹窗 onClose() { this.setData({ show: false }); }, // 格式化日期 formatDate(date: any) { date = new Date(date); return `${date.getMonth() + 1}/${date.getDate()}`; }, // 确认选择日期 onConfirm(event: any) { const selectedDate = event.detail; if (selectedDate) { // 解析日期 const dateObj = new Date(selectedDate); dateObj.setHours(0, 0, 0, 0); // 格式化日期字符串用于比较 const dateValue = `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, '0')}-${String(dateObj.getDate()).padStart(2, '0')}`; // 检查选择的日期是否在当前展示的5天中 const existingDateIndex = this.data.dateList.findIndex(item => item.date === dateValue); if (existingDateIndex !== -1) { // 如果选择的日期在已展示的5天中,只更新选中状态 const dateList = this.data.dateList.map((item, index) => ({ ...item, isSelected: index === existingDateIndex, })); // 重新初始化时间列表,根据选中的日期禁用已过去的时间 this.initTimeSlots(dateValue); // 清空已选时间 this.setData({ show: false, dateList, selectedDate: dateValue, date: this.formatDate(selectedDate), selectedTime: "", }); } else { // 如果选择的日期不在已展示的5天中,重新生成日期列表 this.initDateList(dateObj); // 重新初始化时间列表,根据选中的日期禁用已过去的时间 this.initTimeSlots(dateValue); // 清空已选时间 this.setData({ show: false, date: this.formatDate(selectedDate), selectedTime: "", }); } } else { this.setData({ show: false }); } }, });