Files
YGChatCS/src/pages/goods/index.vue
2025-10-28 20:34:18 +08:00

258 lines
7.6 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>
<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>