diff --git a/inc/helpers/user-center-renderers/vip-tab.php b/inc/helpers/user-center-renderers/vip-tab.php
index 1c75ba6b..7fd5319a 100644
--- a/inc/helpers/user-center-renderers/vip-tab.php
+++ b/inc/helpers/user-center-renderers/vip-tab.php
@@ -36,7 +36,9 @@ $vip_state_label = __('未开通', 'aksrt');
$vip_level_number = 0;
$vip_level_name = __('未开通会员', 'aksrt');
$vip_description = $desc_top !== '' ? $desc_top : __('开通会员,尊享专属特权', 'aksrt');
-$vip_expiry_text = __('到期时间:未开通', 'aksrt');
+// 未开通时不留到期文案:状态标签已显示「未开通」,参考主题对从未开通
+// 用户同样不输出任何到期信息(仅生效中/永久/已过期才有)。
+$vip_expiry_text = '';
$vip_is_permanent = false;
$btn_type = 'pay';
@@ -95,7 +97,7 @@ $status_html = '
'
. '' . esc_html($vip_level_name) . ''
. '
'
. '' . esc_html($vip_description) . '
'
- . '' . esc_html($vip_expiry_text) . '
'
+ . ($vip_expiry_text !== '' ? '' . esc_html($vip_expiry_text) . '
' : '')
. '';
// Level cards.
diff --git a/tests/widget-system/vip-tab-status-card.test.cjs b/tests/widget-system/vip-tab-status-card.test.cjs
new file mode 100644
index 00000000..3e05222a
--- /dev/null
+++ b/tests/widget-system/vip-tab-status-card.test.cjs
@@ -0,0 +1,36 @@
+/**
+ * 用户中心 VIP 页状态卡契约(inc/helpers/user-center-renderers/vip-tab.php)。
+ *
+ * 硬约束:
+ * 1) 未开通用户不渲染到期时间行——状态标签已显示「未开通」,参考主题
+ * zibpay_user_page_tab_content_vip 对从未开通用户同样不输出任何到期
+ * 信息(仅生效中/永久/已过期才有);
+ * 2) 生效中、永久、已过期三个分支的到期文案保持产出;
+ * 3) 到期行整体按文案非空条件渲染,不留空壳 div。
+ */
+const test = require('node:test');
+const assert = require('node:assert');
+const fs = require('node:fs');
+const path = require('node:path');
+
+const root = path.join(__dirname, '..', '..');
+const read = (...seg) => fs.readFileSync(path.join(root, ...seg), 'utf8');
+
+const vipTab = read('inc', 'helpers', 'user-center-renderers', 'vip-tab.php');
+
+test('未开通用户不渲染到期时间行', () => {
+ // 未开通初始化不再产出「到期时间:未开通」文案。
+ assert.ok(!vipTab.includes('到期时间:未开通'), '未开通不应再产出到期文案');
+ assert.match(vipTab, /\$vip_expiry_text\s*=\s*'';/);
+ // 到期行按文案非空条件渲染。
+ assert.match(vipTab, /\$vip_expiry_text !== '' \? '/);
+});
+
+test('生效中/永久/已过期分支仍产出到期文案', () => {
+ assert.match(vipTab, /到期时间:永久会员/);
+ assert.match(vipTab, /到期时间:%s/);
+ assert.match(vipTab, /到期时间:已过期/);
+ // 三个分支都会给 $vip_expiry_text 赋值。
+ const assignments = vipTab.match(/\$vip_expiry_text\s*=/g) || [];
+ assert.ok(assignments.length >= 4, '初始化 + 永久 + 生效中 + 已过期均应赋值');
+});