在线用户进阶版-zibll综合交流社区-zibll子比主题-zibll子比社区

在线用户进阶版

前几天看到了,星空知发的在线用户,觉得挺不错,就想能不能把游客也显示出来

 

于是让AI改了一下,感觉似乎能用,也不知道准不准,反正能运行就不错了

20250814233812602-QQ20250814-233724

20250814233812462-QQ20250814-233746

20250814234025362-QQ20250814-234010

 

 

// 初始化会话以追踪游客
function initialize_visitor_tracking() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'initialize_visitor_tracking');

// 创建游客追踪表
function create_visitor_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'online_visitors';
    
    $charset_collate = $wpdb->get_charset_collate();
    
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        session_id varchar(255) NOT NULL,
        ip_address varchar(45) NOT NULL,
        user_agent text,
        last_activity int(11) NOT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY session_id (session_id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 调试:检查表格是否创建成功
    if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        error_log("游客追踪表创建失败");
    }
}
register_activation_hook(__FILE__, 'create_visitor_table');

// 追踪游客活动 - 修复计数问题
function track_visitor_activity() {
    // 确保会话已启动
    if (!session_id()) {
        session_start();
    }
    
    if (!is_user_logged_in() && session_id()) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'online_visitors';
        $session_id = session_id();
        $ip_address = $_SERVER['REMOTE_ADDR'];
        $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $current_time = time();
        
        // 检查该会话是否已存在
        $visitor = $wpdb->get_row(
            $wpdb->prepare("SELECT id FROM $table_name WHERE session_id = %s", $session_id)
        );
        
        if ($visitor) {
            // 更新现有游客
            $wpdb->update(
                $table_name,
                array('last_activity' => $current_time),
                array('session_id' => $session_id)
            );
        } else {
            // 添加新游客
            $wpdb->insert(
                $table_name,
                array(
                    'session_id' => $session_id,
                    'ip_address' => $ip_address,
                    'user_agent' => $user_agent,
                    'last_activity' => $current_time
                )
            );
        }
        
        // 清理过期游客数据(超过24小时)
        $wpdb->query(
            $wpdb->prepare("DELETE FROM $table_name WHERE last_activity < %d", $current_time - 86400)
        );
    }
}
// 提高优先级确保执行
add_action('init', 'track_visitor_activity', 5);

// 登录时设置活动状态
function track_user_login($user_login, $user) {
    update_user_meta($user->ID, 'last_activity', time());
    update_user_meta($user->ID, 'is_logged_in', '1');
    
    // 登录后清除可能的游客记录
    if (session_id()) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'online_visitors';
        $wpdb->delete(
            $table_name,
            array('session_id' => session_id())
        );
    }
}
add_action('wp_login', 'track_user_login', 10, 2);

// 每次页面加载时更新活动时间
function update_user_activity() {
    if (is_user_logged_in()) {
        $user_id = get_current_user_id();
        update_user_meta($user_id, 'last_activity', time());
        update_user_meta($user_id, 'is_logged_in', '1');
    }
}
add_action('init', 'update_user_activity');

// 登出时更新状态
function track_user_logout() {
    $user_id = get_current_user_id();
    update_user_meta($user_id, 'is_logged_in', '0');
}
add_action('wp_logout', 'track_user_logout');


class Online_Users_Widget extends WP_Widget {

    // 构造函数
    function __construct() {
        parent::__construct(
            'online_users_widget',
            __('在线用户', 'text_domain'),
            array(
                'description' => __('实时显示在线用户和游客列表', 'text_domain'),
                'classname' => 'widget_online_users'
            )
        );
    }

