修改样式
This commit is contained in:
@@ -137,13 +137,12 @@ const isDateSelectable = (date: Date): boolean => {
|
||||
return hasAvailableTimeSlots(date);
|
||||
};
|
||||
|
||||
// 生成未来的日期(显示所有日期,但标记营业状态)
|
||||
// 生成未来 7 天:设计稿为「本周」5 个圆 +「下周」2 个圆
|
||||
const dateOptions = computed(() => {
|
||||
const dates: Date[] = [];
|
||||
const today = new Date();
|
||||
|
||||
// 生成连续的5天日期(包括不营业的日期)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const date = new Date(today);
|
||||
date.setDate(today.getDate() + i);
|
||||
dates.push(date);
|
||||
@@ -152,6 +151,9 @@ const dateOptions = computed(() => {
|
||||
return dates;
|
||||
});
|
||||
|
||||
const thisWeekDates = computed(() => dateOptions.value.slice(0, 5));
|
||||
const nextWeekDates = computed(() => dateOptions.value.slice(5, 7));
|
||||
|
||||
// 状态管理 - 初始化为第一个营业日期
|
||||
const selectedDate = ref<Date>();
|
||||
|
||||
@@ -246,7 +248,6 @@ const initializeSelectedDate = () => {
|
||||
);
|
||||
const firstAllowed = firstOpen || dateOptions.value.find((d) => isAllowedDay(d));
|
||||
selectedDate.value = firstAllowed || dateOptions.value[0];
|
||||
nextTick(() => updateScrollPosition());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -254,9 +255,6 @@ const initializeSelectedDate = () => {
|
||||
for (const date of dateOptions.value) {
|
||||
if (isDateSelectable(date)) {
|
||||
selectedDate.value = date;
|
||||
nextTick(() => {
|
||||
updateScrollPosition();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -266,7 +264,6 @@ const initializeSelectedDate = () => {
|
||||
if (nextBusinessDate) {
|
||||
selectedDate.value = nextBusinessDate;
|
||||
nextTick(() => {
|
||||
updateScrollPosition();
|
||||
uni.showToast({
|
||||
title: t('pages.address.reservationTime.currentTimeExpired'),
|
||||
icon: "none",
|
||||
@@ -275,9 +272,6 @@ const initializeSelectedDate = () => {
|
||||
});
|
||||
} else {
|
||||
selectedDate.value = dateOptions.value[0];
|
||||
nextTick(() => {
|
||||
updateScrollPosition();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -304,59 +298,15 @@ watch(
|
||||
);
|
||||
const selectedTimeSlot = ref<string>("");
|
||||
|
||||
// 横向滚动距离
|
||||
const scrollLeft = ref<number>(0);
|
||||
/** 圆圈内上行:星期(与全局 dayjs 语言一致) */
|
||||
const formatWeekdayCircle = (date: Date) => dayjs(date).format("dddd");
|
||||
|
||||
// 计算并设置横向滚动距离
|
||||
const updateScrollPosition = () => {
|
||||
if (!selectedDate.value) return;
|
||||
|
||||
// 找到选中日期在 dateOptions 中的索引
|
||||
const selectedIndex = dateOptions.value.findIndex(date =>
|
||||
dayjs(date).isSame(dayjs(selectedDate.value), 'day')
|
||||
);
|
||||
|
||||
if (selectedIndex === -1) return;
|
||||
|
||||
// 每个日期卡片的宽度:240rpx + 28rpx 间距 = 268rpx
|
||||
// 但第一个卡片没有左边距,所以需要特殊处理
|
||||
const cardWidth = 240; // rpx
|
||||
const cardMargin = 28; // rpx
|
||||
|
||||
// 计算滚动距离,让选中的卡片尽量居中显示
|
||||
let scrollDistance = 0;
|
||||
if (selectedIndex > 0) {
|
||||
// 第一个卡片没有左边距,从第二个开始每个卡片占用 240 + 28 = 268rpx
|
||||
scrollDistance = selectedIndex * (cardWidth + cardMargin);
|
||||
|
||||
// 减去一些距离让选中项更居中(可根据屏幕宽度调整)
|
||||
scrollDistance = Math.max(0, scrollDistance - 100);
|
||||
}
|
||||
|
||||
scrollLeft.value = scrollDistance;
|
||||
};
|
||||
|
||||
// 格式化日期显示
|
||||
const formatDateDisplay = (date: Date) => {
|
||||
const today = dayjs();
|
||||
const targetDate = dayjs(date);
|
||||
|
||||
if (targetDate.isSame(today, "day")) {
|
||||
return "Today";
|
||||
} else if (targetDate.isSame(today.add(1, "day"), "day")) {
|
||||
return "Tomorrow";
|
||||
} else {
|
||||
// 返回星期几
|
||||
return targetDate.format("dddd");
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化日期为月份和日期(不包含年份),不可选择日期显示"不营业"
|
||||
const formatDateOnly = (date: Date) => {
|
||||
/** 圆圈内下行:MM/DD;不可选时显示文案 */
|
||||
const formatCircleSubLine = (date: Date) => {
|
||||
if (!isDateSelectable(date)) {
|
||||
return t('pages.address.reservationTime.notAvailable')
|
||||
return t("pages.address.reservationTime.notAvailable");
|
||||
}
|
||||
return dayjs(date).format('MMMM D')
|
||||
return dayjs(date).format("MM/DD");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -536,8 +486,16 @@ const selectTimeSlot = (timeSlot: string) => {
|
||||
selectedTimeSlot.value = timeSlot;
|
||||
};
|
||||
|
||||
const isDateSelected = (date: Date) =>
|
||||
!!selectedDate.value && dayjs(selectedDate.value).isSame(dayjs(date), "day");
|
||||
|
||||
// 提交预约
|
||||
const submitReservation = () => {
|
||||
const dateVal = selectedDate.value;
|
||||
if (!dateVal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 非仅选日期模式,需要选择时间段
|
||||
if (!onlySelectDay.value) {
|
||||
if (!selectedTimeSlot.value) {
|
||||
@@ -550,13 +508,13 @@ const submitReservation = () => {
|
||||
}
|
||||
|
||||
// 计算开始/结束时间
|
||||
const selectedDateDayjs = dayjs(selectedDate.value);
|
||||
const selectedDateDayjs = dayjs(dateVal);
|
||||
let startTime: dayjs.Dayjs;
|
||||
let endTime: dayjs.Dayjs;
|
||||
|
||||
if (onlySelectDay.value) {
|
||||
// 仅选日期:优先使用营业时间范围;若无营业时间限制,则使用当天起止
|
||||
const bh = getBusinessHoursForDate(selectedDate.value);
|
||||
const bh = getBusinessHoursForDate(dateVal);
|
||||
if (bh) {
|
||||
const [startHour, startMinute] = bh.startTime.split(':').map(Number);
|
||||
const [endHour, endMinute] = bh.endTime.split(':').map(Number);
|
||||
@@ -592,14 +550,14 @@ const submitReservation = () => {
|
||||
}
|
||||
|
||||
console.log("预约信息:", {
|
||||
date: selectedDate.value,
|
||||
date: dateVal,
|
||||
timeSlot: onlySelectDay.value ? '' : selectedTimeSlot.value,
|
||||
startTime: startTime.valueOf(),
|
||||
endTime: endTime.valueOf(),
|
||||
});
|
||||
|
||||
uni.$emit(EventEnum.CHOOSE_APPOINTMENT_TIME, {
|
||||
date: selectedDate.value,
|
||||
date: dateVal,
|
||||
timeSlot: onlySelectDay.value ? '' : selectedTimeSlot.value,
|
||||
startTime: startTime.valueOf(),
|
||||
endTime: endTime.valueOf(),
|
||||
@@ -633,45 +591,52 @@ onLoad((options: any) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="">
|
||||
<navbar />
|
||||
<view class="mt-20rpx px-30rpx text-46rpx lh-46rpx text-#333 font-bold">
|
||||
{{ t("pages.address.appTime") }}
|
||||
</view>
|
||||
<view class="px-30rpx pt-52rpx pb-50rpx w-screen bg-white">
|
||||
<scroll-view class="w-full whitespace-nowrap" scroll-x="true" :scroll-left="scrollLeft">
|
||||
<template v-for="(item, index) in dateOptions" :key="index">
|
||||
<view class="reservation-time-page min-h-screen pb-180rpx">
|
||||
<navbar
|
||||
:title="t('pages.address.reservationTime.pageTitle')"
|
||||
circle-back
|
||||
custom-class="reservation-time-navbar"
|
||||
/>
|
||||
<view class="reservation-time-body px-40rpx pt-40rpx">
|
||||
<view class="date-section">
|
||||
<text class="section-label">{{ t("pages.address.reservationTime.thisWeek") }}</text>
|
||||
<view class="date-row">
|
||||
<view
|
||||
@click="selectDate(item)"
|
||||
:class="[
|
||||
index === 0 ? '' : 'ml-28rpx',
|
||||
selectedDate && dayjs(selectedDate).isSame(dayjs(item), 'day')
|
||||
? 'border-#333'
|
||||
: 'border-#D8D8D8',
|
||||
!isDateSelectable(item)
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: 'cursor-pointer',
|
||||
]"
|
||||
class="inline-block border-solid border-1px w-240rpx h-140rpx rounded-20rpx px-32rpx py-36rpx"
|
||||
v-for="(item, index) in thisWeekDates"
|
||||
:key="index"
|
||||
class="date-circle"
|
||||
:class="{
|
||||
'date-circle--selected': isDateSelected(item),
|
||||
'date-circle--disabled': !isDateSelectable(item),
|
||||
}"
|
||||
@click="selectDate(item)"
|
||||
>
|
||||
<view
|
||||
:class="!isDateSelectable(item) ? 'text-#999' : 'text-#333'"
|
||||
class="text-28rpx lh-28rpx mb-12rpx"
|
||||
>
|
||||
{{ formatDateDisplay(item) }}
|
||||
</view>
|
||||
<view
|
||||
:class="!isDateSelectable(item) ? 'text-#CCC' : 'text-#7D7D7D'"
|
||||
class="text-28rpx"
|
||||
>
|
||||
{{ formatDateOnly(item) }}
|
||||
</view>
|
||||
<text class="date-circle__weekday">{{ formatWeekdayCircle(item) }}</text>
|
||||
<text class="date-circle__sub">{{ formatCircleSubLine(item) }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="nextWeekDates.length" class="date-section date-section--next">
|
||||
<text class="section-label">{{ t("pages.address.reservationTime.nextWeek") }}</text>
|
||||
<view class="date-row">
|
||||
<view
|
||||
v-for="(item, index) in nextWeekDates"
|
||||
:key="index"
|
||||
class="date-circle"
|
||||
:class="{
|
||||
'date-circle--selected': isDateSelected(item),
|
||||
'date-circle--disabled': !isDateSelectable(item),
|
||||
}"
|
||||
@click="selectDate(item)"
|
||||
>
|
||||
<text class="date-circle__weekday">{{ formatWeekdayCircle(item) }}</text>
|
||||
<text class="date-circle__sub">{{ formatCircleSubLine(item) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 时间段选择区域:在仅选日期模式下隐藏 -->
|
||||
<view v-if="!onlySelectDay" class="pb-138rpx">
|
||||
<view v-if="!onlySelectDay" class="pb-138rpx mx-40rpx bg-white rounded-24rpx overflow-hidden mt-24rpx">
|
||||
<view
|
||||
v-for="(timeSlot, index) in timeSlots"
|
||||
:key="index"
|
||||
@@ -705,8 +670,91 @@ onLoad((options: any) => {
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
page {
|
||||
<style scoped lang="scss">
|
||||
.reservation-time-body {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.date-section {
|
||||
margin-bottom: 48rpx;
|
||||
|
||||
&--next {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-label {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
line-height: 44rpx;
|
||||
color: #111;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.date-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: 20rpx;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.date-circle {
|
||||
width: 118rpx;
|
||||
height: 118rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.date-circle__weekday {
|
||||
font-size: 26rpx;
|
||||
line-height: 32rpx;
|
||||
color: #111;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.date-circle__sub {
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
margin-top: 6rpx;
|
||||
color: #111;
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.date-circle--selected {
|
||||
background-color: #111;
|
||||
box-shadow: none;
|
||||
|
||||
.date-circle__weekday,
|
||||
.date-circle__sub {
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.date-circle--disabled {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.date-circle--disabled.date-circle--selected {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f7f7f9;
|
||||
}
|
||||
|
||||
.reservation-time-page :deep(.reservation-time-navbar.wd-navbar) {
|
||||
background-color: #f7f7f9 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user