fix(comments): match avatar identity layout

This commit is contained in:
2026-09-27 00:37:00 +08:00
parent 47bf9c8f0b
commit 26ac8167f3
14 changed files with 51 additions and 176 deletions
+1 -46
View File
@@ -2598,7 +2598,6 @@ main.container,
* All compact identity marks share one line-height baseline: VIP, level, * All compact identity marks share one line-height baseline: VIP, level,
* certification, and worn medals remain visually aligned in every surface. * certification, and worn medals remain visually aligned in every surface.
*/ */
.aksrt-vip-badge,
.aksrt-user-level-badge, .aksrt-user-level-badge,
.aksrt-user-level-icon, .aksrt-user-level-icon,
.aksrt-identity-medal, .aksrt-identity-medal,
@@ -2615,17 +2614,6 @@ main.container,
flex: 0 0 auto; flex: 0 0 auto;
box-sizing: border-box; box-sizing: border-box;
} }
.aksrt-vip-badge__icon {
display: block;
width: auto;
height: 1.1em;
max-width: 6em;
object-fit: contain;
}
.aksrt-vip-badge > i {
font-size: .9em;
line-height: 1;
}
.aksrt-user-level-badge { .aksrt-user-level-badge {
padding: 0 .35em; padding: 0 .35em;
font-size: .78em; font-size: .78em;
@@ -2639,11 +2627,6 @@ main.container,
height: 1em; height: 1em;
vertical-align: -.12em; vertical-align: -.12em;
} }
.aksrt-vip-badge--sm {
height: 1.1em;
padding: 0;
font-size: inherit;
}
/* No-wrap inline name rows — keep the level icon on the same line as the name. /* No-wrap inline name rows — keep the level icon on the same line as the name.
* The non-standard <name> element (legacy compat) plus .user-name / author-hero / * The non-standard <name> element (legacy compat) plus .user-name / author-hero /
@@ -2913,7 +2896,7 @@ main.container,
white-space: nowrap; white-space: nowrap;
} }
.aksrt-header-userbox .user-right .aksrt-vip-badge, .aksrt-header-userbox .user-right .img-icon,
.aksrt-header-userbox .user-right .aksrt-user-level-icon, .aksrt-header-userbox .user-right .aksrt-user-level-icon,
.aksrt-header-userbox .user-right .aksrt-identity-medal, .aksrt-header-userbox .user-right .aksrt-identity-medal,
.aksrt-header-userbox .user-right .aksrt-header-user-medal, .aksrt-header-userbox .user-right .aksrt-header-user-medal,
@@ -5915,34 +5898,6 @@ body.aksrt-body-scroll .aksrt-show-on-scroll {
transition: transform 0.1s linear; transition: transform 0.1s linear;
} }
/* ============================================================
* 18. VIP 等级标识
* ============================================================ */
.aksrt-vip-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 8px;
border-radius: var(--radius-pill, 999px);
font-size: 11px;
font-weight: 600;
}
.aksrt-vip-badge--gold {
background: linear-gradient(135deg, #FFD700, #FFA500);
color: #fff;
}
.aksrt-vip-badge--silver {
background: linear-gradient(135deg, #C0C0C0, #A8A8A8);
color: #fff;
}
.aksrt-vip-badge--bronze {
background: linear-gradient(135deg, #CD7F32, #A0522D);
color: #fff;
}
/* ============================================================ /* ============================================================
* 20. 用户等级进度条 * 20. 用户等级进度条
* ============================================================ */ * ============================================================ */
+1 -1
View File
File diff suppressed because one or more lines are too long
-17
View File
@@ -195,7 +195,6 @@ main.container,
* All compact identity marks share one line-height baseline: VIP, level, * All compact identity marks share one line-height baseline: VIP, level,
* certification, and worn medals remain visually aligned in every surface. * certification, and worn medals remain visually aligned in every surface.
*/ */
.aksrt-vip-badge,
.aksrt-user-level-badge, .aksrt-user-level-badge,
.aksrt-user-level-icon, .aksrt-user-level-icon,
.aksrt-identity-medal, .aksrt-identity-medal,
@@ -212,17 +211,6 @@ main.container,
flex: 0 0 auto; flex: 0 0 auto;
box-sizing: border-box; box-sizing: border-box;
} }
.aksrt-vip-badge__icon {
display: block;
width: auto;
height: 1.1em;
max-width: 6em;
object-fit: contain;
}
.aksrt-vip-badge > i {
font-size: .9em;
line-height: 1;
}
.aksrt-user-level-badge { .aksrt-user-level-badge {
padding: 0 .35em; padding: 0 .35em;
font-size: .78em; font-size: .78em;
@@ -236,11 +224,6 @@ main.container,
height: 1em; height: 1em;
vertical-align: -.12em; vertical-align: -.12em;
} }
.aksrt-vip-badge--sm {
height: 1.1em;
padding: 0;
font-size: inherit;
}
/* No-wrap inline name rows — keep the level icon on the same line as the name. /* No-wrap inline name rows — keep the level icon on the same line as the name.
* The non-standard <name> element (legacy compat) plus .user-name / author-hero / * The non-standard <name> element (legacy compat) plus .user-name / author-hero /
+2 -38
View File
@@ -282,47 +282,11 @@
color: #fff; color: #fff;
} }
/* ============ VIP 徽标 ============ */ /* Configured paid-content tier icons. */
.aksrt-vip-badge { .aksrt-vip-level-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: auto;
height: 1.1em;
padding: 0;
border-radius: 0;
font: inherit;
line-height: 1;
background: transparent;
color: inherit;
vertical-align: -.15em;
}
.aksrt-vip-level-icon,
.aksrt-vip-badge__icon {
display: block; display: block;
width: auto; width: auto;
height: 1.1em; height: 1.1em;
max-width: 6em; max-width: 6em;
object-fit: contain; object-fit: contain;
} }
.aksrt-vip-badge i {
font-size: .9em;
line-height: 1;
}
.aksrt-vip-badge--sm {
height: 1.1em;
padding: 0;
font-size: inherit;
}
.aksrt-vip-badge--lg {
padding: 4px 12px;
font-size: 13px;
}
.aksrt-vip-badge--lg i {
font-size: 12px;
}
@@ -355,34 +355,6 @@
transition: transform 0.1s linear; transition: transform 0.1s linear;
} }
/* ============================================================
* 18. VIP 等级标识
* ============================================================ */
.aksrt-vip-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 8px;
border-radius: var(--radius-pill, 999px);
font-size: 11px;
font-weight: 600;
}
.aksrt-vip-badge--gold {
background: linear-gradient(135deg, #FFD700, #FFA500);
color: #fff;
}
.aksrt-vip-badge--silver {
background: linear-gradient(135deg, #C0C0C0, #A8A8A8);
color: #fff;
}
.aksrt-vip-badge--bronze {
background: linear-gradient(135deg, #CD7F32, #A0522D);
color: #fff;
}
/* ============================================================ /* ============================================================
* 20. 用户等级进度条 * 20. 用户等级进度条
* ============================================================ */ * ============================================================ */
+1 -1
View File
@@ -202,7 +202,7 @@
white-space: nowrap; white-space: nowrap;
} }
.aksrt-header-userbox .user-right .aksrt-vip-badge, .aksrt-header-userbox .user-right .img-icon,
.aksrt-header-userbox .user-right .aksrt-user-level-icon, .aksrt-header-userbox .user-right .aksrt-user-level-icon,
.aksrt-header-userbox .user-right .aksrt-identity-medal, .aksrt-header-userbox .user-right .aksrt-identity-medal,
.aksrt-header-userbox .user-right .aksrt-header-user-medal, .aksrt-header-userbox .user-right .aksrt-header-user-medal,
+2 -6
View File
@@ -137,7 +137,7 @@
.article-avatar name.flex > .display-name { .article-avatar name.flex > .display-name {
line-height: 1.1; line-height: 1.1;
} }
.article-avatar name.flex > .aksrt-vip-badge, .article-avatar name.flex > .img-icon,
.article-avatar name.flex > .aksrt-identity-certification-icon, .article-avatar name.flex > .aksrt-identity-certification-icon,
.article-avatar name.flex > .aksrt-identity-medal, .article-avatar name.flex > .aksrt-identity-medal,
.article-avatar name.flex > .aksrt-user-level-icon, .article-avatar name.flex > .aksrt-user-level-icon,
@@ -157,16 +157,12 @@
box-sizing: border-box; box-sizing: border-box;
flex: 0 0 auto; flex: 0 0 auto;
} }
.article-avatar name.flex > .aksrt-vip-badge__icon, .article-avatar name.flex > .img-icon,
.article-avatar name.flex > .aksrt-identity-certification-icon, .article-avatar name.flex > .aksrt-identity-certification-icon,
.article-avatar name.flex > .aksrt-identity-medal, .article-avatar name.flex > .aksrt-identity-medal,
.article-avatar name.flex > .aksrt-user-level-icon { .article-avatar name.flex > .aksrt-user-level-icon {
object-fit: contain; object-fit: contain;
} }
.article-avatar name.flex > .aksrt-vip-badge > i {
font-size: .9em;
line-height: 1;
}
.article-avatar name.flex > .aksrt-user-level-badge { .article-avatar name.flex > .aksrt-user-level-badge {
font-size: .78em; font-size: .78em;
white-space: nowrap; white-space: nowrap;
+2 -2
View File
@@ -37,8 +37,8 @@
} }
/* VIP, level and worn-medal marks share the global identity baseline. */ /* VIP, level and worn-medal marks share the global identity baseline. */
.uc-header__name .aksrt-vip-badge__icon, .uc-header__name > .img-icon,
h1.uc-header__name .aksrt-vip-badge__icon, h1.uc-header__name > .img-icon,
.uc-header__name .medal-icon.img-icon, .uc-header__name .medal-icon.img-icon,
.uc-header__name .aksrt-identity-medal, .uc-header__name .aksrt-identity-medal,
h1.uc-header__name .medal-icon.img-icon, h1.uc-header__name .medal-icon.img-icon,
+10 -10
View File
@@ -511,18 +511,18 @@ if (!function_exists('aksrt_comments_render_form')) :
<div class="comt-title text-center flex0 mr10"> <div class="comt-title text-center flex0 mr10">
<?php if ($is_logged_in && $current_user instanceof WP_User) : ?> <?php if ($is_logged_in && $current_user instanceof WP_User) : ?>
<div class="comt-avatar mb10"> <div class="comt-avatar mb10">
<?php echo get_avatar($current_user->ID, 60, '', '', ['class' => 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> <?php echo aksrt_get_avatar_html($current_user->ID, 96, ['class' => 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- canonical avatar helper escapes output. ?>
</div> </div>
<p class="text-ellipsis muted-2-color"><?php echo function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($current_user->ID) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- vip 徽章内部已转义。 ?><?php echo esc_html($current_user->display_name); ?></p> <p class="text-ellipsis muted-2-color"><?php echo function_exists('aksrt_get_vip_icon') ? aksrt_get_vip_icon($current_user->ID, 'em12 mr3') : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- VIP helper escapes output. ?><?php echo esc_html($current_user->display_name); ?></p>
<?php else : ?> <?php else : ?>
<div class="comt-avatar mb10"> <div class="comt-avatar mb10">
<?php echo get_avatar(0, 60, '', '', ['class' => 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> <?php echo aksrt_get_avatar_html(0, 96, ['class' => 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- canonical avatar helper escapes output. ?>
</div> </div>
<p data-toggle-class="open" data-target="#comment-user-info" data-toggle="tooltip" title="<?php esc_attr_e('填写用户信息', 'aksrt'); ?>"> <p class="" data-toggle-class="open" data-target="#comment-user-info" data-toggle="tooltip" title="<?php esc_attr_e('填写用户信息', 'aksrt'); ?>">
<?php echo $comment_author !== '' ? esc_html($comment_author) : esc_html__('昵称', 'aksrt'); ?> <?php echo $comment_author !== '' ? esc_html($comment_author) : esc_html__('昵称', 'aksrt'); ?>
</p> </p>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="comt-box grow1"> <div class="comt-box grow1">
<div class="action-text mb10 em09 muted-2-color" id="comment-reply-info" style="display:none;"></div> <div class="action-text mb10 em09 muted-2-color" id="comment-reply-info" style="display:none;"></div>
<textarea placeholder="<?php echo esc_attr($placeholder); ?>" autoheight="true" maxheight="188" class="form-control grin" name="comment" id="comment" cols="100%" rows="4" tabindex="1"></textarea> <textarea placeholder="<?php echo esc_attr($placeholder); ?>" autoheight="true" maxheight="188" class="form-control grin" name="comment" id="comment" cols="100%" rows="4" tabindex="1"></textarea>
+4 -4
View File
@@ -68,8 +68,8 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
'skip_level' => false, 'skip_level' => false,
]); ]);
$html = ''; $html = '';
if (!empty($args['include_vip']) && function_exists('aksrt_render_vip_badge')) { if (!empty($args['include_vip']) && function_exists('aksrt_get_vip_icon')) {
$vip = aksrt_render_vip_badge($user_id, 'sm'); $vip = aksrt_get_vip_icon($user_id);
if (is_string($vip) && $vip !== '') { if (is_string($vip) && $vip !== '') {
$html .= $vip; $html .= $vip;
} }
@@ -216,8 +216,8 @@ if (!function_exists('aksrt_get_user_name')) {
$vip_html = function_exists('aksrt_get_user_ban_name_badge') $vip_html = function_exists('aksrt_get_user_ban_name_badge')
? aksrt_get_user_ban_name_badge($user_id) ? aksrt_get_user_ban_name_badge($user_id)
: ''; : '';
if ($vip_html === '' && function_exists('aksrt_render_vip_badge')) { if ($vip_html === '' && function_exists('aksrt_get_vip_icon')) {
$vip_html = (string) aksrt_render_vip_badge($user_id, 'sm'); $vip_html = (string) aksrt_get_vip_icon($user_id);
} }
} }
$name_class = trim('display-name text-ellipsis ' . (string) $args['name_class']); $name_class = trim('display-name text-ellipsis ' . (string) $args['name_class']);
+17 -20
View File
@@ -342,32 +342,29 @@ if (!function_exists('aksrt_get_free_download_surplus')) {
/** /**
* 渲染 VIP 徽标 HTML * Render the configured VIP icon with the frontend identity-image contract.
* *
* @param int $user_id * @param int $user_id User ID.
* @param string $size sm | md | lg * @param string $class Additional image classes.
* @return string * @param bool $tooltip Whether to enable the tooltip trigger.
*/ */
function aksrt_render_vip_badge(int $user_id = 0, string $size = 'sm'): string { function aksrt_get_vip_icon(int $user_id = 0, string $class = 'em12 ml3', bool $tooltip = true): string {
if (!aksrt_is_vip($user_id)) { $level = aksrt_get_user_vip_level($user_id);
if ($level <= 0 || !class_exists('\AKSRT\Settings\Settings')) {
return ''; return '';
} }
$level = aksrt_get_user_vip_level($user_id); $vip_settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
$badge_text = aksrt_get_vip_badge_text($user_id); $icon_url = esc_url((string) ($vip_settings['levels'][$level]['img_icon'] ?? ''));
$size_class = 'aksrt-vip-badge--' . $size; if ($icon_url === '') {
$level_class = $level >= 2 ? 'aksrt-vip-badge--vip2' : 'aksrt-vip-badge--vip1'; return '';
$icon_url = '';
if (class_exists('\AKSRT\Settings\Settings')) {
$vip_settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
$icon_url = esc_url((string) ($vip_settings['levels'][$level]['img_icon'] ?? ''));
} }
$icon = $icon_url !== ''
? '<img' . aksrt_get_lazy_attr('lazy_other', $icon_url, 'aksrt-vip-badge__icon') . ' alt="" decoding="async">'
: '<i class="fa fas fa-certificate" aria-hidden="true"></i>';
return '<span class="aksrt-vip-badge aksrt-vip-badge--gold ' . esc_attr($size_class . ' ' . $level_class) . '" title="' . esc_attr($badge_text) . '">' . $icon . '</span>'; $name = sanitize_text_field((string) ($vip_settings['levels'][$level]['name'] ?? aksrt_get_vip_badge_text($user_id)));
$tooltip_attr = $tooltip ? ' data-toggle="tooltip"' : '';
return '<img' . aksrt_get_lazy_attr('lazy_other', $icon_url, trim('img-icon ' . $class), aksrt_get_lazy_thumb())
. $tooltip_attr . ' title="' . esc_attr($name) . '" alt="' . esc_attr($name) . '">';
} }
/** /**
@@ -403,7 +400,7 @@ function aksrt_get_vip_info(int $user_id = 0): array {
'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_get_vip_icon($user_id) : '',
'name' => $name, 'name' => $name,
'expires' => $expires, 'expires' => $expires,
'expires_label' => $expires_label, 'expires_label' => $expires_label,
+1 -1
View File
@@ -142,7 +142,7 @@ if (!function_exists('aksrt_header_user_box_html')) :
$display_name = $user->display_name ?: $user->user_login; $display_name = $user->display_name ?: $user->user_login;
$avatar = aksrt_get_avatar_html($user_id, 44, ['alt' => $display_name]); $avatar = aksrt_get_avatar_html($user_id, 44, ['alt' => $display_name]);
$desc = (string) ($ctx['user_desc'] ?? ''); $desc = (string) ($ctx['user_desc'] ?? '');
$vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id, 'sm') : ''; $vip_badge = function_exists('aksrt_get_vip_icon') ? aksrt_get_vip_icon($user_id) : '';
// Level and certification icons ride inline to the right of the display name. // Level and certification icons ride inline to the right of the display name.
$level_badge = (class_exists('\AKSRT\User\Level') && method_exists('\AKSRT\User\Level', 'get_badge_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') ? \AKSRT\User\Level::get_badge_html($user_id, 'aksrt-user-level-icon--header')
+1 -1
View File
@@ -61,7 +61,7 @@ class CreditsAdmin {
if (function_exists('aksrt_get_user_vip_level')) { if (function_exists('aksrt_get_user_vip_level')) {
$lv = (int) aksrt_get_user_vip_level($user_id); $lv = (int) aksrt_get_user_vip_level($user_id);
if ($lv > 0) { if ($lv > 0) {
$bits[] = '<span class="aksrt-vip-badge">VIP' . esc_html((string) $lv) . '</span>'; $bits[] = '<strong>VIP' . esc_html((string) $lv) . '</strong>';
} }
} }
if (class_exists('\AKSRT\Payment\Revenue')) { if (class_exists('\AKSRT\Payment\Revenue')) {
@@ -169,9 +169,17 @@ test('comment markup keeps the 1:1 legacy DOM contract', () => {
assert.ok(comments.includes('user_url_enabled'), 'guest url field toggle must be wired'); assert.ok(comments.includes('user_url_enabled'), 'guest url field toggle must be wired');
assert.ok(comments.includes("name=\"url\""), 'guest url input must render'); assert.ok(comments.includes("name=\"url\""), 'guest url input must render');
assert.ok(comments.includes("aksrt_get_comment_icon('signup', 'icon mr10')"), 'signarea signup must use the sprite icon'); assert.ok(comments.includes("aksrt_get_comment_icon('signup', 'icon mr10')"), 'signarea signup must use the sprite icon');
assert.ok(comments.includes('aksrt_render_vip_badge'), 'comt-title must render the vip badge (legacy: zibpay_get_vip_icon)'); assert.ok(comments.includes("aksrt_get_vip_icon($current_user->ID, 'em12 mr3')"), 'comt-title must render the direct VIP image with reference-theme spacing');
assert.ok(comments.includes("aksrt_get_avatar_html($current_user->ID, 96, ['class' => 'avatar'])"), 'logged-in avatar must use the canonical avatar helper at the reference source size');
assert.ok(comments.includes("aksrt_get_avatar_html(0, 96, ['class' => 'avatar'])"), 'guest avatar must use the canonical default-avatar helper');
assert.equal(comments.includes('aksrt_render_vip_badge'), false, 'legacy VIP wrapper helper must not remain in the comment form');
assert.equal(comments.includes('aksrt_render_user_identity_chips'), false, 'identity chips must not crowd the narrow comt-title'); assert.equal(comments.includes('aksrt_render_user_identity_chips'), false, 'identity chips must not crowd the narrow comt-title');
const vip = read('inc/helpers/aksrt-vip.php');
assert.ok(vip.includes("trim('img-icon ' . $class)"), 'VIP helper must emit the reference img-icon contract');
assert.equal(vip.includes('function aksrt_render_vip_badge'), false, 'legacy wrapped VIP helper must be removed');
assert.equal(vip.includes('<span class="aksrt-vip-badge'), false, 'VIP helper must not add a badge wrapper');
const formParts = read('inc/helpers/comments/form-parts.php'); const formParts = read('inc/helpers/comments/form-parts.php');
assert.ok(formParts.includes("case 'link':"), 'link dropdown case must exist'); assert.ok(formParts.includes("case 'link':"), 'link dropdown case must exist');
assert.equal(formParts.includes("case 'quick':"), false, 'quick case must be gone'); assert.equal(formParts.includes("case 'quick':"), false, 'quick case must be gone');