    // 前端显示(带实时更新和悬浮效果)
    public function widget($args, $instance) {
        // 获取设置
        $title = apply_filters('widget_title', empty($instance['title']) ? __('在线用户', 'text_domain') : $instance['title']);
        $inactive_time = empty($instance['inactive_time']) ? 60 : absint($instance['inactive_time']);
        $show_count = !empty($instance['show_count']);
        $show_guests = !empty($instance['show_guests']);
        $refresh_interval = empty($instance['refresh_interval']) ? 30 : absint($instance['refresh_interval']);
        $guest_avatar_url = empty($instance['guest_avatar_url']) ? '' : esc_url($instance['guest_avatar_url']);
        
        // 使用默认头像如果未设置
        if (empty($guest_avatar_url)) {
            $guest_avatar_url = plugins_url('guest-avatar.png', __FILE__);
        }
        
        // 生成唯一ID用于JS更新
        $widget_id = 'online-users-widget-' . $this->id;
        
        // 开始输出
        echo $args['before_widget'];
        echo '<div id="' . esc_attr($widget_id) . '" class="online-users-container">';
        if (!empty($title)) {
            echo $args['before_title'] . '<span class="online-title-icon">👥</span>' . esc_html($title) . $args['after_title'];
        }
        
        // 显示加载状态
        echo '<div class="online-users-loading">';
        echo '<div class="loading-spinner"></div>';
        echo '<p>' . __('加载中...', 'text_domain') . '</p>';
        echo '</div>';
        
        // 内容将通过JS动态加载
        echo '<div class="online-users-content" style="display: none;"></div>';
        
        echo '</div>'; // .online-users-container
        echo $args['after_widget'];
        
        // 输出JS配置
        ?>
        <script type="text/javascript">
        // 在线用户组件配置
        var onlineUsersConfig = {
            widgetId: '<?php echo esc_js($widget_id); ?>',
            inactiveTime: <?php echo esc_js($inactive_time); ?>,
            showGuests: <?php echo esc_js($show_guests ? 'true' : 'false'); ?>,
            showCount: <?php echo esc_js($show_count ? 'true' : 'false'); ?>,
            refreshInterval: <?php echo esc_js($refresh_interval * 1000); ?>,
            guestAvatarUrl: '<?php echo esc_js($guest_avatar_url); ?>',
            ajaxUrl: '<?php echo esc_js(admin_url('admin-ajax.php')); ?>',
            nonce: '<?php echo esc_js(wp_create_nonce('online_users_nonce')); ?>'
        };
        
        // 初始化并加载数据
        document.addEventListener('DOMContentLoaded', function() {
            loadOnlineUsersData(onlineUsersConfig);
            
            // 设置定时刷新
            setInterval(function() {
                loadOnlineUsersData(onlineUsersConfig);
            }, onlineUsersConfig.refreshInterval);
        });
        
        // 加载在线用户数据
        function loadOnlineUsersData(config) {
            var container = document.getElementById(config.widgetId);
            var loading = container.querySelector('.online-users-loading');
            var content = container.querySelector('.online-users-content');
            
            // 显示加载状态
            loading.style.display = 'block';
            content.style.display = 'none';
            
            // AJAX请求
            var xhr = new XMLHttpRequest();
            xhr.open('POST', config.ajaxUrl, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    // 隐藏加载状态
                    loading.style.display = 'none';
                    
                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            if (response.success) {
                                // 替换游客头像URL
                                var html = response.data.html;
                                if (config.guestAvatarUrl) {
                                    html = html.replace(/guest-avatar\.png[^"]*/g, config.guestAvatarUrl);
                                }
                                
                                content.innerHTML = html;
                                content.style.display = 'block';
                                
                                // 添加淡入动画
                                content.style.opacity = '0';
                                var opacity = 0;
                                var interval = setInterval(function() {
                                    if (opacity >= 1) {
                                        clearInterval(interval);
                                    }
                                    content.style.opacity = opacity;
                                    opacity += 0.1;
                                }, 30);
                            }
                        } catch (e) {
                            console.error('解析在线用户数据失败:', e);
                        }
                    }
                }
            };
            
            // 发送请求数据
            var data = 'action=get_online_users_data' +
                      '&nonce=' + encodeURIComponent(config.nonce) +
                      '&inactive_time=' + encodeURIComponent(config.inactiveTime) +
                      '&show_guests=' + encodeURIComponent(config.showGuests ? 1 : 0) +
                      '&show_count=' + encodeURIComponent(config.showCount ? 1 : 0);
                      
            xhr.send(data);
        }
        </script>
        <?php
    }
    
    // 相对时间显示
    private function relative_time($timestamp) {
        $current_time = time();
        $diff = $current_time - $timestamp;
        
        if ($diff < 60) {
            return __('刚刚在线', 'text_domain');
        } elseif ($diff < 3600) {
            return sprintf(__('%d分钟前', 'text_domain'), floor($diff/60));
        } elseif ($diff < 86400) {
            return sprintf(__('%d小时前', 'text_domain'), floor($diff/3600));
        } else {
            return date(__('Y年m月d日', 'text_domain'), $timestamp);
        }
    }

    // 后台表单 - 新增游客头像设置
    public function form($instance) {
        $defaults = array(
            'title' => __('在线用户', 'text_domain'),
            'inactive_time' => 60,
            'show_count' => true,
            'show_guests' => true,
            'refresh_interval' => 30,
            'guest_avatar_url' => '' // 游客头像URL设置
        );
        $instance = wp_parse_args((array) $instance, $defaults);
        ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('标题:'); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" 
                   name="<?php echo $this->get_field_name('title'); ?>" 
                   type="text" value="<?php echo esc_attr($instance['title']); ?>" />
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('inactive_time'); ?>"><?php _e('视为在线的时间(秒):'); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id('inactive_time'); ?>" 
                   name="<?php echo $this->get_field_name('inactive_time'); ?>" 
                   type="number" min="60" value="<?php echo esc_attr($instance['inactive_time']); ?>" />
            <small><?php _e('默认60秒'); ?></small>
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('refresh_interval'); ?>"><?php _e('刷新间隔(秒):'); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id('refresh_interval'); ?>" 
                   name="<?php echo $this->get_field_name('refresh_interval'); ?>" 
                   type="number" min="5" value="<?php echo esc_attr($instance['refresh_interval']); ?>" />
            <small><?php _e('默认30秒,建议不小于5秒'); ?></small>
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('guest_avatar_url'); ?>"><?php _e('游客头像URL:'); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id('guest_avatar_url'); ?>" 
                   name="<?php echo $this->get_field_name('guest_avatar_url'); ?>" 
                   type="url" placeholder="https://example.com/guest-avatar.png"
                   value="<?php echo esc_attr($instance['guest_avatar_url']); ?>" />
            <small><?php _e('留空则使用默认头像'); ?></small>
        </p>
        <p>
            <input class="checkbox" type="checkbox" id="<?php echo $this->get_field_id('show_count'); ?>" 
                   name="<?php echo $this->get_field_name('show_count'); ?>" 
                   <?php checked($instance['show_count'], true); ?> />
            <label for="<?php echo $this->get_field_id('show_count'); ?>"><?php _e('显示在线人数'); ?></label>
        </p>
        <p>
            <input class="checkbox" type="checkbox" id="<?php echo $this->get_field_id('show_guests'); ?>" 
                   name="<?php echo $this->get_field_name('show_guests'); ?>" 
                   <?php checked($instance['show_guests'], true); ?> />
            <label for="<?php echo $this->get_field_id('show_guests'); ?>"><?php _e('显示游客'); ?></label>
        </p>
        <?php
    }

    // 更新设置
    public function update($new_instance, $old_instance) {
        $instance = $old_instance;
        $instance['title'] = sanitize_text_field($new_instance['title']);
        $instance['inactive_time'] = absint($new_instance['inactive_time']);
        $instance['show_count'] = !empty($new_instance['show_count']);
        $instance['show_guests'] = !empty($new_instance['show_guests']);
        $instance['refresh_interval'] = absint($new_instance['refresh_interval']);
        $instance['guest_avatar_url'] = esc_url_raw($new_instance['guest_avatar_url']); // 保存游客头像URL
        return $instance;
    }

    // 获取在线用户和游客 - 修复计数问题
    public function get_online_data($inactive_time = 60, $show_guests = true) {
        $current_time = time();
        $online_users = array();
        $online_guests = 0;
        
        // 获取在线用户
        $users = get_users(array(
            'meta_query' => array(
                array(
                    'key' => 'last_activity',
                    'compare' => 'EXISTS'
                )
            )
        ));
        
        foreach ($users as $user) {
            $last_activity = (int)get_user_meta($user->ID, 'last_activity', true);
            $is_logged_in = get_user_meta($user->ID, 'is_logged_in', true);
            
            if (($current_time - $last_activity <= $inactive_time) && $is_logged_in === '1') {
                $online_users[$user->ID] = $user;
            }
        }
        
        // 获取在线游客数量 - 修复计数逻辑
        if ($show_guests) {
            global $wpdb;
            $table_name = $wpdb->prefix . 'online_visitors';
            
            // 确保表格存在
            if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name) {
                $online_guests = $wpdb->get_var(
                    $wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE last_activity >= %d", $current_time - $inactive_time)
                );
            } else {
                // 表格不存在时尝试重新创建
                create_visitor_table();
                $online_guests = 0;
                error_log("游客表不存在,已尝试重新创建");
            }
        }
        
        return array(
            'users' => $online_users,
            'guests' => $online_guests ? $online_guests : 0
        );
    }
    
    // 生成在线用户列表HTML - 用于AJAX响应
    public function generate_online_html($data, $show_count = true, $show_guests = true) {
        $online_users = $data['users'];
        $online_guests = $data['guests'];
        $html = '';
        
        // 显示用户和游客数量
        if ($show_count) {
            $html .= '<div class="online-users-count">';
            $html .= '<span class="count-bubble">' . (count($online_users) + $online_guests) . '</span>';
            
            $total = count($online_users) + $online_guests;
            $users_text = sprintf(
                _n(' %d 位用户', ' %d 位用户', count($online_users), 'text_domain'), 
                count($online_users)
            );
            
            $guests_text = '';
            if ($show_guests) {
                $guests_text = sprintf(
                    _n(',%d 位游客', ',%d 位游客', $online_guests, 'text_domain'), 
                    $online_guests
                );
            }
            
            $html .= sprintf(
                __('当前共有 %d 位访问者' . $users_text . $guests_text, 'text_domain'),
                $total
            );
            
            $html .= '</div>'; 
        }
        
        // 显示用户列表
        if (!empty($online_users) || ($show_guests && $online_guests > 0)) {
            $html .= '<ul class="online-users-list">';
            
            // 显示登录用户
            foreach ($online_users as $user) {
                $display_name = !empty($user->display_name) ? $user->display_name : $user->user_login;
                $avatar = get_avatar($user->ID, 96);
                $user_link = get_author_posts_url($user->ID);
                $last_active = $this->relative_time((int)get_user_meta($user->ID, 'last_activity', true));
                
                $html .= '<li class="online-user">';
                $html .= '<a href="' . esc_url($user_link) . '" rel="external nofollow"  class="user-card" title="' . esc_attr($display_name) . '">';
                $html .= '<div class="avatar-container">';
                $html .= $avatar;
                $html .= '<span class="online-status user-status" title="用户在线"></span>';
                $html .= '</div>';
                $html .= '<span class="online-user-name">' . esc_html($display_name) . '</span>';
                
                // 悬浮卡片
                $html .= '<div class="user-hover-card">';
                $html .= '<div class="hover-avatar">' . get_avatar($user->ID, 120) . '</div>';
                $html .= '<h4>' . esc_html($display_name) . '</h4>';
                $html .= '<p><i class="activity-icon"></i> ' . esc_html($last_active) . '</p>';
                $html .= '<p class="user-type">' . __('注册用户', 'text_domain') . '</p>';
                $html .= '</div>';
                
                $html .= '</a>';
                $html .= '</li>';
            }
            
            // 显示游客
            if ($show_guests && $online_guests > 0) {
                $html .= '<li class="online-guest">';
                $html .= '<div class="guest-card" title="' . sprintf(__('%d位游客在线', 'text_domain'), $online_guests) . '">';
                $html .= '<div class="avatar-container">';
                $html .= '<img src="guest-avatar.png" alt="' . __('游客', 'text_domain') . '" class="avatar guest-avatar">';
                $html .= '<span class="online-status guest-status" title="游客在线"></span>';
                $html .= '</div>';
                $html .= '<span class="online-guest-count">' . sprintf(__('%d位游客', 'text_domain'), $online_guests) . '</span>';
                
                // 游客悬浮卡片
                $html .= '<div class="guest-hover-card">';
                $html .= '<h4>' . __('在线游客', 'text_domain') . '</h4>';
                $html .= '<p>' . sprintf(__('当前有 %d 位游客正在访问', 'text_domain'), $online_guests) . '</p>';
                $html .= '</div>';
                
                $html .= '</div>';
                $html .= '</li>';
            }
            
            $html .= '</ul>';
        } else {
            $html .= '<div class="no-online-users">';
            $html .= '<div class="empty-state">';
            $html .= '<span class="empty-icon">👻</span>';
            $html .= '<p>' . __('当前没有用户和游客在线', 'text_domain') . '</p>';
            $html .= '</div>';
            $html .= '</div>';
        }
        
        return $html;
    }
}

