澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站NET中发送电子邮件的实例

站内信:网站运营人员可以向单个(单发)或多个(群发)用户推送消息,站内信其实就是向数据库中插入一条条记录。

  前几日,发布了博客“群发“站内信”的实现”,得到广大网友呼应,在此表示感谢。

  在很多网站系统(如CMS系统,SNS系统等),都有“站内信”的功能。

首先、导入命名空间:

  • 一、背景
    • 站内信的设计基调
  • 二、需求描述
  • 三、系统设计
    • 功能设计
  • 四、系统流程
    • 发送站内信
    • 获取站内信列表
    • 获取未读站内信数量
    • 批量已阅
    • 全部已阅
    • 批量删除
    • 全部删除
  • 五、数据库设计
    • 站内信内容表
    • 站内信发送表
    • 消息来源表
  • 六、API设计
    • 发送站内信:POST /v1/message
    • 获取站内信列表:GET /v1/message User-Id: xxx
    • 获取未读站内信数量:GET /v1/message/unread_count
    • 获取单个站内信内容:GET /v1/message/:id
    • 已阅、批量已阅站内信:PUT /v1/read_messages/:messageIds
    • 全部已阅 PUT:/v1/read_all_messages
    • 删除、批量删除站内信:PUT /v1/delete_messages/:messageIds
    • 全部删除站内信:PUT /v1/delete_all_messages
    • 澳门新浦京娱乐场网站NET中发送电子邮件的实例教程,有关站内信的数据库设计。获取消息来源列表:GET /v1/module
  • 七、测试注意点
  • 八、优化
  • 九、关键功能点设计
    • 右上角的图标行为
    • 隐藏浏览器进度条
  • 参考文档
  • 参考产品

数据库设计:

message【站内信发件箱表】{每次运营人员发送一条站内信(无论是单发或是群发)就会在发件箱表中添加一条记录}

 澳门新浦京娱乐场网站 1

 表字段:ID、SendID、RecID、MessageID、Statue、DateTime

messagetext【站内信发件内容表】{每次运营人员发送站内信的内容就会保存到站内信发件内容表中}

澳门新浦京娱乐场网站 2

表字段:ID、Title、Message、PData

messageuserinfo【站内信接收箱表】{用户站内信收件箱}

澳门新浦京娱乐场网站 3

表字段:ID、SendID、RecID、MessageID、Statue、DateTime

 

  看了网友的留言。发现大家对文中的前两种情况没有什么异议,对第三种方案争议颇多。我在此再把我的第三种情况详细的阐述一下,和大家交流。另外,本文的主体主要放在“群发”(也就是点到面),至于“单发”(点到点),不在本文的讨论之列。

  “站内信”不同于电子邮件,电子邮件通过专门的邮件服务器发送、保存。而“站内信”是系统内的消息,说白了,“站内信”的实现,就是通过数据库插入记录来实现的。

 代码如下 复制代码
using System.Net.Mail;  


业务逻辑:在运营人员发送了一条站内信后,当用户再次登录时就会刷新历史站内信,而那些不活跃的用户就不会更新站内信。

场景:运营人员向某个(单发)或多个(群发)用户发送站内信

添加发件内容:向messagetext站内信发件内容表中添加一条内容记录 {这里先添加messagetext站内信发件内容表产生一条记录,后面message站内信发件箱表中才有MessageID可以关联}

添加发件人发件记录:向message站内信发件箱表中添加一条发送记录 {备注:如果是单发RecID则是指定用户的UserID,如果是群发RecID则是0。(0表示所有用户)}

