diff --git a/inc/helpers/aksrt-vip.php b/inc/helpers/aksrt-vip.php index e2bcec03..56233b9e 100644 --- a/inc/helpers/aksrt-vip.php +++ b/inc/helpers/aksrt-vip.php @@ -65,10 +65,20 @@ function aksrt_get_user_vip_level(int $user_id = 0): int { if ($meta_level > 0) { if ($expires > 0 && $expires < time()) { - // 过期:lazy 清 level,记录上次等级(zibll vip_level_expired)。 - update_user_meta($user_id, 'aksrt_vip_level_expired', min(2, max(1, $meta_level))); - update_user_meta($user_id, 'aksrt_vip_level', 0); - $candidate = 0; + $base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true); + $base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true); + if ($base_level > 0) { + update_user_meta($user_id, 'aksrt_vip_level', $base_level); + update_user_meta($user_id, 'aksrt_vip_expires', $base_expires); + delete_user_meta($user_id, 'aksrt_vip_base_level'); + delete_user_meta($user_id, 'aksrt_vip_base_expires'); + $candidate = min(2, max(0, $base_level)); + } else { + // 过期:lazy 清 level,记录上次等级(zibll vip_level_expired)。 + update_user_meta($user_id, 'aksrt_vip_level_expired', min(2, max(1, $meta_level))); + update_user_meta($user_id, 'aksrt_vip_level', 0); + $candidate = 0; + } } else { // expires === 0 视为永久;expires >= now 视为有效。 $candidate = min(2, max(0, $meta_level)); diff --git a/inc/helpers/user-center-renderers/vip-tab.php b/inc/helpers/user-center-renderers/vip-tab.php index 6ea2fc1b..3163169f 100644 --- a/inc/helpers/user-center-renderers/vip-tab.php +++ b/inc/helpers/user-center-renderers/vip-tab.php @@ -30,6 +30,8 @@ if (class_exists('\\AKSRT\\Content\\VipService')) { $currency_name = (string) ($vip_catalog['currency_name'] ?? $currency_name); } $expires = (int) get_user_meta($user_id, 'aksrt_vip_expires', true); +$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true); +$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true); $expired_level = (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true); $levels = is_array($vip_settings['levels'] ?? null) ? $vip_settings['levels'] : []; $desc_top = (string) ($vip_settings['desc'] ?? ''); @@ -62,7 +64,14 @@ if ($level > 0) { $vip_state = 'active'; $vip_state_label = __('生效中', 'aksrt'); $vip_expiry_text = sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires)); - $btn_type = 'renew_' . $level; + 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'; diff --git a/src/Admin/Schema/SchemaPayment.php b/src/Admin/Schema/SchemaPayment.php index ce107f99..b88e04f2 100644 --- a/src/Admin/Schema/SchemaPayment.php +++ b/src/Admin/Schema/SchemaPayment.php @@ -129,7 +129,7 @@ class SchemaPayment { ]], ['key' => 'points_exchange', 'title' => '积分兑换会员', 'fields' => [ ['key' => 'pay_vip_points_exchange_s', 'label' => '启用积分兑换', 'type' => 'switch', 'default' => false], - ['key' => 'payment_vip_points_packages', 'label' => '兑换套餐', 'type' => 'textarea', 'default' => "1|500|30|积分月卡\n1|5000|0|积分永久", 'dependsOn' => ['key' => 'pay_vip_points_exchange_s', 'value' => true], 'help' => '每行:等级|积分|天数|标题(天数 0=永久;仅未开通会员可兑)'], + ['key' => 'payment_vip_points_packages', 'label' => '兑换套餐', 'type' => 'textarea', 'default' => "1|500|30|积分月卡\n1|5000|0|积分永久", 'dependsOn' => ['key' => 'pay_vip_points_exchange_s', 'value' => true], 'help' => '每行:等级|积分|天数|标题(天数 0=永久;普通用户可开通,已有会员可续费同等级或升级更高等级)'], ['key' => 'pay_vip_points_exchange_desc', 'label' => '兑换说明', 'type' => 'textarea', 'default' => '', 'dependsOn' => ['key' => 'pay_vip_points_exchange_s', 'value' => true]], ]], ['key' => 'benefit', 'title' => '下载权益', 'fields' => [ diff --git a/src/Content/VipServicePurchase.php b/src/Content/VipServicePurchase.php index 45704ded..f832f2ed 100644 --- a/src/Content/VipServicePurchase.php +++ b/src/Content/VipServicePurchase.php @@ -515,6 +515,16 @@ trait VipServicePurchase { $previous_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true); $previous_expiry = (int) get_user_meta($user_id, 'aksrt_vip_expires', true); + $finite_duration = $time > 0 || $days > 0; + if ($previous_level > 0 && $previous_expiry === 0 && $level > $previous_level && $finite_duration) { + // Preserve a permanent lower tier while a finite higher-tier upgrade is active. + update_user_meta($user_id, 'aksrt_vip_base_level', $previous_level); + update_user_meta($user_id, 'aksrt_vip_base_expires', 0); + } else { + // Only a finite higher-tier upgrade may keep a layered base membership. + delete_user_meta($user_id, 'aksrt_vip_base_level'); + delete_user_meta($user_id, 'aksrt_vip_base_expires'); + } $fulfilled = false; // unit upgrade: raise level only, keep current expiry (zibll). if ($upgrade_mode === 'unit') { @@ -574,14 +584,15 @@ trait VipServicePurchase { if ($days <= 0) { // Permanent. + delete_user_meta($user_id, 'aksrt_vip_base_level'); + delete_user_meta($user_id, 'aksrt_vip_base_expires'); update_user_meta($user_id, 'aksrt_vip_expires', 0); return; } $current_exp = (int) get_user_meta($user_id, 'aksrt_vip_expires', true); - if ($current_exp === 0 && $current_level > 0) { - // Already permanent — keep permanent. - return; + if ($current_exp === 0 && $current_level > 0 && $level <= $current_level) { + return; // keep an existing permanent level when not upgrading it } $base = max($current_exp, time()); update_user_meta($user_id, 'aksrt_vip_expires', $base + ($days * DAY_IN_SECONDS)); @@ -603,13 +614,15 @@ trait VipServicePurchase { delete_user_meta($user_id, 'aksrt_vip_level_expired'); if ($time <= 0) { + delete_user_meta($user_id, 'aksrt_vip_base_level'); + delete_user_meta($user_id, 'aksrt_vip_base_expires'); update_user_meta($user_id, 'aksrt_vip_expires', 0); return; } $current_exp = (int) get_user_meta($user_id, 'aksrt_vip_expires', true); - if ($current_exp === 0 && $current_level > 0) { - return; // keep permanent + if ($current_exp === 0 && $current_level > 0 && $level <= $current_level) { + return; // keep an existing permanent level when not upgrading it } $base = max($current_exp, time()); $modifier = $unit === 'month'