Files
nianxx-h5/src/pages/booking/index.vue
DEV_DSW 051f7d1134 style: fix style utility class inconsistencies and correct CSS syntax
Clean up style-related code across all components:
- Replace deprecated color-* classes with text-[color]/text-white equivalents
- Remove redundant border-box declarations and fix broken empty box-sizing rule
- Correct invalid rounded corner class syntax
- Standardize line-height to leading-[value] utilities
- Uniform margin and padding notation to [xxpx] format
2026-05-29 09:28:37 +08:00

262 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="booking h-screen flex flex-col">
<TopNavBar titleAlign="center" :backgroundColor="$theme - color - 100" backIconColor="#000" :shadow="false">
<template #title>
{{ GOODS_TYPE[orderData.orderType] }}
</template>
</TopNavBar>
<div class="booking-content flex-full p-[12px] overflow-hidden scroll-y">
<!-- 预约内容 -->
<div class=" bg-white p-[12px] rounded-[12px] mb-12">
<!-- 酒店类型入住离店日期部分 -->
<DateRangeSection v-if="orderData.orderType == 0" :selectedDate="selectedDate" :showBtn="true"
@click="navigateToDetail(orderData)" />
<div class="font-size-16 font-500 color-000 line-height-24 ellipsis-1">
{{ orderData.commodityName }}
</div>
<div class=" border-bottom">
<div class="text-[12px] color-99A0AE line-height-16 pb-12 break-all">
{{ orderData.commodityDescription }}
</div>
<!-- 权益部分 -->
<div class="flex flex-items-center mb-8">
<span class="bg-F7F7F7 rounded-4 font-size-11 text-[#525866] mr-[4px] pt-4 pb-4 pl-6 pr-6"
v-for="(item, index) in orderData.commodityFacilityList" :key="index">
{{ item }}
</span>
</div>
</div>
<div class=" flex flex-items-center flex-justify-between pt-12">
<span class="text-[12px] text-[#525866] line-height-18">取消政策及说明</span>
<div class="flex flex-items-center">
<span class="text-[12px] theme-color-500 line-height-16" @click="refundVisible = true">取消政策</span>
<uni-icons type="right" size="15" color="#99A0AE" />
</div>
</div>
</div>
<!-- 非酒店类型 -->
<ContactSection v-if="orderData.orderType != 0" v-model="quantity" :userFormList="userFormList"
v-model:reservationDate="selectedReservationDate" :orderData="orderData" />
<!-- 酒店类型 -->
<UserSection v-if="orderData.orderType == 0" v-model="quantity" :userFormList="userFormList" />
</div>
<!-- 底部 -->
<FooterSection v-if="Object.keys(orderData).length" v-model="quantity" :selectedDate="selectedDate"
:orderData="orderData" @detailClick="detailVisible = true" @payClick="handlePayClick" />
<!-- 取消政策弹窗 -->
<RefundPopup v-model="refundVisible" :orderData="orderData" />
<!-- 明细弹窗 -->
<DetailPopup v-model="detailVisible" :orderData="orderData" />
</div>
</template>
<script setup>
import { ref, watch, nextTick } from "vue";
import { useRouter } from 'vue-router'
import TopNavBar from "@/components/TopNavBar/index.vue";
import DateRangeSection from "@/components/DateRangeSection/index.vue";
import ContactSection from "./components/ConactSection/index.vue";
import UserSection from "./components/UserSection/index.vue";
import RefundPopup from "@/components/RefundPopup/index.vue";
import DetailPopup from "@/components/DetailPopup/index.vue";
import FooterSection from "./components/FooterSection/index.vue";
import { goodsDetail, orderPay } from "@/api/goods";
import { useSelectedDateStore } from "@/store";
import { GOODS_TYPE } from "@/constants/type";
import { ThrottleUtils } from "@/utils/ThrottleUtils";
import { PhoneUtils } from "@/utils/PhoneUtils";
const router = useRouter();
const refundVisible = ref(false);
const detailVisible = ref(false);
const orderData = ref({});
const selectedDate = ref({
startDate: "",
endDate: "",
totalDays: 1,
});
const quantity = ref(1);
const selectedReservationDate = ref("");
// 工具函数
const createEmptyUserForm = () => ({ visitorName: "", contactPhone: "" });
const userFormList = ref([createEmptyUserForm()]);
const isDeleting = ref(false); // 标志位防止删除时watch冲突
// 监听 quantity 变化,动态调整 userFormList
watch(
quantity,
async (newQuantity) => {
// 只有在酒店类型orderType == 0时才动态调整 userFormList
if (orderData.value.orderType !== 0) return;
// 如果正在执行删除操作跳过watch逻辑
if (isDeleting.value) {
isDeleting.value = false;
return;
}
const currentLength = userFormList.value.length;
if (newQuantity > currentLength) {
// 数量增加,添加新的表单项
const newForms = Array.from({ length: newQuantity - currentLength }, () =>
createEmptyUserForm(),
);
userFormList.value.push(...newForms);
} else if (newQuantity < currentLength) {
// 数量减少,删除多余的表单项
userFormList.value.splice(newQuantity);
}
// 等待DOM更新完成
await nextTick();
},
{ immediate: false },
);
// TODO
// onLoad((options) => {
// const { commodityId } = options;
// getGoodsDetail(commodityId);
// });
// onShow(() => {
// const selectedDateStore = useSelectedDateStore();
// selectedDate.value.startDate = selectedDateStore.selectedDate.startDate;
// selectedDate.value.endDate = selectedDateStore.selectedDate.endDate;
// selectedDate.value.totalDays = selectedDateStore.selectedDate.totalDays;
// });
const getGoodsDetail = async (commodityId) => {
const res = await goodsDetail({ commodityId });
console.log("获取商品详情", res);
orderData.value = res.data;
// 取commodityFacilityList前3个
orderData.value.commodityFacilityList = res.data.commodityFacilityList.slice(
0,
3,
);
};
// 跳转商品详情
const navigateToDetail = ({ commodityId }) => {
router.push({
path: "/pages/goods/index",
query: {
commodityId,
},
});
};
// 验证用户姓名
const validateUserForms = () => {
const invalidUsers = userFormList.value.filter((user) => {
return user.visitorName.trim() === "";
});
if (invalidUsers.length) {
showToast("请填写姓名");
return false;
}
return true;
};
// 处理支付点击事件
const handlePayClick = ThrottleUtils.createThrottle(async (goodsData) => {
console.log("处理支付点击事件", userFormList.value);
// 预约日期,酒店类型不需要
if (orderData.value.reservationEnabled) {
if (!selectedReservationDate.value) {
showToast("请选择预约日期");
return;
}
}
// 校验用户姓名
if (!validateUserForms()) {
return;
}
// 校验手机号
if (!PhoneUtils.validatePhone(userFormList.value[0].contactPhone)) {
showToast("请输入正确的手机号");
return;
}
// 购买的商品id
const commodityId = goodsData.commodityId;
// 消费者信息
const consumerInfoEntityList = userFormList.value;
// 购买数量
const purchaseAmount = quantity.value;
// 支付方式 0-微信 1-支付宝 2-云闪付
const payWay = "0";
// 支付渠道 0-app 1-小程序 2-h5
const paySource = "1";
const params = {
commodityId,
purchaseAmount,
payWay,
paySource,
consumerInfoEntityList,
};
// 预约日期,酒店类型不需要
if (orderData.value.reservationEnabled) {
params.reservationDate = selectedReservationDate.value;
}
//酒店类型添加入住时间、离店时间
if (goodsData.orderType == 0 && selectedDate.value) {
const { startDate, endDate } = selectedDate.value;
// 入住时间
params.checkInData = startDate;
// 离店时间
params.checkOutData = endDate;
}
// 点击后立即展示 loading
const res = await orderPay(params);
console.log("确认订单---2:", res);
// 检查接口返回数据
if (!res || !res.data) {
return;
}
const { data } = res;
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
// 验证支付参数是否完整
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
return;
}
}, 1000);
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>