fix(user): replicate level center page

This commit is contained in:
2026-09-13 21:28:10 +08:00
parent 6f1860f5d0
commit 632a7d15ba
4 changed files with 642 additions and 188 deletions
@@ -1,6 +1,6 @@
<?php
/**
* User center: growth level, route and experience history.
* User center: level summary, growth path and experience history.
*
* @package AKSRT
*/
@@ -9,7 +9,7 @@ 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')) {
if ($user_id <= 0 || !class_exists('\\AKSRT\\User\\Level')) {
return;
}
@@ -19,115 +19,152 @@ if (empty($cfg['enabled'])) {
}
$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);
$details = array_slice(\AKSRT\User\Level::get_details($user_id), 0, 50);
$date_details = array_slice(\AKSRT\User\Level::get_date_details($user_id), 0, 30, true);
$labels = \AKSRT\User\Level::integral_labels();
$opt = is_array($cfg['level_opt'] ?? null) ? $cfg['level_opt'] : [];
$level_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();
$current_level = max(1, (int) ($progress['level'] ?? 1));
$max_level = max(1, (int) ($cfg['max'] ?? 10));
$level_icon = (string) ($progress['icon'] ?? '');
$level_name = (string) ($progress['name'] ?? \AKSRT\User\Level::get_level_name($current_level));
$badge_html = '';
if ($level_icon !== '') {
$badge_html = '<img' . aksrt_get_lazy_attr('lazy_other', $level_icon, 'aksrt-level-card__badge img-icon') . ' alt="' . esc_attr($level_name) . '" title="' . esc_attr($level_name) . '" decoding="async">';
} else {
$badge_html = '<span class="aksrt-level-card__badge-text" title="' . esc_attr($level_name) . '">LV' . esc_html((string) $current_level) . '</span>';
}
$avatar_html = function_exists('aksrt_get_avatar_html')
? aksrt_get_avatar_html($user_id, 48, ['class' => 'avatar-mini'])
: get_avatar($user_id, 48);
$next_need = max(0, (int) ($progress['next_need'] ?? 0));
$integral = max(0, (int) ($progress['integral'] ?? 0));
$remaining = max(0, (int) ($progress['remaining'] ?? 0));
$percentage = max(0, min(100, (int) ($progress['progress'] ?? 0)));
?>
<div class="uc-level-page">
<section class="uc-level-hero aksrt-panel">
<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 aksrt-panel">
<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<?php echo aksrt_get_lazy_attr('lazy_other', (string) $icon); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt=""><?php else : ?><span>LV<?php echo esc_html((string) $level); ?></span><?php endif; ?>
<div class="aksrt-level-page">
<div class="row aksrt-level-page__summary">
<div class="col-md-5">
<section class="zib-widget colorful-bg jb-vip1 aksrt-level-card aksrt-level-card--summary">
<div class="colorful-make" aria-hidden="true"></div>
<div class="aksrt-level-card__summary-inner">
<div class="aksrt-level-card__identity">
<div class="avatar-mini aksrt-level-card__avatar"><?php echo $avatar_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<strong><?php esc_html_e('我的等级', 'aksrt'); ?></strong>
</div>
<div class="aksrt-level-card__current">
<?php echo $badge_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<span><?php echo esc_html($level_name); ?></span>
</div>
<div class="aksrt-level-card__progress-copy">
<?php if (!empty($progress['is_max'])) : ?>
<div class="flex jsb mb6 ab"><strong><?php echo esc_html((string) $integral); ?>/<?php echo esc_html((string) $integral); ?></strong><span><?php esc_html_e('已为最高等级', 'aksrt'); ?></span></div>
<?php else : ?>
<div class="flex jsb mb6 ab"><strong><?php echo esc_html((string) $integral); ?>/<?php echo esc_html((string) $next_need); ?></strong><span><?php printf(esc_html__('升级还需 %d 经验', 'aksrt'), $remaining); ?></span></div>
<?php endif; ?>
<div class="aksrt-level-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="<?php echo esc_attr((string) $percentage); ?>" aria-label="<?php esc_attr_e('等级进度', 'aksrt'); ?>"><span style="width:<?php echo esc_attr((string) $percentage); ?>%;"></span></div>
</div>
<strong><?php echo esc_html($name); ?></strong>
<small><?php echo esc_html((string) $need); ?> EXP</small>
</div>
<?php endfor; ?>
</section>
</div>
</section>
<section class="uc-level-section aksrt-panel">
<div class="uc-level-section__head"><h3><?php esc_html_e('获取经验值', 'aksrt'); ?></h3><span><?php esc_html_e('完成互动即可成长', 'aksrt'); ?></span></div>
<div class="uc-level-methods">
<?php
$methods = \AKSRT\User\Level::integral_defaults();
$methods['checkin'] = 0;
$methods['referral'] = 0;
$methods['shop_gift'] = 0;
$referral_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_referral_reward_settings() : [];
$methods['referral'] = max(0, (int) ($referral_settings['level_points'] ?? 0));
foreach ($methods as $key => $default_value) :
if ($key === 'day_max') continue;
$value = in_array($key, ['checkin', 'shop_gift'], true) ? 0 : ($key === 'referral' ? (int) $default_value : \AKSRT\User\Level::task_points($key));
if ($value <= 0 && !in_array($key, ['checkin', 'shop_gift'], true)) continue;
?>
<div class="uc-level-methods__item">
<span><i class="fa fas fa-bolt" aria-hidden="true"></i></span>
<div><strong><?php echo esc_html($labels[$key] ?? $key); ?></strong><small><?php echo in_array($key, ['checkin', 'shop_gift'], true) ? esc_html__('按活动或商品配置发放', 'aksrt') : esc_html__('完成后自动计入经验', 'aksrt'); ?></small></div>
<b><?php echo $value > 0 ? '+' . esc_html((string) $value) : esc_html__('动态', 'aksrt'); ?></b>
<div class="col-md-7">
<section class="zib-widget colorful-bg c-gray aksrt-level-card aksrt-level-card--growth">
<div class="colorful-make" aria-hidden="true"></div>
<div class="aksrt-level-card__growth-inner">
<div class="aksrt-level-card__growth-head">
<div>
<strong><i class="fa fas fa-line-chart" aria-hidden="true"></i><?php esc_html_e('成长体系', 'aksrt'); ?></strong>
<a class="muted-2-color" data-aksrt-level-tab="tab_integral_my" href="#tab_integral_my"><?php printf(esc_html__('我的经验值:%d', 'aksrt'), $integral); ?></a>
</div>
<a id="tab-integral-date-link" class="muted-2-color" data-aksrt-level-tab="tab_integral_date" href="#tab_integral_date"><?php echo $today_integral > 0 ? esc_html(sprintf(__('今日 +%d', 'aksrt'), $today_integral)) : esc_html__('查看详情', 'aksrt'); ?><i class="fa fa-angle-right ml6" aria-hidden="true"></i></a>
</div>
<div class="swiper-container swiper-scroll pillar-box aksrt-level-growth" scroll-nogroup="1">
<div class="swiper-wrapper">
<?php for ($level = 1; $level <= $max_level; $level++) :
$need = $level === 1 ? 0 : max(0, (int) ($level_opt['upgrade_integral_' . $level] ?? (($level - 1) * 500 * $level)));
$name = \AKSRT\User\Level::get_level_name($level);
$icon = \AKSRT\User\Level::get_level_icon_url($level);
$height = $level === 1 ? 0 : (int) round(86 * ($level / $max_level));
$state = $level === $current_level ? ' active' : ($level > $current_level ? ' is-future' : '');
?>
<div class="swiper-slide pillar-item<?php echo esc_attr($state); ?>" title="<?php echo esc_attr($name); ?>">
<div class="value"><?php echo esc_html((string) $need); ?></div>
<div class="pillar" style="height:<?php echo esc_attr((string) $height); ?>px;"></div>
<div class="level-name">
<?php if ($icon !== '') : ?><img<?php echo aksrt_get_lazy_attr('lazy_other', $icon, 'aksrt-level-growth__badge img-icon'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="<?php echo esc_attr($name); ?>" title="<?php echo esc_attr($name); ?>" decoding="async"><?php else : ?><span>LV<?php echo esc_html((string) $level); ?></span><?php endif; ?>
</div>
</div>
<?php endfor; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</section>
</div>
</section>
</div>
<div class="uc-level-history-grid">
<section class="uc-level-section aksrt-panel">
<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));
<section class="zib-widget aksrt-level-experience">
<div class="box-body">
<div class="aksrt-level-tabs" role="tablist" aria-label="<?php esc_attr_e('经验记录', 'aksrt'); ?>">
<a id="tab-integral-get" class="but mr6 is-active" data-aksrt-level-tab="tab_integral_get" href="#tab_integral_get" role="tab" aria-controls="tab_integral_get" aria-selected="true"><?php esc_html_e('获取经验值', 'aksrt'); ?></a>
<a id="tab-integral-my" class="but" data-aksrt-level-tab="tab_integral_my" href="#tab_integral_my" role="tab" aria-controls="tab_integral_my" aria-selected="false"><?php esc_html_e('我的经验值', 'aksrt'); ?></a>
</div>
<div class="tab-content mt20">
<div class="tab-pane fade active in" id="tab_integral_get" role="tabpanel" aria-labelledby="tab-integral-get">
<?php
$methods = \AKSRT\User\Level::integral_defaults();
$methods['checkin'] = 0;
$methods['referral'] = 0;
$methods['shop_gift'] = 0;
$referral_settings = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_referral_reward_settings() : [];
$methods['referral'] = max(0, (int) ($referral_settings['level_points'] ?? 0));
foreach ($methods as $key => $default_value) :
if ($key === 'day_max') {
continue;
}
$value = in_array($key, ['checkin', 'shop_gift'], true) ? 0 : ($key === 'referral' ? (int) $default_value : \AKSRT\User\Level::task_points($key));
if ($value <= 0 && !in_array($key, ['checkin', 'shop_gift'], true)) {
continue;
}
?>
<div class="uc-level-ledger__row">
<span class="uc-level-ledger__icon"><i class="fa 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><small><?php printf(esc_html__('累计:%d', 'aksrt'), max(0, (int) ($row['integral'] ?? 0))); ?></small></div>
<b>+<?php echo esc_html((string) $value); ?></b>
<div class="border-bottom padding-h10 aksrt-level-list-row">
<div class="flex jsb ac">
<div class="flex1 mr20"><div class="font-bold mb6"><?php echo esc_html($labels[$key] ?? $key); ?></div><div class="muted-2-color em09"><?php echo in_array($key, ['checkin', 'shop_gift'], true) ? esc_html__('按活动或商品配置发放', 'aksrt') : esc_html__('完成后自动计入经验', 'aksrt'); ?></div></div>
<span class="focus-color em14 shrink0"><i class="fa fas fa-bolt mr6" aria-hidden="true"></i><?php echo $value > 0 ? '+' . esc_html((string) $value) : esc_html__('动态', 'aksrt'); ?></span>
</div>
</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 aksrt-panel">
<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 class="tab-pane fade" id="tab_integral_my" role="tabpanel" aria-labelledby="tab-integral-my" hidden>
<?php if ($today_integral > 0) : ?>
<div class="border-bottom padding-h10 aksrt-level-list-row"><div class="flex jsb ac"><div class="flex1 mr20"><div class="font-bold mb6"><?php printf(esc_html__('今日累计 +%d', 'aksrt'), $today_integral); ?></div><div class="muted-2-color em09"><?php echo $day_max > $today_integral ? esc_html(sprintf(__('每日最多获得 %d 经验', 'aksrt'), $day_max)) : esc_html__('今日累计已达到上限', 'aksrt'); ?></div></div><a class="muted-2-color shrink0" data-aksrt-level-tab="tab_integral_date" href="#tab_integral_date" role="tab" aria-controls="tab_integral_date"><?php esc_html_e('每日详情', 'aksrt'); ?><i class="fa fa-angle-right ml6" aria-hidden="true"></i></a></div></div>
<?php endif; ?>
<?php if ($details) : ?>
<?php foreach ($details as $row) :
$key = sanitize_key((string) ($row['key'] ?? ''));
$value = max(0, (int) ($row['value'] ?? 0));
$detail_integral = max(0, (int) ($row['integral'] ?? 0));
?>
<div class="border-bottom padding-h10 aksrt-level-list-row"><div class="flex jsb ac"><div class="flex1 mr20"><div class="font-bold mb6"><?php echo esc_html($labels[$key] ?? $key); ?></div><div class="muted-2-color em09"><?php echo esc_html((string) ($row['time'] ?? '')); ?></div></div><div class="text-right shrink0"><div class="focus-color em14 mb6">+ <?php echo esc_html((string) $value); ?></div><div class="muted-2-color em09"><?php printf(esc_html__('累计:%d', 'aksrt'), $detail_integral); ?></div></div></div></div>
<?php endforeach; ?>
<?php else : ?>
<p class="aksrt-level-empty"><?php esc_html_e('暂无经验值获取明细', 'aksrt'); ?></p>
<?php endif; ?>
<?php if ($details) : ?><div class="text-center mt20 muted-3-color"><?php esc_html_e('最多显示近50条记录', 'aksrt'); ?></div><?php endif; ?>
</div>
<?php else : ?>
<p class="uc-level-empty"><?php esc_html_e('还没有每日经验记录。', 'aksrt'); ?></p>
<?php endif; ?>
</section>
</div>
<div class="tab-pane fade" id="tab_integral_date" role="tabpanel" aria-labelledby="tab-integral-date-link" hidden>
<?php if ($date_details) : ?>
<?php foreach ($date_details as $date => $value) : ?><div class="border-bottom padding-h6 flex jsb ac aksrt-level-date-row"><div class="em12"><?php echo esc_html((string) $date); ?></div><div class="text-right shrink0 focus-color em14 font-bold">+ <?php echo esc_html((string) max(0, (int) $value)); ?></div></div><?php endforeach; ?>
<div class="text-center mt20 muted-3-color"><?php esc_html_e('最多显示近30条记录', 'aksrt'); ?></div>
<?php else : ?>
<p class="aksrt-level-empty"><?php esc_html_e('暂无经验值获取明细', 'aksrt'); ?></p>
<?php endif; ?>
</div>
</div>
</div>
</section>
</div>