// 注册小工具
function register_online_users_widget() {
    register_widget('Online_Users_Widget');
}
add_action('widgets_init', 'register_online_users_widget');

// AJAX处理函数 - 用于实时获取在线用户数据
function handle_online_users_ajax() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['nonce'], 'online_users_nonce')) {
        wp_send_json_error(array('message' => '验证失败'));
    }
    
    // 获取参数
    $inactive_time = isset($_POST['inactive_time']) ? absint($_POST['inactive_time']) : 60;
    $show_guests = isset($_POST['show_guests']) ? (bool)$_POST['show_guests'] : true;
    $show_count = isset($_POST['show_count']) ? (bool)$_POST['show_count'] : true;
    
    // 实例化小工具类并获取数据
    $widget = new Online_Users_Widget();
    $online_data = $widget->get_online_data($inactive_time, $show_guests);
    $html = $widget->generate_online_html($online_data, $show_count, $show_guests);
    
    // 返回结果
    wp_send_json_success(array('html' => $html));
}
add_action('wp_ajax_get_online_users_data', 'handle_online_users_ajax');
add_action('wp_ajax_nopriv_get_online_users_data', 'handle_online_users_ajax'); // 允许未登录用户访问

//初始化用户状态
function initialize_user_status() {
    if (!get_option('online_users_status_initialized')) {
        $users = get_users();
        foreach ($users as $user) {
            if (!metadata_exists('user', $user->ID, 'is_logged_in')) {
                update_user_meta($user->ID, 'is_logged_in', '0');
            }
            if (!metadata_exists('user', $user->ID, 'last_activity')) {
                update_user_meta($user->ID, 'last_activity', time());
            }
        }
        
        // 确保游客表已创建
        create_visitor_table();
        
        update_option('online_users_status_initialized', true);
    }
}
add_action('admin_init', 'initialize_user_status');

