登录页面
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import Taro, { usePageScroll, useRouter } from '@tarojs/taro';
|
||||
import type { ProductDetailContentDto } from '@dukang/shared-types';
|
||||
import PageShell from '../../components/PageShell';
|
||||
import PageNavBar from '../../components/PageNavBar';
|
||||
import ProductCarousel from '../../components/ProductCarousel';
|
||||
import { request, toast } from '../../lib/api';
|
||||
import {
|
||||
getProductCarouselImages,
|
||||
getProductDetailImages,
|
||||
type ProductImageSource,
|
||||
} from '../../lib/product-images';
|
||||
import iconHome from '../../assets/tabbar/home.png';
|
||||
|
||||
type Product = ProductImageSource & {
|
||||
id: string;
|
||||
name: string;
|
||||
subtitle?: string | null;
|
||||
price: number;
|
||||
benefitAmount?: number;
|
||||
benefitDisplay?: number;
|
||||
detailContent?: ProductDetailContentDto | null;
|
||||
};
|
||||
|
||||
export default function ProductDetailPage() {
|
||||
const router = useRouter();
|
||||
const productId = router.params.id ?? '';
|
||||
const [product, setProduct] = useState<Product | null>(null);
|
||||
const [headerSolid, setHeaderSolid] = useState(false);
|
||||
|
||||
usePageScroll(({ scrollTop }) => {
|
||||
setHeaderSolid(scrollTop > 100);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!productId) return;
|
||||
request<Product>(`/catalog/products/${productId}`)
|
||||
.then(setProduct)
|
||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
||||
}, [productId]);
|
||||
|
||||
function goBack() {
|
||||
const pages = Taro.getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
Taro.navigateBack();
|
||||
return;
|
||||
}
|
||||
Taro.switchTab({ url: '/pages/home/index' });
|
||||
}
|
||||
|
||||
function goHome() {
|
||||
Taro.switchTab({ url: '/pages/home/index' });
|
||||
}
|
||||
|
||||
function goBuy() {
|
||||
if (!productId) return;
|
||||
Taro.navigateTo({ url: `/pages/order-confirm/index?productId=${productId}&qty=2` });
|
||||
}
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<PageShell variant="scroll" className="product-detail-page">
|
||||
<PageNavBar title="商品详情" solid onBack={goBack} />
|
||||
<View className="page-with-nav-bar u-empty">加载中…</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
const benefit = Number(product.benefitDisplay ?? product.benefitAmount ?? product.price);
|
||||
const carouselImages = getProductCarouselImages(product);
|
||||
const detailImages = getProductDetailImages(product);
|
||||
const detail = product.detailContent ?? {};
|
||||
const features = detail.features ?? [];
|
||||
|
||||
return (
|
||||
<PageShell variant="scroll" className="product-detail-page" hasFixedFooter>
|
||||
<PageNavBar
|
||||
title={product.name}
|
||||
solid={headerSolid}
|
||||
titleVisible={headerSolid}
|
||||
onBack={goBack}
|
||||
right={(
|
||||
<View className="page-nav-bar__btn" onClick={() => toast('分享功能开发中')}>
|
||||
<Text className="page-nav-bar__icon page-nav-bar__icon--share">⤴</Text>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
|
||||
<View className="product-detail-main">
|
||||
<View className="product-detail-hero full-bleed">
|
||||
<ProductCarousel images={carouselImages} alt={product.name} variant="detail" />
|
||||
</View>
|
||||
|
||||
<View className="product-detail-info">
|
||||
<View className="product-detail-price">
|
||||
<Text className="product-detail-price-symbol">¥</Text>
|
||||
<Text className="product-detail-price-value">{Number(product.price).toFixed(2)}</Text>
|
||||
</View>
|
||||
<Text className="product-detail-name">{product.name}</Text>
|
||||
{product.subtitle ? (
|
||||
<Text className="product-detail-subtitle">{product.subtitle}</Text>
|
||||
) : null}
|
||||
|
||||
<View className="product-detail-promo">
|
||||
<View className="product-detail-promo-glow" />
|
||||
<View className="product-detail-promo-head">
|
||||
<View className="product-detail-promo-icon">
|
||||
<Text className="product-detail-promo-icon-text">惠</Text>
|
||||
</View>
|
||||
<Text className="product-detail-promo-title">
|
||||
买杜康美酒 · 享全城好客礼遇
|
||||
<Text className="product-detail-promo-amount"> ¥{benefit}</Text>
|
||||
</Text>
|
||||
</View>
|
||||
<Text className="product-detail-promo-desc">
|
||||
购酒即享本城专属好客权益,为您安排一场地道饭局。权益金可直接用于本地签约门店消费,到店享用,醇香美酒配佳肴。
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="product-detail-content">
|
||||
<View className="product-detail-section-head">
|
||||
<View className="product-detail-section-bar" />
|
||||
<Text className="product-detail-section-title">商品详情</Text>
|
||||
</View>
|
||||
|
||||
{detailImages.map((src, index) => (
|
||||
<Image
|
||||
key={`${src}-${index}`}
|
||||
className="product-detail-banner full-bleed"
|
||||
src={src}
|
||||
mode="widthFix"
|
||||
/>
|
||||
))}
|
||||
|
||||
{(detail.storyTitle || detail.storyText || features.length > 0) ? (
|
||||
<View className="product-detail-copy">
|
||||
{(detail.storyTitle || detail.storyText) ? (
|
||||
<View className="product-detail-story">
|
||||
{detail.storyTitle ? (
|
||||
<Text className="product-detail-story-title">{detail.storyTitle}</Text>
|
||||
) : null}
|
||||
{detail.storyText ? (
|
||||
<Text className="product-detail-story-text">{detail.storyText}</Text>
|
||||
) : null}
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{features.length > 0 ? (
|
||||
<View className="product-detail-features">
|
||||
{features.map((f) => (
|
||||
<View key={`${f.title}-${f.icon}`} className="product-detail-feature">
|
||||
<Text className="product-detail-feature-icon">★</Text>
|
||||
<Text className="product-detail-feature-title">{f.title}</Text>
|
||||
<Text className="product-detail-feature-desc">{f.desc}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="product-detail-bar">
|
||||
<View className="product-detail-bar-home" onClick={goHome}>
|
||||
<Image className="product-detail-bar-home-icon" src={iconHome} mode="aspectFit" />
|
||||
<Text className="product-detail-bar-home-label">首页</Text>
|
||||
</View>
|
||||
<View className="product-detail-buy-btn" onClick={goBuy}>
|
||||
<Text className="product-detail-buy-btn-text">立即购买</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user