From 7dc03145658de4f1705e489428c75857800a1b60 Mon Sep 17 00:00:00 2001 From: gqt <3217233537@qq.com> Date: Fri, 14 Aug 2026 15:56:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(private):=20=E8=AE=A2=E5=9C=BA=E9=A1=B5?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20=E8=AE=A2=E5=9C=BA/=E6=88=91=E7=9A=84?= =?UTF-8?q?=E9=A2=84=E5=AE=9A=20Tab=E5=88=87=E6=8D=A2=20+=20=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E5=88=97=E8=A1=A8=E5=8F=AA=E6=98=BE=E7=A4=BA=E8=BF=91?= =?UTF-8?q?10=E5=A4=A9+=E6=9C=AA=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 顶部Tab从羽毛球改为 订场/我的预定 - 我的预定: 卡片列表展示已预约记录,点击跳转详情 - 我的预定只显示最近10天到未来的已预约记录 - 移除未使用的 openTime/closeTime/historyLoaded - 修复 -radius-md 变量不存在的问题 --- .../src/pages/comprehensive/private/index.vue | 162 ++++++++++++++++-- 1 file changed, 148 insertions(+), 14 deletions(-) diff --git a/miniprogram/src/pages/comprehensive/private/index.vue b/miniprogram/src/pages/comprehensive/private/index.vue index 1da2a76..c883d02 100644 --- a/miniprogram/src/pages/comprehensive/private/index.vue +++ b/miniprogram/src/pages/comprehensive/private/index.vue @@ -2,14 +2,15 @@ {{ item.label }} + :class="{ active: activeTab === tab.value }" + @tap="switchTab(tab.value)" + >{{ tab.label }} + + + + @@ -94,6 +111,8 @@ import { computed, onMounted, ref } from 'vue' import dayjs from 'dayjs' import { privateBookingApi } from '@/modules/comprehensive/api/privateBooking' import { useComprehensiveSessionStore } from '@/modules/comprehensive/stores/session' +import { bookingApi } from '@/modules/comprehensive/api/booking' +import { formatTimeRange } from '@/modules/comprehensive/utils/date' import { toAmountNumber } from '@/modules/comprehensive/utils/money' const HEADER_HEIGHT = 75 @@ -101,9 +120,11 @@ const CELL_HEIGHT = 107 const TIME_COL_WIDTH = 128 const COURT_COL_WIDTH = 149 -const typeOptions = [ - { label: '羽毛球', value: 'badminton' } +const mainTabs = [ + { label: '订场', value: 'booking' }, + { label: '我的预定', value: 'history' } ] +const activeTab = ref('booking') const session = useComprehensiveSessionStore() const courtType = ref('badminton') @@ -115,6 +136,12 @@ const selectedCells = ref({}) const now = ref(dayjs()) let loadRequestId = 0 +const historyList = ref([]) +const historyLoading = ref(false) +const historyPage = ref(1) +const historyPageSize = 20 +const historyHasMore = ref(true) + const bookingConfig = ref({ member_advance_days: 7, non_member_advance_days: 3 }) const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] @@ -134,9 +161,6 @@ const dateOptions = computed(() => { }) }) -const openTime = computed(() => normalizeClock(grid.value?.open_time)) -const closeTime = computed(() => normalizeClock(grid.value?.close_time)) - const occupationMap = computed(() => { const map = {} if (!grid.value) return map @@ -257,10 +281,59 @@ async function loadGrid() { } } -function selectType(type) { - if (courtType.value === type) return - courtType.value = type - loadGrid() +function switchTab(tab) { + if (activeTab.value === tab) return + activeTab.value = tab + if (tab === 'history') { + loadHistory(true) + } +} + +async function loadHistory(reset = false) { + if (historyLoading.value) return + if (reset) { + historyPage.value = 1 + historyHasMore.value = true + } + if (!historyHasMore.value) return + historyLoading.value = true + try { + const data = await bookingApi.getPrivateBookings({ + page: historyPage.value, + pageSize: historyPageSize + }) + const tenDaysAgo = dayjs().subtract(10, 'day') + const booked = data.items.filter( + (item) => item.status === 'booked' && item.start_at && dayjs(item.start_at) >= tenDaysAgo + ) + if (reset) { + historyList.value = booked + } else { + historyList.value = [...historyList.value, ...booked] + } + historyHasMore.value = data.page * data.page_size < data.total + if (historyHasMore.value) historyPage.value++ + } catch { + if (reset) historyList.value = [] + } finally { + historyLoading.value = false + } +} + +function historyCourtNames(item) { + return item.courts?.map((c) => c.name).join('、') || '包场预约' +} + +function historyTimeText(item) { + if (!item.start_at || !item.end_at) return '-' + const start = dayjs(item.start_at) + return `${start.month() + 1}/${start.date()} ${formatTimeRange(item.start_at, item.end_at)}` +} + +function goBookingDetail(item) { + uni.navigateTo({ + url: `/pages/comprehensive/bookings/private-detail?id=${item.id}` + }) } function selectDate(date) { @@ -693,4 +766,65 @@ defineExpose({ color: $text-color-light; font-size: 24rpx; } + +.history-empty { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + color: $text-color-light; + font-size: 24rpx; +} + +.history-scroll { + flex: 1; + min-height: 0; +} + +.history-card { + background: $bg-color-main; + border-radius: $border-radius-base; + padding: $spacing-md; + margin: $spacing-sm $spacing-md; + display: flex; + flex-direction: column; + gap: $spacing-xs; +} + +.history-card-top { + display: flex; + justify-content: space-between; + align-items: center; +} + +.history-court { + font-size: 30rpx; + font-weight: 800; + color: $text-color-main; +} + +.history-status { + font-size: 22rpx; + font-weight: 700; + color: #52c41a; +} + +.history-time { + font-size: 26rpx; + font-weight: 600; + color: $text-color-regular; +} + +.history-amount { + font-size: 32rpx; + font-weight: 900; + color: $color-primary; +} + +.history-tip { + text-align: center; + padding: $spacing-md; + color: $text-color-light; + font-size: 24rpx; +}