澳门新浦京娱乐场网站NET中发送电子邮件的实例教程,有关站内信的数据库设计。用户登录时刷新与自己有关的站内信,并将数据添加到messageuserinfo站内信接收箱表

  1. 查询条件:【发件人不是自己】并且【收件人是自己或者收件人是所有人】并且【自己收件表中不存在的记录】

    select m.id from Message as m where (m.recid='所有人' or m.recid='自己的ID') and m.sendid!='自己的ID' and m.MessageID not in (select u.messageid from MessageUserInfo as u  where u.recid='自己的ID')
    

      

  2. 将相关的站内信消息添加到自己的收件表中,并标记未读。

    1.   将上面【查询条件】中查询出来的id信息用做查询message站内信发件箱表的条件

      select * from message  where id=上面的m.id
      

        

    2. 将获取到message站内信发件箱表数据添加到messageuserinfo站内信接收箱表

  3. 查询出自己的站内信记录

    select u.ID,u.RecID,m.Title,m.Message,u.Statue,m.PDate from messageuserinfo as u join messagetext as m on u.MessageID = m.ID where u.RecID='自己的ID'
    

      

     

  先看看,第三种情况。站内的用户是大量级的(上百万)。

  “站内信”有两个基本功能。一:点到点的消息传送。用户给用户发送站内信;管理员给用户发送站内信。二:点到面的消息传送。管理员给用户(指定满足某一条件的用户群)群发消息。点到点的消息传送很容易实现,本文不再详述。下面将根据不同的情况,来说说“站内信”的群发是如何实现的。

定义发送电子邮件的方法[网上很多不同的,可以对比着看一下,WinForm的也适用]:

一、背景

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

  • 站内信。

  经过考虑,表设计修正如下

  第一种情况,站内的用户是少量级别的。(几十到上百)

 代码如下 复制代码
/// <summary>
/// 发送电子邮件
/// </summary>
/// <param name="MessageFrom">发件人邮箱地址</param>
/// <param name="MessageTo">收件人邮箱地址</param>
/// <param name="MessageSubject">邮件主题</param>
/// <param name="MessageBody">邮件内容</param>
/// <returns></returns>
public bool Send(MailAddress MessageFrom, string MessageTo, string MessageSubject, string MessageBody)
{
 MailMessage message = new MailMessage();
 message.From = MessageFrom;
 message.To.Add(MessageTo); //收件人邮箱地址可以是多个以实现群发
 message.Subject = MessageSubject;
 message.Body = MessageBody;
 message.IsBodyHtml = true; //是否为html格式
 message.Priority = MailPriority.Normal; //发送邮件的优先等级
 SmtpClient sc = new SmtpClient();
 sc.Host = "smtp.qq.com"; //指定发送邮件的服务器地址或IP
 sc.Port = 25; //指定发送邮件端口
 //指定登录服务器的用户名和密码(发件人的邮箱登陆密码)
 sc.Credentials = new System.Net.NetworkCredential("【发件箱地址】", "【www.111cn.net发件箱密码】");
 try
 {
  sc.Send(message); //发送邮件
 }
 catch
 {
  return false;
 }
 return true;
}  

站内信的设计基调

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

  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. 发送全站消息

  表名:Message

  数据库的设计如下:表名:Message

调用定义的方法,实现发送邮件:

三、系统设计

  ID:编号;RecID:接受者编号;MessageID:站内信编号;Statue:站内信的查看状态;

  ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);Message:站内信内容;Statue:站内信的查看状态;PDate:站内信发送时间;

 代码如下 复制代码
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ForMail(string name, string mail)
{
 try
 {
  //string email = txtemail.Text.Trim();
  MailAddress MessageFrom = new MailAddress("【发件箱地址】"); //发件人邮箱地址
                  string MessageTo = mail; //收件人邮箱地址
  string MessageSubject = bs.HtmlEncode(邮件主题);
  //邮件内容 (一般是一个网址链接,生成随机数加验证id参数,点击去网站验证。)";
  string MessageBody = "" content1.Value.Trim() "";
  if (Send(MessageFrom, MessageTo, MessageSubject, MessageBody))
  {
   //Response.Write("发送邮件成功");
  }
  else
  {
   //Response.Write("发送邮件失败");
  }
 }
 catch
             {
  //ClientScript.RegisterStartupScript(ClientScript.GetType(), "myscript", "<script>alert('客户信息删除失败')</script>");
 }
}  

