744 lines
23 KiB
Vue
744 lines
23 KiB
Vue
<template>
|
||
<view class="page">
|
||
<!-- 固定头部 -->
|
||
<view class="header">
|
||
<view class="center" style="width: 50rpx; height: 50rpx; margin-left: 32rpx;">
|
||
<image src="/static/ic_back.png" @click="back" style="width: 48rpx; height: 48rpx;" mode=""></image>
|
||
</view>
|
||
<text style="font-size: 30rpx;">{{ $t('infoEntry.title') }}</text>
|
||
<view style="width: 50rpx;margin-right: 32rpx;"></view>
|
||
</view>
|
||
|
||
<!-- 可滚动内容区域 -->
|
||
<view class="scroll-content">
|
||
<view class="content">
|
||
<!-- 预约登记规则区域 -->
|
||
<view class="booking-rules-box" v-if="bookingRules">
|
||
<view class="rules-title">预约登记规则</view>
|
||
<view class="rules-content">{{ bookingRules }}</view>
|
||
</view>
|
||
<view v-else class=""
|
||
style="width: 680rpx; height: 396rpx; background-image: linear-gradient(-45deg, #60D7FF, #68BBD7); margin-top: 32rpx; border-radius: 20rpx; box-shadow: 0 0 10rpx 10rpx rgba(0, 0, 0, 0.1);">
|
||
</view>
|
||
|
||
<view class="" style="width: 100%; font-size: 40rpx; padding-left: 54rpx; margin-top: 38rpx;">
|
||
{{ $t('infoEntry.personalInfo') }}
|
||
</view>
|
||
|
||
<!-- 真实姓名 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'userName' }"
|
||
style="width: 680rpx; margin-top: 38rpx;" id="fieldUserName">
|
||
<text style="font-size: 30rpx;"><text
|
||
style="color: #FF0000;">*</text>{{ $t('infoEntry.realName') }}</text>
|
||
<up-input :placeholder="$t('infoEntry.realNamePlaceholder')" border="surround"
|
||
v-model="userName"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 微信号 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldContact">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.wechat') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<up-input :placeholder="$t('infoEntry.wechatPlaceholder')" border="surround"
|
||
v-model="userWechat"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 手机号 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.phone') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<view class="row" style="margin-top: 10rpx; margin-bottom: 10rpx;">
|
||
<aure-country-picker v-model="selectedDialCode" :title="$t('infoEntry.selectCountry')"
|
||
:height="'70%'" :width="'60vw'" :duration="350" :position="'bottom'" :round="true"
|
||
:radius="'24rpx'" :mask-closable="true"></aure-country-picker>
|
||
<up-input :placeholder="$t('infoEntry.phonePlaceholder')" border="surround"
|
||
v-model="userPhone"></up-input>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- whatsApp -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.whatsapp') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<up-input :placeholder="$t('infoEntry.whatsappPlaceholder')" border="surround"
|
||
v-model="userWhats"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 备注 -->
|
||
<view class="column" style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;">{{ $t('infoEntry.remark') }}</text>
|
||
<up-input :placeholder="$t('infoEntry.remarkPlaceholder')" border="surround"
|
||
v-model="remark"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 服务预约信息 -->
|
||
<view class="" style="width: 100%; font-size: 40rpx; padding-left: 54rpx; margin-top: 38rpx;">
|
||
{{ $t('infoEntry.serviceInfo') }}
|
||
</view>
|
||
|
||
<!-- 单程/往返 -->
|
||
<view class="column" style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>单程 / 往返</text>
|
||
<view class="date-item" @click="showTripPicker = true">
|
||
<text class="date-text">{{ tripTypeText }}</text>
|
||
<image src="/static/arrow_down.png" style="width: 32rpx; height: 32rpx;" mode="aspectFit">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 出发日期 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'departureDate' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldDepartureDate">
|
||
<text style="font-size: 30rpx;"><text
|
||
style="color: #FF0000;">*</text>{{ $t('infoEntry.departureDate') }}</text>
|
||
<view class="date-item" @click="openDepartureCalendar">
|
||
<text class="date-text" :class="{ 'date-placeholder': !departureDate }">
|
||
{{ departureDate || $t('infoEntry.departureDatePlaceholder') }}
|
||
</text>
|
||
<image src="/static/arrow_right2.png" style="width: 32rpx; height: 32rpx;" mode="aspectFit">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 返程日期 (往返时显示) -->
|
||
<view v-if="tripType === 'round'" class="column"
|
||
:class="{ 'flash-animation': flashingField === 'returnDate' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldReturnDate">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>返程日期</text>
|
||
<view class="date-item" @click="openReturnCalendar">
|
||
<text class="date-text" :class="{ 'date-placeholder': !returnDate }">
|
||
{{ returnDate || '请选择返程日期' }}
|
||
</text>
|
||
<image src="/static/arrow_right2.png" style="width: 32rpx; height: 32rpx;" mode="aspectFit">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view v-if="tripType === 'round'" class=""
|
||
style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 出发城市 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'departureCity' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldDepartureCity">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>出发城市</text>
|
||
<up-input placeholder="请输入出发城市" border="surround" v-model="departureCity"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 到达城市 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'arrivalCity' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldArrivalCity">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>到达城市</text>
|
||
<up-input placeholder="请输入到达城市" border="surround" v-model="arrivalCity"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 人数 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'personCount' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldPersonCount">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>人数</text>
|
||
|
||
<!-- 成人 -->
|
||
<view class="person-row">
|
||
<view class="person-info">
|
||
<text class="person-title">成人</text>
|
||
<text class="person-desc">13岁或以上</text>
|
||
</view>
|
||
<view class="person-counter">
|
||
<view class="counter-btn" @click="decreaseCount('adult')">
|
||
<text class="counter-icon">-</text>
|
||
</view>
|
||
<text class="counter-value">{{ adultCount }}人</text>
|
||
<view class="counter-btn" @click="increaseCount('adult')">
|
||
<text class="counter-icon">+</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 儿童 -->
|
||
<view class="person-row">
|
||
<view class="person-info">
|
||
<text class="person-title">儿童</text>
|
||
<text class="person-desc">2~12岁</text>
|
||
</view>
|
||
<view class="person-counter">
|
||
<view class="counter-btn" @click="decreaseCount('child')">
|
||
<text class="counter-icon">-</text>
|
||
</view>
|
||
<text class="counter-value">{{ childCount }}人</text>
|
||
<view class="counter-btn" @click="increaseCount('child')">
|
||
<text class="counter-icon">+</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 婴儿 -->
|
||
<view class="person-row">
|
||
<view class="person-info">
|
||
<text class="person-title">婴儿</text>
|
||
<text class="person-desc">2岁以下</text>
|
||
</view>
|
||
<view class="person-counter">
|
||
<view class="counter-btn" @click="decreaseCount('infant')">
|
||
<text class="counter-icon">-</text>
|
||
</view>
|
||
<text class="counter-value">{{ infantCount }}人</text>
|
||
<view class="counter-btn" @click="increaseCount('infant')">
|
||
<text class="counter-icon">+</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 舱位选择 -->
|
||
<view class="column" style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>舱位选择</text>
|
||
<view class="date-item" @click="showCabinPicker = true">
|
||
<text class="date-text">{{ cabinTypeText }}</text>
|
||
<image src="/static/arrow_down.png" style="width: 32rpx; height: 32rpx;" mode="aspectFit">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 行李件数 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'luggageCount' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldLuggageCount">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>行李件数</text>
|
||
<up-input placeholder="请输入行李件数" border="surround" v-model="luggageCount" type="number"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<view class="center" @click="checkData()"
|
||
style="width: 642rpx; height: 72rpx; background-color: #57C9DD; border-radius: 16rpx; box-shadow: 0 0 10rpx 10rpx rgba(0, 0, 0, 0.1); margin-top: 50rpx; margin-bottom: 100rpx;">
|
||
{{ $t('common.submit') }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 行程类型选择器 -->
|
||
<up-picker :show="showTripPicker" :columns="tripTypeColumns" @confirm="onTripTypeConfirm"
|
||
@cancel="showTripPicker = false" @close="showTripPicker = false" :defaultIndex="[tripTypeIndex]"
|
||
keyName="label">
|
||
</up-picker>
|
||
<!-- 舱位选择器 -->
|
||
<up-picker :show="showCabinPicker" :columns="cabinTypeColumns" @confirm="onCabinTypeConfirm"
|
||
@cancel="showCabinPicker = false" @close="showCabinPicker = false" :defaultIndex="[cabinTypeIndex]"
|
||
keyName="label">
|
||
</up-picker>
|
||
<!-- 日历选择器 -->
|
||
<up-calendar :show="showCalendar" mode="single" :minDate="minDate" :maxDate="maxDate"
|
||
@confirm="onCalendarConfirm" @close="closeCalendar" :confirmText="$t('common.confirm')" color="#57C9DD">
|
||
</up-calendar>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { AppServer } from '@/modules/api/AppServer.js'
|
||
import bookingRulesMixin from '@/mixins/bookingRulesMixin.js'
|
||
const appServer = new AppServer()
|
||
|
||
export default {
|
||
mixins: [bookingRulesMixin],
|
||
data() {
|
||
return {
|
||
serviceId: "", // 服务ID(来自分类页)
|
||
hotServiceId: "", // 热门服务ID(来自热门服务)
|
||
source: "", // 来源:hot=热门服务,其他=分类页
|
||
serviceTitle: "", // 服务标题
|
||
userName: "",
|
||
userWechat: "",
|
||
userPhone: "",
|
||
userWhats: "",
|
||
remark: "",
|
||
departureDate: "",
|
||
returnDate: "",
|
||
departureCity: "",
|
||
arrivalCity: "",
|
||
luggageCount: "",
|
||
adultCount: 0,
|
||
childCount: 0,
|
||
infantCount: 0,
|
||
calendarType: "departure",
|
||
tripType: "single",
|
||
tripTypeIndex: 0,
|
||
submitting: false, // 提交状态
|
||
tripTypeColumns: [
|
||
[{
|
||
label: '单程',
|
||
value: 'single'
|
||
},
|
||
{
|
||
label: '往返',
|
||
value: 'round'
|
||
}
|
||
]
|
||
],
|
||
cabinType: "economy",
|
||
cabinTypeIndex: 0,
|
||
cabinTypeColumns: [
|
||
[{
|
||
label: '经济舱',
|
||
value: 'economy'
|
||
},
|
||
{
|
||
label: '超级经济舱',
|
||
value: 'premium_economy'
|
||
},
|
||
{
|
||
label: '商务舱',
|
||
value: 'business'
|
||
}
|
||
]
|
||
],
|
||
flashingField: '',
|
||
selectedDialCode: '86',
|
||
showCalendar: false,
|
||
showTripPicker: false,
|
||
showCabinPicker: false,
|
||
minDate: '',
|
||
maxDate: ''
|
||
}
|
||
},
|
||
computed: {
|
||
tripTypeText() {
|
||
const item = this.tripTypeColumns[0].find(t => t.value === this.tripType)
|
||
return item ? item.label : '单程'
|
||
},
|
||
cabinTypeText() {
|
||
const item = this.cabinTypeColumns[0].find(t => t.value === this.cabinType)
|
||
return item ? item.label : '经济舱'
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
this.initDateRange()
|
||
// 获取页面参数
|
||
if (options.id) {
|
||
this.source = options.source || ''
|
||
// 根据来源判断是 serviceId 还是 hotServiceId
|
||
if (this.source === 'hot') {
|
||
this.hotServiceId = options.id
|
||
} else {
|
||
this.serviceId = options.id
|
||
}
|
||
}
|
||
if (options.title) {
|
||
this.serviceTitle = decodeURIComponent(options.title)
|
||
}
|
||
// 加载预约规则
|
||
this.loadBookingRules('flight')
|
||
},
|
||
methods: {
|
||
initDateRange() {
|
||
const now = new Date()
|
||
const year = now.getFullYear()
|
||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
const day = String(now.getDate()).padStart(2, '0')
|
||
this.minDate = `${year}-${month}-${day}`
|
||
this.maxDate = `${year + 2}-12-31`
|
||
},
|
||
openDepartureCalendar() {
|
||
console.log('打开出发日期选择器')
|
||
this.calendarType = 'departure'
|
||
this.initDateRange()
|
||
this.$nextTick(() => {
|
||
this.showCalendar = true
|
||
})
|
||
},
|
||
openReturnCalendar() {
|
||
console.log('打开返程日期选择器')
|
||
this.calendarType = 'return'
|
||
// 返程日期最小值为出发日期
|
||
if (this.departureDate) {
|
||
this.minDate = this.departureDate
|
||
} else {
|
||
this.initDateRange()
|
||
}
|
||
this.$nextTick(() => {
|
||
this.showCalendar = true
|
||
})
|
||
},
|
||
closeCalendar() {
|
||
this.showCalendar = false
|
||
this.initDateRange()
|
||
},
|
||
onCalendarConfirm(dates) {
|
||
console.log('日历确认:', dates)
|
||
if (dates && dates.length > 0) {
|
||
if (this.calendarType === 'departure') {
|
||
this.departureDate = dates[0]
|
||
// 如果返程日期早于出发日期,清空返程日期
|
||
if (this.returnDate && this.returnDate < dates[0]) {
|
||
this.returnDate = ''
|
||
}
|
||
} else {
|
||
this.returnDate = dates[0]
|
||
}
|
||
}
|
||
this.showCalendar = false
|
||
this.initDateRange()
|
||
},
|
||
onTripTypeConfirm(e) {
|
||
const selected = e.value[0]
|
||
this.tripType = selected.value
|
||
this.tripTypeIndex = this.tripTypeColumns[0].findIndex(t => t.value === selected.value)
|
||
this.showTripPicker = false
|
||
},
|
||
onCabinTypeConfirm(e) {
|
||
const selected = e.value[0]
|
||
this.cabinType = selected.value
|
||
this.cabinTypeIndex = this.cabinTypeColumns[0].findIndex(t => t.value === selected.value)
|
||
this.showCabinPicker = false
|
||
},
|
||
checkData() {
|
||
// 验证规则列表(按顺序)
|
||
const validations = [{
|
||
field: 'userName',
|
||
selector: '#fieldUserName',
|
||
check: () => !this.userName.trim(),
|
||
message: '请输入真实姓名'
|
||
},
|
||
{
|
||
field: 'contact',
|
||
selector: '#fieldContact',
|
||
check: () => !this.userWechat.trim() && !this.userPhone.trim() && !this.userWhats.trim(),
|
||
message: '请至少填写一种联系方式(微信号/手机号/WhatsApp)'
|
||
},
|
||
{
|
||
field: 'departureDate',
|
||
selector: '#fieldDepartureDate',
|
||
check: () => !this.departureDate,
|
||
message: '请选择出发日期'
|
||
},
|
||
{
|
||
field: 'returnDate',
|
||
selector: '#fieldReturnDate',
|
||
check: () => this.tripType === 'round' && !this.returnDate,
|
||
message: '请选择返程日期'
|
||
},
|
||
{
|
||
field: 'departureCity',
|
||
selector: '#fieldDepartureCity',
|
||
check: () => !this.departureCity.trim(),
|
||
message: '请输入出发城市'
|
||
},
|
||
{
|
||
field: 'arrivalCity',
|
||
selector: '#fieldArrivalCity',
|
||
check: () => !this.arrivalCity.trim(),
|
||
message: '请输入到达城市'
|
||
},
|
||
{
|
||
field: 'personCount',
|
||
selector: '#fieldPersonCount',
|
||
check: () => this.adultCount === 0 && this.childCount === 0 && this.infantCount === 0,
|
||
message: '请至少选择一位乘客'
|
||
},
|
||
{
|
||
field: 'luggageCount',
|
||
selector: '#fieldLuggageCount',
|
||
check: () => !this.luggageCount || this.luggageCount === '',
|
||
message: '请输入行李件数'
|
||
}
|
||
]
|
||
|
||
// 遍历验证
|
||
for (const validation of validations) {
|
||
if (validation.check()) {
|
||
uni.showToast({
|
||
title: validation.message,
|
||
icon: 'none'
|
||
})
|
||
// 滚动到对应元素
|
||
this.scrollToElement(validation.selector)
|
||
// 闪烁效果
|
||
this.flashingField = validation.field
|
||
setTimeout(() => {
|
||
this.flashingField = ''
|
||
}, 1500)
|
||
return
|
||
}
|
||
}
|
||
|
||
// 所有验证通过,提交数据
|
||
this.submitAppointment()
|
||
},
|
||
async submitAppointment() {
|
||
if (this.submitting) return
|
||
this.submitting = true
|
||
|
||
uni.showLoading({
|
||
title: '提交中...',
|
||
mask: true
|
||
})
|
||
|
||
try {
|
||
// 构建预约数据
|
||
const appointmentData = {
|
||
serviceId: this.serviceId || null,
|
||
hotServiceId: this.hotServiceId ? parseInt(this.hotServiceId) : null,
|
||
serviceType: 'flight', // 机票类型
|
||
realName: this.userName.trim(),
|
||
// 多联系方式
|
||
wechatId: this.userWechat.trim() || null,
|
||
phone: this.userPhone.trim() || null,
|
||
phoneCountryCode: this.userPhone.trim() ? this.selectedDialCode : null,
|
||
whatsapp: this.userWhats.trim() || null,
|
||
notes: this.remark.trim() || null,
|
||
// 机票专用字段
|
||
tripType: this.tripType,
|
||
departureDate: this.departureDate,
|
||
returnDate: this.tripType === 'round' ? this.returnDate : null,
|
||
departureCity: this.departureCity.trim(),
|
||
arrivalCity: this.arrivalCity.trim(),
|
||
adultCount: this.adultCount,
|
||
childCount: this.childCount,
|
||
infantCount: this.infantCount,
|
||
cabinType: this.cabinType,
|
||
luggageCount: parseInt(this.luggageCount) || 0,
|
||
}
|
||
|
||
const result = await appServer.CreateAppointment(appointmentData)
|
||
|
||
uni.hideLoading()
|
||
|
||
// 兼容两种返回格式: { success: true } 或 { code: 0 }
|
||
if (result.success || result.code === 0) {
|
||
uni.showToast({
|
||
title: '预约提交成功',
|
||
icon: 'success'
|
||
})
|
||
// 延迟返回上一页
|
||
setTimeout(() => {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
})
|
||
}, 1500)
|
||
} else {
|
||
uni.showToast({
|
||
title: result.error?.message || '提交失败,请重试',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
uni.hideLoading()
|
||
console.error('提交预约失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
this.submitting = false
|
||
}
|
||
},
|
||
scrollToElement(selector) {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
const screenHeight = systemInfo.windowHeight
|
||
const query = uni.createSelectorQuery().in(this)
|
||
query.select(selector).boundingClientRect()
|
||
query.selectViewport().scrollOffset()
|
||
query.exec((res) => {
|
||
if (res[0] && res[1]) {
|
||
const rect = res[0]
|
||
const scrollInfo = res[1]
|
||
// 当前滚动位置 + 元素相对视口的top - 屏幕高度的一半 + 元素高度的一半
|
||
const targetScrollTop = scrollInfo.scrollTop + rect.top - (screenHeight / 2) + (rect
|
||
.height / 2)
|
||
uni.pageScrollTo({
|
||
scrollTop: Math.max(0, targetScrollTop),
|
||
duration: 300
|
||
})
|
||
}
|
||
})
|
||
},
|
||
back() {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
},
|
||
increaseCount(type) {
|
||
if (type === 'adult') {
|
||
this.adultCount++
|
||
} else if (type === 'child') {
|
||
this.childCount++
|
||
} else if (type === 'infant') {
|
||
this.infantCount++
|
||
}
|
||
},
|
||
decreaseCount(type) {
|
||
if (type === 'adult' && this.adultCount > 0) {
|
||
this.adultCount--
|
||
} else if (type === 'child' && this.childCount > 0) {
|
||
this.childCount--
|
||
} else if (type === 'infant' && this.infantCount > 0) {
|
||
this.infantCount--
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.page {
|
||
min-height: 100vh;
|
||
background-color: #F3F3F3;
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
padding-top: 88rpx;
|
||
padding-bottom: 20rpx;
|
||
background-color: #F3F3F3;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.scroll-content {
|
||
padding-top: 140rpx;
|
||
background-color: #F3F3F3;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
background-color: #F3F3F3;
|
||
min-height: 100%;
|
||
}
|
||
|
||
.date-item {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
height: 80rpx;
|
||
padding: 0 10rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.date-text {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.date-placeholder {
|
||
color: #c0c4cc;
|
||
}
|
||
|
||
@keyframes flash {
|
||
0% {
|
||
background-color: #F3F3F3;
|
||
}
|
||
|
||
50% {
|
||
background-color: #ff6666;
|
||
}
|
||
|
||
100% {
|
||
background-color: #F3F3F3;
|
||
}
|
||
}
|
||
|
||
.flash-animation {
|
||
animation: flash 0.5s ease-in-out 3;
|
||
}
|
||
|
||
.person-row {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
padding: 20rpx 10rpx;
|
||
}
|
||
|
||
.person-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.person-title {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.person-desc {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
.person-counter {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
}
|
||
|
||
.counter-btn {
|
||
width: 50rpx;
|
||
height: 50rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #BFBFBF;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.counter-icon {
|
||
font-size: 28rpx;
|
||
color: #fff;
|
||
font-weight: bold;
|
||
line-height: 50rpx;
|
||
text-align: center;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.counter-value {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
min-width: 80rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 预约登记规则样式 */
|
||
.booking-rules-box {
|
||
width: 680rpx;
|
||
margin-top: 32rpx;
|
||
padding: 30rpx;
|
||
background-image: linear-gradient(-45deg, #60D7FF, #68BBD7);
|
||
border-radius: 20rpx;
|
||
box-shadow: 0 0 10rpx 10rpx rgba(0, 0, 0, 0.1);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.rules-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #fff;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.rules-content {
|
||
font-size: 26rpx;
|
||
color: #fff;
|
||
line-height: 1.6;
|
||
white-space: pre-wrap;
|
||
}
|
||
</style> |