Merge pull request 'fix(vip): 1:1 zibll VIP profile card with dual-column layout' (#254) from worktree-float-qr-uc-vip into main

Reviewed-on: CYL/wordpress-theme-aksrt#254
This commit is contained in:
2026-07-21 20:39:03 +08:00
2 changed files with 183 additions and 48 deletions
+122 -28
View File
@@ -1080,63 +1080,136 @@ body.uc-modal-open {
.uc-vip-tab {
min-width: 0;
}
/* Top profile card — zibll .user-content-myvip 1:1 */
.uc-vip-tab .user-content-myvip {
position: relative;
display: flex;
align-items: center;
gap: 16px;
padding: 16px 18px;
gap: 20px;
padding: 18px 20px;
margin-bottom: 16px;
overflow: hidden;
}
.uc-vip-tab .user-content-myvip .vip-img {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
opacity: 0.08;
font-size: 3em;
line-height: 1;
pointer-events: none;
z-index: 0;
}
.uc-vip-tab .user-content-myvip .uc-vip-user-row {
.uc-vip-tab .user-content-myvip > .flex2,
.uc-vip-tab .user-content-myvip > .flex4,
.uc-vip-tab .user-content-myvip > .uc-vip-profile,
.uc-vip-tab .user-content-myvip > .uc-vip-state {
position: relative;
z-index: 1;
min-width: 0;
}
.uc-vip-tab .user-content-myvip .flex2,
.uc-vip-tab .user-content-myvip .uc-vip-profile {
flex: 2 1 0;
}
.uc-vip-tab .user-content-myvip .flex4,
.uc-vip-tab .user-content-myvip .uc-vip-state {
flex: 4 1 0;
}
/* Crown watermark — zibll .user-content-myvip .vip-img.abs-right */
.uc-vip-tab .user-content-myvip .vip-img,
.uc-vip-tab .user-content-myvip .vip-img.abs-right {
position: absolute;
right: -10px;
top: 50%;
transform: translateY(-50%);
font-size: 160px;
line-height: 1;
opacity: 0.15;
pointer-events: none;
z-index: 0;
color: currentColor;
}
.uc-vip-tab .user-content-myvip .vip-img i {
font-size: inherit;
line-height: 1;
}
/* Left user box */
.uc-vip-tab .uc-vip-userbox {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
flex: 1 1 auto;
}
.uc-vip-tab .uc-vip-userbox .mr20 {
margin-right: 20px;
}
.uc-vip-tab .uc-vip-userbox .shrink0 {
flex-shrink: 0;
}
/* avatar-md = 55×55 circle (zibll --this-size: 55px) */
.uc-vip-tab .user-content-myvip .avatar-img {
flex: 0 0 auto;
position: relative;
display: inline-block;
flex-shrink: 0;
--this-size: 55px;
width: var(--this-size);
height: var(--this-size);
line-height: 0;
}
.uc-vip-tab .user-content-myvip .avatar-img.avatar-md {
--this-size: 55px;
}
.uc-vip-tab .user-content-myvip .avatar-img .avatar,
.uc-vip-tab .user-content-myvip .avatar-img img {
border-radius: 50%;
display: block;
width: 56px;
height: 56px;
width: 100% !important;
height: 100% !important;
max-width: none;
border-radius: 50%;
object-fit: cover;
aspect-ratio: 1 / 1;
}
.uc-vip-tab .user-content-myvip .min-w-0 {
.uc-vip-tab .uc-vip-userbox .name {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
line-height: 1.35;
min-width: 0;
}
.uc-vip-tab .mb3 {
margin-bottom: 3px;
.uc-vip-tab .uc-vip-userbox .name .display-name,
.uc-vip-tab .uc-vip-userbox .name a {
font-weight: 700;
color: inherit;
text-decoration: none;
}
.uc-vip-status {
.uc-vip-tab .uc-vip-userbox .desc {
max-width: 100%;
line-height: 1.45;
}
.uc-vip-tab .em12 { font-size: 1.2em; }
.uc-vip-tab .em16 { font-size: 1.6em; line-height: 1.2; }
.uc-vip-tab .em09 { font-size: 0.9em; }
.uc-vip-tab .mt6 { margin-top: 6px; }
.uc-vip-tab .mr10 { margin-right: 10px; }
.uc-vip-tab .mr3 { margin-right: 3px; }
.uc-vip-tab .ml6 { margin-left: 6px; }
.uc-vip-tab .font-bold { font-weight: 700; }
.uc-vip-tab .c-red { color: #ff5473; }
.uc-vip-tab .min-w-0 { min-width: 0; }
.uc-vip-tab .text-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
/* Right status column — zibll my_vip_box */
.uc-vip-status,
.uc-vip-tab .uc-vip-status.flex.xx {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.uc-vip-status__title {
display: inline-flex;
.uc-vip-status .flex.ac {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
font-size: 1.05em;
line-height: 1.3;
}
.uc-vip-status .badg {
display: inline-flex;
@@ -1349,6 +1422,27 @@ html:not(.dark):not(.theme-dark) .uc-vip-level-card.level-2 .v-name {
flex: 1 1 auto;
}
.uc-vip-tab .user-content-myvip {
padding: 14px;
padding: 14px 16px;
gap: 12px;
flex-wrap: wrap;
}
/* zibll: hide-sm on left profile column on mobile */
.uc-vip-tab .user-content-myvip .hide-sm,
.uc-vip-tab .user-content-myvip .uc-vip-profile.hide-sm {
display: none !important;
}
.uc-vip-tab .user-content-myvip .flex4,
.uc-vip-tab .user-content-myvip .uc-vip-state {
flex: 1 1 100%;
}
.uc-vip-tab .user-content-myvip .vip-img {
font-size: 110px;
opacity: 0.12;
}
}
@media (min-width: 768px) {
.uc-vip-tab .user-content-myvip .hide-sm {
display: block;
}
}
+61 -20
View File
@@ -27,47 +27,89 @@ $desc_top = (string) ($vip_settings['desc'] ?? '');
$user = get_userdata($user_id);
$display = $user ? $user->display_name : '';
$avatar = get_avatar($user_id, 56);
$user_bio = $user ? trim((string) $user->description) : '';
if ($user_bio === '') {
$user_bio = __('这家伙很懒,什么都没有写…', 'aksrt');
}
// Status header box.
// Avatar: zibll avatar-img avatar-md (55px fixed box).
$avatar = get_avatar($user_id, 110, '', $display, ['class' => 'avatar']);
// Name row with identity chips (zibll zib_get_user_name parity).
$name_html = '';
if (function_exists('aksrt_get_user_name')) {
$name_html = aksrt_get_user_name([
'id' => $user_id,
'class' => 'flex1 flex ac',
'vip' => true,
'follow' => false,
]);
}
if ($name_html === '') {
$name_html = esc_html($display);
if (function_exists('aksrt_render_user_identity_chips')) {
$name_html .= aksrt_render_user_identity_chips($user_id, 'card');
}
}
// Status column (zibll my_vip_box).
$status_html = '';
$btn_type = 'pay';
if ($level > 0) {
$lv_name = (string) ($levels[$level]['name'] ?? ('VIP' . $level));
$lv_desc = (string) ($levels[$level]['desc'] ?? '');
if ($expires <= 0) {
$badge = '<span class="badg c-green p2-10 em09"><i class="fas fa-clock" aria-hidden="true"></i> ' . esc_html__('永久会员', 'aksrt') . '</span>';
$badge = '<span class="badg c-green p2-10 em09"><i class="fas fa-clock mr3" aria-hidden="true"></i>' . esc_html__('永久会员', 'aksrt') . '</span>';
if ($level < 2) {
$btn_type = 'upgrade';
}
} else {
$badge = '<span class="badg c-yellow p2-10 em09"><i class="fas fa-clock" aria-hidden="true"></i> '
$badge = '<span class="badg c-yellow p2-10 em09"><i class="fas fa-clock mr3" aria-hidden="true"></i>'
. esc_html(sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires))) . '</span>';
$btn_type = 'renew_' . $level;
}
$status_html = '<div class="uc-vip-status">'
. '<div class="uc-vip-status__title flex ac"><i class="fas fa-crown" aria-hidden="true"></i><span class="font-bold ml6">' . esc_html($lv_name) . '</span></div>'
$status_html = '<div class="uc-vip-status flex xx gap6">'
. '<div class="em09 muted-2-color">' . esc_html__('我的会员', 'aksrt') . '</div>'
. '<div class="flex ac">'
. '<div class="em16 mr10 flex ac"><i class="fas fa-crown" aria-hidden="true"></i><div class="font-bold ml6">' . esc_html($lv_name) . '</div></div>'
. $badge
. ($lv_desc !== '' ? '<div class="muted-color em09">' . esc_html($lv_desc) . '</div>' : '')
. '</div>'
. '<div class="muted-color em09">' . esc_html($lv_desc !== '' ? $lv_desc : __('尊享专属特权', 'aksrt')) . '</div>'
. '</div>';
} elseif ($expired_level > 0) {
$exp_label = $expires > 0
? sprintf(__('过期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires))
: __('已过期', 'aksrt');
$status_html = '<div class="uc-vip-status">'
. '<div class="font-bold c-red">' . esc_html__('会员已过期', 'aksrt') . '</div>'
. '<div class="badg c-red em09"><i class="fas fa-clock" aria-hidden="true"></i> ' . esc_html($exp_label) . '</div>'
$status_html = '<div class="uc-vip-status flex xx gap6">'
. '<div class="em09 muted-2-color">' . esc_html__('当前会员状态', 'aksrt') . '</div>'
. '<div class="flex ac">'
. '<div class="em16 c-red mr10">' . esc_html__('已过期', 'aksrt') . '</div>'
. '<div class="badg c-red em09"><i class="fas fa-clock mr3" aria-hidden="true"></i>' . esc_html($exp_label) . '</div>'
. '</div>'
. ($desc_top !== '' ? '<div class="muted-color em09">' . esc_html($desc_top) . '</div>' : '')
. '</div>';
$btn_type = 'pay';
} else {
$status_html = '<div class="uc-vip-status">'
. '<div class="font-bold">' . esc_html__('开通会员', 'aksrt') . '</div>'
. ($desc_top !== '' ? '<div class="muted-color em09">' . esc_html($desc_top) . '</div>' : '<div class="muted-color em09">' . esc_html__('开通会员,尊享专属特权', 'aksrt') . '</div>')
// Never opened VIP — zibll: 当前会员状态 / 未开通会员 / desc.
$status_html = '<div class="uc-vip-status flex xx gap6">'
. '<div class="em09 muted-2-color">' . esc_html__('当前会员状态', 'aksrt') . '</div>'
. '<div class="flex ac">'
. '<div class="em16 c-red mr10">' . esc_html__('未开通会员', 'aksrt') . '</div>'
. '</div>'
. '<div class="muted-color em09">' . esc_html($desc_top !== '' ? $desc_top : __('开通会员,尊享专属特权', 'aksrt')) . '</div>'
. '</div>';
$btn_type = 'pay';
}
// Left user box (zibll user_box).
$user_box = '<div class="flex ac uc-vip-userbox">'
. '<div class="mr20 shrink0"><div class="avatar-img avatar-md">' . $avatar . '</div></div>'
. '<div class="flex1 min-w-0">'
. '<div class="name em12 font-bold">' . $name_html . '</div>'
. '<div class="desc em09 mt6 muted-2-color text-ellipsis">' . esc_html($user_bio) . '</div>'
. '</div>'
. '</div>';
// Level cards.
$cards = '';
foreach ([1, 2] as $lv) {
@@ -133,14 +175,13 @@ if ($level <= 0 && !empty($vip_settings['points_exchange']['enabled'])) {
}
?>
<div class="uc-vip-tab" data-aksrt-vip-tab>
<div class="zib-widget flex ac user-content-myvip overflow-hidden">
<div class="zib-widget flex ac gap20 user-content-myvip overflow-hidden">
<div class="vip-img abs-right" aria-hidden="true"><i class="fas fa-crown"></i></div>
<div class="flex ac flex1 relative uc-vip-user-row">
<div class="avatar-img"><?php echo $avatar; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<div class="flex1 min-w-0">
<div class="font-bold mb3"><?php echo esc_html($display); ?></div>
<?php echo $status_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<div class="flex2 hide-sm uc-vip-profile">
<?php echo $user_box; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<div class="flex4 uc-vip-state">
<?php echo $status_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
</div>