美文网首页
站内信设计方案

站内信设计方案

作者: 四火流年 | 来源:发表于2018-01-23 19:43 被阅读5469次

    一、背景

    当前使用运维平台的用户进行沟通时,更多的是依赖微信和邮件通知,而运维平台作为一个整体的产品,也需要能够进行内部沟通的一种服务 - 站内信。

    站内信的设计基调

    站内信的设计基调取决于用户如何使用站内信:

    1. 用户不会守着运维平台这个页面,等待消息通知,查看消息内容,然后跳转到要操作的页面。
      1. 也就是说站内信不是第一入口,站内信的实时性意义也不大。
      2. 同很多社交网站不同(Facebook,知乎,微博等),用户会守在社交网站的主页面,不断刷新新内容,同时检查新消息(主要是个人私信、别人的回复等,也绝不是为了检查系统通知消息)
    2. 用户会根据邮件通知,决定是否要进入运维平台进行操作
    3. 如果邮件特别多,例如同时有多个工单需要用户处理,用户也会在工单平台提供的“我的待办”页面进行所有工作。
    4. 如果邮件被误删了,没有邮件链接直接进入要操作的模块
      1. 那么或者通过索要链接/单号的方式,前往指定页面
      2. 或者直接在相关模块进行搜索

    上面的描述都意味着用户基本不会使用站内信,那么在什么样的场合会使用站内信呢?

    1. 不发邮件,只发站内信的消息通知,例如全站通知、编辑操作、Comment操作等
    2. 当具体模块没有详细的操作记录时,可以通过查看站内信的发生时间

    当前只有产品消息通知,消息展示也没有进行归类聚合,以后增加全站通知、mention、like、comment等类型的站内信时,就需要考虑按类型进行消息聚合了。

    二、需求描述

    站内信通常需要解决两个需求:

    1. 用户对用户的站内信,管理员对用户的站内信:即一对一发送
    2. 管理员对多用户、用户组、全站的站内信:即一对多发送

    (还有一种是用户对产品的站内信,例如对某个模块的反馈、疑问之类的)

    我们目前的需求是:

    1. 管理员对多用户发送站内信
      1. 对用户真实性不做校验
      2. 对标题长度、内容长度进行限制(分别是45个字节、150个字节,对应中文字符15个、50个)
      3. 对收件人的拼音长度进行限制(最长50个字节)
    2. 用户可以查看自己的站内信
      1. 按“全部、已读、未读”过滤
      2. 按消息来源分类:工单平台、资源管理、自动装机、漏洞平台、故障平台。。。
    3. 用户可以删除、批量删除站内信
    4. 用户可以已阅、批量已阅、全部标记为已读 站内信
    5. 运维平台页面顶部的消息图标
      1. 展示未读消息数,超过99显示 99+
      2. 鼠标放上去,会有下拉框,展示最近10条未读消息(展示“时间”,“消息来源”,“标题”)
      3. 下拉框的底部有两个按钮:“更多”,加载更多未读消息;“查看全部”,跳转到站内信列表页面(最好另开一个窗口)
      4. 点击下拉框里的未读消息,通过弹出框展示详情;然后在未读列表里删除该记录,在数据库里标记为已读,消息图标的未读消息数量减一
    6. 管理员页面:
      1. 更新用户
      2. 删除消息
      3. 统计数据
      4. 增加module
      5. 增加站内信类型
      6. 发送全站消息

    三、系统设计

    功能设计

    功能 接口 详情
    发送站内信 POST /v1/message 校验module_name,校验title content receiver_name 长度
    获取站内信列表 GET /
    统计信息 暂无

    四、系统流程

    发送站内信

    1. 读取POST请求的request body
    2. 校验长度
    3. 插入数据库
    4. 返回

    获取站内信列表

    1. 调用子模块,插入发送给全站或我所属用户组的站内信
    2. 根据查询条件,返回数据库数据

    获取未读站内信数量

    1. 调用子模块,插入发送给全站或我所属用户组的站内信
    2. 返回数量

    批量已阅

    1. 检查messageId是不是属于当前用户

    2. inbox_message表里把 read 置为1,修改update_time

    全部已阅

    1. update inbox_message set "read"=1, "update_time"=now where "receiver_name"=currentUser() and "read" = 0

    批量删除

    1. 检查messageId是不是属于当前用户

    2. inbox_message表里把 deleted 置为1,修改update_time

    全部删除

    1. update inbox_message set "deleted"=1, "update_time"=now where "receiver_name"=currentUser() and "deleted" = 0

    五、数据库设计

    站内信内容表

    CREATE TABLE `inbox_message_text` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `title` varchar(128) NOT NULL DEFAULT '',
      `content` longtext NOT NULL,
      `create_time` datetime NOT NULL,
      `update_time` datetime NOT NULL,
      `send_type` tinyint(4) NOT NULL DEFAULT '0',
      `creator_name` varchar(255) NOT NULL DEFAULT '',
      `deleted` tinyint(4) NOT NULL DEFAULT '0',
      `module_id` bigint(20) NOT NULL,
      `link` varchar(255) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    Field Type Null Key Default Extra Comment
    id bigint(20) NO PRI NULL auto_increment
    title varchar(128) NO
    content longtext NO NULL
    create_time datetime NO NULL
    update_time datetime NO NULL
    send_type tinyint(4) NO 0 0是发全部,1是指定用户
    creator_name varchar(255) NO 系统管理员是 sysadmin
    module_id bigint(20) NO 0
    deleted tinyint(4) NO 0
    link varchar(255) NO 详情链接

    站内信本身除了消息来源(module_name),还有一个纬度的描述,叫消息类型(message_type),例如安全消息、活动消息、服务消息等,每一大类里,又可以划分子类,例如活动消息-优惠活动

    消息来源和消息类型可以是正交关系,即工单平台也可以有活动消息;消息来源也可以是消息类型的一种,称为“产品消息”

    站内信发送表

    CREATE TABLE `inbox_message` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `message_text_id` bigint(20) NOT NULL,
      `receiver_name` varchar(255) NOT NULL DEFAULT '',
      `read` tinyint(4) NOT NULL DEFAULT '0',
      `deleted` tinyint(4) NOT NULL DEFAULT '0',
      `create_time` datetime NOT NULL,
      `update_time` datetime NOT NULL,
      PRIMARY KEY (`id`),
      KEY `inbox_message_receiver_name_deleted_read_id` (`receiver_name`,`deleted`,`read`,`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    Field Type Null Key Default Extra Comment
    id bigint(20) NO PRI NULL auto_increment
    message_text_id bigint(20) NO NULL
    receiver_name varchar(255) NO MUL 拼音
    read tinyint(4) NO 0
    deleted tinyint(4) NO 0
    create_time datetime NO NULL
    update_time datetime NO NULL

    消息来源表

    CREATE TABLE `inbox_module` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `code` varchar(128) NOT NULL DEFAULT '',
      `name` varchar(128) NOT NULL DEFAULT '',
      `create_time` datetime NOT NULL,
      `update_time` datetime NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `code` (`code`),
      UNIQUE KEY `name` (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    Field Type Null Key Default Extra Comment
    id bigint(20) NO PRI NULL auto_increment
    code varchar(128) NO UNI 英文标记( worksheet)
    name varchar(128) NO UNI 中文标记(工单平台)
    create_time datetime NO NULL
    update_time datetime NO NULL

    六、API设计

    发送站内信:POST /v1/message

    request body Content-Type: application/json

    {
        "title": "工单审批",
        "content": "XXX提交了变更申请,请审批",
        "to": "sunzhongyuan,shenli,wangya",
        "module_name": "工单平台",
        "link": "xxx"
    }
    

    response

    {
        "code": 200,
        "data": 32,
        "msg": "OK"
    }
    

    获取站内信列表:GET /v1/message User-Id: xxx

    http://127.0.0.1:10085/v1/message?query=message_text_id.module_id.name:xxx&limit=1
    
    {
        "code": 200,
        "data": {
            "data": [
                {
                    "id": 1,
                    "message_text": {
                        "id": 1,
                        "title": "title 2",
                        "content": "content 2",
                        "create_time": "2018-01-12 11:13:48",
                        "update_time": "2018-01-12 11:13:48",
                        "send_type": 1,
                        "creator_name": "sysadmin",
                        "deleted": 0,
                        "link": "xxx",
                        "Messages": null,
                        "module": {
                            "id": 4,
                            "code": "secure",
                            "name": "xxx",
                            "create_time": "2018-01-11 15:38:01",
                            "update_time": "2018-01-11 15:38:01",
                            "MessageTexts": null
                        }
                    },
                    "receiver_name": "xxx",
                    "read": 0,
                    "deleted": 0,
                    "create_time": "2018-01-12 11:13:48",
                    "update_time": "2018-01-12 11:13:48"
                }
            ],
            "total": 2
        },
        "msg": "OK"
    }
    

    注:

    1. 返回数据的个数是由 limit 限制,而 total 是符合query条件的总数(用于分页)
    2. 目前没有发送用户组、全站的行为,如果有的话,在获取列表接口里,增加一步“插入所有发送给我所在用户组,或发给全站的,且我自己的站内信列表里没有记录到的站内信”

    获取未读站内信数量:GET /v1/message/unread_count

    response

    {
        "code": 200,
        "data": 29,
        "msg": "OK"
    } 
    

    获取单个站内信内容:GET /v1/message/:id

    {
        "code": 200,
        "data": {
            "id": 2,
            "message_text": {
                "id": 2,
                "title": "title 2",
                "content": "content 3",
                "create_time": "2018-01-12 11:37:54",
                "update_time": "2018-01-12 11:37:54",
                "send_type": 1,
                "creator_name": "sysadmin",
                "deleted": 0,
                "link": "",
                "Messages": null,
                "module": {
                    "id": 4,
                    "code": "secure",
                    "name": "xxx",
                    "create_time": "2018-01-11 15:38:01",
                    "update_time": "2018-01-11 15:38:01",
                    "MessageTexts": null
                }
            },
            "receiver_name": "xxx",
            "read": 1,
            "deleted": 0,
            "create_time": "2018-01-12 11:37:54",
            "update_time": "2018-01-22 17:33:20"
        },
        "msg": "OK"
    }
    

    已阅、批量已阅站内信:PUT /v1/read_messages/:messageIds

    response

    {
        "code": 200,
        "data": "OK",
        "msg": "OK"
    }
    

    全部已阅 PUT:/v1/read_all_messages

    response 同上

    删除、批量删除站内信:PUT /v1/delete_messages/:messageIds

    response 同上

    全部删除站内信:PUT /v1/delete_all_messages

    response 同上

    获取消息来源列表:GET /v1/module

    response

    {
        "code": 200,
        "data": [
            {
                "id": 1,
                "code": "worksheet",
                "name": "工单平台",
                "create_time": "2018-01-11 15:21:38",
                "update_time": "2018-01-11 15:21:38",
                "MessageTexts": null
            },
            {
                "id": 2,
                "code": "cmdb",
                "name": "资源管理",
                "create_time": "2018-01-11 15:22:28",
                "update_time": "2018-01-11 15:22:28",
                "MessageTexts": null
            },
            ...
        ],
        "msg": "OK"
    }
    

    七、测试注意点

    1. 发送站内信
      1. 纯接口
      2. 收件用户以逗号分割,真实性不做校验
      3. 收件用户有长度校验,50个字节
      4. title content 有长度校验,分别是45,150个字节
      5. module_name 是一个列表,必须从这里选一个
    2. 其他接口都可以通过前端页面测试

    八、优化

    1. 未读列表可以加上粗体显示,已读则是普通字体
    2. 对站内信进行分类,打上不同纬度的标签,方便过滤、搜索、屏蔽
    3. 用户可以设置允许接收的站内信的消息来源
    4. 管理员可以对全站消息、全站人员、全站的消息属性进行增删改查,比如撤销某个站内信,让所有人都看不见
    5. 管理员可以统计站内信的发送数量、各产品的使用情况、消息被读的比例、消息被读的时间、消息被读的方式(点开还是批量操作),等

    九、关键功能点设计

    右上角的图标行为

    1. 点击图标,展示最近的N条未读消息
      1. 展示下拉框
      2. 实时获取最近N条未读消息
      3. N可以为5~10,具体数值取决于下拉框的高度限制
      4. 当未读数不足N时,下拉框能自适应高度
      5. 如果没有未读消息,展示"暂无新消息"
      6. 停止每10秒的获取未读消息数接口
    2. 下拉框里,展示消息来源、时间(相对现在的时间:10分钟前)、title
      1. 向下滑动下拉框,展示更多未读消息(只获取id小于已展示消息列表里的最小id,即不获取点击图标后新来的消息)
    3. 点击下拉框里的某一个消息
      1. 下拉框不消失
      2. 依然停止每10秒的获取未读消息数接口
      3. 未读消息数减1
      4. 未读消息列表删除当前消息(slice)
      5. 展示弹出框
    4. 弹出框展示消息的来源、时间(绝对时间)、title、content
    5. 关闭弹出框或者点击外围:
      1. 弹出框消失
      2. 下拉框不消失
      3. 可以继续点击某一个未读消息
    6. 再次点击下拉框和图标的外围
      1. 下拉框消失
      2. 清空已有的未读消息列表
      3. 恢复每10秒的获取未读消息数接口
    7. 再次点击图标,重新回到#1状态

    阿里云的图标行为是:

    1. 刷新页面的时候才会请求一次未读消息数,之后不再定时刷新(当然也可能是刷新时间间隔比较长,没发现;又或者采用了 socket 的方式,建立了一个长链接)

    2. hover图标,即显示未读消息的下拉框

    3. 点击图标,进入站内信管理页面,默认是“未读消息”

      1. image.png
    4. 点击未读消息,新开一个Tab,展示该消息的详情(detail页面),原Tab内容不变,即没有未读数减一,也没从下拉框里删除刚点击的消息

    5. 最多展示5条消息,只要不刷新页面,就一直是这5条

    6. 没有滚动更多的功能,只有查看更多,点击进入站内信管理页面,默认是“未读消息”

      1. 和点击图标的区别是:点击图标直接当前页面跳转到站内信管理页面,点击“查看更多”会新建一个Tab
    7. 多了一个“消息接受管理”的按钮,当前页面跳转到站内信管理页面,但是默认即“基本接收管理”

      1. 基本接收管理页面.png

    隐藏浏览器进度条

    每10秒的获取未读消息数接口,会触发浏览器展示进度条,导致分散用户注意力,要把这个进度条隐藏掉。
    其他刷新页面的行为不受影响。

    参考文档

    1. 《站内信需求背景及需求分析的全过程》
    2. 《站内信功能设计》
    3. 《站内信的实现:数据库的设计》
    4. 《站内信的实现思路表的设计》
    5. 《Web网站通知系统设计》

    参考产品

    优云.png 阿里云.png
    阿里云.png
    阿里云.png Wiki.png 简书.png Facebook & 知乎.png 腾讯云-右上角消息图标.png 腾讯云-站内信首页.png 腾讯云-站内信消息订阅 腾讯云-站内信消息订阅编辑.png 腾讯云-站内信公告.png

    注:

    1. 鼠标放在该条消息上时,右上角显示的时“标记已读”,未放上去之前,显示的是时间“44秒前”
    2. 站内信和公告分离
    3. 站内信和公告各有各的分类管理
    4. 消息订阅是按照“站内信”的分类进行管理的

    相关文章

      网友评论

          本文标题:站内信设计方案

          本文链接:https://www.haomeiwen.com/subject/saleaxtx.html