修改样式
This commit is contained in:
@@ -18,15 +18,17 @@ function handleClickSearch() {
|
||||
chooseAddress: (data: any) => {
|
||||
console.log('搜索的地址信息', data)
|
||||
if (data) {
|
||||
addressStore.clearAddressInfo()
|
||||
addressStore.setAddressLocation({
|
||||
displayName: data.displayName,
|
||||
formattedAddress: data.formattedAddress,
|
||||
longitude: data.location.lng,
|
||||
latitude: data.location.lat
|
||||
})
|
||||
addressStore.pendingIntroBuildingType = true
|
||||
setTimeout(()=> {
|
||||
uni.navigateTo({
|
||||
url: '/pages/address/choose-type'
|
||||
url: '/pages/address/save-address/other'
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -99,6 +99,13 @@ onLoad(()=> {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
if (addressStore.pendingIntroBuildingType && !addressStore.addressInfo.id) {
|
||||
buildingTypeRef.value?.openIntroSheet?.()
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(()=> {
|
||||
if(!isSwitch.value) {
|
||||
addressStore.clearAddressInfo()
|
||||
@@ -176,7 +183,11 @@ function chooseStateConfirm(data: any) {
|
||||
<view class="mb-20rpx text-36rpx lh-36rpx text-#333 font-500">{{ t('pages.address.choose-type.navTitle') }}</view>
|
||||
<view @click="openBuildingType" class="bg-#F6F6F6 rounded-16rpx px-24rpx h-98rpx flex-center-sb">
|
||||
<text class="text-30rpx lh-30rpx text-#333">
|
||||
{{ `${t(`pages.address.choose-type.${addressStore.addressInfo.type}`)}` }}
|
||||
{{
|
||||
addressStore.addressInfo.type
|
||||
? t(`pages.address.choose-type.${addressStore.addressInfo.type}`)
|
||||
: t('common.placeholder.pleaseSelect')
|
||||
}}
|
||||
</text>
|
||||
<image src="@img/chef/142.png" class="w-32rpx h-32rpx shrink-0 rotate-90"></image>
|
||||
</view>
|
||||
|
||||
@@ -1,70 +1,228 @@
|
||||
<script setup lang="ts">
|
||||
import {UserAddressType} from "@/constant/enums";
|
||||
import { UserAddressType } from '@/constant/enums';
|
||||
import { useAddressStore } from '@/pages/address/store/address';
|
||||
|
||||
const { t } = useI18n();
|
||||
const show = ref(false);
|
||||
const value = ref('house')
|
||||
const addressStore = useAddressStore();
|
||||
|
||||
const emit = defineEmits(['submit'])
|
||||
/** 新地址首次进入保存页:与原先 choose-type 全页等价的介绍弹窗 */
|
||||
const showIntro = ref(false);
|
||||
/** 点击表单「建筑类型」行:原有滚轮选择器 */
|
||||
const showPicker = ref(false);
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [value: string];
|
||||
}>();
|
||||
|
||||
const typeList = computed(() => [
|
||||
{
|
||||
label: t('pages.address.choose-type.house'),
|
||||
desc: t('pages.address.choose-type.houseDescription'),
|
||||
value: UserAddressType.HOUSE,
|
||||
icon: '/static/images/chef/147.png',
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.apartment'),
|
||||
desc: t('pages.address.choose-type.apartmentDescription'),
|
||||
value: UserAddressType.APARTMENT,
|
||||
icon: '/static/images/chef/148.png',
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.office'),
|
||||
desc: t('pages.address.choose-type.officeDescription'),
|
||||
value: UserAddressType.OFFICE,
|
||||
icon: '/static/images/chef/149.png',
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.hotel'),
|
||||
desc: t('pages.address.choose-type.hotelDescription'),
|
||||
value: UserAddressType.HOTEL,
|
||||
icon: '/static/images/chef/150.png',
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.other'),
|
||||
desc: t('pages.address.choose-type.otherDescription'),
|
||||
value: UserAddressType.OTHER,
|
||||
icon: '/static/images/chef/151.png',
|
||||
},
|
||||
]);
|
||||
|
||||
const columns = computed(() => [
|
||||
{ label: t('pages.address.choose-type.house'), value: UserAddressType.HOUSE },
|
||||
{ label: t('pages.address.choose-type.apartment'), value: UserAddressType.APARTMENT },
|
||||
{ label: t('pages.address.choose-type.office'), value: UserAddressType.OFFICE },
|
||||
{ label: t('pages.address.choose-type.hotel'), value: UserAddressType.HOTEL },
|
||||
{ label: t('pages.address.choose-type.other'), value: UserAddressType.OTHER },
|
||||
]);
|
||||
|
||||
const pickerValue = ref<string>(UserAddressType.HOUSE);
|
||||
|
||||
function routeForType(type: string): string {
|
||||
switch (type) {
|
||||
case UserAddressType.HOUSE:
|
||||
return 'pages/address/save-address/house';
|
||||
case UserAddressType.APARTMENT:
|
||||
return 'pages/address/save-address/apartment';
|
||||
case UserAddressType.OFFICE:
|
||||
return 'pages/address/save-address/office';
|
||||
case UserAddressType.HOTEL:
|
||||
return 'pages/address/save-address/hotel';
|
||||
case UserAddressType.OTHER:
|
||||
return 'pages/address/save-address/other';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function currentSaveAddressRoute(): string {
|
||||
const pages = getCurrentPages();
|
||||
return pages[pages.length - 1]?.route ?? '';
|
||||
}
|
||||
|
||||
/** 点击表单行:滚轮选择器(原效果) */
|
||||
function onOpen() {
|
||||
show.value = true;
|
||||
}
|
||||
function handleClose() {
|
||||
show.value = false;
|
||||
}
|
||||
function handleSubmit() {
|
||||
console.log('value', value.value)
|
||||
emit('submit', value.value)
|
||||
handleClose()
|
||||
pickerValue.value =
|
||||
addressStore.addressInfo.type && `${addressStore.addressInfo.type}`.length > 0
|
||||
? (addressStore.addressInfo.type as string)
|
||||
: UserAddressType.HOUSE;
|
||||
showPicker.value = true;
|
||||
}
|
||||
|
||||
const columns = ref(
|
||||
[
|
||||
{
|
||||
label: t('pages.address.choose-type.house'),
|
||||
value: UserAddressType.HOUSE,
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.apartment'),
|
||||
value: UserAddressType.APARTMENT,
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.office'),
|
||||
value: UserAddressType.OFFICE,
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.hotel'),
|
||||
value: UserAddressType.HOTEL,
|
||||
},
|
||||
{
|
||||
label: t('pages.address.choose-type.other'),
|
||||
value: UserAddressType.OTHER,
|
||||
},
|
||||
]
|
||||
)
|
||||
function onChange({picker, value, index}) {
|
||||
function handlePickerClose() {
|
||||
showPicker.value = false;
|
||||
}
|
||||
|
||||
function handlePickerCancel() {
|
||||
showPicker.value = false;
|
||||
}
|
||||
|
||||
function handlePickerConfirm() {
|
||||
addressStore.addressInfo.type = pickerValue.value;
|
||||
showPicker.value = false;
|
||||
const next = routeForType(pickerValue.value);
|
||||
if (next && currentSaveAddressRoute() !== next) {
|
||||
emit('submit', pickerValue.value);
|
||||
}
|
||||
}
|
||||
|
||||
/** 新地址首次进入页面时由父级调用 */
|
||||
function openIntroSheet() {
|
||||
showIntro.value = true;
|
||||
}
|
||||
|
||||
function handleIntroClose() {
|
||||
showIntro.value = false;
|
||||
}
|
||||
|
||||
/** 蒙层关闭且尚未完成选择时,与「跳过」一致 */
|
||||
function onIntroPopupClosed() {
|
||||
if (!addressStore.pendingIntroBuildingType) return;
|
||||
addressStore.pendingIntroBuildingType = false;
|
||||
addressStore.addressInfo.type = UserAddressType.OTHER;
|
||||
const next = routeForType(UserAddressType.OTHER);
|
||||
if (next && currentSaveAddressRoute() !== next) {
|
||||
emit('submit', UserAddressType.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
function chooseIntroType(item: { value: string }) {
|
||||
addressStore.pendingIntroBuildingType = false;
|
||||
addressStore.addressInfo.type = item.value;
|
||||
showIntro.value = false;
|
||||
const next = routeForType(item.value);
|
||||
if (next && currentSaveAddressRoute() !== next) {
|
||||
emit('submit', item.value);
|
||||
}
|
||||
}
|
||||
|
||||
function handleIntroSkip() {
|
||||
addressStore.pendingIntroBuildingType = false;
|
||||
addressStore.addressInfo.type = UserAddressType.OTHER;
|
||||
showIntro.value = false;
|
||||
const next = routeForType(UserAddressType.OTHER);
|
||||
if (next && currentSaveAddressRoute() !== next) {
|
||||
emit('submit', UserAddressType.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
onOpen,
|
||||
openIntroSheet,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 新地址首次:建筑类型介绍底部弹窗 -->
|
||||
<wd-popup
|
||||
v-model="show"
|
||||
position="bottom"
|
||||
@close="handleClose"
|
||||
v-model="showIntro"
|
||||
position="bottom"
|
||||
:z-index="120"
|
||||
custom-style="background: transparent;"
|
||||
@close="onIntroPopupClosed"
|
||||
>
|
||||
<view class="bg-white rounded-t-32rpx overflow-hidden pb-[calc(24rpx+env(safe-area-inset-bottom))]">
|
||||
<view class="relative px-30rpx pt-40rpx pb-8rpx">
|
||||
<text
|
||||
class="absolute right-30rpx top-40rpx z-1 text-32rpx lh-32rpx text-#CE7138"
|
||||
@click="handleIntroSkip"
|
||||
>
|
||||
{{ t('common.skip') }}
|
||||
</text>
|
||||
<view class="text-center text-36rpx lh-44rpx text-#333 font-500 pr-100rpx pl-100rpx">
|
||||
{{ t('pages.address.choose-type.title') }}
|
||||
</view>
|
||||
<view class="mt-24rpx text-center text-28rpx lh-36rpx text-#666">
|
||||
{{ t('pages.address.choose-type.description') }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y class="box-border max-h-[62vh] px-30rpx pb-8rpx pt-28rpx">
|
||||
<view
|
||||
v-for="(item, index) in typeList"
|
||||
:key="item.value"
|
||||
:class="[
|
||||
index === 0 ? '' : 'mt-28rpx',
|
||||
item.value === addressStore.addressInfo.type
|
||||
? 'border-#000 border-4rpx'
|
||||
: 'border-#DFDFDF border-2rpx',
|
||||
'border-solid rounded-16rpx px-28rpx py-34rpx flex items-center',
|
||||
]"
|
||||
@click="chooseIntroType(item)"
|
||||
>
|
||||
<image :src="item.icon" class="h-48rpx mr-28rpx shrink-0 w-48rpx" />
|
||||
<view class="min-w-0 flex-1">
|
||||
<view class="text-36rpx lh-40rpx text-#333 font-500">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
<view class="mt-18rpx text-28rpx lh-32rpx text-#6D6D6D">
|
||||
{{ item.desc }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
<!-- 点击建筑类型行:原滚轮选择 -->
|
||||
<wd-popup
|
||||
v-model="showPicker"
|
||||
position="bottom"
|
||||
:z-index="121"
|
||||
@close="handlePickerClose"
|
||||
>
|
||||
<view>
|
||||
<view class="flex-center-sb h-102rpx bg-#F7F7F7 px-30rpx">
|
||||
<view @click="handleClose" class="text-30rpx text-#999">{{ t('common.cancel') }}</view>
|
||||
<view class="text-30rpx text-#999" @click="handlePickerCancel">{{ t('common.cancel') }}</view>
|
||||
<view class="text-34rpx text-#333">{{ t('common.buildingType') }}</view>
|
||||
<view @click="handleSubmit" class="text-30rpx text-#FF6106">{{ t('common.confirm') }}</view>
|
||||
<view class="text-30rpx text-#FF6106" @click="handlePickerConfirm">{{ t('common.confirm') }}</view>
|
||||
</view>
|
||||
<view class="bg-#fff px-54rpx py-56rpx">
|
||||
<wd-picker-view :columns="columns" v-model="value" @change="onChange" label-key="label" value-key="value" />
|
||||
<wd-picker-view
|
||||
:columns="columns"
|
||||
v-model="pickerValue"
|
||||
label-key="label"
|
||||
value-key="value"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
@@ -90,4 +248,4 @@ defineExpose({
|
||||
:deep(.uni-picker-view-indicator) {
|
||||
height: 94rpx !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -98,6 +98,13 @@ onLoad(()=> {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
if (addressStore.pendingIntroBuildingType && !addressStore.addressInfo.id) {
|
||||
buildingTypeRef.value?.openIntroSheet?.()
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(()=> {
|
||||
if(!isSwitch.value) {
|
||||
addressStore.clearAddressInfo()
|
||||
@@ -173,7 +180,11 @@ function chooseStateConfirm(data: any) {
|
||||
<view class="mb-20rpx text-36rpx lh-36rpx text-#333 font-500">{{ t('pages.address.choose-type.navTitle') }}</view>
|
||||
<view @click="openBuildingType" class="bg-#F6F6F6 rounded-16rpx px-24rpx h-98rpx flex-center-sb">
|
||||
<text class="text-30rpx lh-30rpx text-#333">
|
||||
{{ `${t(`pages.address.choose-type.${addressStore.addressInfo.type}`)}` }}
|
||||
{{
|
||||
addressStore.addressInfo.type
|
||||
? t(`pages.address.choose-type.${addressStore.addressInfo.type}`)
|
||||
: t('common.placeholder.pleaseSelect')
|
||||
}}
|
||||
</text>
|
||||
<image src="@img/chef/142.png" class="w-32rpx h-32rpx shrink-0 rotate-90"></image>
|
||||
</view>
|
||||
|
||||
@@ -98,6 +98,13 @@ onLoad(()=> {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
if (addressStore.pendingIntroBuildingType && !addressStore.addressInfo.id) {
|
||||
buildingTypeRef.value?.openIntroSheet?.()
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(()=> {
|
||||
if(!isSwitch.value) {
|
||||
addressStore.clearAddressInfo()
|
||||
@@ -173,7 +180,11 @@ function chooseStateConfirm(data: any) {
|
||||
<view class="mb-20rpx text-36rpx lh-36rpx text-#333 font-500">{{ t('pages.address.choose-type.navTitle') }}</view>
|
||||
<view @click="openBuildingType" class="bg-#F6F6F6 rounded-16rpx px-24rpx h-98rpx flex-center-sb">
|
||||
<text class="text-30rpx lh-30rpx text-#333">
|
||||
{{ `${t(`pages.address.choose-type.${addressStore.addressInfo.type}`)}` }}
|
||||
{{
|
||||
addressStore.addressInfo.type
|
||||
? t(`pages.address.choose-type.${addressStore.addressInfo.type}`)
|
||||
: t('common.placeholder.pleaseSelect')
|
||||
}}
|
||||
</text>
|
||||
<image src="@img/chef/142.png" class="w-32rpx h-32rpx shrink-0 rotate-90"></image>
|
||||
</view>
|
||||
|
||||
@@ -98,6 +98,13 @@ onLoad(()=> {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
if (addressStore.pendingIntroBuildingType && !addressStore.addressInfo.id) {
|
||||
buildingTypeRef.value?.openIntroSheet?.()
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(()=> {
|
||||
if(!isSwitch.value) {
|
||||
addressStore.clearAddressInfo()
|
||||
@@ -173,7 +180,11 @@ function chooseStateConfirm(data: any) {
|
||||
<view class="mb-20rpx text-36rpx lh-36rpx text-#333 font-500">{{ t('pages.address.choose-type.navTitle') }}</view>
|
||||
<view @click="openBuildingType" class="bg-#F6F6F6 rounded-16rpx px-24rpx h-98rpx flex-center-sb">
|
||||
<text class="text-30rpx lh-30rpx text-#333">
|
||||
{{ `${t(`pages.address.choose-type.${addressStore.addressInfo.type}`)}` }}
|
||||
{{
|
||||
addressStore.addressInfo.type
|
||||
? t(`pages.address.choose-type.${addressStore.addressInfo.type}`)
|
||||
: t('common.placeholder.pleaseSelect')
|
||||
}}
|
||||
</text>
|
||||
<image src="@img/chef/142.png" class="w-32rpx h-32rpx shrink-0 rotate-90"></image>
|
||||
</view>
|
||||
|
||||
@@ -98,6 +98,13 @@ onLoad(()=> {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
if (addressStore.pendingIntroBuildingType && !addressStore.addressInfo.id) {
|
||||
buildingTypeRef.value?.openIntroSheet?.()
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(()=> {
|
||||
if(!isSwitch.value) {
|
||||
addressStore.clearAddressInfo()
|
||||
@@ -173,7 +180,11 @@ function chooseStateConfirm(data: any) {
|
||||
<view class="mb-20rpx text-36rpx lh-36rpx text-#333 font-500">{{ t('pages.address.choose-type.navTitle') }}</view>
|
||||
<view @click="openBuildingType" class="bg-#F6F6F6 rounded-16rpx px-24rpx h-98rpx flex-center-sb">
|
||||
<text class="text-30rpx lh-30rpx text-#333">
|
||||
{{ `${t(`pages.address.choose-type.${addressStore.addressInfo.type}`)}` }}
|
||||
{{
|
||||
addressStore.addressInfo.type
|
||||
? t(`pages.address.choose-type.${addressStore.addressInfo.type}`)
|
||||
: t('common.placeholder.pleaseSelect')
|
||||
}}
|
||||
</text>
|
||||
<image src="@img/chef/142.png" class="w-32rpx h-32rpx shrink-0 rotate-90"></image>
|
||||
</view>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineStore } from "pinia";
|
||||
import type { UserAddressBo } from '@/service/types';
|
||||
export const useAddressStore = defineStore('store-address', () => {
|
||||
/** 从地图搜索新增地址进入保存页时,首次需弹出建筑类型介绍层(与原先进入 choose-type 页等价) */
|
||||
const pendingIntroBuildingType = ref(false)
|
||||
|
||||
const addressInfo = ref<UserAddressBo>({
|
||||
type: '',
|
||||
/** 配送类型 1-亲自送达 2-放门口,默认放门口 */
|
||||
@@ -57,6 +60,7 @@ export const useAddressStore = defineStore('store-address', () => {
|
||||
}
|
||||
|
||||
function clearAddressInfo() {
|
||||
pendingIntroBuildingType.value = false
|
||||
addressInfo.value = {
|
||||
id: '',
|
||||
type: '',
|
||||
@@ -102,6 +106,7 @@ export const useAddressStore = defineStore('store-address', () => {
|
||||
return {
|
||||
addressInfo,
|
||||
addressLocation,
|
||||
pendingIntroBuildingType,
|
||||
setAddressLocation,
|
||||
clearAddressInfo
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user