Discuz .net版本中的短消息系统

  在Discuz中,消息可以分为公用消息(管理后台 --> 其他 -->公共消息管理)如下:

Discuz .net版本中的短消息系统

  另外还有批量短消息发送(用户管理):

Discuz .net版本中的短消息系统

以及个人用户时的发送:

Discuz .net版本中的短消息系统

  而在discuz中,短信息只用到了一张表:dnt_pms

Discuz .net版本中的短消息系统

  其字段说明如下:

  

复制代码 代码如下:

  pmid:自递增的id

  msgfrom:发送者的用户名,若为系统消息则为“系统”。

  msgfromid:发送者的id

  msgto:接收者的用户名

  msgtoid:接收者的id

  folder: 0、收件箱,1、发件箱,2、草稿箱

  new:是否是新消息,未读,1;0已读

  subject:标题

  postdatetime:发送时间

  message:消息内容

  看下公用信息部分的函数:

  

复制代码 代码如下:

  /// <summary>

  /// 得到公共消息数量

  /// </summary>

  /// <returns>公共消息数量</returns>

  public int GetAnnouncePrivateMessageCount()

  {

  return Utils.StrToInt(DbHelper.ExecuteScalar(CommandType.Text, "SELECT COUNT(pmid) FROM [" + BaseConfigs.GetTablePrefix + "pms] WHERE [msgtoid] = 0").ToString(), 0);

  }

  /// <summary>

  /// 获得指定用户的短信息列表

  /// </summary>

  /// <param name="pagesize">每页显示短信息数</param>

  /// <param name="pageindex">当前要显示的页数</param>

  /// <returns>短信息列表</returns>

  public IDataReader GetAnnouncePrivateMessageList(int pagesize, int pageindex)

  {

  string sql = "";

  if(pageindex <= 1)

  {

  sql = string.Format("SELECT TOP {0} * FROM [{1}pms] WHERE [msgtoid] = 0 ORDER BY [pmid] DESC", pagesize, BaseConfigs.GetTablePrefix);

  }

  else

  {

  sql = string.Format("SELECT TOP {0} * FROM [{1}pms] WHERE [msgtoid] = 0 AND [pmid] < (SELECT MIN([pmid]) FROM (SELECT TOP " + (pageindex - 1) * pagesize + " [pmid] FROM [{1}pms] WHERE [msgtoid] = 0 ORDER BY [pmid] DESC) AS tblTmp) ORDER BY [pmid] DESC", pagesize, BaseConfigs.GetTablePrefix);

  }

  IDataReader reader = DbHelper.ExecuteReader(CommandType.Text, sql);

  return reader;

  }

  可见:msgtoid=0为判断是否公用信息的条件。

  而在注册部分发送一条欢迎的信息到新用户的收件箱中,欢迎信息只有一条,而公用信息可以有很多条,每个注册的用户如果后台设置了发送欢迎消息,则都会执行以下代码:

  

复制代码 代码如下:

  PrivateMessageInfo privatemessageinfo = new PrivateMessageInfo();

  string curdatetime = Utils.GetDateTime();

  // 收件箱

  privatemessageinfo.Message = config.Welcomemsgtxt;

  privatemessageinfo.Subject = "欢迎您的加入! (请勿回复本信息)";

  privatemessageinfo.Msgto = userinfo.Username;

  privatemessageinfo.Msgtoid = uid;

  privatemessageinfo.Msgfrom = PrivateMessages.SystemUserName;

  privatemessageinfo.Msgfromid = 0;

  privatemessageinfo.New = 1;

  privatemessageinfo.Postdatetime = curdatetime;

  privatemessageinfo.Folder = 0;

  PrivateMessages.CreatePrivateMessage(privatemessageinfo, 0);

  而其批量发送短消息:

