使用实时更新将在线用户显示为绿色,将离线用户显示为灰色

Posted

技术标签:

【中文标题】使用实时更新将在线用户显示为绿色,将离线用户显示为灰色【英文标题】:Display online users as green and offline as grey using real time updates 【发布时间】:2014-05-14 12:17:07 【问题描述】:

我想让每个帖子在其作者上线时变为绿色。我已经尝试解决我的编码问题至少一个星期了!!!请帮帮我!

例如,如果有 3 个用户发布了一些内容:

而user1登录,会变成:

那么说user2也同时登录:

现在如果 user2 或 user1 退出,它会变回灰色。一切都是实时的 - 无需刷新。我想这样当我打开网站时,我可以立即看到谁在线,而不是等待 2 秒(在这种情况下)立即看到实时更新。

我还希望能够为帖子添加动态链接。有没有办法在 div 之前插入标签,这取决于用户是否登录?

我的尝试:

更新:

Status.php

header('Content-Type: application/json');
$array = array();

$res = mysql_query("SELECT * FROM `users` WHERE `status` = 1");
if(mysql_num_rows($res) > 0)
    while($row = mysql_fetch_assoc($res))  
        $array[] = $row['user_id'];  // this adds each online user id to the array         
    

echo json_encode($array);

主页

$(document).ready(function()                                
    setInterval(function()
        $.ajax(
            url: 'status.php',
            dataType: "json",
            type: 'GET',
            success: function(data) 
                if (data.length > 0)   // if at least 1 is online
                    $('.status').each(function()   // loop through each of the user posts                      
                        if($.inArray(data) !== -1)     // if userid in the returned data array, set to online
                            $(this).css(background: 'green');
                      //add a link here  
                         else  // if not, set to offline
                            $(this).css(background: 'grey');
                         alert($.inArray(data)); 
                        
                    );
                 else     // if no one is online, set all to offline
                    $('.status').css(background: 'grey');
                           
            
        );
    , 2000);
);

CSS 样式

.status background: grey; 

一切似乎都开始工作了,但我无法让在线用户变绿。我尝试向阵列发出警报,但由于某种原因我收到“-1”警报。我该如何解决?

我尽量说清楚!非常感谢所有帮助!

【问题讨论】:

您将在每个 while() 循环上覆盖 $array['message']$array['userId'],因此您将始终只有 1 个用户数据。您需要返回一个数组,然后在您的 ajax 成功中循环遍历该数组。 另外<div class="status" id="user'.$user_id.'">'.$title.'</div> 会导致多个divs 具有相同的id,其中ids 需要是唯一的,这样您的js 将无法正常工作。更改为类或添加data- 属性。 我在我的问题中将 放在了错误的位置。我更新了我的问题。 div 是 while 循环的一部分,因此 id 会有所不同。如何返回一个数组?只需返回 json_encode($array);而不是回声? 如果用户有超过 1 个帖子,ids 将不是唯一的,即。您的示例有 2 个 user1 的帖子,因此您将有 2 个 id="user1",因为您使用的是 user_id。我正在寻找答案,很快就会发布。 你应该使用 web sockets 来做这样的事情...... PHP 并不是我的专长,但我敢肯定有一些不错的实时框架类似于 socket.io 【参考方案1】:

Status.php 中,您想要返回一个数组,而不仅仅是 1 个用户状态。此外,由于您只选择在线用户,因此您只需要他们的 id。所以你可以做$array[] = $row['user_id'];

header('Content-Type: application/json');
$array = array();

$res = mysql_query("SELECT * FROM `posts` WHERE status=1");
if(mysql_num_rows($res) > 0)
    while($row = mysql_fetch_assoc($res))  
        $array[] = $row['user_id'];  // this adds each online user id to the array         
    

echo json_encode($array);

然后在您的Main Page 中将您的<script> 移到循环之外,因此它不会在每个后循环中创建它。然后改变它,让它遍历返回的数组 -

更新

<script type="text/javascript">    
   $(document).ready(function()                                
     setInterval(function()
      $.ajax(
           url: 'status.php',
           dataType: "json",
           type: 'GET',
           success: function(data) 
               if (data.length > 0)  // if at least 1 is online
                  $('.status').each(function()  // loop through each of the user posts
                      var userid = parseInt($(this).attr('id').replace('user','')); // get just the userid #
                      if($.inArray(userid, data) !== -1)  // if userid # in the returned data array set to online
                           $(this).css(background: 'green');  
                       else  // else if userid # not in the returned data array set to offline
                           $(this).css(background: 'grey');  
                      
                  );
                
               else  // if no one is online, set all to offline
                   $('.status').css(background: 'grey');
               

           
        );
    , 2000); //2s just for testing. Set to 15s when code fully works.
   );
 </script>

