feat(user): complete growth level chain
This commit is contained in:
@@ -159,7 +159,11 @@ if (!function_exists('aksrt_get_user_name')) {
|
||||
if ($type === 'verify' && !empty($args['auth']) && $auth_html === '') {
|
||||
$auth_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--success" title="' . esc_attr($title) . '"><i class="fa fa-check-circle" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
||||
} elseif ($type === 'level' && !empty($args['level']) && $level_html === '') {
|
||||
$level_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--info" title="' . esc_attr($title) . '"><i class="fa fa-layer-group" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
||||
if ($icon_url !== '') {
|
||||
$level_html = '<img class="aksrt-user-level-icon img-icon ml3" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
||||
} else {
|
||||
$level_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--info" title="' . esc_attr($title) . '"><i class="fa fa-layer-group" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
||||
}
|
||||
} elseif ($type === 'badge' && !empty($args['medal']) && $medal_html === '' && !empty($signal['wear'])) {
|
||||
if ($icon_url !== '') {
|
||||
$medal_html = '<img class="medal-icon img-icon ml3 aksrt-identity-medal is-wear" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
||||
|
||||
@@ -409,7 +409,7 @@ if (!function_exists('aksrt_resolve_allow_view_rule')) :
|
||||
$ok = true;
|
||||
}
|
||||
if (!$ok && $need_level > 0) {
|
||||
$user_level = (int) get_user_meta($user_id, 'aksrt_user_level', true);
|
||||
$user_level = class_exists('\AKSRT\User\Level') ? \AKSRT\User\Level::get_level($user_id) : 0;
|
||||
if ($user_level >= $need_level) {
|
||||
$ok = true;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ if (!function_exists('aksrt_capture_user_center_view')) {
|
||||
function aksrt_capture_user_center_view(string $view, array $context): string {
|
||||
// Built-in panels map to renderer files; "profile" content lives in profile-form.php.
|
||||
$map = [
|
||||
'level' => 'level',
|
||||
'profile' => 'form',
|
||||
'posts' => 'posts',
|
||||
'comments' => 'comments',
|
||||
@@ -173,7 +174,7 @@ if (!function_exists('aksrt_capture_user_center_panel')) {
|
||||
* Capture a built-in or registered user-center panel body.
|
||||
*/
|
||||
function aksrt_capture_user_center_panel(string $tab_key, array $tab, array $context): string {
|
||||
$built_in_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings'];
|
||||
$built_in_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings'];
|
||||
if (in_array($tab_key, $built_in_tabs, true)) {
|
||||
return aksrt_capture_user_center_view($tab_key, $context);
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* User center: my level + integral growth (Zibll level card parity).
|
||||
*
|
||||
* Expects $user_id from profile-credits context when required.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!class_exists('\AKSRT\User\Level')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cfg = \AKSRT\User\Level::settings();
|
||||
if (empty($cfg['enabled'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = (int) ($user_id ?? get_current_user_id());
|
||||
if ($user_id <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$level = \AKSRT\User\Level::get_level($user_id);
|
||||
$integral = \AKSRT\User\Level::get_integral($user_id);
|
||||
$max = max(1, (int) ($cfg['max'] ?? 10));
|
||||
$prefix = (string) ($cfg['prefix'] ?? 'Lv.');
|
||||
$opt = is_array($cfg['level_opt'] ?? null) ? $cfg['level_opt'] : [];
|
||||
$name = (string) ($opt['name_' . $level] ?? ($prefix . $level));
|
||||
|
||||
$next_need = 0;
|
||||
$is_max = $level >= $max;
|
||||
if (!$is_max) {
|
||||
$next_need = (int) ($opt['upgrade_integral_' . ($level + 1)] ?? 0);
|
||||
if ($next_need <= $integral) {
|
||||
// Resolve again in case meta lag.
|
||||
$level = \AKSRT\User\Level::resolve_level($integral, $cfg);
|
||||
$is_max = $level >= $max;
|
||||
$next_need = $is_max ? $integral : (int) ($opt['upgrade_integral_' . ($level + 1)] ?? $integral);
|
||||
$name = (string) ($opt['name_' . $level] ?? ($prefix . $level));
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_max) {
|
||||
$proportion = 100;
|
||||
$need_html = esc_html__('已为最高等级', 'aksrt');
|
||||
$frac_html = esc_html((string) $integral) . '/' . esc_html((string) $integral);
|
||||
} else {
|
||||
$den = max(1, $next_need);
|
||||
$proportion = (int) min(100, max(0, ($integral / $den) * 100));
|
||||
$need_left = max(0, $next_need - $integral);
|
||||
$need_html = sprintf(
|
||||
/* translators: %s: remaining XP */
|
||||
esc_html__('升级还需%s经验', 'aksrt'),
|
||||
'<span class="em14 font-bold ml3 mr3">' . esc_html((string) $need_left) . '</span>'
|
||||
);
|
||||
$frac_html = esc_html((string) $integral) . '/' . esc_html((string) $next_need);
|
||||
}
|
||||
|
||||
$avatar = function_exists('aksrt_get_avatar_html')
|
||||
? aksrt_get_avatar_html($user_id, 42, ['class' => 'avatar avatar-mini'])
|
||||
: get_avatar($user_id, 42);
|
||||
|
||||
// Growth rows (next few levels).
|
||||
$growth = '';
|
||||
$from = max(1, $level);
|
||||
$to = min($max, $level + 5);
|
||||
for ($i = $from; $i <= $to; $i++) {
|
||||
$need_i = (int) ($opt['upgrade_integral_' . $i] ?? 0);
|
||||
$nm = (string) ($opt['name_' . $i] ?? ($prefix . $i));
|
||||
$state = $integral >= $need_i ? 'is-done' : ($i === $level + 1 ? 'is-next' : '');
|
||||
$growth .= '<div class="uc-level-growth__row ' . esc_attr($state) . '">';
|
||||
$growth .= '<span class="uc-level-growth__lv">' . esc_html($prefix . $i) . '</span>';
|
||||
$growth .= '<span class="uc-level-growth__name">' . esc_html($nm) . '</span>';
|
||||
$growth .= '<span class="uc-level-growth__need">' . esc_html((string) $need_i) . '</span>';
|
||||
$growth .= '</div>';
|
||||
}
|
||||
?>
|
||||
<div class="uc-level-card zib-widget">
|
||||
<div class="uc-level-card__head flex ac">
|
||||
<div class="avatar-mini mr10"><?php echo $avatar; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
<div class="font-bold"><?php esc_html_e('我的等级', 'aksrt'); ?></div>
|
||||
</div>
|
||||
<div class="uc-level-card__body">
|
||||
<div class="uc-level-card__badge flex ac em14">
|
||||
<span class="badg badg-sm mr10 aksrt-identity-chip aksrt-identity-chip--info"><?php echo esc_html($prefix . $level); ?></span>
|
||||
<span class="font-bold"><?php echo esc_html($name); ?></span>
|
||||
</div>
|
||||
<div class="uc-level-card__progress mt10">
|
||||
<div class="flex jsb mb6 ab">
|
||||
<div class="em12 font-bold"><?php echo $frac_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
<div class="opacity8 em09"><?php echo $need_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
</div>
|
||||
<div class="integral-progress progress">
|
||||
<div class="progress-bar" style="width: <?php echo (int) $proportion; ?>%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($growth !== '') : ?>
|
||||
<div class="uc-level-growth mt12">
|
||||
<div class="uc-level-growth__title muted-2-color em09 mb6"><?php esc_html_e('成长路线', 'aksrt'); ?></div>
|
||||
<?php echo $growth; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -54,7 +54,7 @@ $can_apply = !empty($settings['enabled']) && !empty($settings['allow_apply']) &&
|
||||
<?php if (empty($settings['allow_apply'])) : ?>
|
||||
<div class="uc-auth-card__notice"><?php echo wp_kses_post(nl2br(esc_html((string) ($settings['disable_desc'] ?? __('暂时不能申请身份认证', 'aksrt'))))); ?></div>
|
||||
<?php elseif ($blocked_level) : ?>
|
||||
<div class="uc-auth-card__notice"><?php printf(esc_html__('达到 LV.%d 后即可申请', 'aksrt'), $limit); ?></div>
|
||||
<div class="uc-auth-card__notice"><?php printf(esc_html__('达到 %s 后即可申请', 'aksrt'), esc_html(class_exists('\AKSRT\User\Level') ? \AKSRT\User\Level::get_level_name($limit) : ('LV' . $limit))); ?></div>
|
||||
<?php elseif (in_array($status, ['rejected', 'cancelled'], true) && $reason !== '') : ?>
|
||||
<div class="uc-auth-card__notice">
|
||||
<strong><?php echo $status === 'cancelled' ? esc_html__('认证已取消', 'aksrt') : esc_html__('上次申请未通过', 'aksrt'); ?></strong><br>
|
||||
|
||||
@@ -52,9 +52,6 @@ if (!empty($show_vip)) {
|
||||
if ($show_credits) {
|
||||
require $dir . '/credits-signin.php';
|
||||
}
|
||||
if (class_exists('\AKSRT\User\Level')) {
|
||||
require $dir . '/credits-level.php';
|
||||
}
|
||||
|
||||
// Tabbed ledgers (Zibll record tabs).
|
||||
if ($show_wallet || $show_credits) :
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* User center: growth level, route and experience history.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$context = is_array($args['context'] ?? null) ? $args['context'] : [];
|
||||
$user_id = (int) ($context['user_id'] ?? get_current_user_id());
|
||||
if ($user_id <= 0 || !class_exists('\AKSRT\User\Level')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cfg = \AKSRT\User\Level::settings();
|
||||
if (empty($cfg['enabled'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$progress = \AKSRT\User\Level::get_progress($user_id);
|
||||
$details = \AKSRT\User\Level::get_details($user_id);
|
||||
$date_details = \AKSRT\User\Level::get_date_details($user_id);
|
||||
$labels = \AKSRT\User\Level::integral_labels();
|
||||
$opt = is_array($cfg['level_opt'] ?? null) ? $cfg['level_opt'] : [];
|
||||
$today = current_time('Y-m-d');
|
||||
$today_integral = max(0, (int) ($date_details[$today] ?? 0));
|
||||
$day_max = \AKSRT\User\Level::day_max();
|
||||
?>
|
||||
<div class="uc-level-page">
|
||||
<section class="uc-level-hero zib-widget">
|
||||
<div class="uc-level-hero__identity">
|
||||
<div class="uc-level-hero__icon">
|
||||
<?php echo \AKSRT\User\Level::get_badge_html($user_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
<div>
|
||||
<p><?php esc_html_e('我的等级', 'aksrt'); ?></p>
|
||||
<h2><?php echo esc_html((string) $progress['name']); ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uc-level-hero__stats">
|
||||
<div><strong><?php echo esc_html((string) $progress['integral']); ?></strong><span><?php esc_html_e('累计经验', 'aksrt'); ?></span></div>
|
||||
<div><strong><?php echo esc_html((string) $today_integral); ?><?php echo $day_max > 0 ? '/' . esc_html((string) $day_max) : ''; ?></strong><span><?php esc_html_e('今日经验', 'aksrt'); ?></span></div>
|
||||
<div><strong><?php echo esc_html((string) $progress['remaining']); ?></strong><span><?php echo !empty($progress['is_max']) ? esc_html__('已达最高等级', 'aksrt') : esc_html__('升级还需', 'aksrt'); ?></span></div>
|
||||
</div>
|
||||
<div class="uc-level-hero__progress">
|
||||
<div class="uc-level-hero__progress-meta">
|
||||
<span><?php echo esc_html((string) $progress['integral']); ?> EXP</span>
|
||||
<span><?php echo !empty($progress['is_max']) ? esc_html__('最高等级', 'aksrt') : esc_html((string) $progress['next_need']) . ' EXP'; ?></span>
|
||||
</div>
|
||||
<div class="uc-level-progress"><span style="width:<?php echo esc_attr((string) $progress['progress']); ?>%"></span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="uc-level-section zib-widget">
|
||||
<div class="uc-level-section__head"><h3><?php esc_html_e('成长路线', 'aksrt'); ?></h3><span><?php printf(esc_html__('最高 %d 级', 'aksrt'), (int) $cfg['max']); ?></span></div>
|
||||
<div class="uc-level-road">
|
||||
<?php for ($level = 1; $level <= (int) $cfg['max']; $level++) :
|
||||
$need = $level === 1 ? 0 : max(0, (int) ($opt['upgrade_integral_' . $level] ?? (($level - 1) * 500 * $level)));
|
||||
$name = \AKSRT\User\Level::get_level_name($level);
|
||||
$state = $level < (int) $progress['level'] ? ' is-done' : ($level === (int) $progress['level'] ? ' is-current' : '');
|
||||
?>
|
||||
<div class="uc-level-road__item<?php echo esc_attr($state); ?>">
|
||||
<div class="uc-level-road__icon">
|
||||
<?php $icon = \AKSRT\User\Level::get_level_icon_url($level); ?>
|
||||
<?php if ($icon !== '') : ?><img src="<?php echo esc_url($icon); ?>" alt="" loading="lazy"><?php else : ?><span>LV<?php echo esc_html((string) $level); ?></span><?php endif; ?>
|
||||
</div>
|
||||
<strong><?php echo esc_html($name); ?></strong>
|
||||
<small><?php echo esc_html((string) $need); ?> EXP</small>
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="uc-level-history-grid">
|
||||
<section class="uc-level-section zib-widget">
|
||||
<div class="uc-level-section__head"><h3><?php esc_html_e('经验明细', 'aksrt'); ?></h3><span><?php esc_html_e('最近 50 条', 'aksrt'); ?></span></div>
|
||||
<?php if ($details) : ?>
|
||||
<div class="uc-level-ledger">
|
||||
<?php foreach ($details as $row) :
|
||||
$key = sanitize_key((string) ($row['key'] ?? ''));
|
||||
$value = max(0, (int) ($row['value'] ?? 0));
|
||||
?>
|
||||
<div class="uc-level-ledger__row">
|
||||
<span class="uc-level-ledger__icon"><i class="fas fa-chart-line" aria-hidden="true"></i></span>
|
||||
<div><strong><?php echo esc_html($labels[$key] ?? $key); ?></strong><time><?php echo esc_html((string) ($row['time'] ?? '')); ?></time></div>
|
||||
<b>+<?php echo esc_html((string) $value); ?></b>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="uc-level-empty"><?php esc_html_e('还没有经验获取记录。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="uc-level-section zib-widget">
|
||||
<div class="uc-level-section__head"><h3><?php esc_html_e('每日经验', 'aksrt'); ?></h3><span><?php esc_html_e('最近 30 天', 'aksrt'); ?></span></div>
|
||||
<?php if ($date_details) : ?>
|
||||
<div class="uc-level-dates">
|
||||
<?php foreach ($date_details as $date => $value) : ?>
|
||||
<div><time><?php echo esc_html((string) $date); ?></time><span>+<?php echo esc_html((string) max(0, (int) $value)); ?> EXP</span></div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="uc-level-empty"><?php esc_html_e('还没有每日经验记录。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,8 +8,8 @@
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cart_url = function_exists('aksrt_get_cart_page_url') ? aksrt_get_cart_page_url() : '';
|
||||
$level_url = isset($dashboard_tabs['credits'])
|
||||
? add_query_arg('asset_tab', 'points', aksrt_get_user_center_tab_url('credits'))
|
||||
$level_url = isset($dashboard_tabs['level'])
|
||||
? aksrt_get_user_center_tab_url('level')
|
||||
: '';
|
||||
$auth_url = isset($dashboard_tabs['auth']) ? aksrt_get_user_center_tab_url('auth') : '';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user