// CSS样式 - 深色模式改为#323335
function online_users_widget_styles() {
    ?>
    <style>
    /* 基础样式 - 优化阴影 */
    .widget_online_users {
        background: linear-gradient(135deg, #f5f7fa 0%, #f8fafc 100%);
        border-radius: 16px;
        box-shadow: 
            0 1px 1px rgba(0,0,0,0.02),
            0 2px 2px rgba(0,0,0,0.02),
            0 4px 4px rgba(0,0,0,0.02),
            0 8px 8px rgba(0,0,0,0.03),
            0 16px 16px rgba(0,0,0,0.03);
        padding: 25px;
        margin-bottom: 30px;
        border: 1px solid rgba(255,255,255,0.5);
        backdrop-filter: blur(8px);
        transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
    }
    
    .widget_online_users:hover {
        box-shadow: 
            0 1px 1px rgba(0,0,0,0.03),
            0 2px 2px rgba(0,0,0,0.03),
            0 4px 4px rgba(0,0,0,0.03),
            0 8px 8px rgba(0,0,0,0.04),
            0 16px 16px rgba(0,0,0,0.04),
            0 24px 24px rgba(0,0,0,0.05);
        transform: translateY(-3px) scale(1.005);
    }
    
    /* 标题样式 */
    .widget_online_users .widget-title {
        font-size: 1.3em;
        color: #2d3748;
        margin-bottom: 20px;
        padding-bottom: 12px;
        border-bottom: 1px solid rgba(0,0,0,0.05);
        display: flex;
        align-items: center;
        font-weight: 600;
    }
    
    .online-title-icon {
        margin-right: 10px;
        font-size: 1.2em;
        filter: drop-shadow(0 1px 1px rgba(0,0,0,0.1));
    }
    
    /* 在线人数统计 */
    .widget_online_users .online-users-count {
        background: rgba(74, 85, 104, 0.1);
        padding: 8px 15px;
        border-radius: 50px;
        font-size: 0.9em;
        color: #4a5568;
        margin-bottom: 20px;
        display: inline-flex;
        align-items: center;
        transition: all 0.3s ease;
    }
    .widget_online_users .online-users-count:hover {
        background: rgba(74, 85, 104, 0.2);
    }
    
    .count-bubble {
        background: linear-gradient(135deg, #4CAF50 0%, #81C784 100%);
        color: white;
        width: 24px;
        height: 24px;
        border-radius: 50%;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        margin-right: 8px;
        font-size: 0.8em;
        font-weight: bold;
        box-shadow: 
            0 1px 1px rgba(76, 175, 80, 0.2),
            0 2px 2px rgba(76, 175, 80, 0.15),
            0 4px 4px rgba(76, 175, 80, 0.1);
    }
    
    /* 用户列表 */
    .widget_online_users .online-users-list {
        list-style: none;
        padding: 0;
        margin: 0 -5px;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
    }
    
    /* 单个用户项 */
    .widget_online_users .online-user,
    .widget_online_users .online-guest {
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 80px;
        margin: 0 5px 15px;
        position: relative;
    }
    
    .widget_online_users .user-card,
    .widget_online_users .guest-card {
        display: flex;
        flex-direction: column;
        align-items: center;
        text-decoration: none;
        transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
        position: relative;
        will-change: transform;
    }
    
    .widget_online_users .user-card:hover,
    .widget_online_users .guest-card:hover {
        transform: translateY(-5px);
    }
    
    /* 头像容器 */
    .widget_online_users .avatar-container {
        position: relative;
        margin-bottom: 8px;
        transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
        will-change: transform;
    }
    
    .widget_online_users .user-card:hover .avatar-container,
    .widget_online_users .guest-card:hover .avatar-container {
        transform: scale(1.05);
    }
    
    /* 用户头像和游客头像 */
    .widget_online_users .online-user img.avatar,
    .widget_online_users .guest-avatar {
        width: 60px;
        height: 60px;
        border-radius: 50%;
        object-fit: cover;
        border: 3px solid white;
        box-shadow: 
            0 1px 1px rgba(0,0,0,0.05),
            0 2px 2px rgba(0,0,0,0.05),
            0 4px 4px rgba(0,0,0,0.05),
            0 6px 6px rgba(0,0,0,0.06);
        transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
    }
    
    .widget_online_users .guest-avatar {
        background-color: #e2e8f0;
        padding: 8px;
        box-sizing: border-box;
    }
    
    .widget_online_users .user-card:hover img.avatar,
    .widget_online_users .guest-card:hover .guest-avatar {
        box-shadow: 
            0 2px 2px rgba(0,0,0,0.06),
            0 4px 4px rgba(0,0,0,0.06),
            0 8px 8px rgba(0,0,0,0.07),
            0 12px 12px rgba(0,0,0,0.08);
    }
    
    /* 在线状态指示器 */
    .widget_online_users .online-status {
        position: absolute;
        bottom: 5px;
        right: 5px;
        width: 14px;
        height: 14px;
        border-radius: 50%;
        box-shadow: 
            0 0 0 1px rgba(76, 175, 80, 0.2),
            0 0 0 2px rgba(76, 175, 80, 0.15);
        animation: pulse 1.5s infinite;
        z-index: 2;
    }
    
    .widget_online_users .user-status {
        background: linear-gradient(135deg, #4CAF50 0%, #81C784 100%);
        border: 2px solid white;
    }
    
    .widget_online_users .guest-status {
        background: linear-gradient(135deg, #FFB74D 0%, #FFCC80 100%);
        border: 2px solid white;
    }
    
    /* 用户名和游客数量 */
    .widget_online_users .online-user-name,
    .widget_online_users .online-guest-count {
        font-size: 0.8em;
        color: #4a5568;
        text-align: center;
        word-break: break-word;
        line-height: 1.4;
        font-weight: 500;
        transition: all 0.3s ease;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
    
    .widget_online_users .user-card:hover .online-user-name,
    .widget_online_users .guest-card:hover .online-guest-count {
        color: #2d3748;
        font-weight: 600;
    }
    
    /* 用户类型标签 */
    .widget_online_users .user-type {
        font-size: 0.8em;
        color: #718096;
        margin-top: 5px;
        padding-top: 5px;
        border-top: 1px dashed rgba(0,0,0,0.05);
    }
    
    /* 悬浮卡片 */
    .widget_online_users .user-hover-card,
    .widget_online_users .guest-hover-card {
        position: absolute;
        bottom: calc(100% + 10px);
        left: 50%;
        transform: translateX(-50%) translateY(10px);
        width: 180px;
        background: white;
        border-radius: 12px;
        padding: 15px;
        opacity: 0;
        visibility: hidden;
        transition: 
            opacity 0.3s ease-out,
            transform 0.4s cubic-bezier(0.23, 1, 0.32, 1);
        z-index: 10;
        pointer-events: none;
        text-align: center;
    }
    
    .widget_online_users .user-card:hover .user-hover-card,
    .widget_online_users .guest-card:hover .guest-hover-card {
        opacity: 1;
        visibility: visible;
        transform: translateX(-50%) translateY(0);
    }
    
    /* 加载状态样式 */
    .online-users-loading {
        text-align: center;
        padding: 20px 0;
    }
    
    .loading-spinner {
        width: 40px;
        height: 40px;
        margin: 0 auto 10px;
        border: 3px solid rgba(76, 175, 80, 0.2);
        border-radius: 50%;
        border-top-color: #4CAF50;
        animation: spin 1s ease-in-out infinite;
    }
    
    @keyframes spin {
        to { transform: rotate(360deg); }
    }
    
    /* 添加卡片升起时的微光效果 */
    .widget_online_users .user-hover-card::before,
    .widget_online_users .guest-hover-card::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 40%;
        background: linear-gradient(to bottom, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 100%);
        border-radius: 12px 12px 0 0;
        opacity: 0;
        transition: opacity 0.4s ease;
    }
    
    .widget_online_users .user-card:hover .user-hover-card::before,
    .widget_online_users .guest-card:hover .guest-hover-card::before {
        opacity: 0.6;
    }
    
    /* 优化卡片内容过渡 */
    .widget_online_users .user-hover-card > *,
    .widget_online_users .guest-hover-card > * {
        transform: translateY(5px);
        opacity: 0.9;
        transition: 
            transform 0.4s cubic-bezier(0.23, 1, 0.32, 1),
            opacity 0.4s ease;
    }
    
    .widget_online_users .user-card:hover .user-hover-card > *,
    .widget_online_users .guest-card:hover .guest-hover-card > * {
        transform: translateY(0);
        opacity: 1;
    }
    
    /* 延迟子元素动画 */
    .widget_online_users .user-hover-card .hover-avatar,
    .widget_online_users .guest-hover-card h4 {
        transition-delay: 0.05s;
    }
    
    .widget_online_users .user-hover-card h4,
    .widget_online_users .guest-hover-card p {
        transition-delay: 0.1s;
    }
    
    .widget_online_users .user-hover-card p {
        transition-delay: 0.15s;
    }
    
    .activity-icon {
        display: inline-block;
        width: 12px;
        height: 12px;
        background: #4CAF50;
        border-radius: 50%;
        margin-right: 5px;
        animation: pulse 1.5s infinite;
    }
    
    /* 无用户状态 */
    .widget_online_users .no-online-users {
        padding: 20px 0;
    }
    .widget_online_users .empty-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        text-align: center;
    }
    
    .widget_online_users .empty-icon {
        font-size: 2em;
        opacity: 0.5;
        margin-bottom: 10px;
        filter: drop-shadow(0 1px 1px rgba(0,0,0,0.1));
    }
    
    .widget_online_users .empty-state p {
        margin: 0;
        color: #718096;
        font-size: 0.9em;
    }
    
    @keyframes pulse {
        0% { 
            transform: scale(0.95); 
            box-shadow: 
                0 0 0 0 rgba(76, 175, 80, 0.4),
                0 0 0 1px rgba(76, 175, 80, 0.3);
        }
        70% { 
            transform: scale(1.05); 
            box-shadow: 
                0 0 0 4px rgba(76, 175, 80, 0.1),
                0 0 0 6px rgba(76, 175, 80, 0);
        }
        100% { 
            transform: scale(0.95); 
            box-shadow: 
                0 0 0 0 rgba(76, 175, 80, 0),
                0 0 0 1px rgba(76, 175, 80, 0.1);
        }
    }
    
    @media (max-width: 480px) {
        .widget_online_users {
            padding: 20px 15px;
            border-radius: 12px;
        }
        
        .widget_online_users .online-user,
        .widget_online_users .online-guest {
            width: 70px;
        }
        
        .widget_online_users .online-user img.avatar,
        .widget_online_users .guest-avatar {
            width: 50px;
            height: 50px;
        }
        
        .widget_online_users .user-hover-card,
        .widget_online_users .guest-hover-card {
            width: 160px;
            padding: 12px;
        }
    }
    
    /* Zibll主题夜间模式适配(使用#323335深色) */
    .dark-theme .widget_online_users {
        background: #323335;
        border-color: rgba(255,255,255,0.08);
    }
    
    .dark-theme .widget_online_users .widget-title {
        color: #e2e8f0;
        border-bottom-color: rgba(255,255,255,0.08);
    }
    
    .dark-theme .widget_online_users .online-title-icon {
        filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3));
    }
    
    .dark-theme .widget_online_users .online-users-count {
        background: rgba(255,255,255,0.08);
        color: #e2e8f0;
    }
    
    .dark-theme .widget_online_users .online-users-count:hover {
        background: rgba(255,255,255,0.12);
    }
    
    .dark-theme .widget_online_users .online-user-name,
    .dark-theme .widget_online_users .online-guest-count {
        color: #cbd5e0;
    }
    
    .dark-theme .widget_online_users .user-card:hover .online-user-name,
    .dark-theme .widget_online_users .guest-card:hover .online-guest-count {
        color: #f7fafc;
    }
    
    .dark-theme .widget_online_users .online-user img.avatar,
    .dark-theme .widget_online_users .guest-avatar {
        border-color: #323335;
        box-shadow: 
            0 1px 1px rgba(0,0,0,0.2),
            0 2px 2px rgba(0,0,0,0.2),
            0 4px 4px rgba(0,0,0,0.2);
    }
    
    .dark-theme .widget_online_users .guest-avatar {
        background-color: #4a5568;
    }
    
    .dark-theme .widget_online_users .user-status {
        border-color: #323335;
    }
    
    .dark-theme .widget_online_users .guest-status {
        border-color: #323335;
    }
    
    .dark-theme .widget_online_users .user-type {
        color: #a0aec0;
        border-top-color: rgba(255,255,255,0.05);
    }
    
    .dark-theme .widget_online_users .user-hover-card,
    .dark-theme .widget_online_users .guest-hover-card {
        background: #323335;
        border: 1px solid rgba(255,255,255,0.08);
    }
    
    .dark-theme .widget_online_users .user-hover-card::before,
    .dark-theme .widget_online_users .guest-hover-card::before {
        background: linear-gradient(to bottom, rgba(50,51,53,0.9) 0%, rgba(50,51,53,0) 100%);
    }
    
    .dark-theme .online-users-loading p {
        color: #e2e8f0;
    }
    
    .dark-theme .loading-spinner {
        border-color: rgba(76, 175, 80, 0.1);
        border-top-color: #81C784;
    }
    
    .dark-theme .widget_online_users .empty-state p {
        color: #a0aec0;
    }
    
    .dark-theme .widget_online_users .empty-icon {
        filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3));
    }
    </style>
    <?php
}
add_action('wp_head', 'online_users_widget_styles');

 

 

 

请登录后发表评论

    没有回复内容