diff --git a/assets/css/frontend/medal.css b/assets/css/frontend/medal.css index 60f2760e..deb8d39a 100644 --- a/assets/css/frontend/medal.css +++ b/assets/css/frontend/medal.css @@ -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; diff --git a/assets/css/frontend/nav/header-userbox.css b/assets/css/frontend/nav/header-userbox.css index 88d8bc86..fea79320 100644 --- a/assets/css/frontend/nav/header-userbox.css +++ b/assets/css/frontend/nav/header-userbox.css @@ -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; diff --git a/inc/helpers/aksrt-identity.php b/inc/helpers/aksrt-identity.php index eac33cd5..634d3fe4 100644 --- a/inc/helpers/aksrt-identity.php +++ b/inc/helpers/aksrt-identity.php @@ -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'] ?? '')); diff --git a/inc/helpers/header/aksrt-header-navbar.php b/inc/helpers/header/aksrt-header-navbar.php index 73cf36ef..ea1a5976 100644 --- a/inc/helpers/header/aksrt-header-navbar.php +++ b/inc/helpers/header/aksrt-header-navbar.php @@ -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 .= '
'; $con .= '
' - . '' . esc_html($display_name) . '' . $vip_badge . $certification_badge . $level_badge + . '' . esc_html($display_name) . '' . $vip_badge . $medal_badge . $certification_badge . $level_badge . '
' . esc_html($desc) . '
'; $con .= '
'; $con .= $msg_icon; diff --git a/inc/helpers/user-center-renderers/profile-header.php b/inc/helpers/user-center-renderers/profile-header.php index 607a85ca..e41d298a 100644 --- a/inc/helpers/user-center-renderers/profile-header.php +++ b/inc/helpers/user-center-renderers/profile-header.php @@ -37,7 +37,7 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_

display_name); ?> - true]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + true, 'skip_badges' => true]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

diff --git a/src/User/Home.php b/src/User/Home.php index 4578d551..678ab9cc 100644 --- a/src/User/Home.php +++ b/src/User/Home.php @@ -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++; } } } diff --git a/templates/parts/user/author-hero.php b/templates/parts/user/author-hero.php index a532b9e4..75ddf43b 100644 --- a/templates/parts/user/author-hero.php +++ b/templates/parts/user/author-hero.php @@ -93,7 +93,7 @@ $pm_url = ($pm_enabled && $messages_url !== '')

- $user_id, 'class' => 'aksrt-author-hero__name-inner', 'vip' => true, 'medal' => true, 'auth' => true, 'level' => true, 'follow' => false]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + $user_id, 'class' => 'aksrt-author-hero__name-inner', 'vip' => true, 'medal' => false, 'auth' => true, 'level' => true, 'follow' => false]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> display_name); ?>