appointment.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
  2. import DictionariesBehavior from "../../../../core/behavior/dictionaries.behavior";
  3. import tickleBehavior, {
  4. getTickleContext,
  5. } from "../../../../core/behavior/tickle.behavior";
  6. import { patientOfflineTreatmentAppointmentMethod } from "../../request";
  7. // module/order/pages/confirme-order/confirme-order.ts
  8. Page({
  9. behaviors: [PageContainerBehavior, DictionariesBehavior, tickleBehavior],
  10. data: {
  11. goodsInfo: { appointmentTime: '' },
  12. dateList: [] as Array<{
  13. label: string;
  14. dateStr: string;
  15. date: string;
  16. isSelected: boolean;
  17. }>,
  18. timeSlots: [] as Array<{
  19. time: string;
  20. isSelected: boolean;
  21. isDisabled: boolean;
  22. }>,
  23. selectedDate: "",
  24. selectedTime: "",
  25. show: false,
  26. date: '',
  27. offlineId: "",
  28. },
  29. onLoad(options: any) {
  30. // 初始化日期列表(从今天开始5天),内部会调用 initTimeSlots
  31. this.initDateList();
  32. if (options.goodsInfo) {
  33. const goodsInfo = JSON.parse(options.goodsInfo);
  34. this.setData({
  35. goodsInfo: goodsInfo,
  36. offlineId: goodsInfo.offlineId,
  37. });
  38. }
  39. },
  40. // 初始化日期列表
  41. initDateList(startDate?: Date) {
  42. const dateList: Array<{
  43. label: string;
  44. dateStr: string;
  45. date: string;
  46. isSelected: boolean;
  47. }> = [];
  48. const baseDate = startDate || new Date();
  49. // 设置时间为0点,避免时区问题
  50. baseDate.setHours(0, 0, 0, 0);
  51. const today = new Date();
  52. today.setHours(0, 0, 0, 0);
  53. const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  54. for (let i = 0; i < 5; i++) {
  55. const date = new Date(baseDate);
  56. date.setDate(baseDate.getDate() + i);
  57. const month = date.getMonth() + 1;
  58. const day = date.getDate();
  59. const weekDay = weekDays[date.getDay()];
  60. // 判断相对今天的位置
  61. const diffDays = Math.floor((date.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
  62. let label = '';
  63. if (diffDays === 0) {
  64. label = '今天';
  65. } else if (diffDays === 1) {
  66. label = '明天';
  67. } else {
  68. label = weekDay;
  69. }
  70. const dateStr = `${month}月${day}日`;
  71. const dateValue = `${date.getFullYear()}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
  72. dateList.push({
  73. label,
  74. dateStr,
  75. date: dateValue,
  76. isSelected: i === 0, // 默认选中第一个
  77. });
  78. }
  79. this.setData({
  80. dateList,
  81. selectedDate: dateList[0].date, // 默认选中第一个日期
  82. });
  83. // 初始化时间列表,传入默认选中的日期
  84. this.initTimeSlots(dateList[0].date);
  85. },
  86. // 初始化时间列表 - 固定8:00-20:00
  87. initTimeSlots(selectedDate?: string) {
  88. const timeSlots: Array<{
  89. time: string;
  90. isSelected: boolean;
  91. isDisabled: boolean;
  92. }> = [];
  93. const now = new Date();
  94. const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  95. const selectedDateObj = selectedDate ? new Date(selectedDate) : today;
  96. const selectedDateOnly = new Date(selectedDateObj.getFullYear(), selectedDateObj.getMonth(), selectedDateObj.getDate());
  97. // 判断选中的日期是否是今天
  98. const isToday = selectedDateOnly.getTime() === today.getTime();
  99. const currentHour = now.getHours();
  100. const currentMinute = now.getMinutes();
  101. // 从08:00到20:00,每30分钟一个时间段
  102. for (let hour = 8; hour <= 20; hour++) {
  103. for (let minute = 0; minute < 60; minute += 30) {
  104. if (timeSlots.length >= 25) break; // 限制为25个时间段
  105. const timeStr = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  106. // 如果是今天,需要判断时间是否已过去
  107. let isDisabled = false;
  108. if (isToday) {
  109. // 如果时间已过去,禁用
  110. if (hour < currentHour || (hour === currentHour && minute <= currentMinute)) {
  111. isDisabled = true;
  112. }
  113. }
  114. timeSlots.push({
  115. time: timeStr,
  116. isSelected: false,
  117. isDisabled,
  118. });
  119. }
  120. }
  121. this.setData({ timeSlots });
  122. },
  123. // 选择日期
  124. onDateSelect(e: any) {
  125. const index = e.currentTarget.dataset.index;
  126. const dateList = this.data.dateList.map((item, i) => ({
  127. ...item,
  128. isSelected: i === index,
  129. }));
  130. const selectedDate = dateList[index].date;
  131. // 重新初始化时间列表,根据选中的日期禁用已过去的时间
  132. this.initTimeSlots(selectedDate);
  133. this.setData({
  134. dateList,
  135. selectedDate,
  136. // 切换日期时清空已选时间
  137. selectedTime: "",
  138. });
  139. },
  140. // 选择时间
  141. onTimeSelect(e: any) {
  142. const index = e.currentTarget.dataset.index;
  143. const time = e.currentTarget.dataset.time;
  144. const timeSlot = this.data.timeSlots[index];
  145. // 如果时间段被禁用,不处理
  146. if (timeSlot && timeSlot.isDisabled) {
  147. return;
  148. }
  149. // 每次只能选择一个时间段,点击新的会取消之前的选择
  150. const timeSlots = this.data.timeSlots.map((item, i) => ({
  151. ...item,
  152. isSelected: i === index, // 只有当前点击的为选中状态
  153. }));
  154. this.setData({
  155. timeSlots,
  156. selectedTime: time,
  157. });
  158. },
  159. // 提交预约
  160. async onSubmit() {
  161. if (!this.data.selectedDate) {
  162. wx.showToast({
  163. title: "请选择日期",
  164. icon: "none",
  165. });
  166. return;
  167. }
  168. if (!this.data.selectedTime) {
  169. wx.showToast({
  170. title: "请选择时间",
  171. icon: "none",
  172. });
  173. return;
  174. }
  175. console.log(this.data.selectedDate, "this.data.selectedDate", this.data.selectedTime, "this.data.selectedTime", this.data.offlineId, "this.data.offlineId")
  176. // const selectedDateItem = this.data.dateList.find(item => item.isSelected);
  177. const appointmentTime = `${this.data.selectedDate} ${this.data.selectedTime}`;
  178. // console.log(selectedDateItem, "selectedDateItem")
  179. console.log(appointmentTime, "appointmentTime");
  180. console.log(this.data.offlineId, "this.data.offlineId");
  181. this.setData({
  182. goodsInfo: {
  183. ...this.data.goodsInfo,
  184. appointmentTime: `${this.data.selectedDate} ${this.data.selectedTime}`,
  185. },
  186. });
  187. try {
  188. const res = await patientOfflineTreatmentAppointmentMethod(this.data.offlineId, appointmentTime);
  189. console.log(res, "res========预约结果")
  190. setTimeout(() => {
  191. wx.showToast({
  192. title: '预约成功',
  193. icon: 'success',
  194. });
  195. }, 1000);
  196. wx.redirectTo({
  197. url: `/module/order/pages/appointment-success/appointment-success?goodsInfo=${JSON.stringify(this.data.goodsInfo)}`,
  198. });
  199. } catch (error: any) {
  200. wx.showToast({
  201. title: error.errMsg || "预约失败",
  202. icon: "none",
  203. });
  204. console.log(error, "error")
  205. }
  206. // 预约成功后跳转到成功页面,传递预约信息
  207. // const selectedDateItem = this.data.dateList.find(item => item.isSelected);
  208. // const serviceTime = selectedDateItem
  209. // ? `${selectedDateItem.dateStr} ${this.data.selectedTime || '09:00'}`
  210. // : '12月30日 09:00';
  211. // console.log('提交预约:', {
  212. // service: this.data.serviceInfo.name,
  213. // date: selectedDateItem?.label + ' ' + selectedDateItem?.dateStr,
  214. // time: this.data.selectedTime,
  215. // time:appointmentTime,
  216. // offlineId: this.data.offlineId,
  217. // });
  218. // // TODO: 调用预约接口
  219. // wx.showToast({
  220. // title: '预约成功',
  221. // icon: 'success',
  222. // });
  223. // setTimeout(() => {
  224. // wx.redirectTo({
  225. // url: `/module/order/pages/appointment-success/appointment-success?serviceName=${encodeURIComponent(this.data.serviceInfo.name)}&serviceTime=${encodeURIComponent(serviceTime)}&duration=${this.data.serviceInfo.duration}`,
  226. // });
  227. // }, 500);
  228. },
  229. // 打开日历弹窗
  230. onOpenCalendar() {
  231. console.log('onOpenCalendar');
  232. this.setData({ show: true });
  233. },
  234. // 关闭日历弹窗
  235. onClose() {
  236. this.setData({ show: false });
  237. },
  238. // 格式化日期
  239. formatDate(date: any) {
  240. date = new Date(date);
  241. return `${date.getMonth() + 1}/${date.getDate()}`;
  242. },
  243. // 确认选择日期
  244. onConfirm(event: any) {
  245. const selectedDate = event.detail;
  246. console.log('选择的日期:', selectedDate);
  247. if (selectedDate) {
  248. // 解析日期
  249. const dateObj = new Date(selectedDate);
  250. dateObj.setHours(0, 0, 0, 0);
  251. // 格式化日期字符串用于比较
  252. const dateValue = `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, '0')}-${String(dateObj.getDate()).padStart(2, '0')}`;
  253. // 检查选择的日期是否在当前展示的5天中
  254. const existingDateIndex = this.data.dateList.findIndex(item => item.date === dateValue);
  255. if (existingDateIndex !== -1) {
  256. // 如果选择的日期在已展示的5天中,只更新选中状态
  257. const dateList = this.data.dateList.map((item, index) => ({
  258. ...item,
  259. isSelected: index === existingDateIndex,
  260. }));
  261. // 重新初始化时间列表,根据选中的日期禁用已过去的时间
  262. this.initTimeSlots(dateValue);
  263. // 清空已选时间
  264. this.setData({
  265. show: false,
  266. dateList,
  267. selectedDate: dateValue,
  268. date: this.formatDate(selectedDate),
  269. selectedTime: "",
  270. });
  271. } else {
  272. // 如果选择的日期不在已展示的5天中,重新生成日期列表
  273. this.initDateList(dateObj);
  274. // 重新初始化时间列表,根据选中的日期禁用已过去的时间
  275. this.initTimeSlots(dateValue);
  276. // 清空已选时间
  277. this.setData({
  278. show: false,
  279. date: this.formatDate(selectedDate),
  280. selectedTime: "",
  281. });
  282. }
  283. } else {
  284. this.setData({ show: false });
  285. }
  286. },
  287. });