feat(release): v3.4.13 experience optimizations across admin, mini-user, and H5 login

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-05 22:34:29 +08:00
parent 490c26a7e1
commit 1c4b986924
29 changed files with 617 additions and 23 deletions
@@ -15,6 +15,8 @@ import ShareNavButton from '../../components/ShareNavButton';
import StoreRedeemMarquee from '../../components/StoreRedeemMarquee';
import WechatShareReady from '../../components/WechatShareReady';
import { request, toast } from '../../lib/api';
import { maskPhone } from '../../lib/phone';
import { track } from '../../lib/analytics';
import { formatShanghaiDateTime } from '../../lib/datetime';
import {
DEFAULT_SHARE_DESC,
@@ -154,6 +156,7 @@ export default function StoreDetailPage() {
const [loading, setLoading] = useState(true);
const [loadError, setLoadError] = useState('');
const [headerSolid, setHeaderSolid] = useState(false);
const [expandedPackages, setExpandedPackages] = useState<Record<number, boolean>>({});
const storeRef = useRef<Store | null>(null);
storeRef.current = store;
@@ -271,6 +274,7 @@ export default function StoreDetailPage() {
toast('暂无门店电话');
return;
}
track('store_phone_call', { storeId: store.id });
Taro.makePhoneCall({ phoneNumber: store.phone }).catch(() => toast('无法拨打电话'));
}
@@ -374,7 +378,9 @@ export default function StoreDetailPage() {
{store.phone ? (
<View className="store-detail-row">
<Text className="store-detail-meta store-detail-meta--flex">: {store.phone}</Text>
<Text className="store-detail-meta store-detail-meta--flex">
: {maskPhone(store.phone)}
</Text>
<Text className="store-detail-action" onClick={callStore}>
</Text>
@@ -399,15 +405,32 @@ export default function StoreDetailPage() {
{store.packages && store.packages.length > 0 ? (
<View className="store-detail-section">
<Text className="store-detail-section-title"></Text>
{store.packages.map((pkg, index) => (
<View key={`${pkg.name}-${index}`} className="store-detail-package-card">
{store.packages.map((pkg, index) => {
const expanded = !!expandedPackages[index];
const bodyText = `${formatRedeemAmountYuan(pkg.price)} 元 · ${pkg.dishes}`;
const longBody = bodyText.length > 48 || (pkg.otherNotes?.length ?? 0) > 40;
return (
<View
key={`${pkg.name}-${index}`}
className={`store-detail-package-card${expanded || !longBody ? '' : ' store-detail-package-card--collapsed'}`}
>
{pkg.imageUrl ? (
<Image className="store-detail-package-img" src={pkg.imageUrl} mode="aspectFill" />
) : null}
<Text className="store-detail-package-name">{pkg.name}</Text>
<Text className="store-detail-package-body">
{formatRedeemAmountYuan(pkg.price)} · {pkg.dishes}
</Text>
<View className="store-detail-package-head">
<Text className="store-detail-package-name">{pkg.name}</Text>
{longBody ? (
<Text
className="store-detail-package-toggle"
onClick={() =>
setExpandedPackages((prev) => ({ ...prev, [index]: !prev[index] }))
}
>
{expanded ? '收起' : '展开'}
</Text>
) : null}
</View>
<Text className="store-detail-package-body">{bodyText}</Text>
{pkg.usableTime ? (
<Text className="store-detail-package-meta">使{pkg.usableTime}</Text>
) : null}
@@ -415,7 +438,8 @@ export default function StoreDetailPage() {
<Text className="store-detail-package-meta">{pkg.otherNotes}</Text>
) : null}
</View>
))}
);
})}
</View>
) : null}