fix(mini-user): 门店核销走马灯改用 JS 位移

微信端 CSS max-content/百分比 transform 不可靠;改为测量宽度后 translateX 滚动,并上移到店名下方。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 14:33:31 +08:00
parent fd05621660
commit 021b9e0329
4 changed files with 142 additions and 45 deletions
@@ -12,6 +12,7 @@ import PageShell from '../../components/PageShell';
import PageNavBar from '../../components/PageNavBar';
import ProductCarousel from '../../components/ProductCarousel';
import ShareNavButton from '../../components/ShareNavButton';
import StoreRedeemMarquee from '../../components/StoreRedeemMarquee';
import WechatShareReady from '../../components/WechatShareReady';
import { request, toast } from '../../lib/api';
import {
@@ -54,6 +55,7 @@ type RecentRedeem = {
userLabel: string;
amount: number | string;
createdAt: string;
text?: string;
};
function uniqueUrls(urls: Array<string | null | undefined>) {
@@ -119,6 +121,7 @@ function formatRedeemAmountYuan(amount: number | string) {
}
function formatRecentRedeemLine(row: RecentRedeem) {
if (row.text?.trim()) return row.text.trim();
return `${row.userLabel || '用户***'} ${formatRedeemTime(row.createdAt)} 核销${formatRedeemAmountYuan(row.amount)}`;
}
@@ -234,10 +237,10 @@ export default function StoreDetailPage() {
[store, storeId],
);
const marqueeText = useMemo(() => {
if (!recentRedeems.length) return '';
return recentRedeems.map(formatRecentRedeemLine).join('  ');
}, [recentRedeems]);
const marqueeLines = useMemo(
() => recentRedeems.map(formatRecentRedeemLine).filter(Boolean),
[recentRedeems],
);
useShareAppMessage(() => toWeappShareMessage(sharePayload));
useShareTimeline(() => ({
@@ -321,8 +324,6 @@ export default function StoreDetailPage() {
}).catch(() => toast('无法预览图片'));
}
const marqueeDurationSec = Math.max(18, Math.min(60, Math.round((marqueeText.length || 24) / 2.2)));
return (
<PageShell variant="scroll" className="store-detail-page" hasFixedFooter>
<WechatShareReady payload={sharePayload} />
@@ -341,6 +342,8 @@ export default function StoreDetailPage() {
<View className="store-detail-info-card">
<Text className="store-detail-name">{store.name}</Text>
{marqueeLines.length > 0 ? <StoreRedeemMarquee lines={marqueeLines} /> : null}
<View className="store-detail-row">
<Text className="store-detail-meta store-detail-meta--flex">
{store.district ? `${store.district} · ` : ''}
@@ -382,20 +385,6 @@ export default function StoreDetailPage() {
</View>
</View>
{marqueeText ? (
<View className="store-detail-marquee">
<View
className="store-detail-marquee-track"
style={{
animationDuration: `${marqueeDurationSec}s`,
}}
>
<View className="store-detail-marquee-item">{marqueeText}</View>
<View className="store-detail-marquee-item">{marqueeText}</View>
</View>
</View>
) : null}
{intro ? (
<View className="store-detail-section">
<Text className="store-detail-section-title"></Text>