| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- 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()}`;
- },
- // 日历弹窗选择日期(同时监听 change 和 select,双保险)
- _calendarLock: false,
- onCalendarSelect(event: any) {
- // 防止 change 和 select 同时触发导致重复执行
- if ((this as any)._calendarLock) return;
- (this as any)._calendarLock = true;
- setTimeout(() => { (this as any)._calendarLock = false; }, 300);
- const timestamp = event.detail.value;
- if (!timestamp) return;
- const dateObj = new Date(timestamp);
- dateObj.setHours(0, 0, 0, 0);
- const dateValue = `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, '0')}-${String(dateObj.getDate()).padStart(2, '0')}`;
- // 关闭弹窗
- this.setData({ show: false });
- // 检查选择的日期是否在当前展示的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({
- dateList,
- selectedDate: dateValue,
- selectedTime: "",
- });
- } else {
- // 日期不在已展示的5天中,重新生成日期列表
- this.initDateList(new Date(dateObj.getTime())); // 传副本,避免 initDateList 修改原对象
- this.setData({
- selectedDate: dateValue,
- selectedTime: "",
- });
- }
- },
- });
|