feat(vip): skeleton loading state and faster modal/site startup

The VIP purchase/renew modal opened with a single "loading..." line, which
reads as a hang while /pay/vip/modal round-trips. Every frontend pageview
also paid an option write inside wp_head, and the header user-card CSS was
enqueued even for guests who never see the card.

pay-vip.js now builds a full-layout skeleton (user box, level tabs, the
two-column package panel) from vipSkeleton(), reusing the global
aksrt-modal-runtime__skeleton line/block classes; the VIP-specific shapes
live in the conditionally loaded vip-modal.css, and the 640px two-column
threshold matches .pay-vip-form-row. The modal cache TTL goes 15s -> 60s
(purchase, card-pass redeem and points exchange already invalidate the
vip tag), and hover/focus on a .pay-vip trigger now prefetches the payload
through the same cacheKey and flight openRemote uses, so a warm click
opens instantly.

The bottom note and the whole help_text pipeline behind it are removed; the
admin-editable pay_user_vip_desc still renders at the top of the modal, and
the recharge/gateway help_text keys are untouched. get_catalog() reads
points and wallet balance through one new LedgerService::points_and_balance()
call. The StatsTracker counter write moves to shutdown so wp_head only does
the visitor check and setcookie, and header-userbox.css is enqueued for
logged-in users only.

Verification: node --test across the suite (628 tests, including the 7 new
contract assertions in tests/widget-system/vip-modal-skeleton.test.cjs) and
php -l on every changed PHP file. No visual acceptance performed, per request.
This commit is contained in:
kate522 committed 2026-10-18 13:44:01 +08:00
1 parent 319ec2f47f
commit cb76b95b01
9 files changed
+376 -13

No files matched your search

-1
View File
@@ -115,7 +115,6 @@ trait VipServiceModal {
'prefer_level' => $prefer_level,
'catalog' => [
'desc' => (string) ($catalog['desc'] ?? ''),
'help_text' => (string) ($catalog['help_text'] ?? ''),
'more' => (string) ($vip['more'] ?? ''),
'currency_name' => (string) ($catalog['currency_name'] ?? ''),
'level_packages' => $groups,