当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > Discuz .net版本中的短消息系统

ASP.NET
C# Quoted-Printable编码、解码
asp.net Google的translate工具翻译 API
.NET读取所有目录下文件正则匹配文本电子邮件
asp.net 半角全角转化工具
AjaxControlToolKit 显示浏览者本地语言的方法
asp.net HTML文件上传标签
ASP.NET 绑定DataSet中的多个表
ASP.NET 重定向的几种方法小结
Asp.Net 重定向必须要知道的一些资料
ASP.NET 导出到Excel时保留换行的代码
Asp.Net Cache缓存使用代码
document.getElementsByName和document.getElementById 在IE与FF中不同实现
GridView单元格合并
asp.net 大文件上传控件
asp.net 日期函数 某月的第一天和最后一天的日期
asp.net 时间类 一周的周一和周末的日期
C# javaScript函数的相互调用
asp.net membership 密码重设
"虚拟路径"..."映射到另一个应用程序,这是不允许的!
如何传值在2个页面之间 要求不刷新父页面,并且不能用Querystring传值

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-11   浏览: 352 ::
收藏到网摘: n/a

Discuz .net 短消息实现原理。

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

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

以及个人用户时的发送:

Discuz .net 短消息实现原理。
而在discuz中,短信息只用到了一张表:dnt_pms
其字段说明如下:
复制代码 代码如下:

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);

而其批量发送短消息:

执行方法也是让我感到奇怪,居然是:比如我选择了乞丐,而乞丐这个等级有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用户表中的一个字段,而用户表中有两个字段跟短消息是相关的:
不明白这里为什么要用两个字段,用newpmcount一个字段就可以判断是否有新消息了,如果为0说明没有新消息,而查看消息后也只需要对newpmcount进行操作,并不需要对newpm也进行操作。公用消息并不会对这两个字段进行操作。
详细如下,根据自己见解做了修改,在会员阅读信息之后的具体操作大家应该都清楚,就不写那么仔细。