Discuz .net版本中的短消息系统

  

  执行方法也是让我感到奇怪,居然是:比如我选择了乞丐,而乞丐这个等级有10万用户,则取得这10W用户的数据,一条条执行插入。暴汗……这样算法以及实现确实简单了很多,但会员一多,要经常清理这些数据。这也是为什么我们看到discuz的论坛经常一段时间需要清理短消息的原因。建议批量发送只对等级较高,数量较少的用户使用。同时在使用过程中,不明白为什么在“批量短消息发送”中的“文件箱”有“收件箱”、“发件箱”、“草稿箱”3种,这里应该只有“收件箱”比较合适,或者这里根本就不该出现这个“文件箱”。

  批量发送的代码如下:

  

复制代码 代码如下:

  private void BatchSendSM_Click(object sender, EventArgs e)

  {

  #region 批量短消息发送

  if (this.CheckCookie())

  {

  string groupidlist = Usergroups.GetSelectString(",");

  if (groupidlist == "")

  {

  base.RegisterStartupScript( "", "<script>alert('请您先选取相关的用户组,再点击提交按钮');</script>");

  return;

  }

  int percount = 10; //每多少记录为一次等待

  int count = 0; //当前记录数

  // GetUserNameListByGroupid为取得选中的用户组的所有用户的id和用户名

  foreach (DataRow dr in DatabaseProvider.GetInstance().GetUserNameListByGroupid(groupidlist).Rows)

  {

  DatabaseProvider.GetInstance().SendPMToUser(username.Replace("'", "''"), userid, dr["username"].ToString().Replace("'", "''"), Convert.ToInt32(dr["uid"].ToString()), int.Parse(folder.SelectedValue), subject.Text, Convert.ToDateTime(postdatetime.Text), message.Text);

  if (count >= percount)

  {

  Thread.Sleep(3500);

  count = 0;

  }

  count++;

  }

  base.RegisterStartupScript( "PAGE", "window.location.href='global_sendSMtogroup.aspx';");

  }

  #endregion

  }

  //SendPMToUser函数如下:

  public void SendPMToUser(string msgfrom, int msgfromid, string msgto, int msgtoid, int folder, string subject, DateTime postdatetime, string message)

  {

  DbParameter[] parms =

  {

  DbHelper.MakeInParam("@msgfrom", (DbType)SqlDbType.NVarChar,50, msgfrom),

  DbHelper.MakeInParam("@msgfromid", (DbType)SqlDbType.Int, 4, msgfromid),

  DbHelper.MakeInParam("@msgto", (DbType)SqlDbType.NVarChar,50, msgto),

  DbHelper.MakeInParam("@msgtoid", (DbType)SqlDbType.Int, 4, msgtoid),

  DbHelper.MakeInParam("@folder", (DbType)SqlDbType.SmallInt, 2, folder),

  DbHelper.MakeInParam("@subject", (DbType)SqlDbType.NVarChar,60, subject),

  DbHelper.MakeInParam("@postdatetime", (DbType)SqlDbType.DateTime,8, postdatetime),

  DbHelper.MakeInParam("@message",(DbType)SqlDbType.NText, 0,message)

  };

  string sql = "INSERT INTO [" + BaseConfigs.GetTablePrefix + "pms] (msgfrom,msgfromid,msgto,msgtoid,folder,new,subject,postdatetime,message) " +

  "VALUES (@msgfrom,@msgfromid,@msgto,@msgtoid,@folder,1,@subject,@postdatetime,@message)";

  DbHelper.ExecuteNonQuery(CommandType.Text, sql, parms);

  sql = "UPDATE [" + BaseConfigs.GetTablePrefix + "users] SET [newpmcount]=[newpmcount]+1 WHERE [uid] =@msgtoid";

  DbHelper.ExecuteNonQuery(CommandType.Text, sql, parms);

  }

  有一句语句是用于users用户表中的一个字段,而用户表中有两个字段跟短消息是相关的:

Discuz .net版本中的短消息系统

  不明白这里为什么要用两个字段,用newpmcount一个字段就可以判断是否有新消息了,如果为0说明没有新消息,而查看消息后也只需要对newpmcount进行操作,并不需要对newpm也进行操作。公用消息并不会对这两个字段进行操作。

  详细如下,根据自己见解做了修改,在会员阅读信息之后的具体操作大家应该都清楚,就不写那么仔细。

Discuz .net版本中的短消息系统