Files
wordpress-theme-aksrt/inc/helpers/user-center-renderers/vip-tab.php
T
kate522 2801a89c1f fix(vip): 在 /user/vip/ 档位购买卡下方补充积分兑换会员入口
参考主题 zibpay_user_page_tab_content_vip:非会员 + 积分兑换会员开启 +
有可兑换套餐时,在两张档位购买卡下方输出全宽入口横条(points-color 图标
+ 标题 + 立即兑换 badg),点击经 data-aksrt-vip-points-open 打开 wp_footer
静态兑换弹窗,与会员购买弹窗内入口共用同一弹窗。

- aksrt-vip.php 新增 aksrt_get_vip_points_exchange_entry_html(),门控与
  弹窗壳同源(取服务端 catalog),已是会员不展示(对齐参考主题契约)
- vip-tab.php 在卡片区之后输出入口;credits.css 补 .uc-vip-points-entry
  表面样式(与档位卡同一变量体系,暗色自适应)
- pay-vip.js 改文档级委托承接 data-aksrt-vip-points-open,一处绑定覆盖
  静态页面横条与弹窗内按钮;移除 bindModalUi 内的重复分支
- 契约测试更新为双入口(11 项),node --test 420 项通过,php -l 通过

未写数据迁移;未做真实视觉效果验收。
2026-09-23 14:30:54 +08:00

