diff --git a/inc/helpers/aksrt-user-center.php b/inc/helpers/aksrt-user-center.php index c97505ab..a78d9e98 100644 --- a/inc/helpers/aksrt-user-center.php +++ b/inc/helpers/aksrt-user-center.php @@ -136,7 +136,21 @@ if (!function_exists('aksrt_capture_user_center_view')) { * Render an internal user-center view into an inert HTML payload. */ function aksrt_capture_user_center_view(string $view, array $context): string { - $path = AKSRT_DIR . '/inc/helpers/user-center-renderers/profile-' . sanitize_file_name($view) . '.php'; + // Built-in panels map to renderer files; "profile" content lives in profile-form.php. + $map = [ + 'profile' => 'form', + 'posts' => 'posts', + 'comments' => 'comments', + 'favorites' => 'favorites', + 'credits' => 'credits', + 'settings' => 'settings', + 'header' => 'header', + 'sidebar' => 'sidebar', + 'account-modals' => 'account-modals', + ]; + $view = sanitize_file_name($view); + $renderer = $map[$view] ?? $view; + $path = AKSRT_DIR . '/inc/helpers/user-center-renderers/profile-' . $renderer . '.php'; if (!is_file($path)) { return ''; } @@ -220,21 +234,30 @@ if (!function_exists('aksrt_build_user_center_render_context')) { } } -if (!function_exists('aksrt_get_user_center_render_context')) { + +if (!function_exists('aksrt_user_center_empty_svgs')) { /** - * Resolve the current user's complete render context outside template files. + * Shared empty-state icons for user-center panels. + * + * @return array{post:string,comment:string,favorite:string} */ - function aksrt_get_user_center_render_context(WP_User $current_user): array { - $user_id = (int) $current_user->ID; - $user_center_settings = class_exists('AKSRT_Settings') - ? AKSRT_Settings::get_user_center_settings() - : [ - 'tabs' => ['profile', 'posts', 'comments', 'favorites'], - 'avatar_upload' => true, - 'cover_upload' => true, - 'social_links' => true, - ]; - $dashboard_tabs = class_exists('AKSRT_User_Center') + function aksrt_user_center_empty_svgs(): array { + return [ + 'post' => '', + 'comment' => '', + 'favorite' => '', + ]; + } +} + +if (!function_exists('aksrt_user_center_resolve_tabs')) { + /** + * Resolve dashboard tabs + active tab for the private user center. + * + * @return array{tabs:array,keys:array,default:string,active:string,urls:array} + */ + function aksrt_user_center_resolve_tabs(): array { + $tabs = class_exists('AKSRT_User_Center') ? AKSRT_User_Center::get_instance()->get_dashboard_tabs() : [ 'profile' => ['label' => __('个人信息', 'aksrt'), 'icon' => 'user'], @@ -243,130 +266,66 @@ if (!function_exists('aksrt_get_user_center_render_context')) { 'favorites' => ['label' => __('我的收藏', 'aksrt'), 'icon' => 'star'], 'settings' => ['label' => __('账号设置', 'aksrt'), 'icon' => 'cog'], ]; - $dashboard_tabs = aksrt_normalize_user_center_tabs($dashboard_tabs); - $dashboard_tab_keys = array_keys($dashboard_tabs); - $default_dashboard_tab = in_array('profile', $dashboard_tab_keys, true) ? 'profile' : ($dashboard_tab_keys[0] ?? 'profile'); - $active_tab = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : $default_dashboard_tab; - if ('signin' === $active_tab) { - $active_tab = 'credits'; - } elseif ('invite' === $active_tab) { - $active_tab = 'settings'; + $tabs = aksrt_normalize_user_center_tabs($tabs); + $keys = array_keys($tabs); + $default = in_array('profile', $keys, true) ? 'profile' : ($keys[0] ?? 'profile'); + $active = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : $default; + if ('signin' === $active) { + $active = 'credits'; + } elseif ('invite' === $active) { + $active = 'settings'; } - if (!in_array($active_tab, $dashboard_tab_keys, true)) { - $active_tab = $default_dashboard_tab; + if (!in_array($active, $keys, true)) { + $active = $default; } - - $dashboard = function_exists('aksrt_get_user_dashboard_view') - ? aksrt_get_user_dashboard_view($user_id, [ - 'viewer_id' => $user_id, - 'include_recent_posts' => false, - 'include_governance' => false, - ]) - : []; - $target_user = $current_user; - $post_count = (int) ($dashboard['post_count'] ?? count_user_posts($user_id, 'post', true)); - $comment_count = (int) ($dashboard['comment_count'] ?? get_comments(['user_id' => $user_id, 'count' => true, 'status' => 'approve'])); - $favorite_post_ids = $dashboard['favorite_post_ids'] ?? []; - $favorite_count = (int) ($dashboard['favorite_count'] ?? count($favorite_post_ids)); - $user_contacts = $dashboard['user_contacts'] ?? get_user_meta($user_id, 'aksrt_user_contacts', true); - $user_contacts = is_array($user_contacts) ? $user_contacts : []; - $profile_signals = $dashboard['profile_signals'] ?? []; - $user_background_url = (string) ($dashboard['background_url'] ?? get_user_meta($user_id, 'aksrt_background_image', true)); - $allow_bg_upload = !empty($user_center_settings['cover_upload']) && class_exists('AKSRT_Settings') && aksrt_get_setting('allow_background_upload', false); - $show_avatar_edit = !empty($user_center_settings['avatar_upload']); - $avatar_settings_url = admin_url('profile.php'); - $notification_unread_count = function_exists('aksrt_get_user_unread_notification_count') ? aksrt_get_user_unread_notification_count($user_id) : 0; - $messages_url = function_exists('aksrt_get_messages_url') - ? aksrt_get_messages_url() - : aksrt_get_user_center_url('notif'); - $per_page = 10; - $posts_page = max(1, isset($_GET['posts_page']) ? (int) $_GET['posts_page'] : 1); - $comments_page = max(1, isset($_GET['comments_page']) ? (int) $_GET['comments_page'] : 1); - $favorites_page = max(1, isset($_GET['favorites_page']) ? (int) $_GET['favorites_page'] : 1); - $post_status_filter = isset($_GET['post_status']) ? sanitize_key(wp_unslash($_GET['post_status'])) : 'publish'; - if (!in_array($post_status_filter, ['all', 'publish', 'draft', 'pending', 'private'], true)) { - $post_status_filter = 'publish'; + $urls = []; + foreach ($keys as $key) { + $urls[$key] = aksrt_get_user_center_tab_url($key); } - $user_status_counts = ['publish' => 0, 'draft' => 0, 'pending' => 0, 'private' => 0]; - if ('posts' === $active_tab) { - global $wpdb; - $rows = $wpdb->get_results($wpdb->prepare( - "SELECT post_status, COUNT(*) AS num FROM {$wpdb->posts} WHERE post_author = %d AND post_type = 'post' AND post_status IN ('publish','draft','pending','private') GROUP BY post_status", - $user_id - )); - foreach ((array) $rows as $row) { - $user_status_counts[$row->post_status] = (int) $row->num; - } - $post_count = (int) array_sum($user_status_counts); - } - - $svg_empty_post = ''; - $svg_empty_comment = ''; - $svg_empty_favorite = ''; - require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php'; - - $vip_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_payment_vip_settings() : []; - $affiliate_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_payment_affiliate_settings() : []; - $orders_url = function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : ''; - $show_vip = !empty($vip_settings['enabled']); - $show_credit_tabs = (bool) ($dashboard['credits_enabled'] ?? false); - $affiliate_enabled = $show_credit_tabs && !empty($affiliate_settings['enabled']); - $currency_name = (string) ($dashboard['currency_name'] ?? __('积分', 'aksrt')); - $tab_urls = []; - foreach ($dashboard_tab_keys as $tab_key) { - $tab_urls[$tab_key] = aksrt_get_user_center_tab_url($tab_key); - } - - $render_context = [ - 'user_center_settings' => $user_center_settings, - 'dashboard_tabs' => $dashboard_tabs, - 'dashboard_tab_keys' => $dashboard_tab_keys, - 'default_dashboard_tab' => $default_dashboard_tab, - 'active_tab' => $active_tab, - 'dashboard' => $dashboard, - 'target_user' => $target_user, - 'user_id' => $user_id, - 'post_count' => $post_count, - 'comment_count' => $comment_count, - 'favorite_post_ids' => $favorite_post_ids, - 'favorite_count' => $favorite_count, - 'user_contacts' => $user_contacts, - 'profile_signals' => $profile_signals, - 'user_background_url' => $user_background_url, - 'allow_bg_upload' => $allow_bg_upload, - 'show_avatar_edit' => $show_avatar_edit, - 'avatar_settings_url' => $avatar_settings_url, - 'notification_unread_count' => $notification_unread_count, - 'messages_url' => $messages_url, - 'per_page' => $per_page, - 'posts_page' => $posts_page, - 'comments_page' => $comments_page, - 'favorites_page' => $favorites_page, - 'post_status_filter' => $post_status_filter, - 'user_status_counts' => $user_status_counts, - 'svg_empty_post' => $svg_empty_post, - 'svg_empty_comment' => $svg_empty_comment, - 'svg_empty_favorite' => $svg_empty_favorite, - 'orders_url' => $orders_url, - 'show_vip' => $show_vip, - 'show_credit_tabs' => $show_credit_tabs, - 'affiliate_enabled' => $affiliate_enabled, - 'currency_name' => $currency_name, - 'credit_balance' => (float) ($dashboard['credit_balance'] ?? 0.0), - 'credits_enabled' => $show_credit_tabs, - 'vip_settings' => $vip_settings, - 'show_invite_section' => $show_credit_tabs - && class_exists('AKSRT_Settings') - && AKSRT_Settings::invite_enabled() - && AKSRT_Settings::invite_registration_enabled(), - 'user_email' => (string) $current_user->user_email, + return [ + 'tabs' => $tabs, + 'keys' => $keys, + 'default' => $default, + 'active' => $active, + 'urls' => $urls, ]; - $render_context['runtime_config'] = [ + } +} + +if (!function_exists('aksrt_user_center_post_status_counts')) { + /** + * Count the current user's posts by status (posts tab only). + * + * @return array{counts:array,total:int} + */ + function aksrt_user_center_post_status_counts(int $user_id): array { + global $wpdb; + $counts = ['publish' => 0, 'draft' => 0, 'pending' => 0, 'private' => 0]; + $rows = $wpdb->get_results($wpdb->prepare( + "SELECT post_status, COUNT(*) AS num FROM {$wpdb->posts} WHERE post_author = %d AND post_type = 'post' AND post_status IN ('publish','draft','pending','private') GROUP BY post_status", + $user_id + )); + foreach ((array) $rows as $row) { + $counts[$row->post_status] = (int) $row->num; + } + return [ + 'counts' => $counts, + 'total' => (int) array_sum($counts), + ]; + } +} + +if (!function_exists('aksrt_user_center_runtime_config')) { + /** + * Frontend runtime config injected into the private user center page. + */ + function aksrt_user_center_runtime_config(int $user_id, string $default_tab, string $active_tab, array $tab_urls): array { + return [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'publicNonce' => wp_create_nonce('aksrt_public_nonce'), 'settingsNonce' => wp_create_nonce('aksrt_account_settings'), 'userId' => $user_id, - 'defaultTab' => $default_dashboard_tab, + 'defaultTab' => $default_tab, 'activeTab' => $active_tab, 'tabAliases' => ['signin' => 'credits', 'invite' => 'settings'], 'tabUrls' => $tab_urls, @@ -388,7 +347,18 @@ if (!function_exists('aksrt_get_user_center_render_context')) { 'unbind' => __('解除', 'aksrt'), ], ]; - $render_context['cover_upload_config'] = $allow_bg_upload ? [ + } +} + +if (!function_exists('aksrt_user_center_cover_upload_config')) { + /** + * Cover upload config for the private user-center hero. + */ + function aksrt_user_center_cover_upload_config(bool $allow_bg_upload): array { + if (!$allow_bg_upload) { + return []; + } + return [ 'enabled' => true, 'restUrl' => rest_url('aksrt/v1/user/background'), 'restNonce' => wp_create_nonce('wp_rest'), @@ -404,9 +374,112 @@ if (!function_exists('aksrt_get_user_center_render_context')) { 'successText' => __('背景图已更新', 'aksrt'), 'errorText' => __('上传失败', 'aksrt'), 'networkErrorText' => __('网络错误,请重试', 'aksrt'), - ] : []; - $render_context = aksrt_build_user_center_render_context($render_context); + ]; + } +} - return $render_context; +if (!function_exists('aksrt_get_user_center_render_context')) { + /** + * Resolve the current user's complete render context outside template files. + */ + function aksrt_get_user_center_render_context(WP_User $current_user): array { + $user_id = (int) $current_user->ID; + + $user_center_settings = class_exists('AKSRT_Settings') + ? AKSRT_Settings::get_user_center_settings() + : [ + 'tabs' => ['profile', 'posts', 'comments', 'favorites'], + 'avatar_upload' => true, + 'cover_upload' => true, + 'social_links' => true, + ]; + + $tabs = aksrt_user_center_resolve_tabs(); + $active_tab = $tabs['active']; + + $dashboard = function_exists('aksrt_get_user_dashboard_view') + ? aksrt_get_user_dashboard_view($user_id, [ + 'viewer_id' => $user_id, + 'include_recent_posts' => false, + 'include_governance' => false, + ]) + : []; + + $post_count = (int) ($dashboard['post_count'] ?? count_user_posts($user_id, 'post', true)); + $comment_count = (int) ($dashboard['comment_count'] ?? get_comments(['user_id' => $user_id, 'count' => true, 'status' => 'approve'])); + $favorite_post_ids = $dashboard['favorite_post_ids'] ?? []; + $favorite_count = (int) ($dashboard['favorite_count'] ?? count($favorite_post_ids)); + $user_contacts = $dashboard['user_contacts'] ?? get_user_meta($user_id, 'aksrt_user_contacts', true); + $user_contacts = is_array($user_contacts) ? $user_contacts : []; + $user_background_url = (string) ($dashboard['background_url'] ?? get_user_meta($user_id, 'aksrt_background_image', true)); + $allow_bg_upload = !empty($user_center_settings['cover_upload']) && class_exists('AKSRT_Settings') && aksrt_get_setting('allow_background_upload', false); + + $post_status_filter = isset($_GET['post_status']) ? sanitize_key(wp_unslash($_GET['post_status'])) : 'publish'; + if (!in_array($post_status_filter, ['all', 'publish', 'draft', 'pending', 'private'], true)) { + $post_status_filter = 'publish'; + } + $user_status_counts = ['publish' => 0, 'draft' => 0, 'pending' => 0, 'private' => 0]; + if ('posts' === $active_tab) { + $status = aksrt_user_center_post_status_counts($user_id); + $user_status_counts = $status['counts']; + $post_count = $status['total']; + } + + $svgs = aksrt_user_center_empty_svgs(); + require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php'; + + $vip_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_payment_vip_settings() : []; + $affiliate_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_payment_affiliate_settings() : []; + $show_credit_tabs = (bool) ($dashboard['credits_enabled'] ?? false); + $currency_name = (string) ($dashboard['currency_name'] ?? __('积分', 'aksrt')); + + $render_context = [ + 'user_center_settings' => $user_center_settings, + 'dashboard_tabs' => $tabs['tabs'], + 'dashboard_tab_keys' => $tabs['keys'], + 'default_dashboard_tab' => $tabs['default'], + 'active_tab' => $active_tab, + 'dashboard' => $dashboard, + 'target_user' => $current_user, + 'user_id' => $user_id, + 'post_count' => $post_count, + 'comment_count' => $comment_count, + 'favorite_post_ids' => $favorite_post_ids, + 'favorite_count' => $favorite_count, + 'user_contacts' => $user_contacts, + 'profile_signals' => $dashboard['profile_signals'] ?? [], + 'user_background_url' => $user_background_url, + 'allow_bg_upload' => $allow_bg_upload, + 'show_avatar_edit' => !empty($user_center_settings['avatar_upload']), + 'avatar_settings_url' => admin_url('profile.php'), + 'notification_unread_count' => function_exists('aksrt_get_user_unread_notification_count') ? aksrt_get_user_unread_notification_count($user_id) : 0, + 'messages_url' => function_exists('aksrt_get_messages_url') ? aksrt_get_messages_url() : aksrt_get_user_center_url('notif'), + 'per_page' => 10, + 'posts_page' => max(1, isset($_GET['posts_page']) ? (int) $_GET['posts_page'] : 1), + 'comments_page' => max(1, isset($_GET['comments_page']) ? (int) $_GET['comments_page'] : 1), + 'favorites_page' => max(1, isset($_GET['favorites_page']) ? (int) $_GET['favorites_page'] : 1), + 'post_status_filter' => $post_status_filter, + 'user_status_counts' => $user_status_counts, + 'svg_empty_post' => $svgs['post'], + 'svg_empty_comment' => $svgs['comment'], + 'svg_empty_favorite' => $svgs['favorite'], + 'orders_url' => function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : '', + 'show_vip' => !empty($vip_settings['enabled']), + 'show_credit_tabs' => $show_credit_tabs, + 'affiliate_enabled' => $show_credit_tabs && !empty($affiliate_settings['enabled']), + 'currency_name' => $currency_name, + 'credit_balance' => (float) ($dashboard['credit_balance'] ?? 0.0), + 'credits_enabled' => $show_credit_tabs, + 'vip_settings' => $vip_settings, + 'show_invite_section' => $show_credit_tabs + && class_exists('AKSRT_Settings') + && AKSRT_Settings::invite_enabled() + && AKSRT_Settings::invite_registration_enabled(), + 'user_email' => (string) $current_user->user_email, + 'runtime_config' => aksrt_user_center_runtime_config($user_id, $tabs['default'], $active_tab, $tabs['urls']), + 'cover_upload_config' => aksrt_user_center_cover_upload_config($allow_bg_upload), + ]; + + return aksrt_build_user_center_render_context($render_context); } } diff --git a/templates/pages/page-profile.php b/templates/pages/page-profile.php index e9b2be44..d62cf3b3 100644 --- a/templates/pages/page-profile.php +++ b/templates/pages/page-profile.php @@ -63,7 +63,7 @@ get_header(); $render_context]); ?> - $panel]); ?> + $panel]); ?> $render_context]); ?> diff --git a/templates/parts/user-center/README.md b/templates/parts/user-center/README.md index f6fe12b6..1bdb256c 100644 --- a/templates/parts/user-center/README.md +++ b/templates/parts/user-center/README.md @@ -2,19 +2,19 @@ 当前主路径: - 壳层:templates/pages/page-profile.php -- 挂载点:header / sidebar / mobile-tabs / panel-* / account-modals / runtime-config +- 上下文:inc/helpers/aksrt-user-center.php + - aksrt_get_user_center_render_context() + - aksrt_user_center_resolve_tabs() + - aksrt_capture_user_center_view() (profile → form 映射) +- 挂载点:header / sidebar / mobile-tabs / panel / account-modals / runtime-config - 渲染器:inc/helpers/user-center-renderers/profile-*.php + - profile 面板内容文件为 profile-form.php 样式归属: - assets/css/routes/user-center.css - - shell.css — 容器/侧栏/内容区/抽屉 - - credits.css — 余额卡/流水 - - settings.css — 设置区/邀请面板 - - responsive.css — 移动端 tabs/断点/a11y + - shell.css / credits.css / settings.css / responsive.css - assets/css/routes/profile.css — 共享头区/列表/弹窗 脚本归属: - assets/js/routes/user-center.js - -旧 uc-* 草稿 partial 与 templates/parts/profile/part-* 拆分残片已删除,勿再引入。 --> diff --git a/templates/parts/user-center/panel-comments.php b/templates/parts/user-center/panel-comments.php deleted file mode 100644 index 33c615ca..00000000 --- a/templates/parts/user-center/panel-comments.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -
diff --git a/templates/parts/user-center/panel-credits.php b/templates/parts/user-center/panel-credits.php deleted file mode 100644 index ed5af753..00000000 --- a/templates/parts/user-center/panel-credits.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -
diff --git a/templates/parts/user-center/panel-favorites.php b/templates/parts/user-center/panel-favorites.php deleted file mode 100644 index a3ccacfa..00000000 --- a/templates/parts/user-center/panel-favorites.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -
diff --git a/templates/parts/user-center/panel-posts.php b/templates/parts/user-center/panel-posts.php deleted file mode 100644 index 9202a5fe..00000000 --- a/templates/parts/user-center/panel-posts.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -
diff --git a/templates/parts/user-center/panel-profile.php b/templates/parts/user-center/panel-profile.php deleted file mode 100644 index caddeb08..00000000 --- a/templates/parts/user-center/panel-profile.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -
diff --git a/templates/parts/user-center/panel-settings.php b/templates/parts/user-center/panel-settings.php deleted file mode 100644 index f9a765a6..00000000 --- a/templates/parts/user-center/panel-settings.php +++ /dev/null @@ -1,8 +0,0 @@ - -
data-panel-loaded="" data-tab-url=""> - -