From d138c05f771104ec7230eab18179c8456633654a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Aug 2026 13:40:54 +0800 Subject: [PATCH] feat(users): add inline promotion center --- .../src/schema/sections/users/features.js | 4 +- inc/helpers/aksrt-user-center.php | 13 ++-- .../profile-promotion.php | 22 ++++++ .../profile-settings.php | 1 - .../user-center-renderers/settings-invite.php | 70 ------------------- .../user-center-renderers/sidebar-creator.php | 14 ++-- .../user-center-renderers/sidebar-nav.php | 8 +++ inc/modules/user-parts/urls.php | 2 +- src/Admin/Schema/SchemaUsers.php | 2 +- src/Settings/UserRuntime.php | 4 +- src/User/Center.php | 24 +++++++ 11 files changed, 76 insertions(+), 88 deletions(-) create mode 100644 inc/helpers/user-center-renderers/profile-promotion.php delete mode 100644 inc/helpers/user-center-renderers/settings-invite.php diff --git a/assets/admin/src/schema/sections/users/features.js b/assets/admin/src/schema/sections/users/features.js index 7598d059..c3d4616d 100644 --- a/assets/admin/src/schema/sections/users/features.js +++ b/assets/admin/src/schema/sections/users/features.js @@ -4,7 +4,7 @@ export const featuresSchema = { icon: 'fas fa-user-cog', description: '配置用户中心和个人主页的功能模块。', defaults: { - user_center_tabs: 'profile,level,posts,comments,favorites,vip,credits,auth', + user_center_tabs: 'profile,level,posts,comments,favorites,vip,credits,promotion,auth', user_cover_upload: true, user_social_links: true, user_desc_std: '这家伙很懒…', @@ -24,7 +24,7 @@ export const featuresSchema = { title: '用户中心', icon: 'fas fa-user-shield', fields: [ - { key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,level,posts,comments,favorites,vip,credits,auth', help: '逗号分隔。level=我的等级;auth=官方认证;等级、VIP、订单和认证会按功能开关自动注入' }, + { key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,level,posts,comments,favorites,vip,credits,promotion,auth', help: '逗号分隔。level=我的等级;promotion=推广中心;auth=官方认证;等级、VIP、订单、推广中心和认证会按功能开关自动注入' }, { key: 'user_cover_upload', label: '封面上传', type: 'switch', default: true }, { key: 'user_social_links', label: '社交链接', type: 'switch', default: true }, { key: 'user_desc_std', label: '默认签名', type: 'input', default: '这家伙很懒…', help: '用户未设置个人简介时显示的默认文案' }, diff --git a/inc/helpers/aksrt-user-center.php b/inc/helpers/aksrt-user-center.php index a0f67678..ff20d13e 100644 --- a/inc/helpers/aksrt-user-center.php +++ b/inc/helpers/aksrt-user-center.php @@ -102,13 +102,17 @@ if (!function_exists('aksrt_get_user_center_tab_url')) { * Build a canonical full-page user-center tab URL. */ function aksrt_get_user_center_tab_url(string $tab): string { + $tab = sanitize_key($tab); + if ('invite' === $tab) { + $tab = 'promotion'; + } $url = remove_query_arg([ 'tab', 'posts_page', 'comments_page', 'favorites_page', 'credits_page', 'post_status', 'saved', 'profile_error', 'order_tab', 'otab', 'order_status', 'order_page', 'order_type', 'section', ], aksrt_get_user_center_url()); - return add_query_arg('tab', sanitize_key($tab), $url); + return add_query_arg('tab', $tab, $url); } } @@ -150,6 +154,7 @@ if (!function_exists('aksrt_capture_user_center_view')) { 'vip' => 'vip', 'orders' => 'orders', 'auth' => 'auth', + 'promotion' => 'promotion', 'settings' => 'settings', 'header' => 'header', 'sidebar' => 'sidebar', @@ -174,7 +179,7 @@ if (!function_exists('aksrt_capture_user_center_panel')) { * Capture a built-in or registered user-center panel body. */ function aksrt_capture_user_center_panel(string $tab_key, array $tab, array $context): string { - $built_in_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings']; + $built_in_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'promotion', 'settings']; if (in_array($tab_key, $built_in_tabs, true)) { return aksrt_capture_user_center_view($tab_key, $context); } @@ -280,7 +285,7 @@ if (!function_exists('aksrt_user_center_resolve_tabs')) { if ('signin' === $active || 'assets' === $active) { $active = 'credits'; } elseif ('invite' === $active) { - $active = 'settings'; + $active = 'promotion'; } elseif ('vip' === $active) { // Prefer dedicated vip tab when registered; else credits (VIP shop). $active = in_array('vip', $keys, true) ? 'vip' : 'credits'; @@ -339,7 +344,7 @@ if (!function_exists('aksrt_user_center_runtime_config')) { 'activeTab' => $active_tab, 'tabAliases' => [ 'signin' => 'credits', - 'invite' => 'settings', + 'invite' => 'promotion', 'assets' => 'credits', // vip → vip when panel exists; SPA may still map missing keys via server resolve. 'vip' => 'vip', diff --git a/inc/helpers/user-center-renderers/profile-promotion.php b/inc/helpers/user-center-renderers/profile-promotion.php new file mode 100644 index 00000000..1f20a113 --- /dev/null +++ b/inc/helpers/user-center-renderers/profile-promotion.php @@ -0,0 +1,22 @@ + +
+
+ +
+

+

+
+
+

+
diff --git a/inc/helpers/user-center-renderers/profile-settings.php b/inc/helpers/user-center-renderers/profile-settings.php index 2724276a..bff7ded6 100644 --- a/inc/helpers/user-center-renderers/profile-settings.php +++ b/inc/helpers/user-center-renderers/profile-settings.php @@ -13,5 +13,4 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_ $dir = __DIR__; require $dir . '/settings-bindings.php'; require $dir . '/settings-security.php'; -require $dir . '/settings-invite.php'; require $dir . '/settings-runtime-fields.php'; diff --git a/inc/helpers/user-center-renderers/settings-invite.php b/inc/helpers/user-center-renderers/settings-invite.php deleted file mode 100644 index 96c6cf68..00000000 --- a/inc/helpers/user-center-renderers/settings-invite.php +++ /dev/null @@ -1,70 +0,0 @@ - -
-
- -

-
-
-
-
- -

- -

-
-
- - -- -
-
- -
-
- - 0 - -
-
- - 0 - -
-
- - 0 - -
-
-
-
-

- -
-
-
- -
-
-
-
-
diff --git a/inc/helpers/user-center-renderers/sidebar-creator.php b/inc/helpers/user-center-renderers/sidebar-creator.php index 6c2f45b6..9303b3d4 100644 --- a/inc/helpers/user-center-renderers/sidebar-creator.php +++ b/inc/helpers/user-center-renderers/sidebar-creator.php @@ -1,6 +1,6 @@ @@ -25,10 +25,10 @@ if ($creation_url === '' && $promotion_url === '') { - - - - + + + + diff --git a/inc/helpers/user-center-renderers/sidebar-nav.php b/inc/helpers/user-center-renderers/sidebar-nav.php index ec9e682e..b0f27387 100644 --- a/inc/helpers/user-center-renderers/sidebar-nav.php +++ b/inc/helpers/user-center-renderers/sidebar-nav.php @@ -11,6 +11,7 @@ $level_url = isset($dashboard_tabs['level']) ? aksrt_get_user_center_tab_url('level') : ''; $auth_url = isset($dashboard_tabs['auth']) ? aksrt_get_user_center_tab_url('auth') : ''; +$promotion_url = isset($dashboard_tabs['promotion']) ? aksrt_get_user_center_tab_url('promotion') : ''; $orders_available = isset($dashboard_tabs['orders']); $orders_url = $orders_available ? (string) ($orders_url ?? '') : ''; @@ -28,6 +29,13 @@ $services = array_values(array_filter([ 'url' => $auth_url, 'tab' => 'auth', ], + [ + 'label' => __('推广中心', 'aksrt'), + 'icon' => 'user-plus', + 'tone' => 'promotion', + 'url' => $promotion_url, + 'tab' => 'promotion', + ], [ 'label' => __('我的订单', 'aksrt'), 'icon' => 'receipt', diff --git a/inc/modules/user-parts/urls.php b/inc/modules/user-parts/urls.php index ac478d3e..ad51d024 100644 --- a/inc/modules/user-parts/urls.php +++ b/inc/modules/user-parts/urls.php @@ -32,7 +32,7 @@ function aksrt_get_user_center_url(string $tab = ''): string { 'assets' => 'credits', 'vip' => 'vip', // dedicated vip tab when registered; resolver falls back if missing 'signin' => 'credits', - 'invite' => 'settings', + 'invite' => 'promotion', ]; if (isset($aliases[$tab])) { $tab = $aliases[$tab]; diff --git a/src/Admin/Schema/SchemaUsers.php b/src/Admin/Schema/SchemaUsers.php index 26732467..6680e212 100644 --- a/src/Admin/Schema/SchemaUsers.php +++ b/src/Admin/Schema/SchemaUsers.php @@ -526,7 +526,7 @@ class SchemaUsers { 'option_key' => 'aksrt_settings', 'groups' => [ ['key' => 'center', 'title' => '用户中心', 'fields' => [ - ['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,level,posts,comments,favorites,vip,credits,auth', 'help' => '逗号分隔。level=我的等级;auth=官方认证;等级、VIP、订单和认证会按功能开关自动注入'], + ['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,level,posts,comments,favorites,vip,credits,promotion,auth', 'help' => '逗号分隔。level=我的等级;promotion=推广中心;auth=官方认证;等级、VIP、订单、推广中心和认证会按功能开关自动注入'], ['key' => 'user_cover_upload', 'label' => '封面上传', 'type' => 'switch', 'default' => true], ['key' => 'user_social_links', 'label' => '社交链接', 'type' => 'switch', 'default' => true], ['key' => 'user_desc_std', 'label' => '默认签名', 'type' => 'input', 'default' => '这家伙很懒…', 'desc' => '用户未设置个人简介时显示的默认文案'], diff --git a/src/Settings/UserRuntime.php b/src/Settings/UserRuntime.php index 3a86fe6b..8197aea9 100644 --- a/src/Settings/UserRuntime.php +++ b/src/Settings/UserRuntime.php @@ -83,14 +83,14 @@ class UserRuntime { */ public static function get_user_center_settings(): array { $settings = Settings::get_all(); - $raw_tabs = $settings['user_center_tabs'] ?? 'profile,level,posts,comments,credits,favorites,auth'; + $raw_tabs = $settings['user_center_tabs'] ?? 'profile,level,posts,comments,credits,promotion,favorites,auth'; $tabs = is_array($raw_tabs) ? $raw_tabs : preg_split('/[\s,]+/', (string) $raw_tabs, -1, PREG_SPLIT_NO_EMPTY); // 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', 'level', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings']; + $allowed_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'promotion', 'vip', 'orders', 'auth', 'settings']; $normalized_tabs = ['profile']; foreach ((array) $tabs as $tab) { diff --git a/src/User/Center.php b/src/User/Center.php index 96b31f28..3eb47dbb 100644 --- a/src/User/Center.php +++ b/src/User/Center.php @@ -91,6 +91,12 @@ class Center { 'priority' => 50, 'type' => 'panel', ], + 'promotion' => [ + 'label' => __('推广中心', 'aksrt'), + 'icon' => 'user-plus', + 'priority' => 55, + 'type' => 'panel', + ], 'notif' => [ 'label' => __('消息通知', 'aksrt'), 'icon' => 'bell', @@ -121,6 +127,10 @@ class Center { && !empty(\AKSRT\User\Level::settings()['enabled']); $credits_on = class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::credits_enabled(); $balance_on = class_exists('\AKSRT\Credits\Balance') && \AKSRT\Credits\Balance::enabled(); + $promotion_on = $credits_on + && class_exists('\AKSRT\Settings\Settings') + && \AKSRT\Settings\Settings::invite_enabled() + && \AKSRT\Settings\Settings::invite_registration_enabled(); $vip_on = class_exists('\AKSRT\Settings\Settings') && !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']); @@ -167,6 +177,17 @@ class Center { if (($credits_on || $balance_on) && !in_array('credits', $order, true)) { $order[] = 'credits'; } + if ($promotion_on && !in_array('promotion', $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, ['promotion']); + } $auth_on = class_exists('\AKSRT\User\AuthApply') && !empty(\AKSRT\User\AuthApply::settings()['enabled']); if ($auth_on && !in_array('auth', $order, true)) { @@ -186,6 +207,9 @@ class Center { if ($key === 'credits' && !$credits_on && !$balance_on) { continue; } + if ($key === 'promotion' && !$promotion_on) { + continue; + } if ($key === 'vip' && !$vip_on) { continue; }