258 lines
7.6 KiB
Vue
258 lines
7.6 KiB
Vue
<template>
|
||
<view class="goods-container bg-gray">
|
||
<TopNavBar
|
||
title="商品详情"
|
||
:backgroundColor="`rgba(217, 238, 255, ${navOpacity})`"
|
||
:titleColor="navOpacity < 0.5 ? '#ffffff' : '#000000'"
|
||
:backIconColor="navOpacity < 0.5 ? '#ffffff' : '#000000'"
|
||
/>
|
||
|
||
<!-- 滚动区域 -->
|
||
<scroll-view class="content-wrapper" scroll-y @scroll="handleScroll">
|
||
<ImageSwiper
|
||
:border-radius="0"
|
||
:height="300"
|
||
:images="goodsData.commodityPhotoList"
|
||
thumbnailBottom="42px"
|
||
/>
|
||
|
||
<view class="goods-content">
|
||
<!-- 商品信息组件 -->
|
||
<GoodInfo :goodsData="goodsData" />
|
||
|
||
<!-- 地址区域 -->
|
||
<LocationCard :orderData="goodsData" />
|
||
|
||
<!-- 日期选择区域 -->
|
||
<DateSelector
|
||
v-if="goodsData.commodityTypeCode === '0'"
|
||
@showCalendar="showCalendar"
|
||
:checkInDate="selectedDate.startDate"
|
||
:checkOutDate="selectedDate.endDate"
|
||
:checkInDay="''"
|
||
:checkOutDay="''"
|
||
:nights="selectedDate.totalDays"
|
||
/>
|
||
|
||
<!-- 商品设施组件 -->
|
||
<GoodFacility :goodsData="goodsData" />
|
||
|
||
<!-- 商品详情组件 -->
|
||
<GoodDetail :goodsData="goodsData" />
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 立即抢购 -->
|
||
<view class="footer border-top">
|
||
<view
|
||
class="amt font-size-20 font-bold color-FF3D60 line-height-28 flex flex-items-center mr-8"
|
||
>
|
||
{{ calculatedTotalPrice }}
|
||
</view>
|
||
|
||
<view
|
||
class="btn border-box rounded-10 flex flex-items-center ml-auto pl-8"
|
||
@click="navigateToPay(goodsData)"
|
||
>
|
||
<image
|
||
class="icon"
|
||
src="https://oss.nianxx.cn/mp/static/version_101/common/btn.png"
|
||
/>
|
||
<text class="font-size-16 font-500 color-white">立即预定</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日历组件 -->
|
||
<Calender
|
||
:visible="calendarVisible"
|
||
:price-data="priceData"
|
||
mode="range"
|
||
@close="handleCalendarClose"
|
||
@range-select="handleDateSelect"
|
||
/>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import { goodsDetail, commodityDailyPriceList } from "@/request/api/GoodsApi";
|
||
import { DateUtils } from "@/utils";
|
||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||
import ImageSwiper from "@/components/ImageSwiper/index.vue";
|
||
import GoodInfo from "./components/GoodInfo/index.vue";
|
||
import GoodConfirm from "./components/GoodConfirm/index.vue";
|
||
import Calender from "@/components/Calender/index.vue";
|
||
import LocationCard from "@/components/LocationCard/index.vue";
|
||
import DateSelector from "./components/DateSelector/index.vue";
|
||
import GoodDetail from "@/components/GoodDetail/index.vue";
|
||
import GoodFacility from "./components/GoodFacility/index.vue";
|
||
import { useSelectedDateStore } from "@/store";
|
||
|
||
// 导航栏透明度 - 默认透明,随滚动变为不透明
|
||
const navOpacity = ref(0);
|
||
const calendarVisible = ref(false);
|
||
const goodsData = ref({});
|
||
|
||
// 处理滚动事件
|
||
const handleScroll = (e) => {
|
||
const scrollTop = e.detail.scrollTop;
|
||
// 设置一个阈值,当滚动超过200px时,导航栏完全不透明
|
||
const threshold = 200;
|
||
// 计算透明度,范围从0到1
|
||
navOpacity.value = Math.min(scrollTop / threshold, 1);
|
||
};
|
||
|
||
const selectedDate = ref({
|
||
startDate: DateUtils.formatDate(), // 当天日期
|
||
endDate: DateUtils.formatDate(new Date(Date.now() + 24 * 60 * 60 * 1000)), // 第二天日期
|
||
totalDays: 1,
|
||
});
|
||
const priceData = ref([]);
|
||
|
||
// 计算的总价格
|
||
const calculatedTotalPrice = ref(0);
|
||
|
||
// 获取商品详情数据
|
||
const goodsInfo = async (params) => {
|
||
const res = await goodsDetail(params);
|
||
|
||
goodsData.value = res.data;
|
||
|
||
// 初始化计算价格
|
||
calculatedTotalPrice.value = goodsData.value.specificationPrice || 0;
|
||
|
||
// 判断是酒店类型订单再获取获取商品日价格及库存
|
||
if (goodsData.value.commodityTypeCode === "0") {
|
||
configGoodsData();
|
||
getGoodsDailyPrice({
|
||
commodityId: goodsData.value.commodityId,
|
||
});
|
||
}
|
||
|
||
if (goodsData.value.commodityStatus !== "1") {
|
||
uni.showModal({
|
||
title: "温馨提示",
|
||
content: "您选的商品暂不可预订,请重新选择。",
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.navigateBack({ delta: 1 });
|
||
}
|
||
},
|
||
});
|
||
return;
|
||
}
|
||
};
|
||
|
||
const configGoodsData = () => {
|
||
goodsData.value.startDate = selectedDate.value.startDate;
|
||
goodsData.value.endDate = selectedDate.value.endDate;
|
||
goodsData.value.totalDays = selectedDate.value.totalDays;
|
||
goodsData.value.calculatedTotalPrice = calculatedTotalPrice.value;
|
||
};
|
||
|
||
// 获取商品日价格及库存
|
||
const getGoodsDailyPrice = async (params) => {
|
||
const res = await commodityDailyPriceList(params);
|
||
|
||
priceData.value = res.data;
|
||
};
|
||
|
||
const selectedDateStore = useSelectedDateStore();
|
||
onLoad(({ commodityId = "1950766939442774018" }) => {
|
||
// 从store中获取选中的日期
|
||
selectedDate.value = selectedDateStore.selectedDate;
|
||
|
||
goodsInfo({ commodityId });
|
||
});
|
||
|
||
// 显示日历弹窗
|
||
const showCalendar = () => (calendarVisible.value = true);
|
||
|
||
const handleCalendarClose = () => (calendarVisible.value = false);
|
||
|
||
const handleDateSelect = (data) => {
|
||
console.log("选择的日期:", data);
|
||
|
||
// 保存选择的日期范围
|
||
selectedDate.value = {
|
||
startDate: data.startDate,
|
||
endDate: data.endDate,
|
||
totalDays: data.totalDays,
|
||
};
|
||
|
||
selectedDateStore.setData(selectedDate.value);
|
||
|
||
// 根据商品类型计算价格
|
||
if (goodsData.value.commodityTypeCode === "0") {
|
||
// 酒店类型:计算dateRange总价格,排除最后一天(同一天除外)
|
||
if (data.dateRange && Array.isArray(data.dateRange)) {
|
||
// 获取默认价格作为回退值
|
||
const defaultPrice = Number(goodsData.value.specificationPrice) || 0;
|
||
|
||
// 检查价格是否有效的函数
|
||
const isValidPrice = (price) => {
|
||
return (
|
||
price !== null &&
|
||
price !== undefined &&
|
||
price !== "" &&
|
||
price !== "-" &&
|
||
!isNaN(Number(price)) &&
|
||
Number(price) > 0
|
||
);
|
||
};
|
||
|
||
// 如果是同一天(数组长度为1),使用该天的价格
|
||
if (data.dateRange.length === 1) {
|
||
const dayPrice = data.dateRange[0].price;
|
||
calculatedTotalPrice.value = isValidPrice(dayPrice)
|
||
? Number(dayPrice)
|
||
: defaultPrice;
|
||
console.log(
|
||
"同一天选择,价格:",
|
||
calculatedTotalPrice.value,
|
||
"(原价格:",
|
||
dayPrice,
|
||
")"
|
||
);
|
||
} else {
|
||
// 多天选择,排除最后一天
|
||
const dateRangeExcludingLast = data.dateRange.slice(0, -1);
|
||
calculatedTotalPrice.value = dateRangeExcludingLast.reduce(
|
||
(total, dateItem) => {
|
||
const dayPrice = dateItem.price;
|
||
const priceToAdd = isValidPrice(dayPrice)
|
||
? Number(dayPrice)
|
||
: defaultPrice;
|
||
return total + priceToAdd;
|
||
},
|
||
0
|
||
);
|
||
console.log(
|
||
"酒店类型计算总价格(排除最后一天):",
|
||
calculatedTotalPrice.value
|
||
);
|
||
}
|
||
configGoodsData();
|
||
}
|
||
} else {
|
||
// 非酒店类型:如果没有dateRange,使用默认价格
|
||
calculatedTotalPrice.value = goodsData.value.specificationPrice || 0;
|
||
}
|
||
|
||
// 日历组件会自动关闭,无需手动设置
|
||
calendarVisible.value = false;
|
||
};
|
||
|
||
// 跳转订购
|
||
const navigateToPay = ({ commodityId }) => {
|
||
uni.navigateTo({
|
||
url: `/pages-booking/index?commodityId=${commodityId}`,
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import "./styles/index.scss";
|
||
</style>
|