From 40b9a3f36b9df6c0a7016afece07e07be992dc32 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Oct 2026 17:17:39 +0800 Subject: [PATCH] fix(frontend): align the VIP expiry badge with the reference semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 到期徽章改成参考主题 zib_get_user_vip_exp_date_text() 的语义:只有真的拿到到期时间才渲染这枚徽章,已过期显示「会员已过期」否则显示裸日期;「永久会员」只留给显式永久会员;拿不到到期数据时参考主题返回 false,整枚徽章都不渲染。 之前只要 expires 为 0 就无条件显示「永久会员」,于是订单来源且没有到期时间的会员也会多出一枚徽章,把会员条撑宽、内容被挤到换行,观感和参考主题对不上。 同时不再依赖 aksrt_get_vip_info():它的 expires_label 是另一套口径,返回值里也没有 is_permanent 字段。改读 aksrt_get_user_vip_state(),和等级判断共用同一个数据源。 用无头浏览器把参考主题卡片和本站卡片并排渲染,逐行量了 offsetHeight:总高 306px,user-info 43、会员条 37、到期徽章 20、签到 31、钱包 53、统计 27、操作行 81,两套完全一致;没有到期数据时会员条也一致。另外确认 vipbg-v2 在参考主题全部 59 个样式表里都没有定义,之前删掉它不影响任何视觉。 新增 3 条断言锁住到期逻辑,573 项测试全部通过。 --- inc/helpers/aksrt-header-userbox.php | 20 ++++++++++--------- .../page-display-contract.test.cjs | 6 ++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/inc/helpers/aksrt-header-userbox.php b/inc/helpers/aksrt-header-userbox.php index 9b1e1cbf..9f27eab7 100644 --- a/inc/helpers/aksrt-header-userbox.php +++ b/inc/helpers/aksrt-header-userbox.php @@ -199,16 +199,18 @@ if (!function_exists('aksrt_header_payvip_bar')) : if ($level > 0) { $levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : []; $name = (string) ($levels[$level]['name'] ?? ($level === 2 ? __('二级会员', 'aksrt') : __('一级会员', 'aksrt'))); + // 到期徽章语义对齐参考主题 zib_get_user_vip_exp_date_text():只有真的拿到 + // 到期时间才渲染这枚徽章,已过期显示「会员已过期」否则显示裸日期;显式永久 + // 会员显示「永久会员」;拿不到到期数据时参考主题返回 false,整枚徽章不渲染。 $exp_label = ''; - if (function_exists('aksrt_get_vip_info')) { - $info = aksrt_get_vip_info($user_id); - $expires = max(0, (int) ($info['expires'] ?? 0)); - // 到期文案对齐参考主题:已过期 / 永久会员 / 裸日期。 - if ((string) ($info['state'] ?? '') === 'expired') { - $exp_label = __('会员已过期', 'aksrt'); - } elseif ($expires > 0) { - $exp_label = wp_date('Y年m月d日', $expires); - } else { + if (function_exists('aksrt_get_user_vip_state')) { + $state = aksrt_get_user_vip_state($user_id); + $expires = max(0, (int) ($state['expires'] ?? 0)); + if ($expires > 0) { + $exp_label = $expires <= time() + ? __('会员已过期', 'aksrt') + : wp_date('Y年m月d日', $expires); + } elseif (!empty($state['is_permanent'])) { $exp_label = __('永久会员', 'aksrt'); } } diff --git a/tests/widget-system/page-display-contract.test.cjs b/tests/widget-system/page-display-contract.test.cjs index fbfecdd5..10dc6076 100644 --- a/tests/widget-system/page-display-contract.test.cjs +++ b/tests/widget-system/page-display-contract.test.cjs @@ -382,6 +382,12 @@ test('header user-card membership stays on one row with a date-only expiry', () // The CTA wrapper is the reference padding wrapper, not a bespoke hook. assert.match(headerUserbox, /'
'/) assert.doesNotMatch(headerUserbox, /aksrt-header-payvip/) + // Expiry badge follows zib_get_user_vip_exp_date_text(): an expiry that has + // passed reads 会员已过期, a live one reads the bare date, 永久会员 is reserved + // for an explicit permanent membership, and no expiry data renders no badge. + assert.match(headerUserbox, /\$expires <= time\(\)/) + assert.match(headerUserbox, /empty\(\$state\['is_permanent'\]\)/) + assert.doesNotMatch(headerUserbox, /aksrt_get_vip_info/) }) test('save contract rejects invalid input and round-trips canonical nested values', () => {