v3.5.3版本更新1
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-08-20 18:54:15 +08:00
parent ee493823bf
commit fc2e5b65de
65 changed files with 2297 additions and 875 deletions
@@ -0,0 +1,27 @@
import { Image, Text, View } from '@tarojs/components';
import iconStoreBenefit from '../assets/icons/store-benefit.png';
type BenefitFigureSize = 'sm' | 'md' | 'lg' | 'xl';
type BenefitFigureProps = {
value: string;
size?: BenefitFigureSize;
prefix?: string;
className?: string;
};
/** 好客权益金额:门店核销图标 + 数字,替代人民币符号 */
export default function BenefitFigure({
value,
size = 'md',
prefix = '',
className = '',
}: BenefitFigureProps) {
return (
<View className={`benefit-figure benefit-figure--${size} ${className}`.trim()}>
{prefix ? <Text className="benefit-figure-prefix">{prefix}</Text> : null}
<Image className="benefit-figure-icon" src={iconStoreBenefit} mode="aspectFit" />
<Text className="benefit-figure-value">{value}</Text>
</View>
);
}
@@ -1,4 +1,5 @@
import { Text } from '@tarojs/components';
import { Text, View } from '@tarojs/components';
import BenefitFigure from './BenefitFigure';
type CouponBadgeProps = {
amount: number | string;
@@ -10,8 +11,9 @@ export default function CouponBadge({ amount, label = '好客权益' }: CouponBa
const n = Number(amount);
const display = Number.isFinite(n) ? (Number.isInteger(n) ? String(n) : n.toFixed(0)) : String(amount);
return (
<Text className="coupon-badge">
¥{display} {label}
</Text>
<View className="coupon-badge">
<Text></Text>
<BenefitFigure value={`${display} ${label}`} size="sm" />
</View>
);
}
@@ -0,0 +1,32 @@
import { useEffect, useRef, useState } from 'react';
import { CoverView, View } from '@tarojs/components';
import { registerFloatingToastListener } from '../lib/floating-toast';
const TOAST_MS = 2600;
export default function FloatingToastHost() {
const [text, setText] = useState('');
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
return registerFloatingToastListener((message) => {
if (timerRef.current) clearTimeout(timerRef.current);
setText(message);
timerRef.current = setTimeout(() => {
setText('');
timerRef.current = null;
}, TOAST_MS);
});
}, []);
useEffect(() => {
return () => {
if (timerRef.current) clearTimeout(timerRef.current);
};
}, []);
if (!text) return null;
const Box = process.env.TARO_ENV === 'weapp' ? CoverView : View;
return <Box className="mu-float-toast">{text}</Box>;
}
@@ -1,5 +1,6 @@
import type { PropsWithChildren, ReactNode } from 'react';
import { View } from '@tarojs/components';
import FloatingToastHost from './FloatingToastHost';
import { pageShellCssVars, useNavBarMetrics } from '../lib/nav-bar';
type PageShellVariant = 'tab' | 'scroll' | 'sub' | 'plain';
@@ -35,6 +36,7 @@ export default function PageShell({
return (
<View className={classes} style={pageShellCssVars(metrics)}>
{children as ReactNode}
<FloatingToastHost />
</View>
);
}
@@ -14,6 +14,8 @@ type ProductCarouselProps = {
* 依赖 swiper 原生 auto-height:海报有多高,轮播就有多高,无裁切。
*/
imageFit?: 'cover' | 'contain' | 'adaptive';
/** 预览相册(默认等于 images);门店详情可传入封面+环境图合并列表 */
previewUrls?: string[];
};
/** 商品/门店轮播(对齐 h5 ProductCarousel 三变体) */
@@ -23,6 +25,7 @@ export default function ProductCarousel({
variant = 'detail',
previewable = false,
imageFit = 'cover',
previewUrls,
}: ProductCarouselProps) {
const slides = images.length > 0 ? images : [''];
const [activeIndex, setActiveIndex] = useState(0);
@@ -33,10 +36,10 @@ export default function ProductCarousel({
const wrapClass = `${prefix}-wrap${isContain ? ` ${prefix}-wrap--contain` : ''}${isAdaptive ? ` ${prefix}-wrap--adaptive` : ''}`;
function previewAt(index: number) {
const urls = slides.filter(Boolean);
if (!urls.length) return;
const current = slides[index] || urls[0];
Taro.previewImage({ current, urls }).catch(() => undefined);
const album = (previewUrls?.length ? previewUrls : slides).filter(Boolean);
if (!album.length) return;
const current = slides[index] || album[0];
Taro.previewImage({ current, urls: album }).catch(() => undefined);
}
return (