Worktile即时消息

  1. 本课程是Worktile的一部分。

  2. 演示

  1. 获取私有群(群成员包含我)和公开群的列表信息,并把它们的_id组成列表$V.消息.群ID

  2. 打开连接$socket.open()
    群组_id列表作为channels,这样可收到相关群组的消息;
    saveToDB设为true,把信息都保存到数据库,这样通过$socket.hist()可以查看历史消息,即时不在线是别人发送的未读消息也能收到;
    allowMultiLogin设为true,这样打开的多个设备/浏览器都可以同时收到消息。

  3. onConnect 已连上
    通过$socket.hist()获取所有私聊的历史消息。
    通过$socket.hist($V.消息.群ID)获取所有私有群和公开群的历史消息。
    给各消息添加发送消息日期,为了方便在消息列表中显示分割用的日期和星期。
    获取置顶会话的_id列表。
    根据私聊对象_id或群聊_id:
    把各消息列表放入$V.消息.chat中;
    把各更多消息的列表放入$V.消息.more中,每当聊天窗口滚到顶部时就从中拿出一个_id去获取更早的历史消息;
    把各消息_id放入$V.消息.histID中,删除历史消息时用;
    把各消息的发送时间大于其已读时间$V.s.已读的消息条数放入其$V.s.未读中;

  4. onData 收到新消息
    根据聊天对象(私聊对象_id或群聊_id)把消息放入对应的消息列表$V.消息.chat中。
    如果此消息是当前正在打开的聊天会话中,则渲染后把新消息滚入视图,否则给其未读消息数加 1。
    如果此消息包含@我的信息,弹出一个通知窗口notification(如未被阻止)。

  1. 创建群组/群组设置

  2. 加入群组

  3. 发起私聊

  4. 会话列表。无论置顶会话是否有消息都全部先展示出来,然后展示除去置顶的有消息的会话:
    $V.消息.置顶.concat($V.消息.chat.keys().filter('!$V.消息.置顶.includes($x)'))

  5. 会话过滤:
    .filter('$f.search.kw ? ($c.user[$x].x.姓名 || $c.xdb[$x].x.name).includes($f.search.kw) : 1')

  6. 未读消息,包含历史未读和即时未读新消息。
    未读总数:$V.s.未读.values().reduce('$acc + $x', 0)

  7. 点击会话时
    把会话ID赋给$V.s.消息,渲染消息列表后滚到最新一条消息
    如果未读消息数小于6时把所有消息设为已读(清空未读并记录最新消息的发送时间)

  8. 删除会话
    A. 删除关联会话的文件列表
    B. 删除文件列表中的文件本身
    C. 删除关联会话的固定消息列表
    D. 删除整个消息历史。

  1. 消息列表
    $V.消息.chat[$V.s.消息]

  2. 当跟前一个消息不是同一天时展示日期分割。
    date !== $array[$index - 1].date

  3. 把自己发送的消息向右对齐,以区别于别人发送的消息
    $c.me._id === from ? " message-item--me" : ""

  4. 消息弹出框
    固定消息,删除自己发送的消息

  5. HTML组件渲染消息体

  6. 交叉观察器
    如果还有更多消息未读取出来时($V.消息.more[$V.s.消息].length),当滚到消息框顶部是会触发交叉观察器从$V.消息.more里拿出一项交给$socket.more()来获取更多消息,并放入消息列表头部,渲染后滚到第一个消息但交叉观察器却在窗口外的位置,这样避免连续触发,而是等用户再往上滚的时候又会触发一次。
    一个注意点是引入临时变量$v.l.more来阻止每次新渲染交叉观察器时导致的首次执行,因为此时并不是由有户主动往上滚引起的。

  7. 未读消息
    展示未读消息数,点击时往上滚到上次的已读消息或者消息框顶部以触发获取更多消息的交叉观察器,然后触发“全部标记为已读”

  8. 发送文本消息
    [表情文本]替换成对应的img:.replace($c.reg.表情, $c.fun.表情)
    @某人:在群组会话中按下@时(即Shift + 2,2的keyCode是50)弹出排除自己的群组成员列表,但在已弹窗时按下非Shift键(keyCode为16)则关闭弹窗;
    @24位的某人_id替换成对应的姓名:.replace($c.reg.提及, $c.fun.提及);点击时还有成员弹窗是因为添加了onClick事件:window.提及click()
    $socket.send($V.s.消息, "text", $f.消息.txt);

  9. 发送图片/文件消息
    点击文件图标是弹出上传对话框,选择一个或多个文件后上传至服务器;
    然后根据不同的文件类型转化成对应的HTML文本:i为图片,直接显示图片缩略图;v为视频,显示对应的视频截图;f为其它文件类型,会根据其文件后缀format来显示不同的图标);
    消息发送后把文件信息添加到此会话的文件列表中。
    值得注意的是消息发送完了并没有立即操作数据库而是先把内容放在变量$v.待保存文件消息中,等待消息返回后在$c.exp.onData再执行,因为考虑到以后删除文件时也要把它从消息历史中删除,删除时要用到消息发送时间d:$socket.pull(_id, from, d),而这个时间是在服务器端生成的,只有收到消息后才知道。

  10. 发送项目任务/审批/网盘消息

  1. 文件列表
    从网盘发送到聊天的文件不在此列表中
    删除一个文件要:
    A. 删除文件本身
    B. 从关联会话的文件列表中移除
    C. 消息历史中移除对应消息。

  2. 固定消息列表
    删除时从关联会话的固定消息列表中移除

  3. 点击成员图标
    群组时显示群组成员,可进一步显示成员资料或移除成员
    私聊时显示成员资料

  4. 点击设置图标
    置顶会话和取消置顶会话
    群组设置
    退出群组
    删除群组

Make in ZC APP Platform