商品只支持现场提货的功能修改
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
/** 商品履约能力(与 HQ / 交易硬闸一致) */
|
||||||
|
|
||||||
|
export type FulfillmentFlags = {
|
||||||
|
allowOnlinePurchase?: boolean | null;
|
||||||
|
allowOnSitePickup?: boolean | null;
|
||||||
|
allowCrossCityDelivery?: boolean | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 未返回时默认允许线上(存量商品) */
|
||||||
|
export function canBuyOnline(p: FulfillmentFlags): boolean {
|
||||||
|
return p.allowOnlinePurchase !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 仅显式开启才展示现场取货 */
|
||||||
|
export function canPickupOnSite(p: FulfillmentFlags): boolean {
|
||||||
|
return p.allowOnSitePickup === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canCrossCity(p: FulfillmentFlags): boolean {
|
||||||
|
return p.allowCrossCityDelivery !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeFulfillmentFlags<T extends FulfillmentFlags>(p: T): T {
|
||||||
|
return {
|
||||||
|
...p,
|
||||||
|
allowOnlinePurchase: canBuyOnline(p),
|
||||||
|
allowOnSitePickup: canPickupOnSite(p),
|
||||||
|
allowCrossCityDelivery: canCrossCity(p),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -17,6 +17,12 @@ import { isLoggedIn, request, toast } from '../../lib/api';
|
|||||||
import { ensurePayReady } from '../../lib/pay-ready';
|
import { ensurePayReady } from '../../lib/pay-ready';
|
||||||
import { capturePromoSceneAndTouchScan } from '../../lib/promo';
|
import { capturePromoSceneAndTouchScan } from '../../lib/promo';
|
||||||
import { getProductMainImage } from '../../lib/product-images';
|
import { getProductMainImage } from '../../lib/product-images';
|
||||||
|
import {
|
||||||
|
canBuyOnline,
|
||||||
|
canCrossCity,
|
||||||
|
canPickupOnSite,
|
||||||
|
normalizeFulfillmentFlags,
|
||||||
|
} from '../../lib/product-fulfillment';
|
||||||
import { getCityCodeForCatalog, resolveUserCity } from '../../lib/user-location';
|
import { getCityCodeForCatalog, resolveUserCity } from '../../lib/user-location';
|
||||||
import {
|
import {
|
||||||
DEFAULT_SHARE_DESC,
|
DEFAULT_SHARE_DESC,
|
||||||
@@ -50,9 +56,9 @@ const FULFILLMENT_FILTERS: Array<{ key: FulfillmentFilter; label: string }> = [
|
|||||||
|
|
||||||
function matchFulfillmentFilter(p: Product, filter: FulfillmentFilter): boolean {
|
function matchFulfillmentFilter(p: Product, filter: FulfillmentFilter): boolean {
|
||||||
if (filter === 'ALL') return true;
|
if (filter === 'ALL') return true;
|
||||||
if (filter === 'ONLINE') return p.allowOnlinePurchase !== false;
|
if (filter === 'ONLINE') return canBuyOnline(p);
|
||||||
if (filter === 'CROSS_CITY') return p.allowCrossCityDelivery !== false;
|
if (filter === 'CROSS_CITY') return canCrossCity(p);
|
||||||
return !!p.allowOnSitePickup;
|
return canPickupOnSite(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
type MiniHomeConfig = {
|
type MiniHomeConfig = {
|
||||||
@@ -117,7 +123,9 @@ export default function HomePage() {
|
|||||||
const loadProducts = useCallback(() => {
|
const loadProducts = useCallback(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
return request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(cityCode)}`)
|
return request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(cityCode)}`)
|
||||||
.then((list) => setProducts(Array.isArray(list) ? list : []))
|
.then((list) =>
|
||||||
|
setProducts(Array.isArray(list) ? list.map((p) => normalizeFulfillmentFlags(p)) : []),
|
||||||
|
)
|
||||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
|
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}, [cityCode]);
|
}, [cityCode]);
|
||||||
@@ -138,7 +146,7 @@ export default function HomePage() {
|
|||||||
request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(nextCode)}`),
|
request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(nextCode)}`),
|
||||||
loadMiniHome(),
|
loadMiniHome(),
|
||||||
]);
|
]);
|
||||||
setProducts(Array.isArray(list) ? list : []);
|
setProducts(Array.isArray(list) ? list.map((p) => normalizeFulfillmentFlags(p)) : []);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast(e instanceof Error ? e.message : '加载失败');
|
toast(e instanceof Error ? e.message : '加载失败');
|
||||||
} finally {
|
} finally {
|
||||||
@@ -268,7 +276,7 @@ export default function HomePage() {
|
|||||||
<CouponBadge amount={p.benefitDisplay ?? p.price} label="好客权益" />
|
<CouponBadge amount={p.benefitDisplay ?? p.price} label="好客权益" />
|
||||||
</View>
|
</View>
|
||||||
<View className="home-product-actions">
|
<View className="home-product-actions">
|
||||||
{p.allowOnSitePickup ? (
|
{canPickupOnSite(p) ? (
|
||||||
<Text
|
<Text
|
||||||
className="home-pickup-btn"
|
className="home-pickup-btn"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@@ -279,7 +287,7 @@ export default function HomePage() {
|
|||||||
现场取货
|
现场取货
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
{p.allowOnlinePurchase !== false ? (
|
{canBuyOnline(p) ? (
|
||||||
<Text
|
<Text
|
||||||
className="home-buy-btn"
|
className="home-buy-btn"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ import {
|
|||||||
getProductMainImage,
|
getProductMainImage,
|
||||||
type ProductImageSource,
|
type ProductImageSource,
|
||||||
} from '../../lib/product-images';
|
} from '../../lib/product-images';
|
||||||
|
import {
|
||||||
|
canBuyOnline,
|
||||||
|
canPickupOnSite,
|
||||||
|
normalizeFulfillmentFlags,
|
||||||
|
} from '../../lib/product-fulfillment';
|
||||||
import {
|
import {
|
||||||
DEFAULT_SHARE_DESC,
|
DEFAULT_SHARE_DESC,
|
||||||
DEFAULT_SHARE_TITLE,
|
DEFAULT_SHARE_TITLE,
|
||||||
@@ -49,7 +54,7 @@ export default function ProductDetailPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!productId) return;
|
if (!productId) return;
|
||||||
request<Product>(`/catalog/products/${productId}`)
|
request<Product>(`/catalog/products/${productId}`)
|
||||||
.then(setProduct)
|
.then((p) => setProduct(normalizeFulfillmentFlags(p)))
|
||||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
||||||
}, [productId]);
|
}, [productId]);
|
||||||
|
|
||||||
@@ -107,9 +112,6 @@ export default function ProductDetailPage() {
|
|||||||
Taro.navigateTo({ url: returnPath });
|
Taro.navigateTo({ url: returnPath });
|
||||||
}
|
}
|
||||||
|
|
||||||
const allowOnline = product?.allowOnlinePurchase !== false;
|
|
||||||
const allowOnSite = !!product?.allowOnSitePickup;
|
|
||||||
|
|
||||||
if (!product) {
|
if (!product) {
|
||||||
return (
|
return (
|
||||||
<PageShell variant="scroll" className="product-detail-page">
|
<PageShell variant="scroll" className="product-detail-page">
|
||||||
@@ -119,6 +121,8 @@ export default function ProductDetailPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const allowOnline = canBuyOnline(product);
|
||||||
|
const allowOnSite = canPickupOnSite(product);
|
||||||
const benefit = Number(product.benefitDisplay ?? product.benefitAmount ?? product.price);
|
const benefit = Number(product.benefitDisplay ?? product.benefitAmount ?? product.price);
|
||||||
const carouselImages = getProductCarouselImages(product);
|
const carouselImages = getProductCarouselImages(product);
|
||||||
const detailImages = getProductDetailImages(product);
|
const detailImages = getProductDetailImages(product);
|
||||||
|
|||||||
Reference in New Issue
Block a user