功能设计

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

  表名:MessageText 

  如果,某一个管理员要给所有人发站内信,则先遍历用户表,再按照用户表中的所有用户依次将站内信插入到Message表中。这样,如果有56个用户,则群发一条站内信要执行56个插入操作。这个理解上比较简单,比较耗损空间。

调用方法发送邮件  

四、系统流程

  ID:编号;SendID:发送者编号;Message:站内信的内容;PDate:站内信发送时间;

  某一个用户登陆后,查看站内信的语句则为:

不同邮箱的smtp地址都不一样、需要比如QQ的是smtp.qq.com、163的是smtp.163.com

发送站内信

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

 

  Select * FROM Message Where RecID=‘ID’ OR RecID=0

更多详细内容请查看:

获取站内信列表

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

  这样,管理员(假设ID=1)给所有的用户发一封站内信。就在MessageText表中插入一条记录。例如:

  第二种情况,站内的用户中量级别的(上千到上万)。

获取未读站内信数量

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

  ID:4;SendID=1;Message=Good;PDate:2010-4-9

  如果还是按照第一种情况的思路。那发一条站内信的后果基本上就是后台崩溃了。因为,发一条站内信,得重复上千个插入记录,这还不是最主要的,关键是上千乃至上万条记录,Message字段的内容是一样的,而Message有大量的占用存储空间。比方说,Message字段有100个汉字,占用200个字节,那么5万条,就占用200×50000=10000000个字节=10M。简单的一份站内信,就占用10M,这还让不让人活了。

批量已阅

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

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

 

  因此,将原先的表格拆分为两个表,将Message的主体放在一个表内,节省空间的占用

全部已阅

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

  某个用户(假设ID=7),登陆系统后,发现在MessageText的表中,有ID=4的记录,并且在Message中没有RecID=7且MessageID=4的记录,说明这条记录这个用户没有读过,给个提示信息给用户,提示用户看站内信。注意,此时仍然没有在Message中插入记录。一旦该用户点击查看该站内信的时候,在Message中插入一条记录,如:

  数据库的设计如下:

批量删除

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

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

  ID:55;RecID=7;MessageID=4;Statue=已读

  表名:Message

全部删除

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

  如果该用户删除这条站内信,则实际上是修改上面这条记录:

  ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);MessageID:站内信编号;Statue:站内信的查看状态;

五、数据库设计

  ID:55;RecID=7;MessageID=4;Statue=删除

  表名:MessageText 

站内信内容表

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),例如安全消息、活动消息、服务消息等,每一大类里,又可以划分子类,例如活动消息-优惠活动

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

  这样一来,这个用户下次登陆的时候,由于Message表中有相应的记录,也不会提示用户看站内信。

  ID:编号;Message:站内信的内容;PDate:站内信发送时间;

站内信发送表

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

 

  在管理员发一封站内信的时候,执行两步操作。先在MessageText表中,插入站内信的内容。然后在Message表中给所有的用户插入一条记录,标识有一封站内信。

消息来源表

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"
}

  假设,网站用户200万,其中活跃用户40万。

  大家都有这样的经历,某日看一个网站比较好,一时心情澎湃,就注册了一个用户。过了一段时间,由于种种原因,就忘记了注册时的用户名和密码,也就不再登陆了。那么这个用户就称为不活跃的。从实际来看,不活跃的用户占着不小的比例。

获取站内信列表: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. 目前没有发送用户组、全站的行为,如果有的话,在获取列表接口里,增加一步“插入所有发送给我所在用户组,或发给全站的,且我自己的站内信列表里没有记录到的站内信”

  一封站内信,在MessageText中有一条记录,40万活跃用户都看了站内信(其实,这也不大可能,有不少的人是不看站内信的)。在Message中插入了40万条记录。以后,不管是阅读或者是删除,在Message中保留了这40万条记录。

  我们以注册用户2百万,其中活跃用户只占其中的10%。

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

