酒店详情
This commit is contained in:
1 parent
0958d8dded
commit
d441fffc19
1 file changed
+53
-7
@@ -21,7 +21,7 @@
|
||||
<image v-else class="ht-hero__img" :src="banners[0] || placeholderCover" mode="aspectFill" />
|
||||
</view>
|
||||
|
||||
<view class="ht-body pb-180rpx">
|
||||
<view class="ht-body" :style="{ paddingBottom: bodyPadBottom }">
|
||||
<!-- 基本信息(上浮卡片) -->
|
||||
<view class="ht-card ht-card--main">
|
||||
<view class="ht-name">{{ hotel.hotelName }}</view>
|
||||
@@ -87,8 +87,8 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部起价 -->
|
||||
<view v-if="hotel && roomCards.length" class="ht-bottom">
|
||||
<!-- 底部起价:iOS/Android 用 safeAreaInsets 垫高,避免 Home 条/手势条遮挡 -->
|
||||
<view v-if="showBottomBar" class="ht-bottom" :style="{ paddingBottom: bottomBarPadBottom }">
|
||||
<view class="ht-bottom__price">
|
||||
<text class="ht-unit">起价</text>
|
||||
<text class="ht-yen">¥</text>
|
||||
@@ -112,6 +112,7 @@ const STAR_MAP: Record<number, string> = { 1: "民宿", 2: "经济", 3: "舒适"
|
||||
const placeholderCover = "/static/page/blue-bg.png"
|
||||
|
||||
const statusBarHeight = ref(20)
|
||||
const safeBottomPx = ref(0)
|
||||
const scrollHeight = ref("100vh")
|
||||
const hotelId = ref("")
|
||||
const MAX_STAY_NIGHTS = 30
|
||||
@@ -123,6 +124,13 @@ const hotel = ref<any>(null)
|
||||
const products = ref<any[]>([])
|
||||
const rooms = ref<any[]>([])
|
||||
|
||||
/** 底部栏内容高度(上内边距 + 按钮 + 下内边距),不含安全区 */
|
||||
const BOTTOM_BAR_INNER_RPX = 16 + 84 + 16
|
||||
/** 无底栏时内容区额外留白 */
|
||||
const BODY_PAD_BASE_RPX = 24
|
||||
/** 有底栏时内容区额外缓冲,避免最后一张房型贴边 */
|
||||
const BODY_PAD_EXTRA_RPX = 24
|
||||
|
||||
const nightCount = computed(() => {
|
||||
const n = dayjs(checkOut.value).diff(dayjs(checkIn.value), "day")
|
||||
return n > 0 ? n : 1
|
||||
@@ -212,6 +220,26 @@ const minPrice = computed(() => {
|
||||
return nums.length ? Math.min(...nums) : null
|
||||
})
|
||||
|
||||
const showBottomBar = computed(() => !!(hotel.value && roomCards.value.length))
|
||||
|
||||
const rpx2px = (rpx: number) => {
|
||||
try {
|
||||
return uni.upx2px(rpx)
|
||||
} catch {
|
||||
return Math.round(rpx / 2)
|
||||
}
|
||||
}
|
||||
|
||||
/** 滚动区底部留白:底栏高度 + 安全区,避免 iOS Home 条 / Android 手势条遮住房型 */
|
||||
const bodyPadBottom = computed(() => {
|
||||
if (showBottomBar.value) {
|
||||
return `${rpx2px(BOTTOM_BAR_INNER_RPX + BODY_PAD_EXTRA_RPX) + safeBottomPx.value}px`
|
||||
}
|
||||
return `${rpx2px(BODY_PAD_BASE_RPX) + safeBottomPx.value}px`
|
||||
})
|
||||
|
||||
const bottomBarPadBottom = computed(() => `${rpx2px(16) + safeBottomPx.value}px`)
|
||||
|
||||
const formatMd = (ymd: string) => dayjs(ymd).format("M月D日")
|
||||
const formatPrice = (v: any) => {
|
||||
const n = Number(v)
|
||||
@@ -226,9 +254,21 @@ const facilityIcon = (name: string) => {
|
||||
return "checkbox-circle-line"
|
||||
}
|
||||
|
||||
const readSafeBottom = (sys: any) => {
|
||||
const inset = sys?.safeAreaInsets?.bottom
|
||||
if (typeof inset === "number" && inset >= 0) return inset
|
||||
const area = sys?.safeArea
|
||||
if (area && typeof sys?.screenHeight === "number") {
|
||||
const bottom = sys.screenHeight - (area.bottom || 0)
|
||||
if (bottom > 0 && bottom < 80) return bottom
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
const layout = () => {
|
||||
const sys = uni.getSystemInfoSync()
|
||||
statusBarHeight.value = sys.statusBarHeight || 20
|
||||
safeBottomPx.value = readSafeBottom(sys)
|
||||
scrollHeight.value = `${sys.windowHeight || 667}px`
|
||||
}
|
||||
|
||||
@@ -255,7 +295,6 @@ const load = async () => {
|
||||
|
||||
const book = (p: any) => {
|
||||
if (!p?.productCode) return
|
||||
// 页面跳转 query 只带关键键;名称/地址/封面等进确认页后用详情接口补齐,避免整单信息挂在 URL 上
|
||||
router.jump("/pages/hotel/confirm", {
|
||||
hotelId: hotelId.value,
|
||||
productCode: p.productCode,
|
||||
@@ -272,7 +311,6 @@ onLoad((opt: any) => {
|
||||
checkIn.value = opt?.checkIn || checkIn.value
|
||||
checkOut.value = opt?.checkOut || checkOut.value
|
||||
roomsCount.value = Number(opt?.rooms || 1) || 1
|
||||
// 连住最多 30 晚,避免超长区间带入确认页
|
||||
const nights = dayjs(checkOut.value).diff(dayjs(checkIn.value), "day")
|
||||
if (nights > MAX_STAY_NIGHTS) {
|
||||
checkOut.value = dayjs(checkIn.value).add(MAX_STAY_NIGHTS, "day").format("YYYY-MM-DD")
|
||||
@@ -320,9 +358,12 @@ onLoad((opt: any) => {
|
||||
}
|
||||
.ht-body {
|
||||
margin-top: -36rpx;
|
||||
padding: 0 24rpx 24rpx;
|
||||
padding-left: 24rpx;
|
||||
padding-right: 24rpx;
|
||||
/* padding-bottom 由 bodyPadBottom 动态计算(底栏 + iOS/Android 安全区) */
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.ht-card {
|
||||
background: #fff;
|
||||
@@ -492,11 +533,16 @@ onLoad((opt: any) => {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 20;
|
||||
padding: 16rpx 28rpx calc(16rpx + env(safe-area-inset-bottom));
|
||||
padding-top: 16rpx;
|
||||
padding-left: 28rpx;
|
||||
padding-right: 28rpx;
|
||||
padding-bottom: calc(16rpx + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
.ht-bottom__price {
|
||||
|
||||
Reference in new issue
Block a user