feat: 新增快速预定页面
This commit is contained in:
@@ -62,6 +62,7 @@ const ICON_MAP = {
|
|||||||
0: "https://oss.nianxx.cn/mp/static/version_101/order/room.png", // 酒店订单
|
0: "https://oss.nianxx.cn/mp/static/version_101/order/room.png", // 酒店订单
|
||||||
1: "https://oss.nianxx.cn/mp/static/version_101/order/ticket.png", // 门票订单
|
1: "https://oss.nianxx.cn/mp/static/version_101/order/ticket.png", // 门票订单
|
||||||
2: "https://oss.nianxx.cn/mp/static/version_101/order/food.png", // 餐饮
|
2: "https://oss.nianxx.cn/mp/static/version_101/order/food.png", // 餐饮
|
||||||
|
3: "https://oss.nianxx.cn/mp/static/version_101/order/package.png", // 套餐
|
||||||
};
|
};
|
||||||
|
|
||||||
// 订单类型映射
|
// 订单类型映射
|
||||||
@@ -69,6 +70,7 @@ const ORDER_NAME_MAP = {
|
|||||||
0: "房间",
|
0: "房间",
|
||||||
1: "门票",
|
1: "门票",
|
||||||
2: "餐饮",
|
2: "餐饮",
|
||||||
|
3: "套餐",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取状态图标
|
// 获取状态图标
|
||||||
|
|||||||
66
src/pages-quick/components/Card/index.vue
Normal file
66
src/pages-quick/components/Card/index.vue
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="card bg-white border-box p-8 rounded-12 flex flex-items-start m-12"
|
||||||
|
@click="handleClick(item)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="left rounded-10"
|
||||||
|
:src="item.commodityIcon"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<view class="right border-box flex-full pl-12">
|
||||||
|
<view class="font-size-16 line-height-24 color-171717 mb-4">
|
||||||
|
{{ item.commodityName }}
|
||||||
|
</view>
|
||||||
|
<view class="font-size-12 line-height-16 color-99A0AE mb-4">
|
||||||
|
1 张 1.8 米大床
|
||||||
|
</view>
|
||||||
|
<view class="font-size-12 line-height-18 color-43669A">
|
||||||
|
{{ item.commodityTradeRuleList.join(" / ") }}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex flex-items-center flex-justify-end">
|
||||||
|
<text
|
||||||
|
class="amt font-size-18 font-500 font-family-misans-vf line-height-24 color-FF3D60 mr-4"
|
||||||
|
>
|
||||||
|
{{ item.commodityPrice }}
|
||||||
|
</text>
|
||||||
|
<text class="font-size-12 line-height-16 color-99A0AE">
|
||||||
|
/{{ item.stockUnitLabel }}
|
||||||
|
</text>
|
||||||
|
<text class="btn border-box rounded-10 color-white ml-16">订</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps } from "vue";
|
||||||
|
|
||||||
|
// Props
|
||||||
|
const props = defineProps({
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({
|
||||||
|
commodityIcon: "",
|
||||||
|
commodityId: "",
|
||||||
|
commodityName: "",
|
||||||
|
commodityPrice: "",
|
||||||
|
commodityServices: [],
|
||||||
|
commodityTags: [], // 商品标签
|
||||||
|
commodityTradeRuleList: [], // 交易规则列表
|
||||||
|
specificationId: "", // 规格ID
|
||||||
|
stockUnitLabel: "", // 库存单位
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClick = ({ commodityId }) => {
|
||||||
|
uni.navigateTo({ url: `/pages/goods/index?commodityId=${commodityId}` });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "./styles/index.scss";
|
||||||
|
</style>
|
||||||
21
src/pages-quick/components/Card/styles/index.scss
Normal file
21
src/pages-quick/components/Card/styles/index.scss
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.left {
|
||||||
|
height: 107px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amt {
|
||||||
|
&::before {
|
||||||
|
content: "¥";
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background: linear-gradient(90deg, #ff3d60 57%, #ff990c 100%);
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
276
src/pages-quick/components/Tabs/index.vue
Normal file
276
src/pages-quick/components/Tabs/index.vue
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<template>
|
||||||
|
<view class="tab-container relative">
|
||||||
|
<view class="tab-wrapper flex flex-items-center flex-justify-center">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
:class="[
|
||||||
|
'tab-item flex flex-full flex-items-center flex-justify-center relative',
|
||||||
|
activeIndex === index && 'tab-item-active',
|
||||||
|
]"
|
||||||
|
@click="handleTabClick(index)"
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
:class="[
|
||||||
|
'font-size-16 font-500 color-525866 absolute',
|
||||||
|
activeIndex === index && 'tab-text-active',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 下划线指示器 -->
|
||||||
|
<view
|
||||||
|
:class="[
|
||||||
|
'tab-indicator absolute',
|
||||||
|
indicatorAnimating && 'animating',
|
||||||
|
indicatorInitialized && 'initialized',
|
||||||
|
]"
|
||||||
|
:style="{
|
||||||
|
left: indicatorLeft + 'px',
|
||||||
|
width: indicatorWidth + 'px',
|
||||||
|
}"
|
||||||
|
></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onMounted,
|
||||||
|
nextTick,
|
||||||
|
watch,
|
||||||
|
getCurrentInstance,
|
||||||
|
} from "vue";
|
||||||
|
|
||||||
|
// 获取组件实例
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
|
||||||
|
// Props
|
||||||
|
const props = defineProps({
|
||||||
|
tabs: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ label: "客房", value: "0" },
|
||||||
|
{ label: "门票", value: "1" },
|
||||||
|
{ label: "餐食", value: "2" },
|
||||||
|
{ label: "套餐", value: "3" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultActive: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
indicatorColor: {
|
||||||
|
type: String,
|
||||||
|
default: "#007AFF",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["change", "update:modelValue"]);
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const activeIndex = ref(props.defaultActive);
|
||||||
|
const tabList = ref(props.tabs);
|
||||||
|
const indicatorLeft = ref(0);
|
||||||
|
const indicatorWidth = ref(0);
|
||||||
|
const tabItemRects = reactive([]);
|
||||||
|
const isUpdating = ref(false);
|
||||||
|
const indicatorAnimating = ref(false);
|
||||||
|
const indicatorInitialized = ref(false);
|
||||||
|
|
||||||
|
// 处理Tab点击
|
||||||
|
const handleTabClick = (index) => {
|
||||||
|
if (activeIndex.value === index) return;
|
||||||
|
|
||||||
|
activeIndex.value = index;
|
||||||
|
indicatorAnimating.value = true;
|
||||||
|
updateIndicator();
|
||||||
|
|
||||||
|
// 动画结束后移除动画类
|
||||||
|
setTimeout(() => {
|
||||||
|
indicatorAnimating.value = false;
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
emit("change", {
|
||||||
|
index,
|
||||||
|
item: tabList.value[index],
|
||||||
|
});
|
||||||
|
emit("update:modelValue", index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新指示器位置
|
||||||
|
const updateIndicator = async () => {
|
||||||
|
if (isUpdating.value) return;
|
||||||
|
isUpdating.value = true;
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// 检查实例是否存在
|
||||||
|
if (!instance) {
|
||||||
|
console.warn("Component instance not available");
|
||||||
|
isUpdating.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 uni.createSelectorQuery 是否可用
|
||||||
|
if (!uni || !uni.createSelectorQuery) {
|
||||||
|
console.warn("uni.createSelectorQuery not available");
|
||||||
|
isUpdating.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = uni.createSelectorQuery().in(instance);
|
||||||
|
|
||||||
|
// 同时获取tab项和容器的位置信息
|
||||||
|
query.selectAll(".tab-item").boundingClientRect();
|
||||||
|
query.select(".tab-wrapper").boundingClientRect();
|
||||||
|
|
||||||
|
query.exec((res) => {
|
||||||
|
try {
|
||||||
|
const [tabRects, wrapperRect] = res || [];
|
||||||
|
|
||||||
|
if (tabRects && tabRects.length > 0 && wrapperRect) {
|
||||||
|
tabItemRects.splice(0, tabItemRects.length, ...tabRects);
|
||||||
|
|
||||||
|
const activeRect = tabRects[activeIndex.value];
|
||||||
|
if (activeRect) {
|
||||||
|
// 计算相对于容器的位置,居中显示
|
||||||
|
const tabCenter =
|
||||||
|
activeRect.left - wrapperRect.left + activeRect.width / 2;
|
||||||
|
indicatorLeft.value = tabCenter - 10; // 15px宽度的一半
|
||||||
|
// 固定宽度15px,不动态计算宽度
|
||||||
|
indicatorWidth.value = 20;
|
||||||
|
|
||||||
|
// 标记为已初始化
|
||||||
|
if (!indicatorInitialized.value) {
|
||||||
|
indicatorInitialized.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Failed to get tab rects or wrapper rect");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in updateIndicator exec:", error);
|
||||||
|
} finally {
|
||||||
|
isUpdating.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听activeIndex变化
|
||||||
|
watch(
|
||||||
|
() => activeIndex.value,
|
||||||
|
() => {
|
||||||
|
// 如果是初始化阶段,使用initIndicator
|
||||||
|
if (indicatorLeft.value === 0 && indicatorWidth.value === 0) {
|
||||||
|
initIndicator();
|
||||||
|
} else {
|
||||||
|
updateIndicator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听tabs变化
|
||||||
|
watch(
|
||||||
|
() => props.tabs,
|
||||||
|
(newTabs) => {
|
||||||
|
tabList.value = newTabs;
|
||||||
|
// 重置初始化状态
|
||||||
|
indicatorInitialized.value = false;
|
||||||
|
// 重新初始化指示器
|
||||||
|
initIndicator();
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听defaultActive变化
|
||||||
|
watch(
|
||||||
|
() => props.defaultActive,
|
||||||
|
(newActive) => {
|
||||||
|
if (newActive !== activeIndex.value) {
|
||||||
|
activeIndex.value = newActive;
|
||||||
|
// 重置初始化状态
|
||||||
|
indicatorInitialized.value = false;
|
||||||
|
initIndicator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 初始化指示器
|
||||||
|
const initIndicator = async (retryCount = 0) => {
|
||||||
|
// 等待DOM完全渲染
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// 延迟一帧确保布局完成
|
||||||
|
setTimeout(() => {
|
||||||
|
// 检查实例是否存在
|
||||||
|
if (!instance) {
|
||||||
|
console.warn("Component instance not available in initIndicator");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 uni.createSelectorQuery 是否可用
|
||||||
|
if (!uni || !uni.createSelectorQuery) {
|
||||||
|
console.warn("uni.createSelectorQuery not available in initIndicator");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = uni.createSelectorQuery().in(instance);
|
||||||
|
query.selectAll(".tab-item").boundingClientRect();
|
||||||
|
query.select(".tab-wrapper").boundingClientRect();
|
||||||
|
|
||||||
|
query.exec((res) => {
|
||||||
|
try {
|
||||||
|
const [tabRects, wrapperRect] = res || [];
|
||||||
|
|
||||||
|
// 如果DOM元素还未准备好,重试
|
||||||
|
if (
|
||||||
|
(!tabRects || tabRects.length === 0 || !wrapperRect) &&
|
||||||
|
retryCount < 3
|
||||||
|
) {
|
||||||
|
setTimeout(() => {
|
||||||
|
initIndicator(retryCount + 1);
|
||||||
|
}, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行正常的更新逻辑
|
||||||
|
updateIndicator();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in initIndicator exec:", error);
|
||||||
|
// 如果出错且还有重试次数,尝试重试
|
||||||
|
if (retryCount < 3) {
|
||||||
|
setTimeout(() => {
|
||||||
|
initIndicator(retryCount + 1);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载后初始化指示器
|
||||||
|
onMounted(() => {
|
||||||
|
initIndicator();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
setActiveIndex: (index) => {
|
||||||
|
if (index >= 0 && index < tabList.value.length) {
|
||||||
|
handleTabClick(index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getActiveIndex: () => activeIndex.value,
|
||||||
|
getActiveItem: () => tabList.value[activeIndex.value],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "./styles/index.scss";
|
||||||
|
</style>
|
||||||
67
src/pages-quick/components/Tabs/styles/index.scss
Normal file
67
src/pages-quick/components/Tabs/styles/index.scss
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
.tab-wrapper {
|
||||||
|
background-color: #d9eeff;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item-active {
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20px 20px 0 0;
|
||||||
|
transform: perspective(40px) rotateX(6deg) translate(0, -1px);
|
||||||
|
transform-origin: bottom bottom;
|
||||||
|
box-shadow: 0 -0.5px 0 #2d91ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text-active {
|
||||||
|
color: #2d91ff;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-indicator {
|
||||||
|
bottom: 0;
|
||||||
|
height: 3px;
|
||||||
|
background-color: #2d91ff;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
z-index: 3;
|
||||||
|
transform: translateZ(0); /* 启用硬件加速 */
|
||||||
|
will-change: left, width; /* 优化动画性能 */
|
||||||
|
|
||||||
|
/* 初始状态:未初始化时隐藏 */
|
||||||
|
opacity: 0;
|
||||||
|
width: 20px; /* 默认宽度15px */
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 已初始化状态 */
|
||||||
|
.tab-indicator.initialized {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画增强 */
|
||||||
|
@keyframes tabSwitch {
|
||||||
|
0% {
|
||||||
|
transform: translateZ(0) scaleX(0.8);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateZ(0) scaleX(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-indicator.animating {
|
||||||
|
animation: tabSwitch 0.3s ease-out;
|
||||||
|
}
|
||||||
118
src/pages-quick/list.vue
Normal file
118
src/pages-quick/list.vue
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging
|
||||||
|
ref="paging"
|
||||||
|
v-model="dataList"
|
||||||
|
use-virtual-list
|
||||||
|
:force-close-inner-list="true"
|
||||||
|
cell-height-mode="dynamic"
|
||||||
|
safe-area-inset-bottom
|
||||||
|
@query="queryList"
|
||||||
|
>
|
||||||
|
<template #top>
|
||||||
|
<TopNavBar title="快速预定" />
|
||||||
|
<header>
|
||||||
|
<Tabs @change="handleTabChange" />
|
||||||
|
|
||||||
|
<!-- 选择入住、离店日期 -->
|
||||||
|
<view class="bg-white border-box flex flex-items-center p-12">
|
||||||
|
<view class="in flex flex-items-center">
|
||||||
|
<text class="font-size-11 font-500 color-99A0AE mr-4">入住</text>
|
||||||
|
<text class="font-size-14 font-500 color-171717">
|
||||||
|
{{ DateUtils.formatDate() }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 几晚 -->
|
||||||
|
<text
|
||||||
|
class="nights bg-E5E8EE border-box font-size-11 font-500 color-525866 rounded-50 ml-8 mr-8"
|
||||||
|
>
|
||||||
|
{{ 1 }}晚
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<view class="out flex flex-items-center">
|
||||||
|
<text class="font-size-11 font-500 color-99A0AE mr-4">离店</text>
|
||||||
|
<text class="font-size-14 font-500 color-171717">
|
||||||
|
{{ DateUtils.formatDate() }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 日期图标 -->
|
||||||
|
<uni-icons
|
||||||
|
class="ml-auto"
|
||||||
|
type="calendar"
|
||||||
|
size="24"
|
||||||
|
color="#2D91FF"
|
||||||
|
@click="calendarVisible = true"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<Card v-for="(item, index) in dataList" :key="index" :item="item" />
|
||||||
|
</z-paging>
|
||||||
|
|
||||||
|
<!-- 日历组件 -->
|
||||||
|
<Calender
|
||||||
|
:visible="calendarVisible"
|
||||||
|
mode="single"
|
||||||
|
:default-value="selectedDate"
|
||||||
|
@close="handleCalendarClose"
|
||||||
|
@select="handleDateSelect"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||||
|
import Calender from "@/components/Calender/index.vue";
|
||||||
|
import Tabs from "./components/Tabs/index.vue";
|
||||||
|
import Card from "./components/Card/index.vue";
|
||||||
|
import { quickBookingComponent } from "@/request/api/MainPageDataApi";
|
||||||
|
import { DateUtils } from "@/utils";
|
||||||
|
|
||||||
|
const calendarVisible = ref(false);
|
||||||
|
const selectedDate = ref("");
|
||||||
|
const dataList = ref([]);
|
||||||
|
const paging = ref(null);
|
||||||
|
|
||||||
|
const queryList = async (pageNum = 1, pageSize = 10) => {
|
||||||
|
try {
|
||||||
|
const res = await quickBookingComponent(DateUtils.formatDate());
|
||||||
|
console.log("API响应:", res.data.commodityGroupDTOList);
|
||||||
|
|
||||||
|
if (res && res.data && res.data.commodityGroupDTOList) {
|
||||||
|
const records = res.data.commodityGroupDTOList[0].commodityList;
|
||||||
|
|
||||||
|
// 完成数据加载,第二个参数表示是否还有更多数据
|
||||||
|
paging.value.complete(records);
|
||||||
|
} else {
|
||||||
|
// 没有数据
|
||||||
|
paging.value.complete([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("查询列表失败:", error);
|
||||||
|
// 加载失败
|
||||||
|
paging.value.complete(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTabChange = ({ index, item }) => {};
|
||||||
|
|
||||||
|
// 处理日历关闭
|
||||||
|
const handleCalendarClose = () => {
|
||||||
|
calendarVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理日期选择
|
||||||
|
const handleDateSelect = (data) => {
|
||||||
|
selectedDate.value = data.date;
|
||||||
|
calendarVisible.value = false;
|
||||||
|
console.log("选择的日期:", data.date);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.nights {
|
||||||
|
padding: 3px 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -47,6 +47,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages-quick",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "list",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ const sendReply = (item) => {
|
|||||||
uni.$emit("SHOW_MORE_POPUP");
|
uni.$emit("SHOW_MORE_POPUP");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 快速预定
|
||||||
|
if (item.type === Command.quickBooking) {
|
||||||
|
uni.navigateTo({ url: "/pages-quick/list" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
|
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const list = ref([
|
|||||||
content: "预定门票、房间、餐食",
|
content: "预定门票、房间、餐食",
|
||||||
btnText: "去预定",
|
btnText: "去预定",
|
||||||
type: Command.quickBooking,
|
type: Command.quickBooking,
|
||||||
path: "",
|
path: "/pages-quick/list",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "https://oss.nianxx.cn/mp/static/version_101/home/tsfx.png",
|
icon: "https://oss.nianxx.cn/mp/static/version_101/home/tsfx.png",
|
||||||
@@ -98,10 +98,12 @@ const close = () => {
|
|||||||
|
|
||||||
const handleClick = (item) => {
|
const handleClick = (item) => {
|
||||||
close();
|
close();
|
||||||
|
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
uni.navigateTo({ url: item.path });
|
uni.navigateTo({ url: item.path });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
|
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@
|
|||||||
background-color: #17294e;
|
background-color: #17294e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-E5E8EE {
|
||||||
|
background-color: #e5e8ee;
|
||||||
|
}
|
||||||
|
|
||||||
.bg-liner {
|
.bg-liner {
|
||||||
background: linear-gradient(205deg, #8ae3fc 0%, rgba(138, 227, 252, 0) 20%),
|
background: linear-gradient(205deg, #8ae3fc 0%, rgba(138, 227, 252, 0) 20%),
|
||||||
linear-gradient(155deg, #fef7e1 0%, rgba(254, 247, 225, 0) 20%),
|
linear-gradient(155deg, #fef7e1 0%, rgba(254, 247, 225, 0) 20%),
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
// 外边距-bottom
|
// 外边距-bottom
|
||||||
|
.ml-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.m-4 {
|
.m-4 {
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
@@ -7,6 +11,18 @@
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-6 {
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-6 {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
.m-8 {
|
.m-8 {
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
}
|
}
|
||||||
@@ -15,6 +31,10 @@
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ml-8 {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.mr-8 {
|
.mr-8 {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
@@ -39,18 +59,14 @@
|
|||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-6 {
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb-6 {
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ml-12 {
|
.ml-12 {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ml-16 {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.ml-20 {
|
.ml-20 {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rounded-10 {
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded-12 {
|
.rounded-12 {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,12 +299,33 @@ export class ThrottleUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期工具类
|
||||||
|
* 提供日期格式化功能
|
||||||
|
* */
|
||||||
|
export class DateUtils {
|
||||||
|
/**
|
||||||
|
* 格式化日期为指定格式
|
||||||
|
* @param {Date} date - 日期对象
|
||||||
|
* @param {string} format - 格式化字符串,默认值为 "yyyy-MM-dd"
|
||||||
|
* @returns {string} 格式化后的日期字符串
|
||||||
|
*/
|
||||||
|
static formatDate(date = new Date(), format = "yyyy-MM-dd") {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
|
||||||
|
return format.replace("yyyy", year).replace("MM", month).replace("dd", day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 默认导出所有工具类
|
// 默认导出所有工具类
|
||||||
export default {
|
export default {
|
||||||
IdUtils,
|
IdUtils,
|
||||||
CallbackUtils,
|
CallbackUtils,
|
||||||
MessageUtils,
|
MessageUtils,
|
||||||
TimerUtils,
|
TimerUtils,
|
||||||
|
DateUtils,
|
||||||
DebounceUtils,
|
DebounceUtils,
|
||||||
ThrottleUtils,
|
ThrottleUtils,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user