feat(v3.4.14): mini-user store UX, brand config, client settings
Store list/detail package flow, configurable WeChat mini brand assets and customer service, shop H5 home refresh. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { View, Text, Image, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import Taro, {
|
||||
useDidShow,
|
||||
useLoad,
|
||||
@@ -156,14 +156,9 @@ export default function StoreDetailPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [loadError, setLoadError] = useState('');
|
||||
const [headerSolid, setHeaderSolid] = useState(false);
|
||||
const [activePackageIndex, setActivePackageIndex] = useState(0);
|
||||
const storeRef = useRef<Store | null>(null);
|
||||
storeRef.current = store;
|
||||
|
||||
useEffect(() => {
|
||||
setActivePackageIndex(0);
|
||||
}, [store?.id]);
|
||||
|
||||
usePageScroll(({ scrollTop }) => {
|
||||
setHeaderSolid(scrollTop > 100);
|
||||
});
|
||||
@@ -326,13 +321,18 @@ export default function StoreDetailPage() {
|
||||
const envPhotos = envPhotoUrls(store);
|
||||
const heroImages = uniqueUrls([store.coverUrl, ...(store.carouselUrls || [])]);
|
||||
const packages = store.packages ?? [];
|
||||
const activePackage = packages[activePackageIndex] ?? packages[0];
|
||||
|
||||
const intro = store.intro?.trim() || '';
|
||||
const benefitRuleRaw = store.benefitUsageRule?.trim() || '';
|
||||
const benefitRule =
|
||||
benefitRuleRaw && !/^null$/i.test(benefitRuleRaw) ? benefitRuleRaw : '';
|
||||
|
||||
function openPackageDetail(index: number) {
|
||||
Taro.navigateTo({
|
||||
url: `/pages/store-package-detail/index?storeId=${storeId}&index=${index}`,
|
||||
});
|
||||
}
|
||||
|
||||
function previewEnv(index: number) {
|
||||
if (!envPhotos.length) return;
|
||||
Taro.previewImage({
|
||||
@@ -353,7 +353,13 @@ export default function StoreDetailPage() {
|
||||
/>
|
||||
|
||||
<View className="store-detail-hero full-bleed">
|
||||
<ProductCarousel images={heroImages} alt={store.name} variant="store" previewable />
|
||||
<ProductCarousel
|
||||
images={heroImages}
|
||||
alt={store.name}
|
||||
variant="store"
|
||||
previewable
|
||||
imageFit="contain"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View className="store-detail-info-card">
|
||||
@@ -408,48 +414,19 @@ export default function StoreDetailPage() {
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{packages.length > 0 && activePackage ? (
|
||||
{packages.length > 0 ? (
|
||||
<View className="store-detail-section store-detail-section--packages">
|
||||
<Text className="store-detail-section-title">门店套餐</Text>
|
||||
{packages.length > 1 ? (
|
||||
<ScrollView className="store-detail-package-tabs" scrollX showScrollbar={false} enhanced>
|
||||
<View className="store-detail-package-tabs-inner">
|
||||
{packages.map((pkg, index) => (
|
||||
<View
|
||||
key={`${pkg.name}-${index}`}
|
||||
className={`store-detail-package-tab${
|
||||
index === activePackageIndex ? ' store-detail-package-tab--active' : ''
|
||||
}`}
|
||||
onClick={() => setActivePackageIndex(index)}
|
||||
>
|
||||
<Text className="store-detail-package-tab-text">{pkg.name}</Text>
|
||||
</View>
|
||||
))}
|
||||
<View className="store-detail-package-list">
|
||||
{packages.map((pkg, index) => (
|
||||
<View
|
||||
key={`${pkg.name}-${index}`}
|
||||
className="store-detail-package-list-item"
|
||||
onClick={() => openPackageDetail(index)}
|
||||
>
|
||||
<Text className="store-detail-package-list-title">{pkg.name}</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
) : null}
|
||||
<View className="store-detail-package-panel">
|
||||
{activePackage.imageUrl ? (
|
||||
<Image
|
||||
className="store-detail-package-thumb"
|
||||
src={activePackage.imageUrl}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
) : null}
|
||||
<View className="store-detail-package-panel-body">
|
||||
{packages.length === 1 ? (
|
||||
<Text className="store-detail-package-name">{activePackage.name}</Text>
|
||||
) : null}
|
||||
<Text className="store-detail-package-body">
|
||||
{formatRedeemAmountYuan(activePackage.price)} 元 · {activePackage.dishes}
|
||||
</Text>
|
||||
{activePackage.usableTime ? (
|
||||
<Text className="store-detail-package-meta">使用时间:{activePackage.usableTime}</Text>
|
||||
) : null}
|
||||
{activePackage.otherNotes ? (
|
||||
<Text className="store-detail-package-meta">说明:{activePackage.otherNotes}</Text>
|
||||
) : null}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user