扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
向应用程序添加在线用户列表
通过在希望显示联系人列表的位置上插入一些 JavaScript 代码,就可以将在线用户列表添加到应用程序的任何页面。图 1 展示了一个在线用户列示。
图 1. 在页面上包含一些简单的 JavaScript 代码
单击图片或用户名,即时消息传递窗口就会出现,如图 2 所示。
图 2. 发起一次即时消息传递对话
图 3 展示了回复。
图 3. 对传入的即时消息的响应
|
工作原理
为了维护在线用户列表,您需要 HTML 和 JavaScript,通过它们您可以为每个登录的用户连续运行代理。代理将使用时间戳(记录每个用户最后一次访问的时间)来维护用户文档。如果他或她最后一次访问的时间戳距离现在不超过两分钟,则该用户被定义为在线用户。在视图中维护在线用户列表将便于使用简单的 @DbColumn 公式来显示在线用户。
接下来,您必须能够和在线用户通信。由于已经为每个用户持续运行代理,因此该代理还可以监视是否存在要发送给指定用户的消息。如果存在消息,则该代理将输出 JavaScript 代码来打开包含消息的弹出窗口。
此解决方案中有四个主要设计元素负责完成实际工作。这四个设计元素为:
通过 Awareness.js 页面来展示哪些人在线
该页面包含了用来展示 Web 页面中在线用户的 JavaScript 代码。实际的设计如图 4 所示。若要向 Web 页面添加提醒,只需在该页面中包含 JavaScript 引用即可。
注意:在 Awareness 数据库中已包括了一个简单示例。在起始页中可看到包含的示例。
图 4 是从 IBM Lotus Domino Designer 中捕获的内容,它展示了 Awareness.js 页面(请注意第一行代码)。该行代码使用 document.write() 方法将一个较小的隐藏的 iFrame(0*0 像素)放置在 Web 页面上。iFrame 的内容是 refreshUserMsg 代理。当然,并不打算让用户看到 iFrame。iFrame 用于承载 Ajax 调用。
图 4. Lotus Domino Designer 中的 Awareness.js 页面
注意:选中该页面底部的 <Computed Value> 元素来展示用于显示每个名称前带有小照片的用户列表的代码。此功能假定您有一个可用的照片列表。
最后一行代码将查找由代理维护的在线用户并使用 @Implode 函数将列表和必需的 HTML 代码放置在一起,以便在用户单击另一个用户名称或照片时显示消息传递窗口。
通过 refreshUserMsg 代理维护在线用户列表
refreshUserMsg 代理由 Awareness.js 脚本所创建的 iFrame 载入。该代理将完成以下三个任务:
清单 1 展示了代理的 Initialize 部分。
清单 1. refreshUserMsg 代理的 Initialize 部分
Sub Initialize Dim session As New notessession Dim doc As notesDocument Dim db As NotesDatabase Set db = session.CurrentDatabase Set doc = session.documentContext Print "Content-type:text/html" ' Format a nice header telling the content type. Print "" Print |<SCRIPT Language="JavaScript">| Print |<!--| ' Check if user is registered. Set status. Call RefreshUser(db, doc) ' Check for messages. Call Check_Messages(db, doc) ' Check for messages regularly. ' Specify your polling time here in milliseconds. Print |timerID = setTimeout("document.location.reload()",1000);| Print |//-->| Print |</script>| End Sub |
第一个和第二个 Print 行设置了 Web 浏览器中对象的内容类型。采用这种方式,Lotus Domino 没有插入默认的 HTML 标题,这使请求节省了几个字节。
|
清单 2 会在每个用户首次访问系统时为其创建一个文档。然后,对于每一个请求,代码将更新用户文档。如果对用户状态文档的修改未超过两分钟,则认为该用户处于在线状态。
请注意对 RefreshUser 的调用(将维持在线用户列表)以及对 Check_Messages 子函数的调用。代理以设置定时器 setTimeout 结束,此定时器将在 1000 毫秒后重新载入 iFrame。
清单 2. RefreshUser 子函数
Sub RefreshUser(db As NotesDataBase, doc As NotesDocument) Dim uDoc As NotesDocument Dim view As NotesView Set view = db.GetView("Users") ' Find the users status document. Set uDoc = view.GetDocumentByKey(doc.Remote_User(0), True) If Not uDoc Is Nothing Then ' Set the users status to logged in. uDoc.status = "Online" Else ' Create a status document for first timers. Set uDoc = db.CreateDocument uDoc.Form = "user" Dim userName As New NotesName(doc.Remote_User(0)) uDoc.userCN = userName.Common uDoc.user = userName.Canonical uDoc.status = "Online" End If Call uDoc.Save(True, True) End Sub |
如清单 3 所示,代理的最后一个子函数将核对用户名和要传递的任何未处理的 e-msg 表单。如果有相匹配的内容,则代理打开包含消息的弹出窗口。注意 Print 行,此行设置了用于打开消息的 JavaScript 代码。
清单 3. Check_Messages 子函数
Sub Check_Messages(db As NotesDatabase, doc As NotesDocument) Dim view As NotesView Set view = db.GetView("e-msg (not delivered)") ' Check for messages. Dim mDoc As NotesDocument Set mDoc = view.GetDocumentByKey(doc.Remote_User(0), True) If Not mDoc Is Nothing then ' User got messages! mDoc.delivered = "1" ' Flag as delivered. Call mDoc.Save(False, False) ' Bring up the pop-up. doc.thisDb = Evaluate(|@WebDbName|) thisDb = doc.thisDb(0) Print |iMsg = window.open('/| + thisDb + |/e-msg?openForm&to=| + mDoc.fromEncoded(0) + |&unid=| + mDoc.UniversalID + |', '','height=220,width=250,resizable=yes,left=500,top=60');| End If End Sub |
通过 Refresh_Logged_in_user_list 代理确保用户退出系统
refreshUserMsg 代理将更新每个用户的文档,对于每个到达代理的请求,都会使用最后修改日期来更新文档。只要用户停留在其中一个启用了提醒的页面上 —— 即上述带有 JavaScript 代码的页面,那么该用户的用户文档就会具有一个递增的时间戳。当用户关闭浏览器或离开应用程序后,时间戳将停止工作。您可以利用此行为来判断用户没有在线,通过使用预定的代理来检查时间戳,并在出现更新的时间戳时重置用户状态。
我们将用户状态变为离线的时间间隔设置为两分钟。代理如清单 4 所示。
清单 4. Refresh_Logged_in_user_list 代理
SELECT Form = "user" & status != "not logged in" & @Adjust(@Now;0;0;0;0;-2;0) > @Modified; @Do( @SetField("status" ; "not logged in") ) |
可以在视图中完成此任务,不过您可能知道在视图中违反代码编写规范并使用 @Now 时将面临的问题。将代理排定为按照 Lotus Domino 所允许的时间间隔(五分钟间隔)来运行,这样在某些用户已经停止活动后,其在线状态仍将保持两分钟以上。
通过 e-msg 表单来发送和接收消息
如图 5 所示,e-msg 表单将定义所发送的消息。它既用于开始消息交换,也用于读取和响应。请注意,即使表单用于读取所发送的消息,也总是使用 ?OpenForm URL 命令来打开表单。您可以使用该命令直接从相同的页面创建响应。文档的惟一 ID 将作为参数进行发送,您可以通过使用 @GetDocField 命令方便地获得消息内容。
图 5. e-msg 表单
首次启动此表单时,将使用 openForm&to=Tomas%20Nielsen 这样的参数。表单的 To 字段将获得该参数,并利用它将消息传递到正确用户。如果需要接收方答复,那么第二次使用该表单时将发送两个参数 to 和 unid。unid 描述了用来存储要显示的消息的文档;然后参数通过使用 @GetDocField 公式来检索消息主体。
如果您的用户启用了弹出窗口拦截器,则应该允许在您自己的域内弹出窗口。否则将无法接收消息。若要避开此类拦截器,您可以使用 DHTML。如果用户在传递消息前关闭了浏览器,则消息将处于等待状态直到用户再次登录系统,并在载入首页时传递消息。
|
向即时消息添加表情
也许这并不是即时消息传递解决方案中最重要的功能,但您知道,用户需要它。我们已经添加了笑脸图片()作为共享资源图片,名为 happy.gif。
回到图 5,看一下 fromMessage 字段。该字段包含以下代码:
清单 5. fromMessage 字段公式
Tmp := @GetDocField( responseUNID; "message"); @ReplaceSubstring(@If(@IsError(Tmp) ; "" ; Tmp) ; @NewLine:":-)" ; "<br />":"<img src=\"/"+@WebDbName + "/happy.gif\">") |
请注意如何将新行转化为换行符,以及如何将所有 :-) 组合转换为笑脸图片。当然,可以使用更多表情来扩展此功能,不过这些留给您作为娱乐消遣。作为一项新增功能,您还可以使用特定的词作为更好的等价对象。
可以方便地利用此功能进行扩展。例如,可以添加动画 GIF 影片。甚至可以尝试嵌入欢呼人群的声音剪辑,每次登录内部网时该声音将传递给所有在线的同时。(隐含的是,我们的同事不同意这样做。)
|
性能考虑事项
在 refreshUserMsg 代理中,我们设置了请求到代理之间的时间段。我们使用的值为 1000 毫秒(1 秒)。这个值对于测试或仅有少数用户的情况是很合适的。对于中等规模的公司,我们发现使用 15,000 毫秒的时间段会比较合适。
如果将该技术用于其它目的,如检查用户是否有新的 email 消息,那么安排代理的时间以及调优代理是很重要的,这样代理才不会占用过多的 CPU 和磁盘时间。您可以完全控制进行下一次轮询的时间,因此完全有可能调整服务器负载应增加的值。例如,根据用户在线的数量,可以动态增加两次轮询的时间间隔。
来总结一下性能问题,我们的第一批提醒解决方案可以在 Lotus Domino 5 上正常运行。从此 Lotus Domino 启动代理和处理 HTTP 请求的速度提高了很多。我们可以说,该技术目前非常适合与 Lotus Domino 一起使用。
|
其他增强功能
为了在一篇文章中涵盖这种即时消息处理技术,我们降低了公司所使用的提醒解决方案版本。例如,我们所使用的版本还包括一个将聊天会话保存到知识库的选项。您可以添加的其他增强功能如下:
|
结束语
Ajax 向 Web 站点添加了一个全新的维度,它能够使服务器将内容推给您。之所以称为推,是因为在 “拉” 内容的同时,您将其隐藏在幕后。
我们热爱这种技术,原因之一是它不会载入 Microsoft ActiveX 控件、不会实例化 Java Virtual Machine(JVM)实例、也不需要 flash 动画播放器。对于大多数客户机来说,它是一种轻量级、容易的解决方案。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者