response

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

 

  就算是按照第二种的情况,发一封“站内信”,那得执行2百万个插入操作。但是其中的有效操作只有10%,因为另外的90%的用户可能永远都不会再登陆了。

获取单个站内信内容: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"
}

  好,如果不采用这种办法,在群发的时候,往Message中插入200万记录,40万活跃用户都看了信,并且都勤快的删除了站内信(这是不大可能的),Message中还是保留了160万条记录。因为,这些不活跃的用户可能永远都不会登陆了。那40万条记录(最坏的情况,因为如果有人不看站内信,就不会生成记录)和160万条记录(最好的情况,因为不是每个用户都会删除站内信。)相比,那个更加节省空间呢?

  在这种情况下,我们还得把思路换换。

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

response

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

 

  数据库的设计和第二种情况一样:

全部已阅 PUT:/v1/read_all_messages

response 同上

  站内信的设计,要根据你的受众群的具体情况而定,如果你的受众群活跃度接近100%,并且每人都很勤快,我的设计当然有问题。可实际中这个理想状态几乎是不可能出现的。

  表名:Message

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

response 同上

  

  ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);MessageID:站内信编号;Statue:站内信的查看状态;

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

response 同上

  有网友提出,如果站内信的对象不是全体而是一部分呢?抱歉,这个也不在本文讨论之列,你可以对我的表进行扩展,以达到你的要求。

  表名:MessageText 

获取消息来源列表: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"
}

 

  ID:编号;Message:站内信的内容;PDate:站内信发送时间;

七、测试注意点

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

  感谢各位网友的交流。我在此想说的是,我们设计一个系统,必须得结合实际情况,根据实际情况来制定,比能达到一个比较理想的状况。

  管理员发站内信的时候,只在MessageText插入站内信的主体内容。Message里不插入记录。

八、优化

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

  那么,用户在登录以后,首先查询MessageText中的那些没有在Message中有记录的记录,表示是未读的站内信。在查阅站内信的内容时,再将相关的记录插入到Message中。

九、关键功能点设计

  这个方法和第二种的比较起来。如果,活跃用户是100%。两者效率是一样的。而活跃用户的比例越低,越能体现第三种的优越来。只插入有效的记录,那些不活跃的,就不再占用空间了。

右上角的图标行为

  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. 澳门新浦京娱乐场网站 4

      image.png

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

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

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

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

    1. 澳门新浦京娱乐场网站 5

      基本接收管理页面.png

  以上,是我对群发“站内信”的实现的想法。也欢迎各位提出自己的建议,大家互相借鉴,共同进步。

隐藏浏览器进度条

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

参考文档

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

参考产品

澳门新浦京娱乐场网站 6

优云.png

澳门新浦京娱乐场网站 7

阿里云.png

澳门新浦京娱乐场网站 8

阿里云.png

澳门新浦京娱乐场网站 9

阿里云.png

澳门新浦京娱乐场网站 10

Wiki.png

澳门新浦京娱乐场网站 11

简书.png

澳门新浦京娱乐场网站 12

Facebook & 知乎.png

澳门新浦京娱乐场网站 13

腾讯云-右上角消息图标.png

澳门新浦京娱乐场网站 14

腾讯云-站内信首页.png

澳门新浦京娱乐场网站 15

腾讯云-站内信消息订阅

澳门新浦京娱乐场网站 16

腾讯云-站内信消息订阅编辑.png

澳门新浦京娱乐场网站 17

腾讯云-站内信公告.png

注:

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

本文由澳门新浦京娱乐场网站发布于数据库,转载请注明出处:澳门新浦京娱乐场网站NET中发送电子邮件的实例