fix(vip): 积分兑换弹窗改服务端渲染并与 Zibll 1:1 对齐
/user/vip/ 的积分兑换会员弹窗原先是前端自行拼装的,结构与层级都与参考主题
Zibll 不一致:Zibll 走 zibpay_get_vip_points_exchange_modal() 服务端渲染静态
壳,前端只按需开合。改为同一模型,前端不再拼 HTML。
- VipServiceModal 新增 get_points_exchange_modal_html():门控(未登录/未开启
返回空串)、vip-card 套餐选择、积分不足提示与提交表单;wp_footer 挂载输出
- pay-vip.js 移除 renderPointsModal / pointsPackage / exchangeFromModal /
vipPointsPay,改为自包含开合(.in + 内联 display:flex + 独立遮罩 +
body.modal-open + ESC),保留 aksrt-vip-points-toast 的 load/success/danger 契约
- 移除 /user/vip/ 页面底部独立积分兑换入口及其样式(uc-vip-points-link)
- credits.js 清理依赖全站不存在选择器的死代码 initVipPointsExchange()
- vip-modal.css 删除 71 行自实现样式,改为 .modal[data-aksrt-vip-points-modal]
显隐契约;层级 100050 < 遮罩 100055 < 弹窗 100060 < notyf 10000000
- 新增 vip-points-exchange-modal 契约测试(7 项),toast-contract 同步
静止态必须显式 display:none,否则 .flex{display:flex} 会覆盖 .modal{display:none}
形成隐形遮罩拦截整页点击。
未写数据迁移。
验证:node --test tests/widget-system/*.test.cjs 308 项全部通过;php -l 全部
改动文件通过;隔离渲染桩确认积分充足 / 积分不足 / 功能关闭 / 未登录四种情形
的 HTML 产物正确。
This commit is contained in:
@@ -503,3 +503,27 @@ if (!function_exists('aksrt_format_vip_equity_html')) {
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局积分兑换会员弹窗(参考主题 refresh_modal 同构静态壳)。
|
||||
*
|
||||
* 入口位于会员购买弹窗(.pay-vip → assets/js/pay-vip.js)内,而 .pay-vip
|
||||
* 触发点全站可见(页头、浮动按钮、用户中心、付费卡),因此弹窗壳在满足
|
||||
* 条件时随 wp_footer 全局输出一次;显隐由 pay-vip.js 自包含开关驱动,
|
||||
* 静止态由 vip-modal.css 的 .modal[data-aksrt-vip-points-modal] 显式隐藏。
|
||||
*/
|
||||
if (!function_exists('aksrt_render_vip_points_exchange_modal')) :
|
||||
function aksrt_render_vip_points_exchange_modal(): void {
|
||||
if (!is_user_logged_in() || !class_exists('\AKSRT\Content\VipService')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$html = \AKSRT\Content\VipService::get_instance()->get_points_exchange_modal_html(get_current_user_id());
|
||||
if ($html === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 各字段已在生成时转义。
|
||||
}
|
||||
endif;
|
||||
add_action('wp_footer', 'aksrt_render_vip_points_exchange_modal');
|
||||
|
||||
@@ -21,15 +21,6 @@ if (empty($vip_settings['enabled'])) {
|
||||
$user_id = (int) ($user_id ?? get_current_user_id());
|
||||
$vip_state = function_exists('aksrt_get_user_vip_state') ? aksrt_get_user_vip_state($user_id) : [];
|
||||
$level = (int) ($vip_state['level'] ?? 0);
|
||||
$points_exchange = [];
|
||||
$user_points = 0;
|
||||
$currency_name = __('积分', 'aksrt');
|
||||
if (class_exists('\\AKSRT\\Content\\VipService')) {
|
||||
$vip_catalog = \AKSRT\Content\VipService::get_instance()->get_catalog($user_id);
|
||||
$points_exchange = is_array($vip_catalog['points_exchange'] ?? null) ? $vip_catalog['points_exchange'] : [];
|
||||
$user_points = (int) ($vip_catalog['user_points'] ?? 0);
|
||||
$currency_name = (string) ($vip_catalog['currency_name'] ?? $currency_name);
|
||||
}
|
||||
$expires = max(0, (int) ($vip_state['current_expires'] ?? $vip_state['expires'] ?? 0));
|
||||
$base_level = min(2, max(0, (int) ($vip_state['fallback_level'] ?? 0)));
|
||||
$base_expires = max(0, (int) ($vip_state['fallback_expires'] ?? 0));
|
||||
@@ -162,20 +153,6 @@ foreach ([1, 2] as $lv) {
|
||||
$cards .= '</div></div>';
|
||||
}
|
||||
|
||||
// Points exchange entry (available for guests, ordinary users, and VIP renewals/upgrades).
|
||||
$points_html = '';
|
||||
$points_pkgs = is_array($points_exchange['packages'] ?? null) ? $points_exchange['packages'] : [];
|
||||
if (!empty($points_exchange['enabled']) && $points_pkgs !== []) {
|
||||
$points_html = '<div class="uc-vip-points-link" data-aksrt-vip-points-modal>'
|
||||
. '<div class="uc-vip-points-link__icon" aria-hidden="true"><i class="fa fas fa-money-bill"></i></div>'
|
||||
. '<div class="uc-vip-points-link__body">'
|
||||
. '<strong>' . esc_html__('积分兑换会员', 'aksrt') . '</strong>'
|
||||
. '<span>' . sprintf(esc_html__('当前有 %1$s %2$s,可兑换专属会员权益', 'aksrt'), esc_html((string) $user_points), esc_html($currency_name)) . '</span>'
|
||||
. '</div>'
|
||||
. '<button type="button" class="uc-vip-points-link__action" data-aksrt-vip-points-open>'
|
||||
. esc_html__('立即兑换', 'aksrt')
|
||||
. ' <i class="fa fas fa-chevron-right" aria-hidden="true"></i></button></div>';
|
||||
}
|
||||
?>
|
||||
<div class="uc-vip-tab" data-aksrt-vip-tab>
|
||||
<div class="uc-vip-summary" data-aksrt-vip-summary data-vip-state="<?php echo esc_attr($vip_state); ?>" data-vip-level="<?php echo (int) $vip_level_number; ?>" data-vip-permanent="<?php echo $vip_is_permanent ? 'true' : 'false'; ?>">
|
||||
@@ -187,8 +164,6 @@ if (!empty($points_exchange['enabled']) && $points_pkgs !== []) {
|
||||
<?php echo $cards; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
|
||||
<?php echo $points_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
|
||||
<?php if (!empty($vip_settings['more'])) : ?>
|
||||
<div class="muted-2-color em09 muted-box padding-10 mini-radius mt15">
|
||||
<?php echo $vip_settings['more']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
|
||||
Reference in New Issue
Block a user