refactor: clean up components, fix date label font size
- Delete unused local image asset and unused GoodInfo SCSS stylesheet - Replace legacy border utility classes with modern Tailwind border-t syntax - Fix incorrect 100px font size on date selector input labels, update to 10px - Refactor LocationCard to use Lucide Phone/Navigation icons instead of VanIcons, improve button styling - Overhaul ImageSwiper component: add proper refs, improve scroll logic, replace VanIcons with Lucide icons, clean up redundant code - Update goods detail and quick booking pages to properly use Pinia selected date store, add date data normalization - Fix scrollbar styles and linear gradient syntax in goods detail page - Update development environment auth token for local development
This commit is contained in:
@@ -14,6 +14,6 @@ VITE_SOCKET_BASE_URL = "/ingress/agent/ws/chat"
|
|||||||
VITE_CLIENT_ID = "6"
|
VITE_CLIENT_ID = "6"
|
||||||
|
|
||||||
# Token
|
# Token
|
||||||
VITE_TOKEN = "eyJraWQiOiJiMTVhZTk0Mi03MjI5LTMyOWUtODA1Yi0wNjFlNmRjYTE1MDQiLCJhbGciOiJSUzI1NiJ9.eyJ0ZW5hbnRfaWQiOjEsInN1YiI6Im94T3NGN2lqTkxvbEFIdkhDZDYtek1acE5kNWsiLCJjbGllbnRJZCI6ImN1c3RvbSIsImlzcyI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsImNsaWVudF9pZCI6ImN1c3RvbSIsImF1dGhvcml0aWVzIjpbXSwiYXVkIjoiY3VzdG9tIiwibGljZW5zZSI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsIndlY2hhdF9vcGVuaWQiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIiwibmJmIjoxNzgwMjE5NjU0LCJ1c2VyX2lkIjoiMjAwNTEwMjg0NDQ2OTM4NzI2NSIsInNjb3BlIjpbInNlcnZlciJdLCJleHAiOjE3ODAyMjk2NTQsImlhdCI6MTc4MDIxOTY1NCwianRpIjoiZTlmZGJiNTAtYjFjZC00YThhLWJkOTctZTU0NTAxMDNhNTkyIiwidXNlcm5hbWUiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIn0.o_nvQVBPt1fYg3DIs7I1mapX124VqAgvHr4jEPoVZuFJjgPfziDvEBJRLw0yw4C1Ii3BxRlKw1CGRjmZ2FHPxk0gYBXGRD31isqezNLiBgVlv7wyI6pkfdk-_QEysu2Lh5hH5RWqndeNNKtQsjeGKOXV1amF7nekN4p9HnSHj6Y2h1iD6Zt2wVoKDlaJZ8yu7LB8uE8XMhKjY_ua2ujDXCRadrD4ihXqPOTaiqb5NERjHyCRKuSkEWUqFtLG7WbdOEH7SmXhlasRQ_ERVb3yKLsQdxSzP88BxKaqB7Xc8hBE1iROrF3iNGQCTK12QN8VuYMDq9CBNW10gGCsdR9vvQ"
|
VITE_TOKEN = "eyJraWQiOiJiMTVhZTk0Mi03MjI5LTMyOWUtODA1Yi0wNjFlNmRjYTE1MDQiLCJhbGciOiJSUzI1NiJ9.eyJ0ZW5hbnRfaWQiOjEsInN1YiI6Im94T3NGN2lqTkxvbEFIdkhDZDYtek1acE5kNWsiLCJjbGllbnRJZCI6ImN1c3RvbSIsImlzcyI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsImNsaWVudF9pZCI6ImN1c3RvbSIsImF1dGhvcml0aWVzIjpbXSwiYXVkIjoiY3VzdG9tIiwibGljZW5zZSI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsIndlY2hhdF9vcGVuaWQiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIiwibmJmIjoxNzgwMjI5ODMzLCJ1c2VyX2lkIjoiMjAwNTEwMjg0NDQ2OTM4NzI2NSIsInNjb3BlIjpbInNlcnZlciJdLCJleHAiOjE3ODAyMzk4MzMsImlhdCI6MTc4MDIyOTgzMywianRpIjoiM2ZkYzhiZTgtNTJlMy00YWIxLWEwOGQtZDU5NzBhZGM4YmE5IiwidXNlcm5hbWUiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIn0.cLOXAoMWxQvUdATgWYamdm12PEnPtLpAyddU398NxSWo-vYNKmH2ooTVXL2tDqWw7Gp2QoqUxHg1jyIAYxfAAXe1LQ946yZkOSHN8F16dTg27siif-8siCbo6NZ6FQmW-Ep1I0txrGB7_gx1AwRONse-zS5hq5ez42-3sF-c-nzcmAA84DMWm427eiPYnLDbd9Ook4VENChjsuWDSDPxhKb9nutOnUp8AR4kXKjzoUBHj33wrlW9Bf8W7w9S6weSxX_tApZ7YY26em6AnUpiOE4MZo5fR6nUncT1aZepBqfcvhqRHn7EGJ27q_cPJyZBB4grf9hd2ylpsxag0oMR7Q"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class=" border-top-8">
|
<div class=" border-t-[8px] border-t-[#f5f5f5]">
|
||||||
<div v-if="goodsData.commodityPurchaseInstruction" class=" pl-[12px] pr-[12px]">
|
<div v-if="goodsData.commodityPurchaseInstruction" class=" pl-[12px] pr-[12px]">
|
||||||
<ModuleTitle v-if="showTitle" :title="goodsData.commodityPurchaseInstruction.templateTitle" />
|
<ModuleTitle v-if="showTitle" :title="goodsData.commodityPurchaseInstruction.templateTitle" />
|
||||||
<div v-for="(moduleItem, index) in goodsData.commodityPurchaseInstruction
|
<div v-for="(moduleItem, index) in goodsData.commodityPurchaseInstruction
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 130 KiB |
@@ -1,78 +1,72 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
<van-swipe class="overflow-hidden" :style="swiperStyle" @change="handleSwiperChange">
|
<van-swipe ref="swipeRef" class="overflow-hidden" :style="swiperStyle" @change="handleSwiperChange">
|
||||||
<van-swipe-item v-for="(item, index) in thumbnails" :key="index">
|
<van-swipe-item v-for="(item, index) in thumbnails" :key="index">
|
||||||
<img class="w-full h-full" :src="item.photoUrl">
|
<img class="w-full h-full" :src="item.photoUrl">
|
||||||
</van-swipe-item>
|
</van-swipe-item>
|
||||||
</van-swipe>
|
</van-swipe>
|
||||||
|
|
||||||
<!-- 缩略图部分 -->
|
|
||||||
<div v-if="showThumbnails && thumbnails.length"
|
<div v-if="showThumbnails && thumbnails.length"
|
||||||
class="absolute left-[12px] right-[12px] flex items-end flex-row flex-nowrap" :style="thumbnailBoxStyle">
|
class="absolute left-[12px] right-[12px] flex items-end flex-row flex-nowrap" :style="thumbnailBoxStyle">
|
||||||
<div class="flex-auto h-full whitespace-nowrap" scroll-x="true" :scroll-left="scrollLeft"
|
<div ref="thumbnailScrollRef" class="flex-auto h-full whitespace-nowrap" scroll-x="true" :scroll-left="scrollLeft"
|
||||||
:scroll-with-animation="true" show-scrollbar="false">
|
:scroll-with-animation="true" show-scrollbar="false">
|
||||||
<div class="flex items-center gap-[10px]" v-if="thumbnails.length > 1">
|
<div class="flex items-center gap-[10px]" v-if="thumbnails.length > 1">
|
||||||
<div v-for="(thumb, index) in thumbnails" :key="index"
|
<div v-for="(thumb, index) in thumbnails" :key="index"
|
||||||
:class="['shrink-0 text-center', index === active && 'border-2 border-white border-solid']"
|
:class="['shrink-0 text-center rounded-card border-solid overflow-hidden', index === active ? 'border-2 border-white ' : 'border border-[#171717]']"
|
||||||
:id="`thumbnail-${index}`" @click="handleThumbnailClick(index)">
|
:id="`thumbnail-${index}`" @click="handleThumbnailClick(index)">
|
||||||
<img class="w-[36px] h-[36px] rounded-card border border-[#171717] border-solid" :src="thumb.photoUrl">
|
<img class="w-[36px] h-[36px]" :src="thumb.photoUrl">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-[12px] bg-[rgba(0,0,0,0.5)] rounded-[50px] p-[0_6px_4px_8px] flex-auto shrink-0 whitespace-nowrap"
|
<div class="ml-[12px] bg-black/50 rounded-full p-[4px_8px] flex items-center" @click="handlePreviewClick">
|
||||||
@click="handlePreviewClick">
|
<Camera size="14" color="#fff" />
|
||||||
<van-icon name="arrow-left" size="10" color="#fff"></van-icon>
|
|
||||||
<span class="mx-[4px] text-[10px] text-white align-center">
|
<span class="mx-[4px] text-[10px] text-white align-center">
|
||||||
{{ thumbnails.length }}
|
{{ thumbnails.length }}
|
||||||
</span>
|
</span>
|
||||||
<van-icon name="arrow-right" size="10" color="#fff"></van-icon>
|
<ChevronRight size="14" color="#fff" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, nextTick } from "vue";
|
import { ref, computed, nextTick, watch } from "vue";
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { Camera, ChevronRight } from '@lucide/vue'
|
||||||
import { usePictureStore } from "@/store";
|
import { usePictureStore } from "@/store";
|
||||||
|
|
||||||
const pictureStore = usePictureStore();
|
const pictureStore = usePictureStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// Props定义
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// 轮播图圆角大小,支持数字(px)或字符串
|
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 8,
|
default: 8,
|
||||||
},
|
},
|
||||||
// 轮播图数据
|
|
||||||
images: {
|
images: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
// 轮播图高度,支持数字(px)或字符串
|
|
||||||
height: {
|
height: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 200,
|
default: 200,
|
||||||
},
|
},
|
||||||
// 是否显示缩略图
|
|
||||||
showThumbnails: {
|
showThumbnails: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
// 缩略图距离底部的距离,支持数字(px)或字符串
|
|
||||||
thumbnailBottom: {
|
thumbnailBottom: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const swipeRef = ref(null);
|
||||||
|
const thumbnailScrollRef = ref(null);
|
||||||
const active = ref(0);
|
const active = ref(0);
|
||||||
const scrollLeft = ref(0);
|
const scrollLeft = ref(0);
|
||||||
|
|
||||||
// 计算圆角样式
|
|
||||||
const borderRadiusStyle = computed(() => {
|
const borderRadiusStyle = computed(() => {
|
||||||
const radius =
|
const radius =
|
||||||
typeof props.borderRadius === "number"
|
typeof props.borderRadius === "number"
|
||||||
@@ -83,7 +77,6 @@ const borderRadiusStyle = computed(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算轮播图样式(包含高度和圆角)
|
|
||||||
const swiperStyle = computed(() => {
|
const swiperStyle = computed(() => {
|
||||||
const radius =
|
const radius =
|
||||||
typeof props.borderRadius === "number"
|
typeof props.borderRadius === "number"
|
||||||
@@ -97,10 +90,8 @@ const swiperStyle = computed(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用传入的图片数据或默认数据
|
const thumbnails = computed(() => Array.isArray(props.images) ? props.images : []);
|
||||||
const thumbnails = computed(() => props.images);
|
|
||||||
|
|
||||||
// 计算缩略图底部距离样式
|
|
||||||
const thumbnailBoxStyle = computed(() => {
|
const thumbnailBoxStyle = computed(() => {
|
||||||
const bottom =
|
const bottom =
|
||||||
typeof props.thumbnailBottom === "number"
|
typeof props.thumbnailBottom === "number"
|
||||||
@@ -111,33 +102,80 @@ const thumbnailBoxStyle = computed(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleThumbnailClick = (index) => {
|
const clampIndex = (index) => {
|
||||||
active.value = index;
|
const maxIndex = Math.max(thumbnails.value.length - 1, 0);
|
||||||
scrollToActiveItem(index);
|
const nextIndex = Number.isFinite(Number(index)) ? Number(index) : 0;
|
||||||
|
return Math.min(Math.max(nextIndex, 0), maxIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setActiveIndex = (index, options = {}) => {
|
||||||
|
const nextIndex = clampIndex(index);
|
||||||
|
active.value = nextIndex;
|
||||||
|
scrollToActiveItem(nextIndex);
|
||||||
|
|
||||||
|
if (options.swipe !== false) {
|
||||||
|
swipeRef.value?.swipeTo?.(nextIndex, {
|
||||||
|
immediate: Boolean(options.immediate),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleThumbnailClick = (index) => {
|
||||||
|
setActiveIndex(index);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 滚动到选中项
|
|
||||||
const scrollToActiveItem = async (index) => {
|
const scrollToActiveItem = async (index) => {
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
||||||
// 计算每个缩略图项的宽度(包括间距)
|
const itemWidth = 58;
|
||||||
const itemWidth = 58; // 48px宽度 + 10px间距
|
const containerWidth = 300;
|
||||||
const containerWidth = 300; // 大概的容器宽度
|
|
||||||
const targetScrollLeft = Math.max(
|
const targetScrollLeft = Math.max(
|
||||||
0,
|
0,
|
||||||
index * itemWidth - containerWidth / 2 + itemWidth / 2,
|
index * itemWidth - containerWidth / 2 + itemWidth / 2,
|
||||||
);
|
);
|
||||||
|
|
||||||
scrollLeft.value = targetScrollLeft;
|
scrollLeft.value = targetScrollLeft;
|
||||||
|
|
||||||
|
const scrollEl = thumbnailScrollRef.value;
|
||||||
|
const activeEl = scrollEl?.querySelector?.(`#thumbnail-${index}`);
|
||||||
|
if (!scrollEl || !activeEl) return;
|
||||||
|
|
||||||
|
const scrollRect = scrollEl.getBoundingClientRect();
|
||||||
|
const activeRect = activeEl.getBoundingClientRect();
|
||||||
|
const h5TargetScrollLeft =
|
||||||
|
scrollEl.scrollLeft +
|
||||||
|
activeRect.left - scrollRect.left -
|
||||||
|
(scrollRect.width - activeRect.width) / 2;
|
||||||
|
|
||||||
|
scrollEl.scrollTo?.({
|
||||||
|
left: Math.max(0, h5TargetScrollLeft),
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听主轮播图变化,同步缩略图滚动
|
const handleSwiperChange = (index) => {
|
||||||
const handleSwiperChange = (e) => {
|
setActiveIndex(index, { swipe: false });
|
||||||
const currentIndex = e.detail.current;
|
|
||||||
active.value = currentIndex;
|
|
||||||
scrollToActiveItem(currentIndex);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => thumbnails.value.length,
|
||||||
|
(length) => {
|
||||||
|
if (!length) {
|
||||||
|
active.value = 0;
|
||||||
|
scrollLeft.value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextIndex = clampIndex(active.value);
|
||||||
|
nextTick(() => {
|
||||||
|
swipeRef.value?.resize?.();
|
||||||
|
setActiveIndex(nextIndex, {
|
||||||
|
immediate: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const handlePreviewClick = () => {
|
const handlePreviewClick = () => {
|
||||||
pictureStore.setPreviewImageData(thumbnails.value);
|
pictureStore.setPreviewImageData(thumbnails.value);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-end justify-between my-[12px] px-[12px]" @click="showCalendar">
|
<div class="flex items-end justify-between my-[12px] px-[12px]" @click="showCalendar">
|
||||||
<div class="flex-1 relative">
|
<div class="flex-1 relative">
|
||||||
<div class="absolute top-[-6px] left-[12px] text-[100px] text-ink-600 bg-white px-[4px]">入住日期</div>
|
<div class="absolute top-[-6px] left-[12px] text-[10px] text-ink-600 bg-white px-[4px]">入住日期</div>
|
||||||
<div class="flex items-center justify-start border border-[#f0f0f0] rounded-[8px] px-[12px] py-[10px] bg-white">
|
<div class="flex items-center justify-start border border-[#f0f0f0] rounded-[8px] px-[12px] py-[10px] bg-white">
|
||||||
<div class="flex items-baseline gap-[4px]">
|
<div class="flex items-baseline gap-[4px]">
|
||||||
<span class="text-[16px] font-medium text-[#333]">{{ checkInDate }}</span>
|
<span class="text-[16px] font-medium text-[#333]">{{ checkInDate }}</span>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-1 relative">
|
<div class="flex-1 relative">
|
||||||
<div class="absolute top-[-6px] left-[12px] text-[100px] text-ink-600 bg-white px-[4px]">退房日期</div>
|
<div class="absolute top-[-6px] left-[12px] text-[10px] text-ink-600 bg-white px-[4px]">退房日期</div>
|
||||||
<div class="flex items-center justify-start border border-[#f0f0f0] rounded-[8px] px-[12px] py-[10px] bg-white">
|
<div class="flex items-center justify-start border border-[#f0f0f0] rounded-[8px] px-[12px] py-[10px] bg-white">
|
||||||
<div class="flex items-baseline gap-[4px]">
|
<div class="flex items-baseline gap-[4px]">
|
||||||
<span class="text-[16px] font-medium text-[#333]">{{ checkOutDate }}</span>
|
<span class="text-[16px] font-medium text-[#333]">{{ checkOutDate }}</span>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="border-top-8">
|
<div class="border-t-[8px] border-t-[#f5f5f5]">
|
||||||
<div class="pt-[12px] pl-[12px] pr-[12px]" v-for="(moduleItem, index) in goodsData.commodityEquipment" :key="index">
|
<div class="pt-[12px] pl-[12px] pr-[12px]" v-for="(moduleItem, index) in goodsData.commodityEquipment" :key="index">
|
||||||
<div class="flex flex-col items-start" :class="{
|
<div class="flex flex-col items-start" :class="{
|
||||||
'border-b border-ink-200': index < goodsData.commodityEquipment.length - 1,
|
'border-b border-ink-200': index < goodsData.commodityEquipment.length - 1,
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
.good-info {
|
|
||||||
// 标题区域
|
|
||||||
|
|
||||||
// 设施信息区域
|
|
||||||
.facilities-section {
|
|
||||||
margin-top: 12px;
|
|
||||||
|
|
||||||
.facilities-grid {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.facility-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 8px;
|
|
||||||
background: #fafafa;
|
|
||||||
border-radius: 6px;
|
|
||||||
|
|
||||||
.facility-text {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center mt-[12px] p-[12px] bg-white border border-t border-[#e0e0e0]">
|
<div class="flex items-center mt-[12px] p-[12px] bg-white border-t border-[#e0e0e0]">
|
||||||
<div class="flex flex-col flex-1">
|
<div class="flex flex-col flex-1">
|
||||||
<span class="text-[14px] font-medium text-ink-800">位于 {{ orderData.oneLevelAddress }}</span>
|
<span class="text-[14px] font-medium text-ink-800">位于 {{ orderData.oneLevelAddress }}</span>
|
||||||
<span class="mt-[4px] text-[12px] text-ink-500">{{ orderData.commodityAddress }}</span>
|
<span class="mt-[4px] text-[12px] text-ink-500">{{ orderData.commodityAddress }}</span>
|
||||||
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
<div class="flex items-center gap-[10px] ml-[16px]">
|
<div class="flex items-center gap-[10px] ml-[16px]">
|
||||||
<div>
|
<div>
|
||||||
<div class="actions-btn">
|
<div class="w-[28px] h-[28px] rounded-[10px] bg-[#F5F5F5] flex items-center justify-center">
|
||||||
<van-icon type="paperplane-filled" size="16" color="#171717" />
|
<Navigation size="16" color="#171717" />
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[12px] text-ink-600">导航</span>
|
<span class="text-[12px] text-ink-600">导航</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="actions-btn" @click.stop="callPhone">
|
<div class="w-[28px] h-[28px] rounded-[10px] bg-[#F5F5F5] flex items-center justify-center"
|
||||||
<van-icon type="phone-filled" size="16" color="#171717" />
|
@click.stop="callPhone">
|
||||||
|
<Phone size="16" color="#171717" />
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[12px] text-ink-600">电话</span>
|
<span class="text-[12px] text-ink-600">电话</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps } from "vue";
|
import { defineProps } from "vue";
|
||||||
|
import { Phone, Navigation } from '@lucide/vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
orderData: {
|
orderData: {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-screen bg-white">
|
<div class="flex flex-col h-screen bg-white">
|
||||||
<!-- 滚动区域 -->
|
<!-- 滚动区域 -->
|
||||||
<div class="flex-1 overflow-y-auto" @scroll="handleScroll">
|
<div class="flex-1 overflow-y-auto scrollbar-none [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden"
|
||||||
|
@scroll="handleScroll">
|
||||||
<ImageSwiper :border-radius="0" :height="300" :images="goodsData.commodityPhotoList" thumbnailBottom="42px" />
|
<ImageSwiper :border-radius="0" :height="300" :images="goodsData.commodityPhotoList" thumbnailBottom="42px" />
|
||||||
|
|
||||||
<div class="bg-white py-[20px] relative mt-[-30px] z-10 rounded-t-[28px]">
|
<div class="bg-white py-[20px] relative mt-[-30px] z-10 rounded-t-[28px]">
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex items-center ml-auto pl-[8px] rounded-[10px] w-[120px] h-[48px] bg-linear-[90deg, #ff3d60_57%, #ff990c_100%]"
|
class="flex items-center ml-auto pl-[8px] rounded-[10px] w-[120px] h-[48px] [background:linear-gradient(90deg,#ff3d60_57%,#ff990c_100%)]"
|
||||||
@click="navigateToPay(goodsData)">
|
@click="navigateToPay(goodsData)">
|
||||||
<img class="w-[34px] h-[48px]" src="https://oss.nianxx.cn/mp/static/version_101/common/btn.png" />
|
<img class="w-[34px] h-[48px]" src="https://oss.nianxx.cn/mp/static/version_101/common/btn.png" />
|
||||||
<span class="text-[16px] font-medium text-white">立即预定</span>
|
<span class="text-[16px] font-medium text-white">立即预定</span>
|
||||||
@@ -58,8 +59,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { goodsDetail, commodityDailyPriceList } from "@/api/goods";
|
import { goodsDetail, commodityDailyPriceList } from "@/api/goods";
|
||||||
import { DateUtils } from "@/utils/dateUtils";
|
import { DateUtils } from "@/utils/dateUtils";
|
||||||
import ImageSwiper from "@/components/ImageSwiper/index.vue";
|
import ImageSwiper from "@/components/ImageSwiper/index.vue";
|
||||||
@@ -72,8 +73,8 @@ import GoodFacility from "./components/GoodFacility/index.vue";
|
|||||||
import GoodPackage from "./components/GoodPackage/index.vue";
|
import GoodPackage from "./components/GoodPackage/index.vue";
|
||||||
import { useSelectedDateStore } from "@/store";
|
import { useSelectedDateStore } from "@/store";
|
||||||
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
// 导航栏透明度 - 默认透明,随滚动变为不透明
|
// 导航栏透明度 - 默认透明,随滚动变为不透明
|
||||||
const calendarVisible = ref(false);
|
const calendarVisible = ref(false);
|
||||||
@@ -143,13 +144,34 @@ const getGoodsDailyPrice = async (params) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// const selectedDateStore = useSelectedDateStore();
|
const selectedDateStore = useSelectedDateStore();
|
||||||
// onLoad(({ commodityId = "1950766939442774018" }) => {
|
const getDefaultSelectedDate = () => ({
|
||||||
// // 从store中获取选中的日期
|
startDate: DateUtils.formatDate(),
|
||||||
// selectedDate.value = selectedDateStore.selectedDate;
|
endDate: DateUtils.formatDate(new Date(Date.now() + 24 * 60 * 60 * 1000)),
|
||||||
|
totalDays: 1,
|
||||||
|
});
|
||||||
|
|
||||||
// goodsInfo({ commodityId });
|
const normalizeSelectedDate = (data) => {
|
||||||
// });
|
if (data?.startDate && data?.endDate && Number(data.totalDays) > 0) {
|
||||||
|
return {
|
||||||
|
startDate: data.startDate,
|
||||||
|
endDate: data.endDate,
|
||||||
|
totalDays: Number(data.totalDays),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDefaultSelectedDate();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 从路由参数中获取商品ID
|
||||||
|
const commodityId = route.query.commodityId || "1950766939442774018";
|
||||||
|
// 从store中获取选中的日期
|
||||||
|
selectedDate.value = normalizeSelectedDate(selectedDateStore.selectedDate);
|
||||||
|
selectedDateStore.setData({ ...selectedDate.value });
|
||||||
|
|
||||||
|
goodsInfo({ commodityId });
|
||||||
|
});
|
||||||
|
|
||||||
// 显示日历弹窗
|
// 显示日历弹窗
|
||||||
const showCalendar = () => (calendarVisible.value = true);
|
const showCalendar = () => (calendarVisible.value = true);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import Tabs from "./components/Tabs/index.vue";
|
|||||||
import Card from "./components/Card/index.vue";
|
import Card from "./components/Card/index.vue";
|
||||||
import { quickBookingList } from "@/api/goods";
|
import { quickBookingList } from "@/api/goods";
|
||||||
import { DateUtils } from "@/utils/dateUtils";
|
import { DateUtils } from "@/utils/dateUtils";
|
||||||
|
import { useSelectedDateStore } from "@/store";
|
||||||
|
|
||||||
type SelectedDate = {
|
type SelectedDate = {
|
||||||
startDate: string;
|
startDate: string;
|
||||||
@@ -66,11 +67,28 @@ type QuickListItem = Record<string, any>;
|
|||||||
|
|
||||||
const PAGE_SIZE = 10;
|
const PAGE_SIZE = 10;
|
||||||
const calenderRef = ref();
|
const calenderRef = ref();
|
||||||
const selectedDate = ref<SelectedDate>({
|
const selectedDateStore = useSelectedDateStore();
|
||||||
|
|
||||||
|
const getDefaultSelectedDate = (): SelectedDate => ({
|
||||||
startDate: DateUtils.formatDate(),
|
startDate: DateUtils.formatDate(),
|
||||||
endDate: DateUtils.formatDate(new Date(Date.now() + 24 * 60 * 60 * 1000)),
|
endDate: DateUtils.formatDate(new Date(Date.now() + 24 * 60 * 60 * 1000)),
|
||||||
totalDays: 1,
|
totalDays: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const normalizeSelectedDate = (data?: Partial<SelectedDate> | null): SelectedDate => {
|
||||||
|
if (data?.startDate && data?.endDate && Number(data.totalDays) > 0) {
|
||||||
|
return {
|
||||||
|
startDate: data.startDate,
|
||||||
|
endDate: data.endDate,
|
||||||
|
totalDays: Number(data.totalDays),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDefaultSelectedDate();
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedDate = ref<SelectedDate>(normalizeSelectedDate(selectedDateStore.selectedDate));
|
||||||
|
selectedDateStore.setData({ ...selectedDate.value });
|
||||||
const dataList = ref<QuickListItem[]>([]);
|
const dataList = ref<QuickListItem[]>([]);
|
||||||
const currentPage = ref(1);
|
const currentPage = ref(1);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@@ -161,7 +179,8 @@ const handleCalendarClose = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDateSelect = (data: SelectedDate) => {
|
const handleDateSelect = (data: SelectedDate) => {
|
||||||
selectedDate.value = data;
|
selectedDate.value = normalizeSelectedDate(data);
|
||||||
|
selectedDateStore.setData({ ...selectedDate.value });
|
||||||
calenderRef.value?.close?.();
|
calenderRef.value?.close?.();
|
||||||
dataList.value = [];
|
dataList.value = [];
|
||||||
reloadList();
|
reloadList();
|
||||||
|
|||||||
Reference in New Issue
Block a user