From 3368261d5246e53b964df4559b3220744714349d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Aug 2026 14:13:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/css/frontend/vip-modal.css | 66 ------------------- src/Content/VipServiceModal.php | 17 ++--- .../page-display-contract.test.cjs | 22 +++++++ 3 files changed, 28 insertions(+), 77 deletions(-) diff --git a/assets/css/frontend/vip-modal.css b/assets/css/frontend/vip-modal.css index c9cb0f0c..261e7983 100644 --- a/assets/css/frontend/vip-modal.css +++ b/assets/css/frontend/vip-modal.css @@ -278,72 +278,6 @@ color: #e74c3c; } -/* Header hover VIP cards - * Markup: .navbar-vip > .navbar-vip-hover.hover-show > a + .hover-show-con.sub-vip-card - * (hover-show is on the INNER span, not on .navbar-vip itself) - */ -.navbar-vip-hover.hover-show, -.navbar-vip .hover-show { - position: relative; -} - -.sub-vip-card { - display: none; - position: absolute; - top: calc(100% + 0px); - right: 0; - z-index: 60; - width: max-content; - max-width: min(520px, 92vw); - padding: 10px; - padding-top: 12px; /* hover bridge */ - border-radius: 12px; - background: transparent; - box-shadow: none; - gap: 10px; - box-sizing: border-box; -} - -.navbar-vip-hover.hover-show:hover .sub-vip-card, -.navbar-vip-hover.hover-show:focus-within .sub-vip-card, -.navbar-vip .hover-show:hover .sub-vip-card, -.navbar-vip .hover-show:focus-within .sub-vip-card { - display: flex; - flex-wrap: wrap; -} - -.vip-card { - position: relative; - flex: 1 1 160px; - min-width: 150px; - padding: 14px 12px; - border-radius: 10px; - overflow: hidden; - background: linear-gradient(135deg, #2b2f3a, #1b1e27); - color: #fff; -} - -.vip-card.vip-theme1 { - background: linear-gradient(135deg, #f6c453, #f39c12); - color: #3b2a00; -} - -.vip-card.vip-theme2 { - background: linear-gradient(135deg, #8e44ad, #3f51b5); - color: #fff; -} - -.vip-card .payvip-button { - display: inline-block; - margin-top: 6px; - padding: 6px 12px; - border-radius: 999px; - background: rgba(255, 255, 255, 0.92); - color: #333; - text-decoration: none; - font-size: 12px; -} - .vipbg-v2 { display: flex; align-items: center; diff --git a/src/Content/VipServiceModal.php b/src/Content/VipServiceModal.php index 55206e8c..a5331c51 100644 --- a/src/Content/VipServiceModal.php +++ b/src/Content/VipServiceModal.php @@ -153,31 +153,26 @@ trait VipServiceModal { return ''; } $name = (string) ($levels[$level]['name'] ?? ('VIP' . $level)); - $desc = (string) ($levels[$level]['desc'] ?? ''); $equity = (string) ($levels[$level]['equity'] ?? ''); $cls = $user_id > 0 ? ' pay-vip' : ' signin-loader'; - // Preserve admin equity HTML as-is (sanitize/wrap only; never re-split). - $equity_html = function_exists('aksrt_format_vip_equity_html') - ? aksrt_format_vip_equity_html($equity, 'mb10 relative') + $equity_html = $equity !== '' + ? '' : ''; $icon_url = esc_url((string) ($levels[$level]['img_icon'] ?? '')); $icon = $icon_url !== '' - ? '' + ? '' : ''; $html = '
'; - $html .= ''; + $html .= ''; $html .= '
' . $icon . '
'; $html .= '
'; - $html .= '
' . $icon . '' . esc_html($name) . '
'; - if ($desc !== '') { - $html .= '
' . esc_html($desc) . '
'; - } + $html .= '
' . $icon . '' . esc_html($name) . '
'; $html .= $equity_html; $html .= '' . esc_html(sprintf(__('开通%s', 'aksrt'), $name)) - . ''; + . ''; $html .= '
'; return $html; } diff --git a/tests/widget-system/page-display-contract.test.cjs b/tests/widget-system/page-display-contract.test.cjs index 15e9acbe..a6b1e033 100644 --- a/tests/widget-system/page-display-contract.test.cjs +++ b/tests/widget-system/page-display-contract.test.cjs @@ -25,6 +25,9 @@ const headerNavbar = read('inc/helpers/header/aksrt-header-navbar.php') const headerUserbox = read('inc/helpers/aksrt-header-userbox.php') const headerSearch = read('inc/helpers/header/aksrt-header-menu-search.php') const headerCss = read('assets/css/frontend/header-userbox.css') +const vipCardRenderer = read('src/Content/VipServiceModal.php') +const vipModalCss = read('assets/css/frontend/vip-modal.css') +const zibllMainCss = read('assets/vendor/zibll/css/main.css') function activeRepositorySource() { const roots = ['assets/admin/src', 'assets/js', 'inc', 'src', 'templates'] @@ -126,6 +129,25 @@ test('VIP navigation purchase switches are saved and consumed end to end', () => assert.match(headerNavbar, /!empty\(\$vs\['enabled'\]\) && !empty\(\$vs\['nav_user_pay_vip'\]\)/) }) +test('header VIP hover cards match the Zibll markup and style contract', () => { + assert.match(vipCardRenderer, /aksrt_get_lazy_attr\('lazy_other', \$icon_url, 'img-icon'\)/) + assert.match(vipCardRenderer, /
]*>/) + assert.match(vipCardRenderer, /
/) + assert.match(vipCardRenderer, /
/) + assert.match(vipCardRenderer, /
    /) + assert.doesNotMatch(vipCardRenderer, /vip-name__(?:icon|label)/) + assert.doesNotMatch(vipCardRenderer, /aksrt_format_vip_equity_html\(\$equity, 'mb10 relative'\)/) + + assert.doesNotMatch(vipModalCss, /Header hover VIP cards/) + assert.doesNotMatch(vipModalCss, /\.navbar-vip-hover\.hover-show/) + assert.doesNotMatch(vipModalCss, /\.sub-vip-card/) + assert.doesNotMatch(vipModalCss, /\.vip-card\.vip-theme[12]/) + assert.match(zibllMainCss, /\.sub-vip-card\s*\{[^}]*font-size:\s*12px;[^}]*padding:\s*0\s*!important;/s) + assert.match(zibllMainCss, /\.sub-vip-card \.vip-card\s*\{[^}]*display:\s*inline-block;[^}]*width:\s*240px;[^}]*margin:\s*5px;/s) + assert.match(zibllMainCss, /\.sub-vip-card \.vip-baicon\.abs-center\s*\{[^}]*font-size:\s*10em;[^}]*left:\s*55%;/s) + assert.match(zibllMainCss, /\.sub-vip-card \.vip-img\s*\{[^}]*display:\s*none;/s) +}) + test('schema REST saves are privileged, section-whitelisted, and deeply sanitized', () => { assert.match(controllerBase, /current_user_can\('manage_options'\)/) assert.match(controllerBase, /sanitize_payload\(\$domain, \$payload, \$section\)/)