Merge pull request 'Worktree zibll badge entry replica' (#429) from worktree-zibll-badge-entry-replica into main

Reviewed-on: CYL/wordpress-theme-aksrt#429
This commit is contained in:
2026-08-11 19:49:47 +08:00
7 changed files with 79 additions and 31 deletions
+24 -9
View File
@@ -8,32 +8,39 @@
* ============================================================ */
/* ---------- 顶部资料卡入口(zibll user-medal-info parity) ---------- */
.aksrt-medal-entry {
.aksrt-medal-entry,
.uc-header__meta-item {
display: inline-flex;
align-items: center;
gap: 4px;
min-width: 0;
margin: 2px 8px 2px 0;
padding: 2px 0;
border: 0;
background: transparent;
color: var(--muted-2-color, var(--color-ink-4));
padding: .3em .6em;
border: 1px solid var(--color-line-soft, var(--main-border-color, rgba(136, 136, 136, .18)));
border-radius: var(--mini-radius, 4px);
background: var(--surface-2, rgba(136, 136, 136, .1));
box-shadow: var(--shadow-xs, 0 1px 3px rgba(0, 0, 0, .08));
color: var(--muted-2-color, var(--color-ink-3));
font: inherit;
font-size: 12px;
line-height: 1.4;
cursor: pointer;
line-height: 1.44;
white-space: nowrap;
transition: color .15s ease, opacity .15s ease;
}
.aksrt-medal-entry {
cursor: pointer;
transition: color .15s ease, background-color .15s ease, border-color .15s ease, box-shadow .15s ease, opacity .15s ease;
}
.aksrt-medal-entry:hover,
.aksrt-medal-entry:focus-visible {
border-color: var(--focus-color-opacity3, var(--focus-color));
background: var(--focus-color-opacity1, rgba(59, 130, 246, .1));
box-shadow: var(--shadow-sm, 0 2px 8px rgba(0, 0, 0, .1));
color: var(--focus-color);
opacity: 1;
}
.aksrt-medal-entry:focus-visible {
outline: 2px solid var(--focus-color);
outline-offset: 2px;
border-radius: var(--mini-radius, 6px);
}
.aksrt-medal-entry__icons {
display: inline-flex;
@@ -63,6 +70,14 @@
.aksrt-medal-entry__count { margin-left: 2px; }
.aksrt-medal-entry__arrow { margin-left: 1px; font-size: .9em; }
@media (max-width: 767px) {
.aksrt-medal-entry,
.uc-header__meta-item {
margin-right: 4px;
max-width: 100%;
}
}
.medal-cat-box {
position: relative;
+2 -1
View File
@@ -231,7 +231,8 @@
max-width: 100%;
}
.sub-user-box .user-right .aksrt-user-level-icon,
.sub-user-box .user-right .aksrt-identity-medal {
.sub-user-box .user-right .aksrt-identity-medal,
.sub-user-box .user-right .aksrt-header-user-medal {
height: 1em;
vertical-align: -.12em;
flex: 0 0 auto;
+10 -1
View File
@@ -36,6 +36,7 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
*
* @type bool $include_vip Whether to prepend VIP badge. Default true.
* @type bool $skip_level Whether to omit the level chip (rendered inline elsewhere). Default false.
* @type bool $skip_badges Whether to omit badge signals from this row. Default false.
* }
*/
function aksrt_render_user_identity_chips(int $user_id, string $context = 'author', array $args = []): string {
@@ -59,7 +60,12 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
$priority = ['verify' => 0, 'badge' => 1, 'level' => 2];
return ($priority[(string) ($left['type'] ?? '')] ?? 3) <=> ($priority[(string) ($right['type'] ?? '')] ?? 3);
});
// Comments stay compact; author/card can show more.
if ($context === 'comment') {
$signals = array_values(array_filter($signals, static function (array $signal): bool {
return (string) ($signal['type'] ?? '') !== 'badge' || !empty($signal['wear']);
}));
}
// Comments stay compact; author/card can show more.
$limit = $context === 'comment' ? 3 : 6;
$n = 0;
foreach ($signals as $signal) {
@@ -75,6 +81,9 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
if (!empty($args['skip_level']) && $type === 'level') {
continue;
}
if (!empty($args['skip_badges']) && $type === 'badge') {
continue;
}
$tone = sanitize_html_class((string) ($signal['tone'] ?? 'info'));
$icon = sanitize_html_class((string) ($signal['icon'] ?? 'check'));
$icon_url = esc_url((string) ($signal['icon_url'] ?? ''));
+5 -2
View File
@@ -155,7 +155,10 @@ if (!function_exists('aksrt_header_user_box_html')) :
$level_badge = (class_exists('\AKSRT\User\Level') && method_exists('\AKSRT\User\Level', 'get_badge_html'))
? \AKSRT\User\Level::get_badge_html($user_id, 'aksrt-user-level-icon--header')
: '';
$certification_badge = '';
$medal_badge = function_exists('aksrt_get_worn_medal_icon')
? aksrt_get_worn_medal_icon($user_id, 'aksrt-header-user-medal')
: '';
$certification_badge = '';
if (function_exists('aksrt_get_user_identity_signals')) {
foreach (aksrt_get_user_identity_signals($user_id) as $signal) {
if ((string) ($signal['type'] ?? '') !== 'verify') {
@@ -238,7 +241,7 @@ if (!function_exists('aksrt_header_user_box_html')) :
$con .= $avatar;
$con .= '<div class="user-right flex flex1 ac jsb ml10">';
$con .= '<div class="flex1" style="max-width: calc(100% - 40px);"><b>'
. '<span class="display-name text-ellipsis">' . esc_html($display_name) . '</span>' . $vip_badge . $certification_badge . $level_badge
. '<span class="display-name text-ellipsis">' . esc_html($display_name) . '</span>' . $vip_badge . $medal_badge . $certification_badge . $level_badge
. '</b><div class="px12 muted-2-color text-ellipsis">' . esc_html($desc) . '</div></div>';
$con .= '</div>';
$con .= $msg_icon;
@@ -37,7 +37,7 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_
<h1 class="uc-header__name">
<?php echo esc_html($target_user->display_name); ?>
<?php if (function_exists('aksrt_render_user_identity_chips')) : ?>
<?php echo aksrt_render_user_identity_chips((int) $user_id, 'author', ['include_vip' => true]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo aksrt_render_user_identity_chips((int) $user_id, 'author', ['include_vip' => true, 'skip_badges' => true]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endif; ?>
</h1>
<div class="uc-header__meta desc user-identity flex ac hh">
+36 -16
View File
@@ -165,31 +165,51 @@ class Home {
$limit = max(1, (int) ($settings['medal']['limit'] ?? 3));
if (class_exists('AKSRT\\User\\Badges')) {
$list = Badges::list_for_user($user_id);
$badge_count = 0;
$done = false;
$badge_items = [];
$worn_item = null;
foreach ((array) ($list['categories'] ?? []) as $cat) {
foreach ((array) ($cat['items'] ?? []) as $item) {
if (empty($item['owned'])) {
continue;
}
if ($badge_count >= $limit) {
$done = true;
break;
if (!empty($item['wear'])) {
$worn_item = $item;
}
$signals[] = [
'type' => 'badge',
'slug' => (string) ($item['slug'] ?? ''),
'label' => (string) ($item['label'] ?? ''),
'icon' => 'award',
'tone' => 'info',
'icon_url' => (string) ($item['icon_url'] ?? ''),
'wear' => !empty($item['wear']),
];
$badge_count++;
$badge_items[] = $item;
}
if ($done) {
}
// Keep the worn badge visible even when it falls after the configured preview limit.
if (is_array($worn_item)) {
$signals[] = [
'type' => 'badge',
'slug' => (string) ($worn_item['slug'] ?? ''),
'label' => (string) ($worn_item['label'] ?? ''),
'icon' => 'award',
'tone' => 'info',
'icon_url' => (string) ($worn_item['icon_url'] ?? ''),
'wear' => true,
];
}
$badge_count = is_array($worn_item) ? 1 : 0;
foreach ($badge_items as $item) {
if (!empty($item['wear'])) {
continue;
}
if ($badge_count >= $limit) {
break;
}
$signals[] = [
'type' => 'badge',
'slug' => (string) ($item['slug'] ?? ''),
'label' => (string) ($item['label'] ?? ''),
'icon' => 'award',
'tone' => 'info',
'icon_url' => (string) ($item['icon_url'] ?? ''),
'wear' => false,
];
$badge_count++;
}
}
}
+1 -1
View File
@@ -93,7 +93,7 @@ $pm_url = ($pm_enabled && $messages_url !== '')
<?php if ($show_name) : ?>
<h1 class="aksrt-author-hero__name">
<?php if (function_exists('aksrt_get_user_name')) : ?>
<?php echo aksrt_get_user_name(['id' => $user_id, 'class' => 'aksrt-author-hero__name-inner', 'vip' => true, 'medal' => true, 'auth' => true, 'level' => true, 'follow' => false]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo aksrt_get_user_name(['id' => $user_id, 'class' => 'aksrt-author-hero__name-inner', 'vip' => true, 'medal' => false, 'auth' => true, 'level' => true, 'follow' => false]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php else : ?>
<?php echo esc_html($user->display_name); ?>
<?php endif; ?>