feat: migrate comprehensive venue module

This commit is contained in:
gqt
2026-06-08 20:54:25 +08:00
parent c9650b0db1
commit 8e1443f7e5
43 changed files with 5017 additions and 0 deletions
@@ -0,0 +1,171 @@
<template>
<view class="tickets-page container page-bottom-safe" v-if="product">
<view class="product-card card">
<view class="product-head">
<view>
<text class="product-title">篮球门票</text>
<text class="product-subtitle">购买后进入会员权益账户到馆由前台核销</text>
</view>
</view>
<view class="price-block">
<text class="unit-price">¥{{ product.unit_price }}</text>
<text class="unit-label">/ </text>
</view>
</view>
<view class="card count-card">
<text class="card-title">购买次数</text>
<view class="stepper-row">
<button class="step-btn" @tap="decrease">-</button>
<text class="quantity">{{ quantity }}</text>
<button class="step-btn" @tap="increase">+</button>
</view>
<view class="amount-row">
<text>合计金额</text>
<text>¥{{ totalAmount }}</text>
</view>
</view>
<view class="fixed-action-bar">
<view class="bar-price">
<text class="bar-label">合计</text>
<text class="price-text">¥{{ totalAmount }}</text>
</view>
<button class="primary-button submit-btn" :disabled="isSubmitting || !product.is_active" @tap="submit">
立即购买
</button>
</view>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue'
import { ticketApi } from '@/modules/comprehensive/api/ticket'
import { multiplyAmount } from '@/modules/comprehensive/utils/money'
const product = ref(null)
const quantity = ref(1)
const isSubmitting = ref(false)
const totalAmount = computed(() => product.value ? multiplyAmount(product.value.unit_price, quantity.value) : '0.00')
onMounted(async () => {
product.value = await ticketApi.getTicketProduct()
})
const decrease = () => {
quantity.value = Math.max(1, quantity.value - 1)
}
const increase = () => {
quantity.value += 1
}
const submit = async () => {
if (isSubmitting.value || !product.value?.is_active) return
isSubmitting.value = true
try {
const data = await ticketApi.createTicketOrder(quantity.value)
uni.navigateTo({ url: `/pages/comprehensive/pay/index?order_id=${data.order.id}` })
} finally {
isSubmitting.value = false
}
}
</script>
<style lang="scss" scoped>
.product-card,
.count-card {
margin-bottom: $spacing-md;
}
.product-head,
.amount-row,
.stepper-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: $spacing-md;
}
.product-title,
.card-title {
display: block;
color: $text-color-main;
font-size: 34rpx;
font-weight: 900;
}
.product-subtitle {
display: block;
margin-top: $spacing-xs;
color: $text-color-muted;
font-size: 24rpx;
line-height: 1.6;
}
.price-block {
margin-top: $spacing-xl;
}
.unit-price {
color: $text-color-main;
font-size: 64rpx;
font-weight: 900;
}
.unit-label {
color: $text-color-muted;
font-size: 26rpx;
}
.stepper-row {
margin: $spacing-lg 0;
}
.step-btn {
width: 86rpx;
height: 70rpx;
border-radius: $border-radius-base;
background: $text-color-main;
color: #FFFFFF;
font-size: 38rpx;
font-weight: 900;
display: flex;
align-items: center;
justify-content: center;
}
.quantity {
color: $text-color-main;
font-size: 42rpx;
font-weight: 900;
}
.amount-row {
padding-top: $spacing-md;
border-top: 1rpx solid $bg-color-hover;
color: $text-color-muted;
font-size: 26rpx;
}
.amount-row text:last-child {
color: $text-color-main;
font-size: 34rpx;
font-weight: 900;
}
.bar-price {
flex: 1;
}
.bar-label {
display: block;
color: $text-color-light;
font-size: 22rpx;
}
.submit-btn {
width: 320rpx;
}
</style>