fix(vip): honor manual membership changes
This commit is contained in:
1 parent
49ba30efa4
commit
ddc762bfbd
6 files changed
+145
-151
No files matched your search
@@ -103,6 +103,8 @@
|
|||||||
|
|
||||||
function activate(name, updateHistory, forceLoad, queryParams) {
|
function activate(name, updateHistory, forceLoad, queryParams) {
|
||||||
if (!panels[name]) name = defaultTab;
|
if (!panels[name]) name = defaultTab;
|
||||||
|
// VIP membership may change outside this page, so never reuse stale HTML.
|
||||||
|
if (name === 'vip' && !forceLoad) forceLoad = true;
|
||||||
return loadPanel(name, forceLoad, queryParams).then(function() {
|
return loadPanel(name, forceLoad, queryParams).then(function() {
|
||||||
switchTo(name);
|
switchTo(name);
|
||||||
if (updateHistory) updateUrl(name);
|
if (updateHistory) updateUrl(name);
|
||||||
|
|||||||
+118
-133
@@ -8,142 +8,130 @@
|
|||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析用户 VIP 等级:0=非 VIP,1=VIP1,2=VIP2。
|
* Resolve the complete VIP membership state for a user.
|
||||||
*
|
*
|
||||||
* 判定顺序:
|
* Explicit membership meta is authoritative, including an explicit level 0.
|
||||||
* 1. VIP 功能未启用 → 0
|
* Order fallback is only for users without a canonical membership level.
|
||||||
* 2. 角色在 vip_exempt_roles 白名单 → 当前启用的最高档
|
|
||||||
* 3. user meta aksrt_vip_level + aksrt_vip_expires(过期 lazy 清 0;expires=0 且 level>0 视为永久)
|
|
||||||
* 4. 有效 VIP 订单兜底 → 1(套餐无 level 列,订单无法区分 VIP2)
|
|
||||||
* 5. 按 pay_user_vip_1/2 开关钳制
|
|
||||||
*
|
*
|
||||||
* @param int $user_id 用户 ID,0 时取当前用户。
|
* @return array{level:int,expires:int,state:string,expired_level:int,source:string,has_explicit_state:bool,is_permanent:bool}
|
||||||
* @return int 0|1|2
|
|
||||||
*/
|
*/
|
||||||
function aksrt_get_user_vip_level(int $user_id = 0): int {
|
function aksrt_get_user_vip_state(int $user_id = 0): array {
|
||||||
|
$empty = [
|
||||||
|
'level' => 0,
|
||||||
|
'expires' => 0,
|
||||||
|
'state' => 'unopened',
|
||||||
|
'expired_level' => 0,
|
||||||
|
'source' => 'none',
|
||||||
|
'has_explicit_state' => false,
|
||||||
|
'is_permanent' => false,
|
||||||
|
];
|
||||||
if ($user_id <= 0) {
|
if ($user_id <= 0) {
|
||||||
$user_id = get_current_user_id();
|
$user_id = get_current_user_id();
|
||||||
}
|
}
|
||||||
if ($user_id <= 0) {
|
if ($user_id <= 0 || !class_exists('\AKSRT\Settings\Settings')) {
|
||||||
return 0;
|
return $empty;
|
||||||
}
|
}
|
||||||
|
$vip = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
if (empty($vip['enabled'])) {
|
||||||
return 0;
|
return $empty;
|
||||||
}
|
}
|
||||||
|
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
|
||||||
$vip_settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
|
||||||
if (empty($vip_settings['enabled'])) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$levels = is_array($vip_settings['levels'] ?? null) ? $vip_settings['levels'] : [];
|
|
||||||
$vip1_enabled = !empty($levels[1]['enabled']);
|
$vip1_enabled = !empty($levels[1]['enabled']);
|
||||||
$vip2_enabled = !empty($levels[2]['enabled']);
|
$vip2_enabled = !empty($levels[2]['enabled']);
|
||||||
|
$has_explicit = metadata_exists('user', $user_id, 'aksrt_vip_level');
|
||||||
|
$level = min(2, max(0, (int) get_user_meta($user_id, 'aksrt_vip_level', true)));
|
||||||
|
$expires = max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true));
|
||||||
|
$expired_level = min(2, max(0, (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true)));
|
||||||
|
|
||||||
// 1. 角色豁免:特权角色取当前启用最高档。
|
if ($has_explicit) {
|
||||||
$paid_settings = \AKSRT\Settings\Settings::get_paid_content_settings();
|
if ($level > 0 && $expires > 0 && $expires < time()) {
|
||||||
$exempt_roles = $paid_settings['vip_exempt_roles'] ?? [];
|
$base_level = min(2, max(0, (int) get_user_meta($user_id, 'aksrt_vip_base_level', true)));
|
||||||
if (!empty($exempt_roles)) {
|
$base_expires = max(0, (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true));
|
||||||
$user = get_userdata($user_id);
|
if ($base_level > 0 && ($base_expires === 0 || $base_expires >= time())) {
|
||||||
if ($user && !empty(array_intersect((array) $user->roles, $exempt_roles))) {
|
|
||||||
if ($vip2_enabled) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if ($vip1_enabled) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$candidate = 0;
|
|
||||||
|
|
||||||
// 2. meta 主路径。
|
|
||||||
$meta_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
|
|
||||||
$expires = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
|
|
||||||
|
|
||||||
if ($meta_level > 0) {
|
|
||||||
if ($expires > 0 && $expires < time()) {
|
|
||||||
$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_level', $base_level);
|
||||||
update_user_meta($user_id, 'aksrt_vip_expires', $base_expires);
|
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_level');
|
||||||
delete_user_meta($user_id, 'aksrt_vip_base_expires');
|
delete_user_meta($user_id, 'aksrt_vip_base_expires');
|
||||||
$candidate = min(2, max(0, $base_level));
|
$level = $base_level;
|
||||||
|
$expires = $base_expires;
|
||||||
|
$expired_level = 0;
|
||||||
} else {
|
} else {
|
||||||
// 过期:lazy 清 level,记录上次等级(zibll vip_level_expired)。
|
$expired_level = max($expired_level, $level);
|
||||||
update_user_meta($user_id, 'aksrt_vip_level_expired', min(2, max(1, $meta_level)));
|
update_user_meta($user_id, 'aksrt_vip_level_expired', $expired_level);
|
||||||
update_user_meta($user_id, 'aksrt_vip_level', 0);
|
update_user_meta($user_id, 'aksrt_vip_level', 0);
|
||||||
$candidate = 0;
|
$level = 0;
|
||||||
}
|
$expires = 0;
|
||||||
} else {
|
|
||||||
// expires === 0 视为永久;expires >= now 视为有效。
|
|
||||||
$candidate = min(2, max(0, $meta_level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 订单兜底(meta 无有效等级时)。
|
|
||||||
if ($candidate <= 0 && class_exists('\AKSRT\Payment\Order')) {
|
|
||||||
$order_mgr = \AKSRT\Payment\Order::get_instance();
|
|
||||||
$valid_order = method_exists($order_mgr, 'get_valid_vip_order')
|
|
||||||
? $order_mgr->get_valid_vip_order($user_id)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (is_array($valid_order) && !empty($valid_order)) {
|
|
||||||
// Order.expires_at is payment checkout deadline, not VIP membership expiry.
|
|
||||||
// Prefer note/meta_payload level + aksrt_vip_expires if present.
|
|
||||||
$meta = [];
|
|
||||||
if (!empty($valid_order['meta_payload']) && is_array($valid_order['meta_payload'])) {
|
|
||||||
$meta = $valid_order['meta_payload'];
|
|
||||||
} elseif (!empty($valid_order['note']) && is_string($valid_order['note'])) {
|
|
||||||
$decoded = json_decode($valid_order['note'], true);
|
|
||||||
if (is_array($decoded)) {
|
|
||||||
$meta = $decoded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$order_level = (int) ($meta['level'] ?? 0);
|
|
||||||
if ($order_level <= 0 && !empty($valid_order['product_id']) && class_exists('\AKSRT\Content\VipService')) {
|
|
||||||
// package_id encodes level: decode if possible via service helpers.
|
|
||||||
$pkg_id = (int) $valid_order['product_id'];
|
|
||||||
// Encode scheme: level * 1000 + index (see VipServicePackages).
|
|
||||||
if ($pkg_id >= 1000) {
|
|
||||||
$order_level = (int) floor($pkg_id / 1000);
|
|
||||||
} elseif ($pkg_id > 0) {
|
|
||||||
$order_level = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$order_level = max(0, min(2, $order_level));
|
|
||||||
|
|
||||||
// Membership still valid if user meta expires is in future or permanent (0 with prior grant).
|
|
||||||
// Without restored meta, treat paid VIP order as at least the ordered level.
|
|
||||||
if ($order_level > 0) {
|
|
||||||
$candidate = $order_level;
|
|
||||||
} else {
|
|
||||||
$candidate = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if ($level > 0) {
|
||||||
|
$level = $level >= 2 && $vip2_enabled ? 2 : ($vip1_enabled ? 1 : 0);
|
||||||
// 4. 按档位开关钳制。
|
return [
|
||||||
if ($candidate >= 2) {
|
'level' => $level,
|
||||||
if ($vip2_enabled) {
|
'expires' => $expires,
|
||||||
return 2;
|
'state' => $expires > 0 ? 'active' : 'permanent',
|
||||||
|
'expired_level' => 0,
|
||||||
|
'source' => 'meta',
|
||||||
|
'has_explicit_state' => true,
|
||||||
|
'is_permanent' => $expires <= 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
if ($vip1_enabled) {
|
return [
|
||||||
return 1;
|
'level' => 0,
|
||||||
|
'expires' => 0,
|
||||||
|
'state' => $expired_level > 0 ? 'expired' : 'unopened',
|
||||||
|
'expired_level' => $expired_level,
|
||||||
|
'source' => 'meta',
|
||||||
|
'has_explicit_state' => true,
|
||||||
|
'is_permanent' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$paid = \AKSRT\Settings\Settings::get_paid_content_settings();
|
||||||
|
$user = get_userdata($user_id);
|
||||||
|
if ($user && array_intersect((array) $user->roles, (array) ($paid['vip_exempt_roles'] ?? []))) {
|
||||||
|
$level = $vip2_enabled ? 2 : ($vip1_enabled ? 1 : 0);
|
||||||
|
return [
|
||||||
|
'level' => $level, 'expires' => 0,
|
||||||
|
'state' => $level > 0 ? 'permanent' : 'unopened',
|
||||||
|
'expired_level' => 0, 'source' => 'exempt',
|
||||||
|
'has_explicit_state' => false, 'is_permanent' => $level > 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class_exists('\AKSRT\Payment\Order')) {
|
||||||
|
$orders = \AKSRT\Payment\Order::get_instance();
|
||||||
|
$order = method_exists($orders, 'get_valid_vip_order') ? $orders->get_valid_vip_order($user_id) : null;
|
||||||
|
if (is_array($order) && $order !== []) {
|
||||||
|
$order_meta = is_array($order['meta_payload'] ?? null) ? $order['meta_payload'] : [];
|
||||||
|
if ($order_meta === [] && is_string($order['note'] ?? null)) {
|
||||||
|
$decoded = json_decode($order['note'], true);
|
||||||
|
$order_meta = is_array($decoded) ? $decoded : [];
|
||||||
|
}
|
||||||
|
$level = (int) ($order_meta['level'] ?? 0);
|
||||||
|
$product_id = (int) ($order['product_id'] ?? 0);
|
||||||
|
if ($level <= 0 && $product_id > 0) {
|
||||||
|
$level = $product_id >= 1000 ? (int) floor($product_id / 1000) : 1;
|
||||||
|
}
|
||||||
|
$level = min(2, max(1, $level));
|
||||||
|
$level = $level >= 2 && $vip2_enabled ? 2 : ($vip1_enabled ? 1 : 0);
|
||||||
|
$order_expires = max(0, (int) ($order_meta['expires'] ?? $order_meta['vip_expires'] ?? 0));
|
||||||
|
return [
|
||||||
|
'level' => $level, 'expires' => $order_expires,
|
||||||
|
'state' => $level > 0 ? 'active' : 'unopened',
|
||||||
|
'expired_level' => 0, 'source' => 'order',
|
||||||
|
'has_explicit_state' => false, 'is_permanent' => false,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return $empty;
|
||||||
|
}
|
||||||
|
|
||||||
if ($candidate === 1) {
|
/**
|
||||||
return $vip1_enabled ? 1 : 0;
|
* @param int $user_id User ID, or current user when zero.
|
||||||
}
|
* @return int 0|1|2
|
||||||
|
*/
|
||||||
return 0;
|
function aksrt_get_user_vip_level(int $user_id = 0): int {
|
||||||
|
return (int) aksrt_get_user_vip_state($user_id)['level'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -373,23 +361,18 @@ function aksrt_render_vip_badge(int $user_id = 0, string $size = 'sm'): string {
|
|||||||
* @return array{is_vip: bool, level: int, badge_text: string, badge_html: string, name: string, expires: int, expires_label: string}
|
* @return array{is_vip: bool, level: int, badge_text: string, badge_html: string, name: string, expires: int, expires_label: string}
|
||||||
*/
|
*/
|
||||||
function aksrt_get_vip_info(int $user_id = 0): array {
|
function aksrt_get_vip_info(int $user_id = 0): array {
|
||||||
$level = aksrt_get_user_vip_level($user_id);
|
$state = function_exists('aksrt_get_user_vip_state') ? aksrt_get_user_vip_state($user_id) : [];
|
||||||
|
$level = (int) ($state['level'] ?? 0);
|
||||||
$is_vip = $level >= 1;
|
$is_vip = $level >= 1;
|
||||||
$badge_text = aksrt_get_vip_badge_text($user_id);
|
$badge_text = aksrt_get_vip_badge_text($user_id);
|
||||||
$expires = $user_id > 0 ? (int) get_user_meta($user_id, 'aksrt_vip_expires', true) : 0;
|
$expires = max(0, (int) ($state['expires'] ?? 0));
|
||||||
$expires_label = __('未开通', 'aksrt');
|
$expires_label = __('未开通', 'aksrt');
|
||||||
if ($level > 0) {
|
if (($state['state'] ?? '') === 'expired') {
|
||||||
if ($expires <= 0) {
|
$expires_label = __('已过期', 'aksrt');
|
||||||
$expires_label = __('永久有效', 'aksrt');
|
} elseif ($is_vip && $expires <= 0 && ($state['source'] ?? 'none') !== 'order') {
|
||||||
} elseif ($expires < time()) {
|
$expires_label = __('永久有效', 'aksrt');
|
||||||
$expires_label = __('已过期', 'aksrt');
|
} elseif ($is_vip) {
|
||||||
} else {
|
$expires_label = sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y-m-d H:i', $expires));
|
||||||
$expires_label = sprintf(
|
|
||||||
/* translators: %s: date */
|
|
||||||
__('到期时间:%s', 'aksrt'),
|
|
||||||
wp_date('Y-m-d H:i', $expires)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$name = __('普通用户', 'aksrt');
|
$name = __('普通用户', 'aksrt');
|
||||||
@@ -401,13 +384,15 @@ function aksrt_get_vip_info(int $user_id = 0): array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'is_vip' => $is_vip,
|
'is_vip' => $is_vip,
|
||||||
'level' => $level,
|
'level' => $level,
|
||||||
'badge_text' => $badge_text,
|
'badge_text' => $badge_text,
|
||||||
'badge_html' => $is_vip ? aksrt_render_vip_badge($user_id) : '',
|
'badge_html' => $is_vip ? aksrt_render_vip_badge($user_id) : '',
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'expires' => $expires,
|
'expires' => $expires,
|
||||||
'expires_label' => $expires_label,
|
'expires_label' => $expires_label,
|
||||||
|
'state' => (string) ($state['state'] ?? 'unopened'),
|
||||||
|
'source' => (string) ($state['source'] ?? 'none'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ if (!$vip_enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user_id = (int) ($user_id ?? get_current_user_id());
|
$user_id = (int) ($user_id ?? get_current_user_id());
|
||||||
$vip_level = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level($user_id) : 0;
|
$vip_state = function_exists('aksrt_get_user_vip_state') ? aksrt_get_user_vip_state($user_id) : [];
|
||||||
$expired_level = (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true);
|
$vip_level = (int) ($vip_state['level'] ?? 0);
|
||||||
$expires = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
|
$expired_level = min(2, max(0, (int) ($vip_state['expired_level'] ?? 0)));
|
||||||
|
$expires = max(0, (int) ($vip_state['expires'] ?? 0));
|
||||||
$vip_url = aksrt_get_user_center_tab_url('vip');
|
$vip_url = aksrt_get_user_center_tab_url('vip');
|
||||||
|
|
||||||
$title = __('开通会员', 'aksrt');
|
$title = __('开通会员', 'aksrt');
|
||||||
@@ -29,7 +30,7 @@ if ($status === '') {
|
|||||||
|
|
||||||
if ($vip_level > 0) {
|
if ($vip_level > 0) {
|
||||||
$title = (string) ($vip_levels[$vip_level]['name'] ?? ('VIP' . $vip_level));
|
$title = (string) ($vip_levels[$vip_level]['name'] ?? ('VIP' . $vip_level));
|
||||||
if ($expires <= 0) {
|
if ($expires <= 0 && $vip_state_source !== 'order') {
|
||||||
$status = __('永久会员', 'aksrt');
|
$status = __('永久会员', 'aksrt');
|
||||||
} else {
|
} else {
|
||||||
$remaining_days = max(1, (int) ceil(($expires - time()) / DAY_IN_SECONDS));
|
$remaining_days = max(1, (int) ceil(($expires - time()) / DAY_IN_SECONDS));
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ if (empty($vip_settings['enabled'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user_id = (int) ($user_id ?? get_current_user_id());
|
$user_id = (int) ($user_id ?? get_current_user_id());
|
||||||
$level = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level($user_id) : 0;
|
$vip_state = function_exists('aksrt_get_user_vip_state') ? aksrt_get_user_vip_state($user_id) : [];
|
||||||
|
$level = (int) ($vip_state['level'] ?? 0);
|
||||||
$points_exchange = [];
|
$points_exchange = [];
|
||||||
$user_points = 0;
|
$user_points = 0;
|
||||||
$currency_name = __('积分', 'aksrt');
|
$currency_name = __('积分', 'aksrt');
|
||||||
@@ -29,10 +30,12 @@ if (class_exists('\\AKSRT\\Content\\VipService')) {
|
|||||||
$user_points = (int) ($vip_catalog['user_points'] ?? 0);
|
$user_points = (int) ($vip_catalog['user_points'] ?? 0);
|
||||||
$currency_name = (string) ($vip_catalog['currency_name'] ?? $currency_name);
|
$currency_name = (string) ($vip_catalog['currency_name'] ?? $currency_name);
|
||||||
}
|
}
|
||||||
$expires = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
|
$expires = max(0, (int) ($vip_state['expires'] ?? 0));
|
||||||
$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
|
$base_level = 0;
|
||||||
$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
|
$base_expires = 0;
|
||||||
$expired_level = (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true);
|
$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'] : [];
|
$levels = is_array($vip_settings['levels'] ?? null) ? $vip_settings['levels'] : [];
|
||||||
$desc_top = (string) ($vip_settings['desc'] ?? '');
|
$desc_top = (string) ($vip_settings['desc'] ?? '');
|
||||||
|
|
||||||
@@ -52,7 +55,7 @@ if ($level > 0) {
|
|||||||
$level_desc = (string) ($levels[$level]['desc'] ?? '');
|
$level_desc = (string) ($levels[$level]['desc'] ?? '');
|
||||||
$vip_description = $level_desc !== '' ? $level_desc : __('尊享专属特权', 'aksrt');
|
$vip_description = $level_desc !== '' ? $level_desc : __('尊享专属特权', 'aksrt');
|
||||||
|
|
||||||
if ($expires <= 0) {
|
if ($expires <= 0 && $vip_state_source !== 'order') {
|
||||||
$vip_state = 'permanent';
|
$vip_state = 'permanent';
|
||||||
$vip_state_label = __('永久有效', 'aksrt');
|
$vip_state_label = __('永久有效', 'aksrt');
|
||||||
$vip_expiry_text = __('到期时间:永久会员', 'aksrt');
|
$vip_expiry_text = __('到期时间:永久会员', 'aksrt');
|
||||||
|
|||||||
@@ -225,10 +225,11 @@ trait UsersMenusVip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function render_vip_operation_fields(array $names): void {
|
private function render_vip_operation_fields(array $names): void {
|
||||||
echo '<select name="vip_operation"><option value="set">' . esc_html__('设置会员', 'aksrt') . '</option><option value="extend">' . esc_html__('延长有效期', 'aksrt') . '</option><option value="disable">' . esc_html__('停用会员', 'aksrt') . '</option></select> ';
|
echo '<select class="aksrt-vip-operation" name="vip_operation"><option value="set">' . esc_html__('设置会员', 'aksrt') . '</option><option value="extend">' . esc_html__('延长有效期', 'aksrt') . '</option><option value="disable">' . esc_html__('停用会员', 'aksrt') . '</option></select> ';
|
||||||
echo '<label>' . esc_html__('档位', 'aksrt') . ' <select name="level"><option value="1">' . esc_html($names[1]) . '</option><option value="2">' . esc_html($names[2]) . '</option></select></label> ';
|
echo '<span class="aksrt-vip-set-fields"><label>' . esc_html__('档位', 'aksrt') . ' <select name="level"><option value="1">' . esc_html($names[1]) . '</option><option value="2">' . esc_html($names[2]) . '</option></select></label> ';
|
||||||
echo '<label><input type="checkbox" name="permanent" value="1">' . esc_html__('永久', 'aksrt') . '</label> <label>' . esc_html__('绝对到期日', 'aksrt') . ' <input type="date" name="expires_date"></label> ';
|
echo '<label><input type="checkbox" name="permanent" value="1">' . esc_html__('永久', 'aksrt') . '</label> <label>' . esc_html__('绝对到期日', 'aksrt') . ' <input type="date" name="expires_date"></label></span> ';
|
||||||
echo '<label>' . esc_html__('延长', 'aksrt') . ' <input type="number" name="amount" min="1" max="3650" value="1" style="width:72px"><select name="unit"><option value="day">' . esc_html__('天', 'aksrt') . '</option><option value="month">' . esc_html__('月', 'aksrt') . '</option></select></label>';
|
echo '<span class="aksrt-vip-extend-fields"><label>' . esc_html__('延长', 'aksrt') . ' <input class="aksrt-vip-amount" type="number" name="amount" min="1" max="3650" value="1" style="width:72px"><select name="unit"><option value="day">' . esc_html__('天', 'aksrt') . '</option><option value="month">' . esc_html__('月', 'aksrt') . '</option></select></label></span>';
|
||||||
|
echo '<script>document.querySelectorAll(".aksrt-vip-operation").forEach(function(select){function sync(){var form=select.closest("form");if(!form)return;var set=form.querySelector(".aksrt-vip-set-fields"),extend=form.querySelector(".aksrt-vip-extend-fields"),danger=select.value==="disable";if(set)set.hidden=select.value!=="set";if(extend)extend.hidden=select.value!=="extend";if(danger&&!form.dataset.confirmBound){form.addEventListener("submit",function(e){if(select.value==="disable"&&!window.confirm("停用后将立即撤销该用户的前端会员权益,并清理恢复状态,确定继续吗?"))e.preventDefault();});form.dataset.confirmBound="1";}}sync();select.addEventListener("change",sync);});</script>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return array<string,mixed>|\WP_Error */
|
/** @return array<string,mixed>|\WP_Error */
|
||||||
|
|||||||
@@ -52,10 +52,11 @@ trait VipServicePurchase {
|
|||||||
return $this->vip_member_cache[$user_id];
|
return $this->vip_member_cache[$user_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
$level = $user_id > 0 && function_exists('aksrt_get_user_vip_level')
|
$vip_state = $user_id > 0 && function_exists('aksrt_get_user_vip_state')
|
||||||
? (int) aksrt_get_user_vip_level($user_id)
|
? aksrt_get_user_vip_state($user_id)
|
||||||
: 0;
|
: ['level' => 0, 'expires' => 0, 'state' => 'unopened', 'source' => 'none'];
|
||||||
$expires = $user_id > 0 ? (int) get_user_meta($user_id, 'aksrt_vip_expires', true) : 0;
|
$level = (int) ($vip_state['level'] ?? 0);
|
||||||
|
$expires = max(0, (int) ($vip_state['expires'] ?? 0));
|
||||||
$member_state = 'unopened';
|
$member_state = 'unopened';
|
||||||
if ($level > 0) {
|
if ($level > 0) {
|
||||||
$member_state = $expires <= 0
|
$member_state = $expires <= 0
|
||||||
@@ -71,6 +72,7 @@ trait VipServicePurchase {
|
|||||||
'expires' => $expires,
|
'expires' => $expires,
|
||||||
'is_permanent' => $level > 0 && $expires <= 0,
|
'is_permanent' => $level > 0 && $expires <= 0,
|
||||||
'state' => $member_state,
|
'state' => $member_state,
|
||||||
|
'source' => (string) ($vip_state['source'] ?? 'none'),
|
||||||
'expires_label' => $member_state === 'expired'
|
'expires_label' => $member_state === 'expired'
|
||||||
? __('已过期', 'aksrt')
|
? __('已过期', 'aksrt')
|
||||||
: $this->format_expires_label($expires, $level),
|
: $this->format_expires_label($expires, $level),
|
||||||
|
|||||||
Reference in new issue
Block a user