ui调整
This commit is contained in:
@@ -25,9 +25,9 @@ defineExpose({
|
||||
@close="handleClose"
|
||||
>
|
||||
<view class="px-30rpx text-#333 text-center pt-48rpx pb-60rpx">
|
||||
<view class="text-40rpx lh-40rpx font-500">Delete shopping cart?</view>
|
||||
<view class="text-40rpx lh-40rpx font-500">{{ t("pages-user.cart.removeCartTitle") }}</view>
|
||||
<view class="text-28rpx lh-28rpx mt-36rpx">
|
||||
Are you sure you want to delete the shopping cart?
|
||||
{{ t("pages-user.cart.removeCartDesc") }}
|
||||
</view>
|
||||
<view class="mt-70rpx">
|
||||
<wd-button @click="handleDelete" custom-class="!h-108rpx !bg-14181B !text-36rpx !lh-108rpx !text-#fff !rounded-16rpx" block>
|
||||
|
||||
@@ -4,6 +4,20 @@ const emit = defineEmits(['confirm','close'])
|
||||
|
||||
const show = ref(false);
|
||||
const goodsName = ref('');
|
||||
|
||||
function fillI18nParams(template: string, params: Record<string, string | number>) {
|
||||
let text = template;
|
||||
Object.keys(params).forEach((key) => {
|
||||
const value = String(params[key] ?? "");
|
||||
text = text.replace(new RegExp(`\\{${key}\\}`, "g"), value);
|
||||
text = text.replace(new RegExp(`\\$\\{${key}\\}`, "g"), value);
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
const removeProductDescText = computed(() =>
|
||||
fillI18nParams(t("pages-user.cart.removeProductDesc"), { name: goodsName.value })
|
||||
);
|
||||
function onOpen(title: string) {
|
||||
if (title) {
|
||||
goodsName.value = title;
|
||||
@@ -31,9 +45,9 @@ defineExpose({
|
||||
@close="handleClose"
|
||||
>
|
||||
<view class="px-30rpx text-#333 text-center pt-48rpx pb-60rpx">
|
||||
<view class="text-40rpx lh-40rpx font-500">Remove the product?</view>
|
||||
<view class="text-40rpx lh-40rpx font-500">{{ t("pages-user.cart.removeProductTitle") }}</view>
|
||||
<view class="text-28rpx lh-28rpx mt-36rpx">
|
||||
Are you sure you want to remove {{ goodsName }} from your shopping cart?
|
||||
{{ removeProductDescText }}
|
||||
</view>
|
||||
<view class="mt-70rpx">
|
||||
<wd-button @click="confirmRemove" custom-class="!h-108rpx !bg-14181B !text-36rpx !lh-108rpx !text-#fff !rounded-16rpx" block>
|
||||
|
||||
@@ -38,6 +38,9 @@ interface CartItem {
|
||||
merchantDishVo: any;
|
||||
sideDishList: any[];
|
||||
checked: boolean;
|
||||
discountPrice: number;
|
||||
originalPrice: number;
|
||||
memberPrice: number;
|
||||
}
|
||||
|
||||
interface CartMerchant {
|
||||
@@ -66,6 +69,59 @@ const selectedCartItems = computed(() => {
|
||||
});
|
||||
|
||||
const selectedCount = computed(() => selectedCartItems.value.length);
|
||||
const appDisplayName = computed(() => {
|
||||
const name = String((Config as any)?.appName ?? "").trim();
|
||||
return name || "CHEFLINK";
|
||||
});
|
||||
|
||||
function fillI18nParams(template: string, params: Record<string, string | number>) {
|
||||
let text = template;
|
||||
Object.keys(params).forEach((key) => {
|
||||
const value = String(params[key] ?? "");
|
||||
text = text.replace(new RegExp(`\\{${key}\\}`, "g"), value);
|
||||
text = text.replace(new RegExp(`\\$\\{${key}\\}`, "g"), value);
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
function normalizePriceString(val: unknown) {
|
||||
const s = String(val ?? "").trim();
|
||||
if (!/^\d+(\.\d+)?$/.test(s)) return "0";
|
||||
const [intRaw, decRaw = ""] = s.split(".");
|
||||
const intPart = intRaw.replace(/^0+(?=\d)/, "") || "0";
|
||||
const decPart = decRaw.slice(0, 2).padEnd(2, "0");
|
||||
return `${intPart}.${decPart}`;
|
||||
}
|
||||
|
||||
function priceToCentString(val: unknown) {
|
||||
const normalized = normalizePriceString(val);
|
||||
const [intPart, decPart = "00"] = normalized.split(".");
|
||||
return `${intPart}${decPart}`.replace(/^0+(?=\d)/, "") || "0";
|
||||
}
|
||||
|
||||
function formatPriceForView(val: unknown) {
|
||||
const normalized = normalizePriceString(val);
|
||||
return normalized.replace(/\.00$/, "").replace(/(\.\d)0$/, "$1");
|
||||
}
|
||||
|
||||
function getCartLineDisplayPrice(item: CartItem) {
|
||||
// const memberCent = priceToCentString(item?.memberPrice);
|
||||
// console.log('memberCent', memberCent);
|
||||
console.log('item?.memberPrice', item?.memberPrice);
|
||||
console.log(userStore.userInfo.userMembershipVo, 'userStore.isMember');
|
||||
if (userStore.userInfo.userMembershipVo!==null) {
|
||||
return item?.memberPrice;
|
||||
}
|
||||
return item?.discountPrice;
|
||||
}
|
||||
|
||||
function showCartLineOriginalPrice(item: CartItem) {
|
||||
const originalCent = priceToCentString(item?.originalPrice);
|
||||
const currentCent = userStore.userInfo.userMembershipVo!==null && priceToCentString(item?.memberPrice) !== "0"
|
||||
? priceToCentString(item?.memberPrice)
|
||||
: priceToCentString(item?.discountPrice);
|
||||
return originalCent !== "0" && originalCent !== currentCent;
|
||||
}
|
||||
|
||||
const priceData = ref<
|
||||
Record<string, any> & {
|
||||
@@ -100,6 +156,17 @@ const selectedGoodsSubtotal = computed(() => {
|
||||
return total.toFixed(2);
|
||||
});
|
||||
|
||||
const deliveryUnifiedText = computed(() =>
|
||||
fillI18nParams(t("pages-user.cart.deliveryUnified"), { name: appDisplayName.value })
|
||||
);
|
||||
|
||||
const itemsTotalWithPriceText = computed(() =>
|
||||
fillI18nParams(t("pages-user.cart.itemsTotalWithPrice"), {
|
||||
count: priceData.value.totalQuantity ?? selectedItemQty.value,
|
||||
amount: selectedGoodsSubtotal.value,
|
||||
})
|
||||
);
|
||||
|
||||
/** 与地址页、结算页一致:展示用户已保存预约日,无则展示今天(选时间会跳转 reservation-time 并写回接口) */
|
||||
const deliveryScheduleLabel = computed(() => {
|
||||
const ap = userStore.appointmentTime as any;
|
||||
@@ -210,7 +277,7 @@ function confirmRemove() {
|
||||
getCartList();
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "删除成功",
|
||||
title: t("toast.deleteSuccess"),
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -324,23 +391,18 @@ function scheduleCartUpdate(item: CartItem, targetValue: number) {
|
||||
pendingUpdateTimers.set(key, timer);
|
||||
}
|
||||
|
||||
function normalizeInputNumberValue(payload: any): number {
|
||||
if (typeof payload === "number") return payload;
|
||||
if (payload && typeof payload === "object") {
|
||||
if (typeof payload.detail?.value === "number")
|
||||
return payload.detail.value;
|
||||
if (typeof payload.value === "number") return payload.value;
|
||||
}
|
||||
const numeric = Number(payload);
|
||||
return Number.isNaN(numeric) ? 0 : numeric;
|
||||
/** wd-input-number change 为 { value },兼容 detail.value */
|
||||
function normalizeInputNumberValue(payload: unknown): number {
|
||||
const raw =
|
||||
typeof payload === "number"
|
||||
? payload
|
||||
: (payload as any)?.value ?? (payload as any)?.detail?.value ?? payload;
|
||||
const n = Number(raw);
|
||||
return Number.isFinite(n) ? n : 0;
|
||||
}
|
||||
|
||||
const delItemData = ref<CartItem | null>(null);
|
||||
|
||||
function onItemQtyChange(item: CartItem) {
|
||||
return (payload: unknown) => handleQuantityChange(payload, item);
|
||||
}
|
||||
|
||||
function handleQuantityChange(payload: any, item: CartItem) {
|
||||
if (!item) return;
|
||||
const nextValue = normalizeInputNumberValue(payload);
|
||||
@@ -593,9 +655,7 @@ async function getCartList() {
|
||||
t("pages-user.cart.localDelivery")
|
||||
}}</text>
|
||||
<text class="cart-delivery-sub">{{
|
||||
t("pages-user.cart.deliveryUnified", {
|
||||
name: Config.appName,
|
||||
})
|
||||
deliveryUnifiedText
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -607,11 +667,7 @@ async function getCartList() {
|
||||
</view>
|
||||
<view class="cart-price-summary">
|
||||
<text class="cart-summary-line1">{{
|
||||
t("pages-user.cart.itemsTotalWithPrice", {
|
||||
count:
|
||||
priceData.totalQuantity ?? selectedItemQty,
|
||||
amount: selectedGoodsSubtotal,
|
||||
})
|
||||
itemsTotalWithPriceText
|
||||
}}</text>
|
||||
<view
|
||||
v-if="
|
||||
@@ -731,26 +787,22 @@ async function getCartList() {
|
||||
<text class="mr-6rpx">{{
|
||||
dish?.merchantSideDishItemVo?.name || ""
|
||||
}}</text>
|
||||
<text
|
||||
<!-- <text
|
||||
v-if="dish?.merchantSideDishItemVo?.price"
|
||||
class="text-[#00A76D] mr-10rpx"
|
||||
>+${{ dish?.merchantSideDishItemVo?.price }}</text
|
||||
>
|
||||
>${{ dish?.merchantSideDishItemVo?.price }}</text
|
||||
> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="cart-line-price-row">
|
||||
<view class="flex items-baseline flex-wrap">
|
||||
<text class="cart-line-price"
|
||||
>${{ item.merchantDishVo?.discountPrice }}</text
|
||||
>${{ getCartLineDisplayPrice(item) }}</text
|
||||
>
|
||||
<text
|
||||
v-if="
|
||||
item.merchantDishVo?.originalPrice &&
|
||||
item.merchantDishVo?.originalPrice !==
|
||||
item.merchantDishVo?.discountPrice
|
||||
"
|
||||
v-if="showCartLineOriginalPrice(item)"
|
||||
class="cart-line-price-old"
|
||||
>${{ item.merchantDishVo?.originalPrice }}</text
|
||||
>${{ item?.originalPrice }}</text
|
||||
>
|
||||
</view>
|
||||
<wd-input-number
|
||||
@@ -761,7 +813,7 @@ async function getCartList() {
|
||||
:input-width="72"
|
||||
button-size="52"
|
||||
custom-class="cart-qty-input"
|
||||
@change="onItemQtyChange(item)"
|
||||
@change="(e) => handleQuantityChange(e, item)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
@@ -809,12 +861,12 @@ async function getCartList() {
|
||||
<template v-else>
|
||||
<view class="flex flex-col items-center justify-center py-100rpx">
|
||||
<image src="@img/chef/100.png" class="w-318rpx h-318rpx" />
|
||||
<text class="text-32rpx text-[#7D7D7D]">Your cart is empty</text>
|
||||
<text class="text-32rpx text-[#7D7D7D]">{{ t("pages-user.cart.emptyTitle") }}</text>
|
||||
<view
|
||||
class="mt-60rpx w-400rpx h-88rpx rounded-16rpx bg-[#14181B] flex items-center justify-center"
|
||||
@click="goToHome"
|
||||
>
|
||||
<text class="text-30rpx text-white">Explore Restaurants</text>
|
||||
<text class="text-30rpx text-white">{{ t("pages-user.cart.emptyAction") }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -115,20 +115,14 @@ function scheduleCartUpdate(item: MerchantCartVo, targetValue: number) {
|
||||
pendingUpdateTimers.set(key, timer)
|
||||
}
|
||||
|
||||
function normalizeInputNumberValue(payload: any): number {
|
||||
if (typeof payload === 'number') {
|
||||
return payload
|
||||
}
|
||||
if (payload && typeof payload === 'object') {
|
||||
if (typeof payload.detail?.value === 'number') {
|
||||
return payload.detail.value
|
||||
}
|
||||
if (typeof payload.value === 'number') {
|
||||
return payload.value
|
||||
}
|
||||
}
|
||||
const numeric = Number(payload)
|
||||
return Number.isNaN(numeric) ? 0 : numeric
|
||||
/** wd-input-number change 为 { value },兼容 detail.value */
|
||||
function normalizeInputNumberValue(payload: unknown): number {
|
||||
const raw =
|
||||
typeof payload === "number"
|
||||
? payload
|
||||
: (payload as any)?.value ?? (payload as any)?.detail?.value ?? payload;
|
||||
const n = Number(raw);
|
||||
return Number.isFinite(n) ? n : 0;
|
||||
}
|
||||
|
||||
const delItemData = ref<MerchantCartVo | null>(null)
|
||||
@@ -247,6 +241,18 @@ function appMerchantCartCalculateSavings() {
|
||||
})
|
||||
}
|
||||
|
||||
function getCartItemDiscountPrice(item: MerchantCartVo) {
|
||||
return item.discountPrice ?? item.merchantDishVo?.discountPrice
|
||||
}
|
||||
|
||||
function getCartItemOriginalPrice(item: MerchantCartVo) {
|
||||
return item.originalPrice ?? item.merchantDishVo?.originalPrice
|
||||
}
|
||||
|
||||
function getCartItemMemberPrice(item: MerchantCartVo) {
|
||||
return item.memberPrice ?? item.merchantDishVo?.memberPrice
|
||||
}
|
||||
|
||||
function navigateTo(url: string) {
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
@@ -301,21 +307,21 @@ function navigateTo(url: string) {
|
||||
|
||||
<view class="price-row flex items-center mt-18rpx">
|
||||
<text class="current-price text-[#333333] text-30rpx font-normal"
|
||||
>${{ item.merchantDishVo.discountPrice }}</text
|
||||
>${{ getCartItemDiscountPrice(item) }}</text
|
||||
>
|
||||
<text
|
||||
v-if="item.merchantDishVo.originalPrice"
|
||||
v-if="getCartItemOriginalPrice(item)"
|
||||
class="original-price text-[#7D7D7D] text-24rpx font-normal line-through ml-10rpx"
|
||||
>${{ item.merchantDishVo.originalPrice }}</text
|
||||
>${{ getCartItemOriginalPrice(item) }}</text
|
||||
>
|
||||
|
||||
<!-- 会员价标签 -->
|
||||
<view
|
||||
v-if="Number(item.merchantDishVo.memberPrice) > 0"
|
||||
v-if="Number(getCartItemMemberPrice(item)) > 0"
|
||||
class="member-price-tag ml-10rpx center pl-16rpx pr-6rpx pb-2rpx"
|
||||
>
|
||||
<text class="text-[#FBE3C3] text-20rpx"
|
||||
>{{ t('pages-store.store.members') }}: ${{ item.merchantDishVo.memberPrice }}</text
|
||||
>{{ t('pages-store.store.members') }}: ${{ getCartItemMemberPrice(item) }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
Reference in New Issue
Block a user