import React, { useState, useEffect } from 'react' import { View, Text, ScrollView, Input } from '@tarojs/components' import Taro from '@tarojs/taro' import { useUser } from '@/hooks/useUser' import { createShopBooking } from '@/api/shop/shopBooking' import { getShopStore } from '@/api/shop/shopStore' import type { ShopStore } from '@/api/shop/shopStore/model' import BottomButton from '@/components/common/BottomButton' import './index.scss' import dayjs from 'dayjs' definePageConfig({ navigationBarTitleText: '穿线预约', }) const BookingPage: React.FC = () => { const { isLoggedIn } = useUser() const { storeId: initStoreId } = Taro.getCurrentInstance().router?.params || {} // 门店信息 const [storeInfo, setStoreInfo] = useState(null) // 表单数据 const [date, setDate] = useState('') const [time, setTime] = useState('') const [serviceType, setServiceType] = useState('') const [contactName, setContactName] = useState('') const [contactPhone, setContactPhone] = useState('') const [remark, setRemark] = useState('') const [submitting, setSubmitting] = useState(false) // 日期范围(今天起30天) const dateRange = (() => { const dates: string[] = [] const today = dayjs() for (let i = 0; i < 30; i++) { dates.push(today.add(i, 'day').format('YYYY-MM-DD')) } return dates })() // 全部可选时间段 const allTimeSlots = [ '09:00-10:00', '10:00-11:00', '11:00-12:00', '14:00-15:00', '15:00-16:00', '16:00-17:00', '17:00-18:00', ] // 根据选中日期过滤已过去的时间段 const timeSlots = (() => { if (!date) return allTimeSlots const today = dayjs().format('YYYY-MM-DD') if (date !== today) return allTimeSlots // 今天:过滤掉已结束的时间段 const now = dayjs() return allTimeSlots.filter(slot => { const endTime = slot.split('-')[1] // 取结束时间如 "10:00" const [h, m] = endTime.split(':').map(Number) const slotEnd = dayjs().hour(h).minute(m).second(0) return slotEnd.isAfter(now) }) })() // 服务类型 const serviceTypes = [ { label: '穿线服务', value: '穿线服务', price: 30 }, { label: '穿线+手胶', value: '穿线+手胶', price: 50 }, { label: '穿线+毛巾胶', value: '穿线+毛巾胶', price: 60 }, { label: '其他', value: '其他', price: 0 }, ] const selectedPrice = serviceTypes.find(s => s.value === serviceType)?.price || 0 // 切换日期时,清除已选时间(如果当前时间在新日期不可用) const handleDateChange = (dateStr: string) => { setDate(dateStr) // 检查当前选中的时间在新的 timeSlots 中是否存在 const today = dayjs().format('YYYY-MM-DD') if (dateStr === today) { const now = dayjs() const availableSlots = allTimeSlots.filter(slot => { const endTime = slot.split('-')[1] const [h, m] = endTime.split(':').map(Number) const slotEnd = dayjs().hour(h).minute(m).second(0) return slotEnd.isAfter(now) }) if (time && !availableSlots.includes(time)) { setTime('') } } } // 初始化 useEffect(() => { if (!isLoggedIn) { Taro.navigateTo({ url: '/passport/login' }) return } if (initStoreId) { fetchStoreInfo(Number(initStoreId)) } // 挂载回调,供门店列表页选中后回传 const pages = Taro.getCurrentPages() const curPage = pages[pages.length - 1] as any curPage.setSelectedStore = (store: ShopStore) => { setStoreInfo(store) } }, [isLoggedIn]) const fetchStoreInfo = async (id: number) => { try { const data = await getShopStore(id) setStoreInfo(data) } catch (e) { console.error('获取门店信息失败:', e) } } // 跳转到门店选择列表 const handleSelectStore = () => { Taro.navigateTo({ url: '/pages/store/list/index?selectMode=1' }) } const formatDateDisplay = (dateStr: string) => { const d = dayjs(dateStr) const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] return `${d.month() + 1}月${d.date()}日 ${weekDays[d.day()]}` } const validateForm = () => { if (!storeInfo) { Taro.showToast({ title: '请选择预约门店', icon: 'none' }) return false } if (!date) { Taro.showToast({ title: '请选择预约日期', icon: 'none' }) return false } if (!time) { Taro.showToast({ title: '请选择预约时间段', icon: 'none' }) return false } if (!serviceType) { Taro.showToast({ title: '请选择服务类型', icon: 'none' }) return false } if (!contactName.trim()) { Taro.showToast({ title: '请输入联系人姓名', icon: 'none' }) return false } if (!contactPhone.trim()) { Taro.showToast({ title: '请输入手机号', icon: 'none' }) return false } if (!/^1[3-9]\d{9}$/.test(contactPhone)) { Taro.showToast({ title: '手机号格式不正确', icon: 'none' }) return false } // 校验预约时间不能是过去 const endTime = time.split('-')[1] const [h, m] = endTime.split(':').map(Number) const bookingDateTime = dayjs(date).hour(h).minute(m).second(0) if (bookingDateTime.isBefore(dayjs())) { Taro.showToast({ title: '预约时间不能是过去的时间', icon: 'none' }) return false } return true } const handleSubmit = () => { if (!validateForm()) return const confirmContent = `门店:${storeInfo!.name}\n日期:${formatDateDisplay(date)}\n时段:${time}\n服务:${serviceType}${selectedPrice > 0 ? `(¥${selectedPrice})` : ''}\n联系人:${contactName}\n电话:${contactPhone}` Taro.showModal({ title: '确认预约', content: confirmContent, confirmText: '确认预约', confirmColor: '#0e932e', success: (res) => { if (res.confirm) submitBooking() }, }) } const submitBooking = async () => { try { setSubmitting(true) await createShopBooking({ storeId: storeInfo!.id || 0, storeName: storeInfo!.name || '', serviceId: 0, serviceName: serviceType, bookingDate: date, bookingTime: time, status: 'pending', price: selectedPrice, remark, contactName, contactPhone, address: storeInfo!.address || '', }) Taro.showToast({ title: '预约成功', icon: 'success' }) setTimeout(() => Taro.navigateBack(), 1500) } catch (e: any) { Taro.showToast({ title: e.message || '预约失败', icon: 'none' }) } finally { setSubmitting(false) } } return ( {/* 选择门店 */} 预约门店 {storeInfo ? ( {storeInfo.name} {storeInfo.address && ( {storeInfo.address} )} {storeInfo.businessHours && ( 🕐 {storeInfo.businessHours} )} ) : ( 请选择门店 )} {/* 门店操作快捷按钮(已选门店时显示) */} {storeInfo && ( {storeInfo.phone && ( Taro.makePhoneCall({ phoneNumber: storeInfo.phone! })} > 📞 拨打电话 )} {storeInfo.lngAndLat && ( { const parts = storeInfo.lngAndLat!.split(',') if (parts.length === 2) { Taro.openLocation({ longitude: parseFloat(parts[0]), latitude: parseFloat(parts[1]), name: storeInfo.name || '', address: storeInfo.address || '', }) } }} > 🗺 查看地图 )} 🔄 重新选择 )} {/* 选择日期 */} 选择日期 {dateRange.map(dateStr => ( handleDateChange(dateStr)} > {formatDateDisplay(dateStr)} ))} {/* 选择时间 */} 选择时间 {timeSlots.map(slot => ( setTime(slot)} > {slot} ))} {/* 服务类型 */} 服务类型 {serviceTypes.map(service => ( setServiceType(service.value)} > {service.label} {service.price > 0 ? ` ¥${service.price}` : ''} ))} {/* 联系人信息 */} 联系人信息 姓名 setContactName(e.detail.value)} placeholder='请输入姓名' className='bg-gray-50 rounded-lg p-3 text-sm' /> 手机号 setContactPhone(e.detail.value)} placeholder='请输入手机号' className='bg-gray-50 rounded-lg p-3 text-sm' maxlength={11} /> {/* 备注 */} 备注(选填) setRemark(e.detail.value)} placeholder='如有特殊需求请注明(球拍型号、穿线磅数等)' className='bg-gray-50 rounded-lg p-3 text-sm' style={{ minHeight: '80px' }} /> 0 ? `费用:¥${selectedPrice}(到店支付)` : undefined} /> ) } export default BookingPage