4.2
消息按主题和层次显示和处理
本论坛中的消息按主题显示,如图1,左框架中消息列在所属主题后。由于每个消息的内容都存在数据库中相应的主题消息表中,所以消息按主题显示易于实现。
在一个特定主题消息表中,消息的显示由两个字段域level和next决定。level确定消息的层次,即消息处于第几层答复,next决定消息的显示顺序。这两个字段域值的确定是本论坛消息处理和显示的关键所在,具体算法和程序实现说明如下:
消息的显示
消息的显示
每个消息按其层次右缩level*2个空格。非答复的消息贴子的level值为1,每多一个答复层次,其level值在所答复的消息的level值的基础上加1。
特定主题消息表中的消息的显示顺序由next域决定。在消息表不为空时,总是从第一个记录开始显示,然后按该记录的next值相对于当前记录移动光标到新的记录处,该新的即成为当前记录。next>0,光标前移;next<0,光标后移。重复这个过程直到记录结束或当前记录的next值为0。这样,有n条消息记录,则光标只需移动最多n-1次,便可完全显示所有消息。
其程序在discuss_left.asp中实现,其引用的变量在前面程序段1中定义赋值。如下:
<%
for i=0 to recordtotal-1 ‘for
循环开始,循环次数为论坛主题数
%>
<a name="#content<%=i%>"></a><font color="#5555aa" size="3"><%=(i+1)%>
<%=contotal( i )%></font> <a href="#toc"><font size="2">[
返回页首] </font></a>
<br> ‘
显示论坛主题,并加以编号
<% set rs=server.createobject("ADODB.recordset")
rs.open "select * from "&contotal( i ),"DSN=forum;UID=user;PWD=",3,1
‘
以只读打开主题消息表,表名存于contotal( i )
if not rs.eof then ‘
该表不为空继续
%>
<!--#INCLUDE VIRTUAL="forum/message_show.inc"-->
‘
显示首条消息记录信息
‘
消息显示处理包含文件message_show.inc见程序段3
<%
endnext=cint(trim(rs("next"))) ‘
获取首条记录的next值
countend=1 ‘
记录当前已处理消息记录数
thiscount=rs.recordcount ‘
获取本主题消息表的记录总数
do until ((endnext=0) or (countend=thiscount))
‘do until
循环,直到当前记录的next=0或处理了所有记录
thisnext=cint(trim(rs("next"))) ‘
获取当前记录的next值
rs.move thisnext,0 ‘
相对于当前记录将光标移动next位
endnext=thisnext
countend=countend+1
%>
<!--#INCLUDE VIRTUAL="forum/message_show.inc"-->
‘
显示当前消息记录信息
<%
loop ‘do until
循环结束
else ‘
该主题消息表记录为空
response.write "<center><font size=2>
尚无讨论提交.</font></center><p>"
end if
rs.close
set rs=nothing ‘
关闭并清除rs
next ‘for
循环结束
%>
程序段2
message_show.inc
的程序如下:
<% for nvspnum=1 to cint(rs("level"))
%>
<%next%> ‘
按记录的level值右缩level*2个空格
<font size="2">
<a href="contentdisplay.asp?contentdis=<%=rs("index")%>&discussarea=<%=contotal( i )%>
<a href="contentdisplay.asp?contentdis=<%=rs("index")%>&discussarea=<%=contotal( i )%>
"target="mainFrame"><%=rs("subject")%></a>
(<%=rs("name")%><font color="#000000">,<%=rs("submitdate")%></font>)
‘
显示消息的标题等信息,并创建面向
‘contentdisplay.asp
的页面的超文本链接,链接内含有
‘
名为contentdis和discussarea的查询字符串变量,
‘
用于将该记录的索引值和所在的主题消息表名传给
‘contentdisplay.asp
处理,以显示消息内容
<% thediff=datevalue(now)-datevalue(rs("submitdate"))
if thediff<=7 then
%>
<font color="#ff0000">new</font>
<%
end if ‘
如果该消息在7天内提交,其后添加new标记
%><br></font>
程序段3
²
消息的处理
当在论坛中发送消息或答复消息时,应用程序在数据库中相应的主题消息表中添加新记录,最重要的就是确定记录中level和next的值,并修改相关的记录的next值。
本论坛应用程序有两个文件涉及到消息的处理,即发送消息的disc_post.asp(表单信息来自于discuss_main.asp),答复消息的disc_response.asp(表单信息来自于disc_reply.asp)。
在disc_post.asp中处理的消息,其level值肯定为1;并且将新消息记录添加到相应主题消息表的末尾,其next值肯定为0。其处理程序段如下:
<%
subject=trim(request.form("subject"))
discussarea=trim(request.form("selectno"))
comments=trim(request.form("comments"))
name=trim(request.form("name"))
email=trim(request.form("email"))
‘
获得来自discuss_main.asp的表单信息
'to create record
on error resume next
%>
<!--#INCLUDE VIRTUAL="forum/opendb33.inc"-->
‘
以光标3和锁定3的方式打开主题消息表discussarea
‘
其内容见程序段5
<%
truefind=true ‘truefind
用于判断是否找到next=0的记录
if not rs.eof then ‘
主题消息表不为空继续
rs.movefirst ‘
光标移动到首条记录
firstindex=cint(trim(rs("index")))
‘
记录首条记录的索引值到变量firstindex中
rs.movelast ‘
光标移动到最后一条记录
tonext=1 ‘
变量tonext用于存储表中next=0的记录到表尾的距离
findit=false ‘findit
判断是否找到next=0的记录或搜索完所有记录
do until findit ‘do until
循环开始
if cint(trim(rs("index")))=firstindex then
findit=true
end if ‘
如果已经搜索到首条记录,findit赋值为真,结束循环
if cint(rs("next"))<>0 then
‘next 不为0,则将光标继续前移
‘next 不为0,则将光标继续前移
truefind=false
rs.moveprevious
tonext=tonext+1
else ‘next=0
,则找到记录
truefind=true
findit=true
end if
loop ‘do until
循环结束
if truefind then
‘
找到next=0的记录,并将该条记录的next值赋为
‘tonext
,这样记录的下一条显示记录即为新添加记录
rs("next")=tonext
end if
else ‘
该主题消息表为空,则tonext应为0
tonext=0
end if
if truefind then ‘
找到next=0的记录,则添加新纪录
rs.addnew
rs("subject")=subject
rs("submitdate")=now
rs("content")=comments
rs("name")=name
rs("next")=0
rs("level")=1
rs("email")=email
rs.update
else ‘
没有找到next=0的记录,其处理在文件closedb33.inc中
%>
<!--#INCLUDE VIRTUAL="forum/closedb33.inc"-->
‘
其内容见程序段6
程序段4
opendb33.inc
的程序如下:
<%
set cnn1=server.createobject("adodb.connection")
cnn1.open "forum","user",""
set rs=server.createobject("ADODB.recordset")
rs.cursortype=3
rs.locktype=3
cnn1.begintrans ‘
开始事务处理
rs.open discussarea,cnn1,,,2 ‘
打开主题消息表discussarea
%>
程序段5
closedb33.inc
的程序如下:
<%
cnn1.rollbacktrans ‘
没有找到next=0的记录,撤销事务处理
response.write "<center>
对不起,本讨论区出现问题,暂时停用!</center>"
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing ‘
关闭并清除rs和cnn1
response.end ‘
页面请求结束,显示页面
end if ‘if truefind then
判断语句结束
if err=0 then ‘程序运行无错,触发事务处理
if err=0 then ‘程序运行无错,触发事务处理
cnn1.committrans
else
cnn1.rollbacktrans ‘
程序运行出错,撤销事务处理
response.write "<center>
讨论提交失败!</center>"
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing ‘
关闭并清除rs和cnn1
response.end
end if
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing ‘
关闭并清除rs和cnn1
%>
程序段6
<%
subject=trim(request.form("subject"))
discussarea=request.form("discussarea")
comments=trim(request.form("comments"))
name=trim(request.form("name"))
email=trim(request.form("email"))
levelreply=request.form("levelreply")+1
indexreply=cint(trim(request.form("indexreply")))
‘
获得来自disc_reply.asp的表单信息
'to create record
on error resume next
%>
<!--#INCLUDE VIRTUAL="forum/opendb33.inc"-->
‘
内容见程序段5
<%
truefind=true
rs.movefirst
firstindex=cint(trim(rs("index")))
rs.movelast
tonext=1
findit=false
do until findit ‘do until
循环开始
if cint(trim(rs("index")))=firstindex then
findit=true
end if
if cint(rs("index"))<>indexreply then
‘
未找到所答复消息记录,光标继续前移
truefind=false
rs.moveprevious
tonext=tonext+1
else ‘
找到所答复消息记录,则truefind和findit赋值为真
truefind=true
findit=true
end if
loop ‘do until
循环结束
if truefind then ‘
找到所答复消息记录,则存储该记录next到变量thisnext
‘
中,并修改该记录的next为到新添加记录的距离
thisnext=cint(trim(rs("next")))
rs("next")=tonext
rs.addnew ‘
添加新记录
rs("subject")=subject
rs("submitdate")=now
rs("content")=comments
rs("name")=name
rs("email")=email
if thisnext<>0 then ‘
如果thisnext不为0,则新记录next值为thisnext-tonext
rs("next")=thisnext-tonext
else ‘
如果thisnext为0,则新记录next=0
rs("next")=0
end if
rs("level")=levelreply
rs.update
else ‘
没有找到所答复消息记录,其处理见closedb33.inc
%>
<!--#INCLUDE VIRTUAL="forum/closedb33.inc"-->
‘
内容见程序段6
程序段7
五、程序清单
这里列出本论坛的程序清单。这只是一个非常简单的WEB程序,可以添加很多功能进行扩展,如添加图片,将主题显示与消息显示分成不同页面。有兴趣不妨一试。
5.1 myforum.html
:
<HTML>
<body>
<p><p>
<center><h3>Welcome to My <a href="discuss.asp" target="_self">Forum</a>!</h3></center>
‘
建立到论坛的页面链接
</body>
</HTML>
5.2 discuss.asp
:
<%@language=VBScript%>
<html>
<head>
<title>
讨论组</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<%
'on error resume next
discussarea="forum_content"
%>
<!--#INCLUDE VIRTUAL="forum/opendb33.inc"-->
‘
打开表forum_content
<%
<%
if rs.recordcount=0 then ‘
无记录,则结束页面请求
cnn1.rollbacktrans
response.write "<center>
对不起,讨论区没有设定内容!</center>"
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing
response.end
end if
for todoit=1 to rs.recordcount ‘
有记录,则对每个主题消息表进行统计
set rs1=server.createobject("ADODB.recordset")
rs1.open "select * from "&rs("contentname"),"DSN=forum;UID=user;PWD=",3,1
newnum=0
for todoit1=1 to rs1.recordcount
thediff=datevalue(now)-datevalue(rs1("submitdate"))
if thediff<=7 then
newnum=newnum+1 ‘7
天之内发送的消息为新消息
end if
rs1.movenext
next
rs("total")=rs1.recordcount
rs("newest")=newnum
rs1.close
set rs1=nothing
rs.movenext
next
if err=0 then
cnn1.committrans
else
cnn1.rollbacktrans
response.write "<center>
对不起,讨论区失败!</center>"
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing
response.end
end if
rs.close
set rs=nothing
cnn1.close
set cnn1=nothing
%>
<frameset frameborder="no" border="0" framespacing="0" bordercolor="#ffffff"
rows="79,421*" cols="*">
<frame name="topFrame" scrolling="NO" noresize src="discuss_top.html">
<frameset frameborder="YES" border="2" framespacing="2" bordercolor="#FFCCFF"
cols="414,379*" rows="*">
<frame name="leftFrame" noresize src="discuss_left.asp">
<frame name="mainFrame" src="discuss_main.asp">
</frameset>
<noframes size="+1">
<body bgcolor="#FFFFFF">
</body>
</noframes> </frameset>
<frameset>
<frameset>
<noframes>
</noframes>
</frameset> ‘
以上为框架定义语句
</html>
5.3 discuss_top.html
:
<html>
<head>
<title>
讨论组</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#FFFFFF">
<p align="center"><fontFONT-SIZE: 10.5pt; COLOR: black;">黑体, System, 楷体_GB2312">
<marquee border="0" align="middle" behavior="alternate" style="color: rgb(0,0,255)">
<kbd><font size="4">
小小论坛欢迎您</font></kbd></marquee></font></p>
<table width="75%" border="0" align="center" height="25">
<tr align="center" valign="middle">
<td height="27" nowrap>
<div align="center"><a href="myforum.html" target="_parent">[
返回主页 ]</a></div>
</td>
<td height="27" nowrap>
<div align="center"> <a href="discuss.asp" target="_parent">[
刷新内容 ]</a></div>
</td>
<td height="27" nowrap>
<div align="center"><a href="discuss_main.asp" target="mainFrame">[
发送 ]</a></div>
</td>
</tr>
</table>
<p> </p>
</body>
</html>