Compare commits
6 Commits
0582a5f6a8
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7139865bff | |||
| d07356e9f1 | |||
| 30cad4e765 | |||
| 37eb77aede | |||
| d00304ec9c | |||
| 4b886840c0 |
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
VITE_ICE_API_BASE_URL=https://8002.frp.chatgqt.top
|
VITE_ICE_API_BASE_URL=https://venue.test.chatgqt.top
|
||||||
VITE_COMPREHENSIVE_API_BASE_URL=https://8002.frp.chatgqt.top
|
VITE_COMPREHENSIVE_API_BASE_URL=https://venue2.test.chatgqt.top
|
||||||
@@ -58,7 +58,7 @@ defineProps({
|
|||||||
},
|
},
|
||||||
primaryText: {
|
primaryText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '微信一键登录'
|
default: '点击登录'
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|||||||
@@ -10,12 +10,22 @@ const toQuoteCourt = (backendCourt = {}) => ({
|
|||||||
court_type_label: backendCourt.court_type_label || ''
|
court_type_label: backendCourt.court_type_label || ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const toQuoteItem = (backendItem = {}) => ({
|
||||||
|
court_id: backendItem.court_id ?? null,
|
||||||
|
court_name: backendItem.court_name || '',
|
||||||
|
start_at: backendItem.start_at || '',
|
||||||
|
end_at: backendItem.end_at || '',
|
||||||
|
unit_count: toNumber(backendItem.unit_count),
|
||||||
|
amount: backendItem.amount || '0.00'
|
||||||
|
})
|
||||||
|
|
||||||
const toPrivateQuote = (backendQuote = {}) => ({
|
const toPrivateQuote = (backendQuote = {}) => ({
|
||||||
amount: backendQuote.amount || '0.00',
|
amount: backendQuote.amount || '0.00',
|
||||||
unit_count: toNumber(backendQuote.unit_count),
|
unit_count: toNumber(backendQuote.unit_count),
|
||||||
start_at: backendQuote.start_at || '',
|
start_at: backendQuote.start_at || '',
|
||||||
end_at: backendQuote.end_at || '',
|
end_at: backendQuote.end_at || '',
|
||||||
courts: toArray(backendQuote.courts).map(toQuoteCourt)
|
courts: toArray(backendQuote.courts).map(toQuoteCourt),
|
||||||
|
items: toArray(backendQuote.items).map(toQuoteItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
const toPrivateCreateResult = (backendData = {}) => ({
|
const toPrivateCreateResult = (backendData = {}) => ({
|
||||||
@@ -36,14 +46,41 @@ const toPrivateBookingOptions = (backendData = {}) => ({
|
|||||||
court_type_label: backendData.court_type_label || '',
|
court_type_label: backendData.court_type_label || '',
|
||||||
open_time: backendData.open_time || '',
|
open_time: backendData.open_time || '',
|
||||||
close_time: backendData.close_time || '',
|
close_time: backendData.close_time || '',
|
||||||
unit_price: backendData.unit_price || '0.00',
|
duration_units: toNumber(backendData.duration_units, 1),
|
||||||
duration_units: toNumber(backendData.duration_units, 2),
|
|
||||||
duration_minutes: toNumber(backendData.duration_minutes, 60),
|
duration_minutes: toNumber(backendData.duration_minutes, 60),
|
||||||
amount_per_court: backendData.amount_per_court || '0.00',
|
|
||||||
total_court_count: toNumber(backendData.total_court_count),
|
total_court_count: toNumber(backendData.total_court_count),
|
||||||
time_options: toArray(backendData.time_options).map(toPrivateTimeOption)
|
time_options: toArray(backendData.time_options).map(toPrivateTimeOption)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const toGridCourt = (backendCourt = {}) => ({
|
||||||
|
id: backendCourt.id ?? null,
|
||||||
|
name: backendCourt.name || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const toGridSlot = (backendSlot = {}) => ({
|
||||||
|
start: backendSlot.start || '',
|
||||||
|
end: backendSlot.end || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const toGridOccupation = (backendOcc = {}) => ({
|
||||||
|
court_id: backendOcc.court_id ?? null,
|
||||||
|
start_at: backendOcc.start_at || '',
|
||||||
|
end_at: backendOcc.end_at || '',
|
||||||
|
source_type: backendOcc.source_type || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const toPrivateBookingGrid = (backendData = {}) => ({
|
||||||
|
date: backendData.date || '',
|
||||||
|
court_type: backendData.court_type || '',
|
||||||
|
court_type_label: backendData.court_type_label || '',
|
||||||
|
open_time: backendData.open_time || '',
|
||||||
|
close_time: backendData.close_time || '',
|
||||||
|
courts: toArray(backendData.courts).map(toGridCourt),
|
||||||
|
time_slots: toArray(backendData.time_slots).map(toGridSlot),
|
||||||
|
occupations: toArray(backendData.occupations).map(toGridOccupation),
|
||||||
|
slot_prices: backendData.slot_prices || {}
|
||||||
|
})
|
||||||
|
|
||||||
export const privateBookingApi = {
|
export const privateBookingApi = {
|
||||||
getPrivateBookingOptions(params = {}) {
|
getPrivateBookingOptions(params = {}) {
|
||||||
return request({
|
return request({
|
||||||
@@ -55,25 +92,33 @@ export const privateBookingApi = {
|
|||||||
})
|
})
|
||||||
}).then(toPrivateBookingOptions)
|
}).then(toPrivateBookingOptions)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getPrivateBookingGrid(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: '/api/bookings/private/grid',
|
||||||
|
data: compactParams({
|
||||||
|
date: params.date,
|
||||||
|
court_type: params.courtType || params.court_type
|
||||||
|
})
|
||||||
|
}).then(toPrivateBookingGrid)
|
||||||
|
},
|
||||||
|
|
||||||
quotePrivateBooking(payload = {}) {
|
quotePrivateBooking(payload = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/bookings/private/quote',
|
url: '/api/bookings/private/quote',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {
|
data: {
|
||||||
court_ids: toArray(payload.court_ids),
|
items: toArray(payload.items)
|
||||||
start_at: payload.start_at,
|
|
||||||
end_at: payload.end_at
|
|
||||||
}
|
}
|
||||||
}).then(toPrivateQuote)
|
}).then(toPrivateQuote)
|
||||||
},
|
},
|
||||||
|
|
||||||
createPrivateBooking(payload = {}) {
|
createPrivateBooking(payload = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/bookings/private',
|
url: '/api/bookings/private',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {
|
data: {
|
||||||
court_ids: toArray(payload.court_ids),
|
items: toArray(payload.items)
|
||||||
start_at: payload.start_at,
|
|
||||||
end_at: payload.end_at
|
|
||||||
}
|
}
|
||||||
}).then(toPrivateCreateResult)
|
}).then(toPrivateCreateResult)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,6 @@
|
|||||||
<text>订单号</text>
|
<text>订单号</text>
|
||||||
<text>{{ booking.order.order_no }}</text>
|
<text>{{ booking.order.order_no }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-row">
|
|
||||||
<text>订单金额</text>
|
|
||||||
<text>¥{{ booking.order.amount }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-row">
|
<view class="info-row">
|
||||||
<text>订单状态</text>
|
<text>订单状态</text>
|
||||||
<text>{{ booking.order.status_label }}</text>
|
<text>{{ booking.order.status_label }}</text>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<block>
|
<block>
|
||||||
<view class="tab-bar">
|
<view class="tab-bar">
|
||||||
<view class="tab-item" :class="{ active: activeTab === 'membership' }" @tap="switchTab('membership')">会员卡</view>
|
<view class="tab-item" :class="{ active: activeTab === 'membership' }" @tap="switchTab('membership')">会员卡</view>
|
||||||
<view class="tab-item" :class="{ active: activeTab === 'group' }" @tap="switchTab('group')">团课</view>
|
|
||||||
<view class="tab-item" :class="{ active: activeTab === 'tickets' }" @tap="switchTab('tickets')">门票</view>
|
<view class="tab-item" :class="{ active: activeTab === 'tickets' }" @tap="switchTab('tickets')">门票</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -85,7 +84,6 @@
|
|||||||
<text class="meta">{{ item.coach_name }}</text>
|
<text class="meta">{{ item.coach_name }}</text>
|
||||||
<view class="course-bottom">
|
<view class="course-bottom">
|
||||||
<text class="meta">剩余 {{ item.remaining_count }}/{{ item.capacity }}</text>
|
<text class="meta">剩余 {{ item.remaining_count }}/{{ item.capacity }}</text>
|
||||||
<text class="course-price">¥{{ item.price }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -118,6 +116,7 @@ const pageSize = 20
|
|||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isLoadingMore = ref(false)
|
const isLoadingMore = ref(false)
|
||||||
|
let loadRequestId = 0
|
||||||
|
|
||||||
const ticketProduct = ref(null)
|
const ticketProduct = ref(null)
|
||||||
const ticketQty = ref(1)
|
const ticketQty = ref(1)
|
||||||
@@ -143,6 +142,7 @@ const dateOptions = computed(() => {
|
|||||||
const hasMore = computed(() => sessions.value.length < total.value)
|
const hasMore = computed(() => sessions.value.length < total.value)
|
||||||
|
|
||||||
const switchTab = (tab) => {
|
const switchTab = (tab) => {
|
||||||
|
if (activeTab.value === tab) return
|
||||||
activeTab.value = tab
|
activeTab.value = tab
|
||||||
if (tab === 'tickets') {
|
if (tab === 'tickets') {
|
||||||
loadTicketProduct()
|
loadTicketProduct()
|
||||||
@@ -153,15 +153,22 @@ const switchTab = (tab) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onDateSelect = (date) => {
|
const onDateSelect = (date) => {
|
||||||
|
if (selectedDate.value === date) return
|
||||||
selectedDate.value = date
|
selectedDate.value = date
|
||||||
loadSessions(true)
|
loadSessions(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadSessions = async (reset) => {
|
const loadSessions = async (reset) => {
|
||||||
if (activeTab.value === 'membership' && !session.isLoggedIn) return
|
if (activeTab.value === 'membership' && !session.isLoggedIn) {
|
||||||
|
sessions.value = []
|
||||||
|
total.value = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const requestId = ++loadRequestId
|
||||||
if (reset) {
|
if (reset) {
|
||||||
page.value = 1
|
page.value = 1
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
sessions.value = []
|
||||||
} else {
|
} else {
|
||||||
isLoadingMore.value = true
|
isLoadingMore.value = true
|
||||||
}
|
}
|
||||||
@@ -172,11 +179,20 @@ const loadSessions = async (reset) => {
|
|||||||
} else {
|
} else {
|
||||||
data = await courseApi.getSessions({ page: page.value, pageSize, date: selectedDate.value })
|
data = await courseApi.getSessions({ page: page.value, pageSize, date: selectedDate.value })
|
||||||
}
|
}
|
||||||
|
if (requestId !== loadRequestId) return
|
||||||
sessions.value = reset ? data.items : [...sessions.value, ...data.items]
|
sessions.value = reset ? data.items : [...sessions.value, ...data.items]
|
||||||
total.value = data.total
|
total.value = data.total
|
||||||
|
} catch {
|
||||||
|
if (requestId !== loadRequestId) return
|
||||||
|
if (reset) {
|
||||||
|
sessions.value = []
|
||||||
|
total.value = 0
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
if (requestId === loadRequestId) {
|
||||||
isLoadingMore.value = false
|
isLoading.value = false
|
||||||
|
isLoadingMore.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,12 +467,6 @@ defineExpose({ refresh, loadMore })
|
|||||||
margin-top: 6rpx;
|
margin-top: 6rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-price {
|
|
||||||
color: $text-color-main;
|
|
||||||
font-size: 28rpx;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 篮球门票 */
|
/* 篮球门票 */
|
||||||
.ticket-section {
|
.ticket-section {
|
||||||
padding: $spacing-md;
|
padding: $spacing-md;
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
<view class="title-row">
|
<view class="title-row">
|
||||||
<text class="course-title">{{ sessionData.title }}</text>
|
<text class="course-title">{{ sessionData.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="price-row">
|
|
||||||
<text class="price-text">¥{{ sessionData.price }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="info-card card">
|
<view class="info-card card">
|
||||||
@@ -172,7 +169,6 @@ const confirmBook = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title-row,
|
.title-row,
|
||||||
.price-row,
|
|
||||||
.info-row {
|
.info-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -188,10 +184,6 @@ const confirmBook = async () => {
|
|||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-row {
|
|
||||||
margin-top: $spacing-md;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-card,
|
.info-card,
|
||||||
.rich-card {
|
.rich-card {
|
||||||
margin-top: $spacing-md;
|
margin-top: $spacing-md;
|
||||||
|
|||||||
@@ -23,24 +23,12 @@
|
|||||||
|
|
||||||
<view class="card method-card">
|
<view class="card method-card">
|
||||||
<text class="card-title">支付方式</text>
|
<text class="card-title">支付方式</text>
|
||||||
<view
|
<view class="method-item active">
|
||||||
v-if="!isStoredValueOrder"
|
|
||||||
class="method-item"
|
|
||||||
:class="{ active: payMethod === 'balance', disabled: !canUseBalance }"
|
|
||||||
@tap="selectMethod('balance')"
|
|
||||||
>
|
|
||||||
<view>
|
|
||||||
<text class="method-title">余额支付</text>
|
|
||||||
<text class="method-sub">当前余额 ¥{{ balance.balance }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="method-check">{{ payMethod === 'balance' ? '已选' : '' }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="method-item" :class="{ active: payMethod === 'wechat' }" @tap="selectMethod('wechat')">
|
|
||||||
<view>
|
<view>
|
||||||
<text class="method-title">微信支付</text>
|
<text class="method-title">微信支付</text>
|
||||||
<text class="method-sub">使用微信支付完成订单</text>
|
<text class="method-sub">使用微信支付完成订单</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="method-check">{{ payMethod === 'wechat' ? '已选' : '' }}</text>
|
<text class="method-check">已选</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -61,28 +49,19 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onUnmounted, ref } from 'vue'
|
import { computed, onUnmounted, ref } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { memberApi } from '@/modules/comprehensive/api/member'
|
|
||||||
import { orderApi } from '@/modules/comprehensive/api/order'
|
import { orderApi } from '@/modules/comprehensive/api/order'
|
||||||
import { formatDateTime } from '@/modules/comprehensive/utils/date'
|
import { formatDateTime } from '@/modules/comprehensive/utils/date'
|
||||||
import { toAmountNumber } from '@/modules/comprehensive/utils/money'
|
|
||||||
|
|
||||||
const orderId = ref('')
|
const orderId = ref('')
|
||||||
const order = ref(null)
|
const order = ref(null)
|
||||||
const balance = ref({ balance: '0.00' })
|
|
||||||
const payMethod = ref('balance')
|
|
||||||
const isSubmitting = ref(false)
|
const isSubmitting = ref(false)
|
||||||
const nowTimestamp = ref(Date.now())
|
const nowTimestamp = ref(Date.now())
|
||||||
let countdownTimer = null
|
let countdownTimer = null
|
||||||
|
|
||||||
const isStoredValueOrder = computed(() => order.value?.business_type === 'stored_value')
|
const canPay = computed(() => order.value?.status === 'pending_pay')
|
||||||
const canUseBalance = computed(() => {
|
|
||||||
if (isStoredValueOrder.value) return false
|
|
||||||
return toAmountNumber(balance.value.balance) >= toAmountNumber(order.value?.amount)
|
|
||||||
})
|
|
||||||
const canPay = computed(() => order.value?.status === 'pending_pay' && (payMethod.value !== 'balance' || canUseBalance.value))
|
|
||||||
const payButtonText = computed(() => {
|
const payButtonText = computed(() => {
|
||||||
if (order.value?.status !== 'pending_pay') return '订单不可支付'
|
if (order.value?.status !== 'pending_pay') return '订单不可支付'
|
||||||
return payMethod.value === 'balance' ? '余额支付' : '微信支付'
|
return '微信支付'
|
||||||
})
|
})
|
||||||
const paymentRemainingSeconds = computed(() => {
|
const paymentRemainingSeconds = computed(() => {
|
||||||
if (!order.value?.expire_at) return 0
|
if (!order.value?.expire_at) return 0
|
||||||
@@ -107,17 +86,7 @@ onUnmounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const loadPage = async () => {
|
const loadPage = async () => {
|
||||||
const [orderData, balanceData] = await Promise.all([
|
order.value = await orderApi.getOrderDetail(orderId.value)
|
||||||
orderApi.getOrderDetail(orderId.value),
|
|
||||||
memberApi.getBalance()
|
|
||||||
])
|
|
||||||
order.value = orderData
|
|
||||||
balance.value = balanceData
|
|
||||||
if (isStoredValueOrder.value) {
|
|
||||||
payMethod.value = 'wechat'
|
|
||||||
} else if (!canUseBalance.value) {
|
|
||||||
payMethod.value = 'wechat'
|
|
||||||
}
|
|
||||||
updateCountdownTimer()
|
updateCountdownTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,33 +108,13 @@ const stopCountdown = () => {
|
|||||||
|
|
||||||
const padTime = (value) => String(value).padStart(2, '0')
|
const padTime = (value) => String(value).padStart(2, '0')
|
||||||
|
|
||||||
const selectMethod = (method) => {
|
|
||||||
if (method === 'balance') {
|
|
||||||
if (isStoredValueOrder.value) {
|
|
||||||
uni.showToast({ title: '储值卡订单仅支持微信支付', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!canUseBalance.value) {
|
|
||||||
uni.showToast({ title: '余额不足', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
payMethod.value = method
|
|
||||||
}
|
|
||||||
|
|
||||||
const pay = async () => {
|
const pay = async () => {
|
||||||
if (!canPay.value || isSubmitting.value) return
|
if (!canPay.value || isSubmitting.value) return
|
||||||
if (isStoredValueOrder.value && payMethod.value === 'balance') return
|
|
||||||
isSubmitting.value = true
|
isSubmitting.value = true
|
||||||
try {
|
try {
|
||||||
if (payMethod.value === 'balance') {
|
const paymentData = await orderApi.payOrderByWechat(order.value.id)
|
||||||
await orderApi.payOrderByBalance(order.value.id)
|
await requestWechatPayment(paymentData.wechat)
|
||||||
uni.showToast({ title: '支付成功', icon: 'success' })
|
uni.showToast({ title: '支付已提交', icon: 'success' })
|
||||||
} else {
|
|
||||||
const paymentData = await orderApi.payOrderByWechat(order.value.id)
|
|
||||||
await requestWechatPayment(paymentData.wechat)
|
|
||||||
uni.showToast({ title: '支付已提交', icon: 'success' })
|
|
||||||
}
|
|
||||||
await loadPage()
|
await loadPage()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.redirectTo({ url: `/pages/comprehensive/orders/detail?id=${order.value.id}` })
|
uni.redirectTo({ url: `/pages/comprehensive/orders/detail?id=${order.value.id}` })
|
||||||
@@ -269,10 +218,6 @@ const requestWechatPayment = (wechatPayload) => new Promise((resolve, reject) =>
|
|||||||
color: $color-primary;
|
color: $color-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.method-item.disabled {
|
|
||||||
opacity: 0.45;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-title,
|
.method-title,
|
||||||
.method-sub {
|
.method-sub {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -2,24 +2,26 @@
|
|||||||
<view class="confirm-page container page-bottom-safe" v-if="quote">
|
<view class="confirm-page container page-bottom-safe" v-if="quote">
|
||||||
<view class="card summary-card">
|
<view class="card summary-card">
|
||||||
<text class="card-title">{{ courtTypeLabel(payload.court_type) }}包场</text>
|
<text class="card-title">{{ courtTypeLabel(payload.court_type) }}包场</text>
|
||||||
<view class="summary-row">
|
<view
|
||||||
<text>预约场地</text>
|
v-for="(item, index) in quote.items"
|
||||||
<text>{{ quote.courts.map(item => item.name).join('、') }}</text>
|
:key="index"
|
||||||
</view>
|
class="item-row"
|
||||||
<view class="summary-row">
|
>
|
||||||
<text>预约时间</text>
|
<view class="item-header">
|
||||||
<text>{{ formatTimeRange(quote.start_at, quote.end_at) }}</text>
|
<text class="item-name">{{ item.court_name }}</text>
|
||||||
</view>
|
<text class="item-amount">¥{{ item.amount }}</text>
|
||||||
<view class="summary-row">
|
</view>
|
||||||
<text>预约时长</text>
|
<view class="item-meta">
|
||||||
<text>{{ formatDuration(quote.start_at, quote.end_at) }}</text>
|
<text>{{ formatTime(item.start_at) }}-{{ formatTime(item.end_at) }}</text>
|
||||||
|
<text>{{ formatDuration(item.start_at, item.end_at) }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="card fee-card">
|
<view class="card fee-card">
|
||||||
<text class="card-title">费用明细</text>
|
<text class="card-title">费用明细</text>
|
||||||
<view class="summary-row">
|
<view class="summary-row">
|
||||||
<text>半小时段</text>
|
<text>时段</text>
|
||||||
<text>{{ quote.unit_count }} 段</text>
|
<text>{{ quote.unit_count }} 段</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="summary-row">
|
<view class="summary-row">
|
||||||
@@ -47,7 +49,7 @@ import { ref } from 'vue'
|
|||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { privateBookingApi } from '@/modules/comprehensive/api/privateBooking'
|
import { privateBookingApi } from '@/modules/comprehensive/api/privateBooking'
|
||||||
import { courtTypeLabel } from '@/modules/comprehensive/utils/status'
|
import { courtTypeLabel } from '@/modules/comprehensive/utils/status'
|
||||||
import { formatDuration, formatTimeRange } from '@/modules/comprehensive/utils/date'
|
import { formatDuration, formatTime } from '@/modules/comprehensive/utils/date'
|
||||||
|
|
||||||
const payload = ref({})
|
const payload = ref({})
|
||||||
const quote = ref(null)
|
const quote = ref(null)
|
||||||
@@ -84,6 +86,42 @@ const submit = async () => {
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-row {
|
||||||
|
padding: $spacing-sm 0;
|
||||||
|
border-bottom: 1rpx solid $bg-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
color: $text-color-main;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-amount {
|
||||||
|
color: $text-color-main;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-md;
|
||||||
|
color: $text-color-muted;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.summary-row {
|
.summary-row {
|
||||||
min-height: 72rpx;
|
min-height: 72rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -122,6 +122,9 @@ const bindPhone = async (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const goHome = () => {
|
const goHome = () => {
|
||||||
|
if (authStorage.getPendingToken()) {
|
||||||
|
session.completeLogin()
|
||||||
|
}
|
||||||
uni.switchTab({ url: '/pages/home/index' })
|
uni.switchTab({ url: '/pages/home/index' })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
defineExpose({
|
||||||
|
refresh() {}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -7,12 +7,22 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
import { getStoredVenue } from '@/utils/venue'
|
import { getStoredVenue } from '@/utils/venue'
|
||||||
import ComprehensivePrivate from '@/pages/comprehensive/private/index.vue'
|
import ComprehensivePrivate from '@/pages/comprehensive/private/index.vue'
|
||||||
import IcePrivate from '@/pages/ice/private/index.vue'
|
import IcePrivate from '@/pages/ice/private/index.vue'
|
||||||
|
|
||||||
const isComprehensive = getStoredVenue() === 'comprehensive'
|
const isComprehensive = getStoredVenue() === 'comprehensive'
|
||||||
const contentRef = ref()
|
const contentRef = ref()
|
||||||
|
let isFirstShow = true
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (isFirstShow) {
|
||||||
|
isFirstShow = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
contentRef.value?.refresh?.()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user