feat(private): 订场页改为 订场/我的预定 Tab切换 + 历史列表只显示近10天+未来
- 顶部Tab从羽毛球改为 订场/我的预定 - 我的预定: 卡片列表展示已预约记录,点击跳转详情 - 我的预定只显示最近10天到未来的已预约记录 - 移除未使用的 openTime/closeTime/historyLoaded - 修复 -radius-md 变量不存在的问题
This commit is contained in:
@@ -2,14 +2,15 @@
|
||||
<view class="private-page">
|
||||
<view class="tab-bar">
|
||||
<view
|
||||
v-for="item in typeOptions"
|
||||
:key="item.value"
|
||||
v-for="tab in mainTabs"
|
||||
:key="tab.value"
|
||||
class="tab-item"
|
||||
:class="{ active: courtType === item.value }"
|
||||
@tap="selectType(item.value)"
|
||||
>{{ item.label }}</view>
|
||||
:class="{ active: activeTab === tab.value }"
|
||||
@tap="switchTab(tab.value)"
|
||||
>{{ tab.label }}</view>
|
||||
</view>
|
||||
|
||||
<template v-if="activeTab === 'booking'">
|
||||
<scroll-view scroll-x class="date-bar" :show-scrollbar="false">
|
||||
<view class="date-list">
|
||||
<view
|
||||
@@ -86,6 +87,22 @@
|
||||
<button class="primary-button submit-btn" :disabled="!canConfirm" @tap="goConfirm">预约</button>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template v-else-if="activeTab === 'history'">
|
||||
<scroll-view scroll-y class="history-scroll" @scrolltolower="loadHistory()">
|
||||
<view v-for="item in historyList" :key="item.id" class="history-card" @tap="goBookingDetail(item)">
|
||||
<view class="history-card-top">
|
||||
<text class="history-court">{{ historyCourtNames(item) }}</text>
|
||||
<text class="history-status">{{ item.status_label }}</text>
|
||||
</view>
|
||||
<text class="history-time">{{ historyTimeText(item) }}</text>
|
||||
<text class="history-amount">¥{{ item.order?.amount || '--' }}</text>
|
||||
</view>
|
||||
<view v-if="historyLoading" class="history-tip">加载中...</view>
|
||||
<view v-else-if="historyList.length === 0" class="history-empty">暂无预定记录</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user