diff --git a/packages/app/src/components/SlotCard.vue b/packages/app/src/components/SlotCard.vue index 34ded69..cf2b27c 100644 --- a/packages/app/src/components/SlotCard.vue +++ b/packages/app/src/components/SlotCard.vue @@ -1,83 +1,88 @@ @@ -109,8 +108,12 @@ const props = defineProps() const emit = defineEmits<{ book: [timeSlot: TimeSlotWithBookingStatus] cancel: [timeSlot: TimeSlotWithBookingStatus] + cardTap: [timeSlot: TimeSlotWithBookingStatus] }>() +const startTimeDisplay = computed(() => props.timeSlot.startTime.slice(0, 5)) +const endTimeDisplay = computed(() => props.timeSlot.endTime.slice(0, 5)) + const durationMin = computed(() => { const [sh, sm] = props.timeSlot.startTime.split(':').map(Number) const [eh, em] = props.timeSlot.endTime.split(':').map(Number) @@ -122,7 +125,7 @@ const capacityLabel = computed(() => { if (status === TimeSlotStatus.CLOSED) return '已关闭' if (status === TimeSlotStatus.FULL) return '已约满' const remaining = capacity - bookedCount - return `剩余 ${remaining} 个名额` + return `剩余${remaining}位` }) const capacityClass = computed(() => { @@ -145,187 +148,147 @@ const isPast = computed(() => isSlotPast(props.timeSlot.date, props.timeSlot.sta diff --git a/packages/app/src/pages/booking/index.vue b/packages/app/src/pages/booking/index.vue index 6af4f6d..a7cb4ef 100644 --- a/packages/app/src/pages/booking/index.vue +++ b/packages/app/src/pages/booking/index.vue @@ -61,6 +61,7 @@ :time-slot="item" @book="onBookTap" @cancel="onCancelTap" + @card-tap="onSlotCardTap" /> @@ -150,7 +151,7 @@ updateLayout() // ─── Filtered slots ─────────────────────────────────────── const filteredSlots = computed(() => { const slots = bookingStore.slots as TimeSlotWithBookingStatus[] - if (!selectedPeriod.value) return [...slots] + if (!selectedPeriod.value) return slots const period = TIME_PERIODS[selectedPeriod.value] return slots.filter((slot) => { @@ -177,7 +178,19 @@ function onDateSelect(date: string) { } function onPeriodChange(_period: PeriodKey) { - // Filtering is done client-side via computed property + // No-op: filtering is done client-side via computed property + void _period +} + +// ─── Card tap → navigate to detail ─────────────────────── +function onSlotCardTap(slot: TimeSlotWithBookingStatus) { + if (slot.isBookedByMe && slot.myBookingId) { + // Already booked → show booking detail + uni.navigateTo({ url: `/pages/booking/detail?id=${slot.myBookingId}` }) + } else { + // Not booked → show slot preview with booking action + uni.navigateTo({ url: `/pages/booking/detail?slotId=${slot.id}&date=${slot.date}` }) + } } // ─── Book flow ──────────────────────────────────────────── @@ -213,7 +226,9 @@ async function onBookTap(slot: TimeSlotWithBookingStatus) { cancelText: '取消', success: (res) => { if (res.confirm) { - uni.navigateTo({ url: '/pages/store/index' }) + // Switch to home tab and auto-scroll to card shop + uni.$emit('scrollToCardShop') + uni.switchTab({ url: '/pages/home/index' }) } }, }) @@ -352,7 +367,7 @@ onMounted(async () => { } .skeleton-card { - height: 140rpx; + height: 220rpx; border-radius: 20rpx; background: #fff; display: flex; @@ -360,6 +375,7 @@ onMounted(async () => { align-items: center; padding: 28rpx 48rpx; gap: 20rpx; + margin: 0 24rpx; box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.03); } diff --git a/packages/app/src/pages/home/index.vue b/packages/app/src/pages/home/index.vue index 3fc7194..964b63c 100644 --- a/packages/app/src/pages/home/index.vue +++ b/packages/app/src/pages/home/index.vue @@ -48,8 +48,8 @@ diff --git a/packages/app/src/pages/profile/index.vue b/packages/app/src/pages/profile/index.vue index bd99850..4386e35 100644 --- a/packages/app/src/pages/profile/index.vue +++ b/packages/app/src/pages/profile/index.vue @@ -4,25 +4,12 @@ - + - + @@ -131,7 +118,6 @@ function handleAbout() {