在各种门户网站中“顶一下”“踩一下”到处可见,无论是博文还是新闻娱乐资讯,众多网站都推出了“顶一下”“踩一下”的功能,以考证此帖的实用性,而且单个用户或单个IP只允许对某贴顶或踩一次。此文将探讨此功能的具体实现,以及网站中通用超链接及按钮css样式的美化。
开发工具:Microsoft Visual Studio 2008 + Microsoft Sql Server 2005
运行环境:Windows 7 + .Net Framework 3.5
一、 数据库设计
这里模拟一个简单的博客,简单地设计了两张表,一张为博文表,一张为“顶”或“踩”的记录表,还有两个存储过程,一个为当用户点击“顶一下”或“踩一下”按钮时执行的存储过程,一个为查询博文包含顶和踩次数的详细信息时的存储过程。
代码 create database Blog
go
use Blog
go
--博文表
create table Blog
(
b_id int primary key identity(1001,1),--编号
b_title nvarchar(64) not null,--博文标题
b_contents ntext not null,--博文内容
b_createtime datetime default(getdate()),--博文创建时间
b_creater nvarchar(32)--博文创建者
)
go
--顶或踩记录表
create table DingRecord
(
d_id int primary key identity(1,1),--编号
b_id int references Blog(b_id) not null,--博文编号
d_operactor varchar(32) not null,--顶或踩的操作者,若登录用户则为登录名,匿名用户则为IP地址
d_isDing bit not null--是否为顶,1则为顶,0则为踩
)
go
--顶或踩的时执行的存储过程
create procedure sp_Ding
@b_id int, --博文id
@d_operactor varchar(32), --顶或踩的操作者
@d_isDing bit --是否为顶
as
--先判断此博文是否已经被顶过或踩过
if((select count(*) from DingRecord where b_id = @b_id and d_operactor = @d_operactor) >= 1)
begin
select '0'--返回0,表明已经被顶过或踩过
end
else
begin
insert into DingRecord values(@b_id,@d_operactor,@d_isDing)
select '1'--返回1,表明成功地执行了顶或踩操作
end
go
--查询包含有顶或踩记录数的博文的存储过程
create procedure sp_Blog
@b_id int
as
declare @dingCount int,@caiCount int
select @dingCount = count(*) from DingRecord where b_id = @b_id and d_isDing = 1
select @caiCount = count(*) from DingRecord where b_id = @b_id and d_isDing = 0
select *,@dingCount as dingCount,@caiCount as caiCount from Blog where b_id = @b_id
go
当执行以下查询
select * from blog
select * from dingrecord
exec sp_Blog 1001
得到结果如下:
二、 页面设计
在这里我们建两个页面
1)BlogList.aspx即为博文列表页,在博文列表页将传递博文的Id到博文详细页,其中博文列表页的代码如下
代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="BlogList.aspx.cs" Inherits="BlogList" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>博文列表</title>
<style type="text/css">
body
{
font-size:12px;
}
a:link,a:visited
{
text-decoration:none;
color:#666666;
}
a:hover
{
text-decoration:underline;
color:#0066cc;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate><ol></HeaderTemplate>
<ItemTemplate>
<li><a href='BlogDetails.aspx?blogid=<%# Eval("b_id") %>'><%# Eval("b_title") %></a></li>
</ItemTemplate>
<FooterTemplate></ol></FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:connstr %>"
SelectCommand="SELECT [b_id], [b_title] FROM [Blog]"></asp:SqlDataSource>
</form>
</body>
</html>
2) BlogDetails.aspx即为博文详细页,博文详细页面中按钮的点击实现了AJAX技术以达到无刷新的效果,“顶一下”,“踩一下”按钮还通过JAVASCRIPT在其onmouseover和onmouseout事件中修改了其样式中的背景图片,图片如下:
博文详细页中的两按钮触发了FormView的ItemCommand事件,将两按钮安置在UpdatePanel中以达到无刷新效果,页面代码如下:
代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="BlogDetails.aspx.cs" Inherits="BlogDetails" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>博文详细页</title>
<style type="text/css">
.btncss
{
width: 194px;
height: 50px;
border-width: 0px;
background-color: Transparent;
font-size: 14px;
font-weight: bold;
color: #666666;
background-repeat: no-repeat;
display: block;
cursor: hand;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:FormView ID="FormView1" runat="server" DataKeyNames="b_id"
DataSourceID="SqlDataSource1" onitemcommand="FormView1_ItemCommand">
<ItemTemplate>
<table border="0" cellpadding="0" cellspacing="0" style="font-size: 12px; width: 600px;">
<tr>
<td colspan="4" style="text-align: center; height: 50px; font-weight: bold; font-size: 16px;
color: Red;">
<%# Eval("b_title") %>
</td>
</tr>
<tr>
<td style="width: 60px; height: 30px;">
作者:
</td>
<td style="width: 240px; color: Red;">
<%# Eval("b_creater") %>
</td>
<td style="width: 60px;">
发布时间:
</td>
<td style="width: 240px; color: Red;">
<%# Eval("b_createtime") %>
</td>
</tr>
<tr>
<td colspan="4" style="padding: 10px;">
<%# Eval("b_contents") %>
</td>
</tr>
<tr>
<td colspan="4">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table border="0" cellpadding="0" cellspacing="0" style="width: 600px; height: 50px;">
<tr>
<td style="width: 206px;">
<asp:Button ID="BtnDing" runat="server" CssClass="btncss" Text='<%# "顶一下(" + Eval("dingCount") + ")" %>'
Style="background-image: url(Img/ding.jpg);" onmouseover="this.style.backgroundImage='url(Img/dinghover.jpg)';"
onmouseout="this.style.backgroundImage='url(Img/ding.jpg)';" CommandName="Ding" />
</td>
<td style="width:194px;">
<asp:Button ID="BtnCai" runat="server" CssClass="btncss" Text='<%# "踩一下(" + Eval("caiCount") + ")" %>'
Style="background-image: url(Img/cai.jpg);" onmouseover="this.style.backgroundImage='url(Img/caihover.jpg)';"
onmouseout="this.style.backgroundImage='url(Img/cai.jpg)';" CommandName="Cai" />
</td>
<td style="width:200px; color:Blue; font-size:12px; padding-left:20px;">
<asp:Literal ID="ltInfo" runat="server"></asp:Literal>
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:FormView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:connstr %>"
SelectCommand="sp_Blog" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:QueryStringParameter DbType="Int32" QueryStringField="blogid" Name="b_id" />
</SelectParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
博文详细页后台代码:
代码 using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data;
public partial class BlogDetails : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//如果QueryString中不存在blogid参数或为空,则跳转到博文列表页面
if (!IsPostBack && (Request.QueryString["blogid"] == null || Request.QueryString["blogid"].ToString() == ""))
{
Response.Redirect("~/BlogList.aspx");
}
(FormView1.FindControl("ltInfo") as Literal).Text = "";
}
protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
{
switch (e.CommandName.ToUpper())
{
case "DING":
Ding(true);
break;
case "CAI":
Ding(false);
break;
}
}
private void Ding(bool isDing)
{
string user;
//如果是已登录用户,则取其登录名
if (User.Identity.AuthenticationType == "Forms" && User.Identity.IsAuthenticated)
{
user = User.Identity.Name;
}
//若为匿名用户,则取其IP地址
else
{
user = Request.UserHostAddress;
}
SqlDataSource sqlds = new SqlDataSource();
sqlds.ConnectionString = ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
sqlds.SelectCommand = string.Format("exec sp_Ding {0},'{1}',{2}",Request.QueryString["blogid"].ToString(),user,isDing ? "1" : "0");
DataView dv = sqlds.Select(DataSourceSelectArguments.Empty) as DataView;
if (dv[0][0].ToString() == "1")
{
(FormView1.FindControl("ltInfo") as Literal).Text = "谢谢支持";
Button btn = FormView1.FindControl(isDing ? "BtnDing" : "BtnCai") as Button;
//截取原来的顶或踩的次数,然后加1
int newDingCount = int.Parse(btn.Text.Substring(btn.Text.IndexOf("(")+1, btn.Text.IndexOf(")") - btn.Text.IndexOf("(") -1)) + 1;
//给按钮重新赋值
btn.Text = (isDing ? "顶一下(" : "踩一下(") + newDingCount + ")";
}
else if(dv[0][0].ToString() == "0")
{
(FormView1.FindControl("ltInfo") as Literal).Text = "你已进行过此操作";
}
}
}
三、 运行效果
博文列表页效果:
鼠标移上去时,超链接变色并加下划线
博文详细页效果:
鼠标未移过时:
鼠标移过时:
未点击按钮时:
点击“顶一下”按钮:
再次点击“顶一下”或“踩一下”按钮:
整个过程不刷新网页