';
$html .= '
' . esc_html($name) . '
';
if ($desc !== '') {
diff --git a/src/AKSRT/Settings/UserRuntime.php b/src/AKSRT/Settings/UserRuntime.php
index d8856981..59c28686 100644
--- a/src/AKSRT/Settings/UserRuntime.php
+++ b/src/AKSRT/Settings/UserRuntime.php
@@ -88,7 +88,9 @@ class UserRuntime {
? $raw_tabs
: preg_split('/[\s,]+/', (string) $raw_tabs, -1, PREG_SPLIT_NO_EMPTY);
- $allowed_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits'];
+ // Built-in switchable panels. VIP is always auto-injected when enabled
+ // by AKSRT\User\Center — keep it allowed for explicit config too.
+ $allowed_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'settings'];
$normalized_tabs = ['profile'];
foreach ((array) $tabs as $tab) {
@@ -106,6 +108,28 @@ class UserRuntime {
$normalized_tabs[] = 'posts';
}
+ // Ensure VIP appears in configured tabs when membership is on, even if
+ // the stored option string is older and omits it.
+ $vip_on = !empty(Settings::get_payment_vip_settings()['enabled']);
+ if ($vip_on && !in_array('vip', $normalized_tabs, true)) {
+ // Prefer after credits, else after favorites, else append before settings.
+ $insert_at = count($normalized_tabs);
+ foreach (['credits', 'favorites', 'posts'] as $anchor) {
+ $idx = array_search($anchor, $normalized_tabs, true);
+ if ($idx !== false) {
+ $insert_at = (int) $idx + 1;
+ break;
+ }
+ }
+ array_splice($normalized_tabs, $insert_at, 0, ['vip']);
+ }
+ if (!$vip_on) {
+ $normalized_tabs = array_values(array_filter(
+ $normalized_tabs,
+ static fn(string $t): bool => $t !== 'vip'
+ ));
+ }
+
return [
'tabs' => $normalized_tabs,
'avatar_upload' => !isset($settings['user_avatar_upload']) || !empty($settings['user_avatar_upload']),
diff --git a/src/AKSRT/User/Center.php b/src/AKSRT/User/Center.php
index 7b6e651f..e86cd5c9 100644
--- a/src/AKSRT/User/Center.php
+++ b/src/AKSRT/User/Center.php
@@ -65,6 +65,12 @@ class Center {
'priority' => 40,
'type' => 'panel',
],
+ 'vip' => [
+ 'label' => __('我的会员', 'aksrt'),
+ 'icon' => 'crown',
+ 'priority' => 45,
+ 'type' => 'panel',
+ ],
'credits' => [
'label' => class_exists('\AKSRT\Settings\Settings')
? sprintf(__('我的%s', 'aksrt'), \AKSRT\Settings\Settings::get_currency_name())
@@ -73,12 +79,6 @@ class Center {
'priority' => 50,
'type' => 'panel',
],
- 'vip' => [
- 'label' => __('我的会员', 'aksrt'),
- 'icon' => 'crown',
- 'priority' => 45,
- 'type' => 'panel',
- ],
'notif' => [
'label' => __('消息通知', 'aksrt'),
'icon' => 'bell',
@@ -94,50 +94,55 @@ class Center {
];
$this->panels = [];
-
- foreach ((array) ($settings['tabs'] ?? []) as $key) {
- if ($key === 'credits') {
- $credits_on = class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::credits_enabled();
- $balance_on = class_exists('\AKSRT\Credits\Balance') && \AKSRT\Credits\Balance::enabled();
- if (!$credits_on && !$balance_on) {
- continue;
- }
- if ($balance_on) {
- $definitions['credits']['label'] = __('我的资产', 'aksrt');
- $definitions['credits']['icon'] = 'wallet';
- }
- }
-
- if (isset($definitions[$key])) {
- $this->panels[$key] = $definitions[$key];
- }
+ $configured = array_values(array_filter(array_map('sanitize_key', (array) ($settings['tabs'] ?? []))));
+ if ($configured === []) {
+ $configured = ['profile', 'posts', 'comments', 'favorites'];
}
- // Ensure assets panel when wallet and/or credits enabled (even if tabs list omitted credits).
$credits_on = class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::credits_enabled();
$balance_on = class_exists('\AKSRT\Credits\Balance') && \AKSRT\Credits\Balance::enabled();
- if (!isset($this->panels['credits']) && ($credits_on || $balance_on)) {
- $panel = $definitions['credits'];
- if ($balance_on) {
+ $vip_on = class_exists('\AKSRT\Settings\Settings')
+ && !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
+
+ // Follow configured order; always auto-include VIP/credits when feature on.
+ $order = $configured;
+ if ($vip_on && !in_array('vip', $order, true)) {
+ $insert_at = count($order);
+ foreach (['credits', 'favorites', 'posts'] as $anchor) {
+ $idx = array_search($anchor, $order, true);
+ if ($idx !== false) {
+ $insert_at = (int) $idx + 1;
+ break;
+ }
+ }
+ array_splice($order, $insert_at, 0, ['vip']);
+ }
+ if (($credits_on || $balance_on) && !in_array('credits', $order, true)) {
+ $order[] = 'credits';
+ }
+ if (!in_array('settings', $order, true)) {
+ $order[] = 'settings';
+ }
+
+ foreach ($order as $key) {
+ if (!isset($definitions[$key])) {
+ continue;
+ }
+ if ($key === 'credits' && !$credits_on && !$balance_on) {
+ continue;
+ }
+ if ($key === 'vip' && !$vip_on) {
+ continue;
+ }
+ $panel = $definitions[$key];
+ if ($key === 'credits' && $balance_on) {
$panel['label'] = __('我的资产', 'aksrt');
$panel['icon'] = 'wallet';
}
- $this->panels['credits'] = $panel;
- }
-
- // Dedicated VIP tab when membership is enabled.
- $vip_on = class_exists('\AKSRT\Settings\Settings')
- && !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
- if ($vip_on && !isset($this->panels['vip'])) {
- $this->panels['vip'] = $definitions['vip'];
- } elseif (!$vip_on && isset($this->panels['vip'])) {
- unset($this->panels['vip']);
- }
-
- if (!isset($this->panels['settings'])) {
- $this->panels['settings'] = $definitions['settings'];
+ $this->panels[$key] = $panel;
}
+ // Notif is a link entry (messages page), not a dashboard panel body.
$this->panels['notif'] = $definitions['notif'];
// Keep stable order by priority.