|
@@ -1,4 +1,5 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
|
|
+import { columns } from './reservation-data'
|
|
|
import router from '@/router'
|
|
import router from '@/router'
|
|
|
|
|
|
|
|
definePage({
|
|
definePage({
|
|
@@ -8,12 +9,176 @@ definePage({
|
|
|
navigationBarTitleText: '预定信息',
|
|
navigationBarTitleText: '预定信息',
|
|
|
},
|
|
},
|
|
|
})
|
|
})
|
|
|
-const columns = ref(['选项1', '选项2', '选项3', '选项4', '选项5', '选项6', '选项7'])
|
|
|
|
|
-const value = ref('选项1')
|
|
|
|
|
|
|
+
|
|
|
|
|
+const productNo = ref(0)
|
|
|
|
|
+const productName = ref('')
|
|
|
|
|
+const selectDate = ref('')
|
|
|
|
|
+const isSingle = ref()
|
|
|
|
|
+const price = ref(0)
|
|
|
|
|
+onLoad((options: any) => {
|
|
|
|
|
+ productNo.value = Number(options.productNo) || 0
|
|
|
|
|
+ productName.value = options.productName || ''
|
|
|
|
|
+ selectDate.value = options.selectDate || ''
|
|
|
|
|
+ price.value = Number(options.price)
|
|
|
|
|
+ isSingle.value = Number(options.isSingle)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 数量选择
|
|
|
|
|
+const quantity = ref(1)
|
|
|
|
|
+function handleMinus() {
|
|
|
|
|
+ if (quantity.value > 1) {
|
|
|
|
|
+ quantity.value--
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+function handlePlus() {
|
|
|
|
|
+ quantity.value++
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 合计价格
|
|
|
|
|
+const totalPrice = computed(() => price.value * quantity.value)
|
|
|
|
|
+
|
|
|
|
|
+// 联系人信息
|
|
|
|
|
+const linkMan = ref('')
|
|
|
|
|
+const linkCreditType = ref(0)
|
|
|
|
|
+const linkCreditNo = ref('')
|
|
|
|
|
+const linkPhone = ref('')
|
|
|
|
|
+
|
|
|
|
|
+// 多游客信息列表
|
|
|
|
|
+interface PeopleInfo {
|
|
|
|
|
+ linkMan: string
|
|
|
|
|
+ linkCreditType: number
|
|
|
|
|
+ linkCreditNo: string
|
|
|
|
|
+}
|
|
|
|
|
+const peopleList = ref<PeopleInfo[]>([{ linkMan: '', linkCreditType: 0, linkCreditNo: '' }])
|
|
|
|
|
+
|
|
|
|
|
+// 监听数量变化,同步游客信息列表
|
|
|
|
|
+watch(quantity, (newVal) => {
|
|
|
|
|
+ if (isSingle.value === 1) {
|
|
|
|
|
+ const diff = newVal - peopleList.value.length
|
|
|
|
|
+ if (diff > 0) {
|
|
|
|
|
+ for (let i = 0; i < diff; i++) {
|
|
|
|
|
+ peopleList.value.push({ linkMan: '', linkCreditType: 0, linkCreditNo: '' })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (diff < 0) {
|
|
|
|
|
+ peopleList.value.splice(newVal)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
const orderPopup = ref(false)
|
|
const orderPopup = ref(false)
|
|
|
|
|
+const orderMemo = ref('')
|
|
|
|
|
+
|
|
|
|
|
+const formattedDate = computed(() => {
|
|
|
|
|
+ if (!selectDate.value)
|
|
|
|
|
+ return ''
|
|
|
|
|
+ const date = new Date(selectDate.value)
|
|
|
|
|
+ const year = date.getFullYear()
|
|
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
|
|
+ return `${year}年${month}月${day}日`
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 接口需要的日期格式 yyyy-MM-dd
|
|
|
|
|
+const travelDate = computed(() => {
|
|
|
|
|
+ if (!selectDate.value)
|
|
|
|
|
+ return ''
|
|
|
|
|
+ const date = new Date(selectDate.value)
|
|
|
|
|
+ const year = date.getFullYear()
|
|
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
|
|
+ return `${year}-${month}-${day}`
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
-function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
|
|
- value.value = selectedValue
|
|
|
|
|
|
|
+const { data: info } = useRequest(() =>
|
|
|
|
|
+ Apis.xsb.findUserPoints({}),
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+function handleLinkCreditConfirm({ value: selectedValue }: { value: number }) {
|
|
|
|
|
+ linkCreditType.value = selectedValue
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handlePeopleCreditConfirm(index: number, { value: selectedValue }: { value: number }) {
|
|
|
|
|
+ peopleList.value[index].linkCreditType = selectedValue
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 表单校验
|
|
|
|
|
+function validateForm(): boolean {
|
|
|
|
|
+ // 联系人姓名校验
|
|
|
|
|
+ if (!linkMan.value.trim()) {
|
|
|
|
|
+ useGlobalToast().show({ msg: '请输入联系人姓名' })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 单游客模式需要校验证件号码
|
|
|
|
|
+ if (isSingle.value === 0) {
|
|
|
|
|
+ if (!linkCreditNo.value.trim()) {
|
|
|
|
|
+ useGlobalToast().show({ msg: '请输入证件号码' })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 手机号码校验
|
|
|
|
|
+ if (!linkPhone.value.trim()) {
|
|
|
|
|
+ useGlobalToast().show({ msg: '请输入手机号码' })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 多游客模式校验游客信息
|
|
|
|
|
+ if (isSingle.value === 1) {
|
|
|
|
|
+ for (let i = 0; i < peopleList.value.length; i++) {
|
|
|
|
|
+ const people = peopleList.value[i]
|
|
|
|
|
+ if (!people.linkMan.trim()) {
|
|
|
|
|
+ useGlobalToast().show({ msg: `请输入游客${i + 1}姓名` })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!people.linkCreditNo.trim()) {
|
|
|
|
|
+ useGlobalToast().show({ msg: `请输入游客${i + 1}证件号码` })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 提交订单
|
|
|
|
|
+async function handleSubmit() {
|
|
|
|
|
+ // 表单校验
|
|
|
|
|
+ if (!validateForm())
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ const peoples: Api.PeopleItem[] = isSingle.value === 1
|
|
|
|
|
+ ? peopleList.value.map(p => ({
|
|
|
|
|
+ linkMan: p.linkMan,
|
|
|
|
|
+ linkCreditType: p.linkCreditType,
|
|
|
|
|
+ linkCreditNo: p.linkCreditNo,
|
|
|
|
|
+ }))
|
|
|
|
|
+ : []
|
|
|
|
|
+
|
|
|
|
|
+ const params: Api.CreateOrderRequest = {
|
|
|
|
|
+ productNo: productNo.value,
|
|
|
|
|
+ productName: productName.value,
|
|
|
|
|
+ num: quantity.value,
|
|
|
|
|
+ travelDate: travelDate.value,
|
|
|
|
|
+ linkMan: linkMan.value,
|
|
|
|
|
+ linkCreditType: isSingle.value === 0 ? linkCreditType.value : undefined,
|
|
|
|
|
+ linkCreditNo: isSingle.value === 0 ? linkCreditNo.value : undefined,
|
|
|
|
|
+ linkPhone: linkPhone.value,
|
|
|
|
|
+ orderMemo: orderMemo.value,
|
|
|
|
|
+ peoples: isSingle.value === 1 ? peoples : undefined,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ useGlobalLoading().loading({ msg: '提交中...' })
|
|
|
|
|
+ const res = await Apis.attractions.createOrder({ data: params })
|
|
|
|
|
+ useGlobalLoading().close()
|
|
|
|
|
+ router.push({ name: 'attractions-order-pay', params: { productName: productName.value, num: String(quantity.value), orderNo: res?.data } })
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ useGlobalLoading().close()
|
|
|
|
|
+ console.error('提交订单失败', error)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -23,12 +188,12 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
<view class="h-20rpx" />
|
|
<view class="h-20rpx" />
|
|
|
<view class="rounded-16rpx bg-#FFF p-24rpx">
|
|
<view class="rounded-16rpx bg-#FFF p-24rpx">
|
|
|
<view class="text-32rpx font-bold">
|
|
<view class="text-32rpx font-bold">
|
|
|
- 日场门票+观光车+飞越黄果树观影票+吉祥物+冰箱贴 经典必打卡
|
|
|
|
|
|
|
+ {{ productName }}
|
|
|
</view>
|
|
</view>
|
|
|
<view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view class="mt-24rpx flex items-center gap-10rpx text-28rpx">
|
|
<view class="mt-24rpx flex items-center gap-10rpx text-28rpx">
|
|
|
<wd-icon name="calendar" size="22px" />
|
|
<wd-icon name="calendar" size="22px" />
|
|
|
- <text>选定日期:2026年3月22日</text>
|
|
|
|
|
|
|
+ <text>选定日期:{{ formattedDate }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
|
|
<view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
|
|
@@ -37,83 +202,87 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
</view>
|
|
</view>
|
|
|
<view class="flex items-center gap-24rpx">
|
|
<view class="flex items-center gap-24rpx">
|
|
|
<view
|
|
<view
|
|
|
- class="h-36rpx w-36rpx rounded-50% bg-#F0F0F0 text-center text-28rpx text-#AAAAAA font-600 line-height-[36rpx]"
|
|
|
|
|
|
|
+ class="h-36rpx w-36rpx rounded-50% text-center text-28rpx font-600 line-height-[36rpx]"
|
|
|
|
|
+ :class="quantity > 1 ? 'bg-#E8FFA7 text-#9ED605' : 'bg-#F0F0F0 text-#AAAAAA'"
|
|
|
|
|
+ @click="handleMinus"
|
|
|
>
|
|
>
|
|
|
-
|
|
-
|
|
|
</view>
|
|
</view>
|
|
|
<view class="text-24rpx font-400">
|
|
<view class="text-24rpx font-400">
|
|
|
- 10
|
|
|
|
|
|
|
+ {{ quantity }}
|
|
|
</view>
|
|
</view>
|
|
|
<view
|
|
<view
|
|
|
class="h-36rpx w-36rpx rounded-50% bg-#E8FFA7 text-center text-28rpx text-#9ED605 font-600 line-height-[36rpx]"
|
|
class="h-36rpx w-36rpx rounded-50% bg-#E8FFA7 text-center text-28rpx text-#9ED605 font-600 line-height-[36rpx]"
|
|
|
|
|
+ @click="handlePlus"
|
|
|
>
|
|
>
|
|
|
+
|
|
+
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<!-- 单游客start -->
|
|
<!-- 单游客start -->
|
|
|
- <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
|
|
|
|
+ <view v-if="isSingle === 0" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
<view class="text-28rpx font-bold">
|
|
<view class="text-28rpx font-bold">
|
|
|
联系人
|
|
联系人
|
|
|
</view>
|
|
</view>
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入联系人姓名" label="联系人姓名" required />
|
|
|
|
|
|
|
+ <wd-input v-model="linkMan" placeholder="请输入联系人姓名" label="联系人姓名" required />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-picker v-model="value" required :columns="columns" label="证件类型" @confirm="handleConfirm" />
|
|
|
|
|
|
|
+ <wd-picker v-model="linkCreditType" required :columns="columns" label="证件类型" @confirm="handleLinkCreditConfirm" />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入证件号码" label="证件号码" required />
|
|
|
|
|
|
|
+ <wd-input v-model="linkCreditNo" placeholder="请输入证件号码" label="证件号码" required />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入手机号码" label="手机号码" required />
|
|
|
|
|
|
|
+ <wd-input v-model="linkPhone" placeholder="请输入手机号码" label="手机号码" required />
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<!-- 单游客end -->
|
|
<!-- 单游客end -->
|
|
|
<!-- 多游客start -->
|
|
<!-- 多游客start -->
|
|
|
- <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
|
|
|
|
+ <view v-if="isSingle === 1" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
<view class="text-28rpx font-bold">
|
|
<view class="text-28rpx font-bold">
|
|
|
联系人
|
|
联系人
|
|
|
</view>
|
|
</view>
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入联系人姓名" label="联系人姓名" required />
|
|
|
|
|
|
|
+ <wd-input v-model="linkMan" placeholder="请输入联系人姓名" label="联系人姓名" required />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入手机号码" label="手机号码" required />
|
|
|
|
|
|
|
+ <wd-input v-model="linkPhone" placeholder="请输入手机号码" label="手机号码" required />
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
|
|
|
|
+ <view v-for="(people, index) in peopleList" :key="index" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
|
|
|
<view class="text-28rpx font-bold">
|
|
<view class="text-28rpx font-bold">
|
|
|
- 游客信息
|
|
|
|
|
|
|
+ 游客信息{{ index + 1 }}
|
|
|
</view>
|
|
</view>
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入游客姓名" label="游客姓名1" required />
|
|
|
|
|
|
|
+ <wd-input v-model="people.linkMan" placeholder="请输入游客姓名" :label="`游客姓名${index + 1}`" required />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-picker v-model="value" required :columns="columns" label="证件类型" @confirm="handleConfirm" />
|
|
|
|
|
|
|
+ <wd-picker v-model="people.linkCreditType" required :columns="columns" label="证件类型" @confirm="(e: { value: number }) => handlePeopleCreditConfirm(index, e)" />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view>
|
|
<view>
|
|
|
- <wd-input placeholder="请输入证件号码" label="证件号码" required />
|
|
|
|
|
|
|
+ <wd-input v-model="people.linkCreditNo" placeholder="请输入证件号码" label="证件号码" required />
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<!-- 多游客end -->
|
|
<!-- 多游客end -->
|
|
|
<view class="mt-20rpx rounded-16rpx bg-#FFF">
|
|
<view class="mt-20rpx rounded-16rpx bg-#FFF">
|
|
|
- <wd-input placeholder="如有特殊需要,请留言" label="订单备注" />
|
|
|
|
|
|
|
+ <wd-input v-model="orderMemo" placeholder="如有特殊需要,请留言" label="订单备注" />
|
|
|
</view>
|
|
</view>
|
|
|
<view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
|
|
<view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
|
|
|
<view class="text-28rpx">
|
|
<view class="text-28rpx">
|
|
|
当前可用积分
|
|
当前可用积分
|
|
|
</view>
|
|
</view>
|
|
|
<view class="text-32rpx font-bold">
|
|
<view class="text-32rpx font-bold">
|
|
|
- 1000积分
|
|
|
|
|
|
|
+ {{ info?.data?.availablePointsTotal || 0 }}积分
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <view class="h-190rpx" />
|
|
|
</view>
|
|
</view>
|
|
|
<view
|
|
<view
|
|
|
class="fixed bottom-0 left-0 z-100 box-border h-174rpx w-full flex items-center justify-between bg-#FFF px-24rpx"
|
|
class="fixed bottom-0 left-0 z-100 box-border h-174rpx w-full flex items-center justify-between bg-#FFF px-24rpx"
|
|
@@ -126,7 +295,7 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
<text class="text-26rpx">
|
|
<text class="text-26rpx">
|
|
|
¥
|
|
¥
|
|
|
</text>
|
|
</text>
|
|
|
- 290
|
|
|
|
|
|
|
+ {{ totalPrice }}
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="flex items-center gap-20rpx">
|
|
<view class="flex items-center gap-20rpx">
|
|
@@ -138,7 +307,7 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
</view>
|
|
</view>
|
|
|
<view
|
|
<view
|
|
|
class="h-80rpx w-180rpx rounded-40rpx bg-#9ED605 text-center text-28rpx text-#FFF font-bold line-height-[80rpx]"
|
|
class="h-80rpx w-180rpx rounded-40rpx bg-#9ED605 text-center text-28rpx text-#FFF font-bold line-height-[80rpx]"
|
|
|
- @click="router.push({ name: 'attractions-order-pay' })"
|
|
|
|
|
|
|
+ @click="handleSubmit"
|
|
|
>
|
|
>
|
|
|
提交
|
|
提交
|
|
|
</view>
|
|
</view>
|
|
@@ -152,19 +321,16 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
|
|
|
<view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
|
|
<view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
|
|
|
<view class="mt24rpx text-28rpx">
|
|
<view class="mt24rpx text-28rpx">
|
|
|
<view class="flex items-center gap-56rpx">
|
|
<view class="flex items-center gap-56rpx">
|
|
|
- <view>黄果树瀑布风景区成人票 16:00-19:00</view>
|
|
|
|
|
|
|
+ <view>{{ productName }}</view>
|
|
|
<view>
|
|
<view>
|
|
|
<text class="text-#FF4A39 font-bold">
|
|
<text class="text-#FF4A39 font-bold">
|
|
|
- ¥290
|
|
|
|
|
|
|
+ ¥{{ price }}
|
|
|
</text>
|
|
</text>
|
|
|
- <text>×1</text>
|
|
|
|
|
|
|
+ <text>×{{ quantity }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="mt-20rpx">
|
|
<view class="mt-20rpx">
|
|
|
- 入园周末节假日
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="mt-20rpx">
|
|
|
|
|
- 2026年3月22日(周日)
|
|
|
|
|
|
|
+ {{ formattedDate }}
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|