这是 JSFiddle 上的一个示例 - http://jsfiddle.net/f5xkZ/2/


更新 2

$.inArray() 是一个 jQuery 函数,用于检查值是否在数组中。如果在数组中,它将返回值(0、1、2等)的数组键,如果不在数组中,它将返回-1。所以这就是为什么你检查它看到它没有返回-1,因此它在数组中-> if($.inArray(userid, data) !== -1)。为方便起见,您可以将user 添加到 php 中的数组值

while($row = mysql_fetch_assoc($res))
      $array[] = 'user'.$row['user_id'];

那就换

var userid = parseInt($(this).attr('id').replace('user',''));

只是

var userid = $(this).attr('id');

所以现在脚本看起来像

<script type="text/javascript">    
   $(document).ready(function()                                
     setInterval(function()
      $.ajax(
           url: 'status.php',
           dataType: "json",
           type: 'GET',
           success: function(data) 
               if (data.length > 0)  // if at least 1 is online
                  $('.status').each(function()  // loop through each of the user posts
                      var userid = $(this).attr('id'); // get the user#
                      if($.inArray(userid, data) !== -1)  // if userid # in the returned data array set to online
                           $(this).css(background: 'green');  
                       else  // else if userid # not in the returned data array set to offline
                           $(this).css(background: 'grey');  
                      
                  );
                
               else  // if no one is online, set all to offline
                   $('.status').css(background: 'grey');
               

           
        );
    , 2000); //2s just for testing. Set to 15s when code fully works.
   );
 </script>

这是一个更新的 jsFiddle - http://jsfiddle.net/f5xkZ/3/

更新 3

要让它立即显示,而不是等待第一个间隔,请将 ajax 调用放在一个函数中,在页面就绪时调用该函数,然后在 setInterval() 中再次调用

<script type="text/javascript">    
   $(document).ready(function()    

     // place ajax call in function that you will call on document ready, and in setInterval every 20 sec                            
     function check_online_status()
      $.ajax(
           url: 'status.php',
           dataType: "json",
           type: 'GET',
           success: function(data) 
               if (data.length > 0)  // if at least 1 is online
                  $('.status').each(function()  // loop through each of the user posts
                      var userid = $(this).attr('id'); // get the user#
                      if($.inArray(userid, data) !== -1)  // if userid # in the returned data array set to online
                           $(this).css(background: 'green');  
                       else  // else if userid # not in the returned data array set to offline
                           $(this).css(background: 'grey');  
                      
                  );
                
               else  // if no one is online, set all to offline
                   $('.status').css(background: 'grey');
               

           
        );
    

    check_online_status(); // call the function on document ready

    setInterval(function()check_online_status(), 20000); // call the function every 20 sec
   );
 </script>

【讨论】:

哇,感谢您抽出宝贵时间帮助我!我测试了你的代码,背景都是灰色的。我试图提醒一条消息进行检查,它通过了 else 但没有通过 if 语句。我感觉 if($.inArray(userid, data)) 有问题 我发现了我的问题并更新了脚本代码并在 JSFiddle 上提供了一个示例 - jsfiddle.net/f5xkZ/2。问题是 (1) 在 $('.status').each(function() 末尾缺少关闭 );,(2) 需要使用 parseInt()var userid 从字符串转换为 int,以及 (3) 需要检查是否不在数组中使用!== -1 -> if($.inArray(userid, data) !== -1) 警报($.inArray(data));返回“-1”,因此在这种情况下,它永远不会显示绿色,因为它会跳过 if 语句。我该如何解决? 我似乎无法弄清楚。但在这种情况下 alert($.inArray(data));将始终返回“-1”,所以我看不到绿色是有道理的,我只是不知道如何解决它 抱歉,有一个项目让我暂时离开了 ***。我已经更新/编辑了我的答案,澄清了$.inArray(),并进行了一些简单的更改,以便更容易检查是否在返回的数组中。【参考方案2】:

您可以通过跟踪所有用户的登录和注销时间来获取在线用户。如果用户的登录时间在注销时间之后,则表示该用户在线

【讨论】:

以上是关于使用实时更新将在线用户显示为绿色,将离线用户显示为灰色的主要内容,如果未能解决你的问题,请参考以下文章

在线/离线用户功能 Firestore 或实时的更好解决方案是啥?

将离线地图作为应用内购买出售

在 openfire 中保持连接处于活动状态,但在 xmpp 中将用户显示为离线

在基于 aws appsync 的聊天应用程序中显示在线用户

使用 Flutter 和 Firebase 实现实时在线/离线状态

我想使用会话在 php 的管理页面中在线显示用户? [关闭]