Files
wordpress-theme-aksrt/templates/parts/profile/part-1.php
T

400 lines
19 KiB
PHP

<?php
/**
* Template Name: 用户中心
* Template Post Type: page
*
* 单一页面模板,根据场景显示不同内容:
* - 登录用户查看自己 → 仪表盘面板(个人信息 / 文章 / 评论 / 收藏 / 通知 / 设置)
* - 查看其他用户主页 → 公开用户主页(头像 / 简介 / 文章 / 评论)
*
* @package AKSRT
*/
// 加载共享辅助函数(分页、空状态)
require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php';
get_header(); ?>
<div id="toast-container"></div>
<script>function showToast(text,d){d=d||2500;var c=document.getElementById('toast-container');if(!c){c=document.createElement('div');c.id='toast-container';document.body.appendChild(c);}var t=document.createElement('div');t.className='toast-item';t.textContent=text;c.appendChild(t);setTimeout(function(){t.classList.add('fade-out');setTimeout(function(){if(t.parentNode)t.parentNode.removeChild(t)},300)},d)}</script>
<?php // ─── Post/Redirect/Get:处理表单提交后跳转,防止刷新重复提交 ──
if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_POST['action'], $_POST['_profile_nonce'] )
&& $_POST['action'] === 'aksrt_save_profile'
&& wp_verify_nonce( $_POST['_profile_nonce'], 'aksrt_profile_save' )
) {
$uid = isset( $_POST['user_id'] ) ? (int) $_POST['user_id'] : 0;
if ( $uid && $uid === get_current_user_id() ) {
if ( isset( $_POST['nickname'] ) ) {
wp_update_user( [ 'ID' => $uid, 'display_name' => sanitize_text_field( $_POST['nickname'] ) ] );
}
if ( isset( $_POST['description'] ) ) {
wp_update_user( [ 'ID' => $uid, 'description' => sanitize_textarea_field( $_POST['description'] ) ] );
}
$contacts = [];
if ( isset( $_POST['contacts'] ) && is_array( $_POST['contacts'] ) ) {
foreach ( $_POST['contacts'] as $c ) {
$u = isset( $c['url'] ) ? esc_url_raw( $c['url'] ) : '';
$i = isset( $c['icon'] ) ? sanitize_key( $c['icon'] ) : '';
// 清理 FA5 类名前缀:fab fa-xxx / fabfa-xxx / fa-xxx → xxx
$i = preg_replace('/^(fab|fas|far)[\s-]*/', '', $i);
$i = preg_replace('/^fa[\s-]*/', '', $i);
$i = preg_replace('/^[\s-]+/', '', $i);
$i = trim( $i, '- ' );
if ( ! $u || ! $i ) continue;
$n = aksrt_icon_key_to_name( $i );
$contacts[] = [ 'name' => $n, 'url' => $u, 'icon' => $i ];
}
}
update_user_meta( $uid, 'aksrt_user_contacts', $contacts );
}
wp_safe_redirect( add_query_arg( 'saved', '1', aksrt_get_user_center_url() ) );
exit;
}
// ─── 确定目标用户 ─────────────────────────────────────────────
// 来源: /user/{昵称} (自定义重写规则)
// 注意: get_queried_object_id() 在页面中返回的是页面 ID 而非用户 ID
$target_user_id = 0;
$target_user_nicename = get_query_var('user_nicename');
if ( $target_user_nicename ) {
$user = get_user_by( 'slug', $target_user_nicename );
if ( $user ) {
$target_user_id = $user->ID;
}
}
// 兜底:检查 queried object
if ( ! $target_user_id ) {
$qid = get_queried_object_id();
if ( $qid && get_userdata( $qid ) ) {
$target_user_id = $qid;
}
}
$current_user = wp_get_current_user();
$target_user = $target_user_id ? get_userdata( $target_user_id ) : null;
$is_own_profile = false;
if ( ! $target_user ) {
if ( is_user_logged_in() ) {
$target_user = $current_user;
$target_user_id = $current_user->ID;
$is_own_profile = true;
} else {
wp_safe_redirect( aksrt_get_login_url( aksrt_get_user_center_url() ) );
exit;
}
} elseif ( is_user_logged_in() && (int) $current_user->ID === (int) $target_user->ID ) {
$is_own_profile = true;
}
if ( $target_user_nicename && ! $is_own_profile && function_exists( 'aksrt_get_user_home_url' ) ) {
wp_safe_redirect( aksrt_get_user_home_url( $target_user ) );
exit;
}
$user_id = $target_user->ID;
$post_count = (int) count_user_posts( $user_id, 'post', true );
$comment_count = (int) get_comments( [ 'user_id' => $user_id, 'count' => true, 'status' => 'approve' ] );
// 加载用户自定义联系方式
$user_contacts = get_user_meta( $user_id, 'aksrt_user_contacts', true ) ?: [];
if ( ! is_array( $user_contacts ) ) $user_contacts = [];
$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,
];
$user_home_settings = class_exists( 'AKSRT_Settings' )
? AKSRT_Settings::get_user_home_settings()
: [
'tabs' => [ 'posts', 'comments', 'favorites' ],
'sidebar' => true,
'cover' => true,
'follow' => true,
'posts_per_page' => 10,
];
$user_home_manager = class_exists( 'AKSRT_User_Home' ) ? AKSRT_User_Home::get_instance() : null;
$profile_signals = $user_home_manager ? $user_home_manager->get_profile_signals( $user_id ) : [];
$profile_notice = $user_home_manager ? $user_home_manager->get_profile_notice( $user_id ) : [];
$show_report_button = $user_home_manager ? $user_home_manager->show_report_entry() : false;
$public_visible_tabs = $user_home_manager
? $user_home_manager->get_visible_tabs( false )
: [
'posts' => [ 'label' => __( '文章', 'aksrt' ) ],
'comments' => [ 'label' => __( '评论', 'aksrt' ) ],
'favorites' => [ 'label' => __( '收藏', 'aksrt' ) ],
];
// 用户自定义背景图
$user_background_url = get_user_meta( $user_id, 'aksrt_background_image', true ) ?: '';
$allow_bg_upload = $is_own_profile
&& ! empty( $user_center_settings['cover_upload'] )
&& class_exists( 'AKSRT_Settings' )
&& aksrt_get_setting( 'allow_background_upload', false );
$show_avatar_edit = $is_own_profile && ! empty( $user_center_settings['avatar_upload'] );
$avatar_settings_url = admin_url( 'profile.php' );
$public_home_url = function_exists( 'aksrt_get_user_home_url' ) ? aksrt_get_user_home_url( $target_user ) : home_url( '/' );
$favorite_post_ids = function_exists( 'aksrt_get_user_interaction_posts' )
? aksrt_get_user_interaction_posts( '_aksrt_favorite_posts', $user_id )
: [];
$favorite_count = count( $favorite_post_ids );
$notification_unread_count = $is_own_profile && function_exists( 'aksrt_get_user_unread_notification_count' )
? aksrt_get_user_unread_notification_count( $user_id )
: 0;
$dashboard_tabs = class_exists( 'AKSRT_User_Center' )
? AKSRT_User_Center::get_instance()->get_dashboard_tabs()
: [
'profile' => [ 'label' => __( '个人信息', 'aksrt' ), 'icon' => 'user' ],
'posts' => [ 'label' => __( '我的文章', 'aksrt' ), 'icon' => 'file-alt' ],
'comments' => [ 'label' => __( '我的评论', 'aksrt' ), 'icon' => 'comment' ],
'favorites' => [ 'label' => __( '我的收藏', 'aksrt' ), 'icon' => 'star' ],
'settings' => [ 'label' => __( '账号设置', 'aksrt' ), 'icon' => 'cog' ],
];
$dashboard_tab_keys = array_keys( $dashboard_tabs );
$public_tab_keys = array_keys( $public_visible_tabs );
if ( empty( $public_tab_keys ) ) {
$public_visible_tabs = [
'posts' => [ 'label' => __( '文章', 'aksrt' ) ],
'comments' => [ 'label' => __( '评论', 'aksrt' ) ],
'favorites' => [ 'label' => __( '收藏', 'aksrt' ) ],
];
$public_tab_keys = array_keys( $public_visible_tabs );
}
$public_tab_labels = [
'posts' => __( '文章', 'aksrt' ),
'comments' => __( '评论', 'aksrt' ),
'favorites' => __( '收藏', 'aksrt' ),
];
foreach ( $public_visible_tabs as $public_tab_key => $public_tab_config ) {
if ( ! empty( $public_tab_config['label'] ) ) {
$public_tab_labels[ $public_tab_key ] = (string) $public_tab_config['label'];
}
}
$public_tab_counts = [
'posts' => $post_count,
'comments' => $comment_count,
'favorites' => $favorite_count,
];
// 消息中心页面 URL
$messages_page = get_pages( [ 'meta_key' => '_wp_page_template', 'meta_value' => 'templates/pages/page-messages.php', 'number' => 1 ] );
$messages_url = ! empty( $messages_page ) ? get_permalink( $messages_page[0] ) : aksrt_get_user_center_url( 'notif' );
// ─── 文章状态计数(仅自己模式;用于状态筛选 chip) ────────────
$user_status_counts = [
'publish' => 0,
'draft' => 0,
'pending' => 0,
'private' => 0,
];
if ( $is_own_profile ) {
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 );
}
// ─── 分页与筛选参数(自己 / 他人 共享) ────────────────────────
$per_page = $is_own_profile ? 10 : max( 5, (int) ( $user_home_settings['posts_per_page'] ?? 10 ) );
$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;
$public_default_tab = $public_tab_keys[0] ?? 'posts';
$public_active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : $public_default_tab;
// 兼容旧链接:签到 / 邀请已经并入新面板
if ( 'signin' === $active_tab ) {
$active_tab = 'credits';
} elseif ( 'invite' === $active_tab ) {
$active_tab = 'settings';
}
if ( ! in_array( $active_tab, $dashboard_tab_keys, true ) ) {
$active_tab = $default_dashboard_tab;
}
if ( ! in_array( $public_active_tab, $public_tab_keys, true ) ) {
$public_active_tab = $public_default_tab;
}
$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 );
$valid_post_status = [ 'all', 'publish', 'draft', 'pending', 'private' ];
$post_status_filter = isset( $_GET['post_status'] ) ? sanitize_key( wp_unslash( $_GET['post_status'] ) ) : 'publish';
if ( ! in_array( $post_status_filter, $valid_post_status, true ) ) {
$post_status_filter = 'publish';
}
// 空状态图标 SVG(提取以减少重复)
$svg_empty_post = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M9 13h6M9 17h6M9 9h1"/></svg>';
$svg_empty_comment = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>';
$svg_empty_favorite = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>';
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<?php if ( $is_own_profile ) : ?>
<!-- ===================== 本人模式:用户中心 ===================== -->
<div class="user-center">
<?php
$oauth_action = isset( $_GET['oauth_action'] ) ? sanitize_key( wp_unslash( $_GET['oauth_action'] ) ) : '';
$oauth_notice_provider = isset( $_GET['oauth_bound'] ) ? sanitize_key( wp_unslash( $_GET['oauth_bound'] ) ) : '';
$oauth_unbound_provider = isset( $_GET['oauth_unbound'] ) ? sanitize_key( wp_unslash( $_GET['oauth_unbound'] ) ) : '';
$oauth_notice_names = [
'github' => 'GitHub',
'gitee' => 'Gitee',
'qq' => 'QQ',
'google' => 'Google',
];
?>
<?php if ( isset( $_GET['saved'] ) || $oauth_notice_provider || $oauth_unbound_provider ) : ?>
<script>
document.addEventListener('DOMContentLoaded',function(){
<?php if ( $oauth_notice_provider && $oauth_action === 'login' ) : ?>
showToast('<?php echo esc_js( sprintf( __( '%s 登录成功', 'aksrt' ), $oauth_notice_names[ $oauth_notice_provider ] ?? ucfirst( $oauth_notice_provider ) ) ); ?>');
<?php elseif ( $oauth_notice_provider ) : ?>
showToast('<?php echo esc_js( sprintf( __( '%s 绑定成功', 'aksrt' ), $oauth_notice_names[ $oauth_notice_provider ] ?? ucfirst( $oauth_notice_provider ) ) ); ?>');
<?php elseif ( $oauth_unbound_provider ) : ?>
showToast('<?php echo esc_js( sprintf( __( '%s 已解绑', 'aksrt' ), $oauth_notice_names[ $oauth_unbound_provider ] ?? ucfirst( $oauth_unbound_provider ) ) ); ?>');
<?php else : ?>
showToast('已保存');
<?php endif; ?>
if(window.history.replaceState){
var u=new URL(window.location);
u.searchParams.delete('saved');
u.searchParams.delete('oauth_bound');
u.searchParams.delete('oauth_unbound');
u.searchParams.delete('oauth_action');
window.history.replaceState({},'',u);
}
});
</script>
<?php endif; ?>
<!-- 头图 + 用户卡 -->
<div class="uc-header">
<div class="uc-header__cover">
<img id="aksrt-cover-img" class="uc-header__cover-img" src="<?php echo esc_url( $user_background_url ? $user_background_url : get_theme_file_uri( 'assets/img/person_background.png' ) ); ?>" alt="">
<div class="uc-header__cover-mask"></div>
<?php if ( $allow_bg_upload ) : ?>
<button type="button" class="uc-header__cover-upload" id="aksrt-upload-bg-btn" title="<?php esc_attr_e( '编辑背景图', 'aksrt' ); ?>">
<i class="fas fa-pen" aria-hidden="true"></i>
<span><?php esc_html_e( '编辑', 'aksrt' ); ?></span>
</button>
<input type="file" id="aksrt-bg-file-input" accept="image/jpeg,image/png,image/webp,image/gif" style="display:none">
<?php endif; ?>
</div>
<div class="uc-header__content">
<div class="uc-header__avatar">
<?php echo get_avatar( $user_id, 120, '', $target_user->display_name ); ?>
</div>
<div class="uc-header__info">
<h1 class="uc-header__name">
<?php echo esc_html( $target_user->display_name ); ?>
<?php
$vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id) : '';
if ($vip_badge) echo $vip_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</h1>
<?php if ( $target_user->description ) : ?>
<p class="uc-header__desc"><?php echo esc_html( $target_user->description ); ?></p>
<?php endif; ?>
<?php if ( ! empty( $profile_signals ) ) : ?>
<div class="aksrt-identity-chips">
<?php foreach ( $profile_signals as $signal ) : ?>
<span class="aksrt-identity-chip aksrt-identity-chip--<?php echo esc_attr( $signal['tone'] ); ?>">
<i class="fas fa-<?php echo esc_attr( $signal['icon'] ); ?>" aria-hidden="true"></i>
<span><?php echo esc_html( $signal['label'] ); ?></span>
</span>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="uc-header__meta">
<span class="uc-header__meta-item" title="<?php esc_attr_e( '用户名', 'aksrt' ); ?>">
<i class="fas fa-user" aria-hidden="true"></i> <?php echo esc_html( $target_user->user_login ); ?>
</span>
<?php if ( $target_user->user_email ) : ?>
<span class="uc-header__meta-item" title="<?php esc_attr_e( '邮箱', 'aksrt' ); ?>">
<i class="fas fa-envelope" aria-hidden="true"></i> <?php echo esc_html( $target_user->user_email ); ?>
</span>
<?php endif; ?>
</div>
</div>
<div class="uc-header__actions">
<?php if ( $show_avatar_edit ) : ?>
<a href="<?php echo esc_url( $avatar_settings_url ); ?>" class="btn-ghost btn-sm">
<i class="fas fa-camera" aria-hidden="true"></i> <?php esc_html_e( '更换头像', 'aksrt' ); ?>
</a>
<?php endif; ?>
<a href="<?php echo esc_url( aksrt_get_user_home_url() ); ?>" class="btn-ghost btn-sm">
<i class="fas fa-map-marker-alt" aria-hidden="true"></i> <?php esc_html_e( '我的主页', 'aksrt' ); ?>
</a>
</div>
</div>
</div>
<!-- 两栏布局 -->
<div class="uc-layout">
<!-- 左侧边栏 -->
<aside class="uc-sidebar">
<!-- 数据统计 -->
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e( '数据统计', 'aksrt' ); ?></div>
<div class="uc-stats">
<?php foreach ( [ 'posts', 'comments', 'favorites' ] as $stat_tab ) : ?>
<?php if ( ! isset( $dashboard_tabs[ $stat_tab ] ) ) { continue; } ?>
<?php
$stat_count = 'posts' === $stat_tab
? $post_count
: ( 'comments' === $stat_tab ? $comment_count : $favorite_count );
?>
<a class="uc-stats__item" href="<?php echo esc_url( add_query_arg( 'tab', $stat_tab, remove_query_arg( 'tab' ) ) ); ?>">
<span class="uc-stats__value"><?php echo esc_html( (string) $stat_count ); ?></span>
<span class="uc-stats__label"><?php echo esc_html( $dashboard_tabs[ $stat_tab ]['label'] ); ?></span>
</a>
<?php endforeach; ?>
<a class="uc-stats__item" href="<?php echo esc_url( $messages_url ); ?>">
<span class="uc-stats__value"><?php echo esc_html( (string) $notification_unread_count ); ?></span>
<span class="uc-stats__label"><?php esc_html_e( '通知', 'aksrt' ); ?></span>
</a>
</div>
</div>
<!-- 我的服务 -->
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e( '我的服务', 'aksrt' ); ?></div>
<div class="uc-sidebar__buttons">
<?php foreach ( $dashboard_tabs as $tab_key => $tab ) : ?>
<button type="button" class="uc-sidebar__btn" data-tab="<?php echo esc_attr( $tab_key ); ?>">
<i class="fas fa-<?php echo esc_attr( $tab['icon'] ); ?>" aria-hidden="true"></i>
<span><?php echo esc_html( $tab['label'] ); ?></span>
</button>
<?php endforeach; ?>
<a href="<?php echo esc_url( $messages_url ); ?>" class="uc-sidebar__btn">
<i class="fas fa-bell" aria-hidden="true"></i>
<span><?php esc_html_e( '消息通知', 'aksrt' ); ?></span>
<?php if ( $notification_unread_count > 0 ) : ?>
<span class="uc-sidebar__badge"><?php echo esc_html( (string) $notification_unread_count ); ?></span>
<?php endif; ?>
</a>
</div>
</div>
<!-- 交易服务 -->
<?php
$orders_url = function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : '';
$show_vip = class_exists('AKSRT_Settings') && !empty(AKSRT_Settings::get_all()['payment_vip_enabled']);
$show_credit_tabs = class_exists('AKSRT_Settings') && AKSRT_Settings::credits_enabled();