179 lines
7.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* User center VIP tab (legacy 我的会员 1:1 structure).
*
* Expects extracted $context vars via profile-vip.php / capture path.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
$vip_settings = is_array($vip_settings ?? null) ? $vip_settings : [];
if (empty($vip_settings['enabled']) && class_exists('\AKSRT\Settings\Settings')) {
$vip_settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
}
if (empty($vip_settings['enabled'])) {
echo '<div class="aksrt-panel padding-20 muted-2-color">' . esc_html__('会员功能未启用。', 'aksrt') . '</div>';
return;
}
$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);
$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));
$expired_level = min(2, max(0, (int) ($vip_state['expired_level'] ?? 0)));
$vip_state_name = (string) ($vip_state['state'] ?? 'unopened');
$vip_state_source = (string) ($vip_state['source'] ?? 'none');
$levels = is_array($vip_settings['levels'] ?? null) ? $vip_settings['levels'] : [];
$desc_top = (string) ($vip_settings['desc'] ?? '');
// Membership summary: title → level → intro → expiry.
$vip_state = 'unopened';
$vip_state_label = __('未开通', 'aksrt');
$vip_level_number = 0;
$vip_level_name = __('未开通会员', 'aksrt');
$vip_description = $desc_top !== '' ? $desc_top : __('开通会员,尊享专属特权', 'aksrt');
$vip_expiry_text = __('到期时间:未开通', 'aksrt');
$vip_is_permanent = false;
$btn_type = 'pay';
if ($level > 0) {
$vip_level_number = $level;
$vip_level_name = (string) ($levels[$level]['name'] ?? ('VIP' . $level));
$level_desc = (string) ($levels[$level]['desc'] ?? '');
$vip_description = $level_desc !== '' ? $level_desc : __('尊享专属特权', 'aksrt');
if ($expires <= 0 && $vip_state_source !== 'order') {
$vip_state = 'permanent';
$vip_state_label = __('永久有效', 'aksrt');
$vip_expiry_text = __('到期时间:永久会员', 'aksrt');
$vip_is_permanent = true;
if ($level < 2) {
$btn_type = 'upgrade';
}
} else {
$vip_state = 'active';
$vip_state_label = __('生效中', 'aksrt');
$vip_expiry_text = sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires));
if ($base_level > 0 && $base_level < $level) {
$base_name = (string) ($levels[$base_level]['name'] ?? ('VIP' . $base_level));
$base_expiry_text = $base_expires > 0
? wp_date('Y年m月d日', $base_expires)
: __('永久', 'aksrt');
$vip_expiry_text .= ';' . sprintf(__('%s:%s', 'aksrt'), $base_name, $base_expiry_text);
}
$btn_type = 'renew_' . $level;
}
} elseif ($expired_level > 0) {
$vip_state = 'expired';
$vip_state_label = __('已过期', 'aksrt');
$vip_level_number = $expired_level;
$vip_level_name = (string) ($levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
$expired_desc = (string) ($levels[$expired_level]['desc'] ?? '');
$vip_description = $expired_desc !== ''
? $expired_desc
: ($desc_top !== '' ? $desc_top : __('会员已过期', 'aksrt'));
$vip_expiry_text = $expires > 0
? sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires))
: __('到期时间:已过期', 'aksrt');
}
$status_icon_url = esc_url((string) ($levels[$vip_level_number]['img_icon'] ?? ''));
$status_icon = $status_icon_url !== ''
? '<img' . aksrt_get_lazy_attr('lazy_other', $status_icon_url, 'aksrt-vip-level-icon') . ' alt="" decoding="async">'
: '<i class="fa fas fa-certificate"></i>';
$status_html = '<div class="uc-vip-status" role="status">'
. '<div class="uc-vip-status__heading">'
. '<h2 class="uc-vip-status__label">' . esc_html__('我的会员', 'aksrt') . '</h2>'
. '<span class="uc-vip-status__state">' . esc_html($vip_state_label) . '</span>'
. '</div>'
. '<div class="uc-vip-status__main uc-vip-status__main--level-' . (int) $vip_level_number . '">'
. '<span class="uc-vip-status__icon" aria-hidden="true">' . $status_icon . '</span>'
. '<span class="uc-vip-status__level">' . esc_html($vip_level_name) . '</span>'
. '</div>'
. '<div class="uc-vip-status__desc">' . esc_html($vip_description) . '</div>'
. '<div class="uc-vip-status__expiry"><i class="fa fas fa-clock" aria-hidden="true"></i><span>' . esc_html($vip_expiry_text) . '</span></div>'
. '</div>';
// Level cards.
$cards = '';
foreach ([1, 2] as $lv) {
if (empty($levels[$lv]['enabled'])) {
continue;
}
$lv_name = (string) ($levels[$lv]['name'] ?? ('VIP' . $lv));
$lv_desc = (string) ($levels[$lv]['desc'] ?? '');
// Preserve admin equity HTML as-is (sanitize/wrap only; never re-split into items).
$equity_raw = (string) ($levels[$lv]['equity'] ?? '');
$equity = function_exists('aksrt_format_vip_equity_html')
? aksrt_format_vip_equity_html($equity_raw)
: '';
$cta = sprintf(__('开通%s', 'aksrt'), $lv_name);
$vip_attr = $lv;
$lv_icon_url = esc_url((string) ($levels[$lv]['img_icon'] ?? ''));
$lv_icon = $lv_icon_url !== ''
? '<img' . aksrt_get_lazy_attr('lazy_other', $lv_icon_url, 'aksrt-vip-level-icon') . ' alt="" decoding="async">'
: '<i class="fa fas fa-certificate" aria-hidden="true"></i>';
if (str_starts_with($btn_type, 'renew_')) {
$renew_lv = (int) substr($btn_type, 6);
if ($lv === $renew_lv) {
$cta = sprintf(__('续费%s', 'aksrt'), $lv_name);
} elseif ($lv > $renew_lv) {
$cta = sprintf(__('升级%s', 'aksrt'), $lv_name);
} else {
continue;
}
} elseif ($btn_type === 'upgrade') {
if ($lv <= $level) {
continue;
}
$cta = sprintf(__('升级%s', 'aksrt'), $lv_name);
$vip_attr = 2;
} elseif ($level > 0 && $lv < $level) {
continue;
} elseif ($level > 0 && $lv === $level) {
$cta = sprintf(__('续费%s', 'aksrt'), $lv_name);
}
$cards .= '<div class="aksrt-panel text-center pay-vip-info flex1 level-' . $lv . ' uc-vip-level-card">';
$cards .= '<div class="relative uc-vip-level-card__inner">';
$cards .= '<div class="v-iconbox mb10">';
$cards .= '<div class="v-name font-bold"><span class="v-icon">' . $lv_icon . '</span>' . esc_html($lv_name) . '</div>';
if ($lv_desc !== '') {
$cards .= '<div class="v-desc em09 muted-2-color">' . esc_html($lv_desc) . '</div>';
}
$cards .= '</div>';
$cards .= $equity;
$cards .= '<a class="padding-lg but jb-vip' . $lv . ' radius pay-vip uc-vip-cta" href="javascript:;" vip-level="' . (int) $vip_attr . '">'
. '<span>' . esc_html($cta) . '</span>'
. ' <i class="fa fas fa-chevron-circle-right" aria-hidden="true"></i></a>';
$cards .= '</div></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'; ?>">
<div class="uc-vip-summary__watermark" aria-hidden="true"><i class="fa fas fa-certificate"></i></div>
<?php echo $status_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<div class="uc-vip-level-cards">
<?php echo $cards; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php
// 积分兑换会员入口(参考主题 zibpay_user_page_tab_content_vip 1:1:档位购买卡
// 下方的全宽横条;仅非会员 + 积分兑换开启 + 有可兑换套餐时输出)。
echo aksrt_get_vip_points_exchange_entry_html($user_id, $level); // 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 ?>
</div>
<?php endif; ?>
</div>