用户在登陆一个系统后通常会因为权限的不同而使用不同的系统功能,我们在实现用户使用的菜单项时有两种选择,一是列出全部系统菜单项,根据用户的权限禁用一部分菜单,二是根据权限动态加载菜单,这样只要列出的菜单都可以使用,而不同用户登陆后看到的菜单项排列是不同的。在这里我使用了第二种方式,利用JavaScript和SQL Server2000在ASP.NET中实现了一个类似于论坛菜单的动态加载功能。
整个菜单的界面如右图所示:
上面共有四个大菜单项,每个菜单项内又有若干个小项,我们所要实现的就是让不同的用户登陆后所看到的大小菜单项都是不同的。
(1)首先我们进行数据库方面的设计。由于不同用户对应不同的权限,而不同的权限对应不同的菜单,所以数据库方面要设计三个表:
表Users
列名 |
数据类型及长度 |
说明 |
UserName |
Varchar(50) |
主键,用户名 |
RoleName |
Varchar(50) |
角色名 |
此表用于记录所有的用户,每个用户可以赋予一个角色
表Roles
列名 |
数据类型及长度 |
备注 |
RoleName |
Varchar(50) |
主键 |
FunctionID |
Int |
主键,功能点序号 |
此表是角色表,包括角色名称和功能点编号(功能点对应着界面内的菜单项)。由于一个角色可以对应多个功能点,而一个功能点也可以由多个角色使用,双方是多对多关系,所以此表设置联合主键。
表Fun
列名 |
数据类型及长度 |
备注 |
ID |
Int(4) |
主键,功能点序号 |
ParentID |
Int(4) |
父功能点序号 |
Text |
Varchar(30) |
功能点的文字描述 |
URL |
Varchar(50) |
点击菜单后转向的页面地址 |
ImageUrl |
Varchar(30) |
菜单项图片本身的地址 |
此表是功能点信息表,由于菜单包括主菜单项和子菜单项,因此每个功能点要记录他的父功能点编号,主菜单的父功能点则为0,由于点击菜单后要进行页面的跳转,因此要记录各功能点对应的页面的URL,同时为了美化菜单我们也可以在菜单上加一下小图标,这个可以通过ImageUrl来保存图标的位置。
这样数据库部分已经设计完毕,接下来我们先要对数据库填充数据,这里首先看Fun表,该表填充后的结果如下(其中URL和ImageUrl分别存储页面和图标的地址,此处省略)
ID |
ParentID |
Text |
1 |
0 |
我的社区 |
2 |
0 |
.NET技术社区 |
3 |
0 |
休闲区 |
4 |
0 |
版主管理 |
5 |
1 |
我的问题 |
6 |
1 |
我得分的问题 |
7 |
1 |
我参与的问题 |
8 |
1 |
我的专家分 |
9 |
2 |
C#编程 |
10 |
2 |
ASP.NET开发 |
11 |
2 |
WinForm开发 |
12 |
2 |
.NET Framework |
13 |
3 |
灌水乐园 |
14 |
3 |
贴图天地 |
15 |
4 |
查询帖子 |
16 |
4 |
回复管理 |
17 |
4 |
封杀帐号 |
这样已经把菜单中全部的功能点填充完毕,然后开始填充表Roles的数据这里非常简单,只要根据事先设计的角色名和可以使用的功能点进行填充就可以了。最后在Users表中添加三个帐号用于测试,此处将后两个表的内容统一列出
帐号(UserName) |
角色(RoleName) |
可用功能点序号 (FunctionID) |
admin |
Administrator |
全部:1-17 |
ue |
User |
1-15 |
Gust |
Guest |
1-3,9-14 |
(2)下面新建一个Web项目,项目中有两个Web窗体,分别是login.aspx 和webform1.aspx
打开login.aspx页面,可以在里面加上一个Textbox和一个Button按钮,其中TextBox用于输入用户名,按钮用来登陆,我们在按钮的Click事件中加入下面的代码
Session.Add("UserName",name); //将用户名加入到session中
Response.Redirect("WebForm1.aspx",true);
(3)打开webform1.aspx页面,切换到html代码视图,在<Head>与</Head>中插入下拉JavaScript代码
<STYLE type="text/css">
A:link { FONT-SIZE: 12px; COLOR: #000000; TEXT-DECORATION: none }
A:visited { FONT-SIZE: 12px; COLOR: #000000; TEXT-DECORATION: none }
A:hover { FONT-SIZE: 12px; COLOR: #006cd9; TEXT-DECORATION: none }
TD { FONT-SIZE: 12px; LINE-HEIGHT: 150% }
</STYLE>
<SCRIPT>
function showitem(id,name)
{
return ("<span><a href='"+id+"' target=_self>"+name+"</a></span><br>")
}
function switchoutlookBar(number)
{
var i = outlookbar.opentitle;
outlookbar.opentitle=number;
var id1,id2,id1b,id2b
if (number!=i && outlooksmoothstat==0){
if (number!=-1)
{
if (i==-1)
{
id2="blankdiv";
id2b="blankdiv";}
else{
id2="outlookdiv"+i;
id2b="outlookdivin"+i;
document.all("outlooktitle"+i).style.border="1px none navy";
document.all("outlooktitle"+i).style.background="#006CD9";
document.all("outlooktitle"+i).style.color="#ffffff";
document.all("outlooktitle"+i).style.textalign="center";
}
id1="outlookdiv"+number
id1b="outlookdivin"+number
document.all("outlooktitle"+number).style.border="1px none white";
document.all("outlooktitle"+number).style.background="#006CD9"; //title
document.all("outlooktitle"+number).style.color="#ffffff";
document.all("outlooktitle"+number).style.textalign="center";
smoothout(id1,id2,id1b,id2b,0);
}
else
{
document.all("blankdiv").style.display="";
document.all("blankdiv").sryle.height="100%";
document.all("outlookdiv"+i).style.display="none";
document.all("outlookdiv"+i).style.height="0%";
document.all("outlooktitle"+i).style.border="1px none navy";
document.all("outlooktitle"+i).style.background="#006CD9";
document.all("outlooktitle"+i).style.color="#ffffff";
document.all("outlooktitle"+i).style.textalign="center";
}
}
}
function smoothout(id1,id2,id1b,id2b,stat)
{
if(stat==0){
tempinnertext1=document.all(id1b).innerHTML;
tempinnertext2=document.all(id2b).innerHTML;
document.all(id1b).innerHTML="";
document.all(id2b).innerHTML="";
outlooksmoothstat=1;
document.all(id1b).style.overflow="hidden";
document.all(id2b).style.overflow="hidden";
document.all(id1).style.height="0%";
document.all(id1).style.display="";
setTimeout("smoothout('"+id1+"','"+id2+"','"+id1b+"','"+id2b+"',"+outlookbar.inc+")",outlookbar.timedalay);
}
else
{
stat+=outlookbar.inc;
if (stat>100)
stat=100;
document.all(id1).style.height=stat+"%";
document.all(id2).style.height=(100-stat)+"%";
if (stat<100)
setTimeout("smoothout('"+id1+"','"+id2+"','"+id1b+"','"+id2b+"',"+stat+")",outlookbar.timedalay);
else
{
document.all(id1b).innerHTML=tempinnertext1;
document.all(id2b).innerHTML=tempinnertext2;
outlooksmoothstat=0;
document.all(id1b).style.overflow="auto";
document.all(id2).style.display="none";
}
}
}
function getOutLine()
{
outline="<table "+outlookbar.otherclass+">";
for (i=0;i<(outlookbar.titlelist.length);i++)
{
outline+="<tr><td name=outlooktitle"+i+" id=outlooktitle"+i+" ";
if (i!=outlookbar.opentitle)
outline+=" nowrap align=center style='cursor:hand;background-color:#006CD9;color:#ffffff;height:5;border:1 none navy' ";
else
outline+=" nowrap align=center style='cursor:hand;background-color:#006CD9;color:white;height:5;border:1 none white' ";
outline+=outlookbar.titlelist[i].otherclass
outline+=" onclick='switchoutlookBar("+i+")'>";
outline+=outlookbar.titlelist[i].title+"</td></tr>";
outline+="<tr><td name=outlookdiv"+i+" valign=top align=center id=outlookdiv"+i+" style='width:100%"
if (i!=outlookbar.opentitle)
outline+=";display:none;height:0%;";
else
outline+=";display:;height:100%;";
outline+="'><div name=outlookdivin"+i+" id=outlookdivin"+i+" style='overflow:auto;width:100%;height:100%'>";
for (j=0;j<outlookbar.itemlist[i].length;j++)
outline+=showitem(outlookbar.itemlist[i][j].key,outlookbar.itemlist[i][j].title);
outline+="</div></td></tr>"
}
outline+="</table>"
return outline
}
function show()
{
var outline;
outline="<div id=outLookBarDiv name=outLookBarDiv style='width=100%;height:100%'>"
outline+=outlookbar.getOutLine();
outline+="</div>"
document.write(outline);
}
function theitem(intitle,instate,inkey)
{
this.state=instate;
this.otherclass=" nowrap ";
this.key=inkey;
this.title=intitle;
}
function addtitle(intitle)
{
outlookbar.itemlist[outlookbar.titlelist.length]=new Array();
outlookbar.titlelist[outlookbar.titlelist.length]=new theitem(intitle,1,0);
return(outlookbar.titlelist.length-1);
}
function additem(intitle,parentid,inkey)
{
if (parentid>=0 && parentid<=outlookbar.titlelist.length)
{
outlookbar.itemlist[parentid][outlookbar.itemlist[parentid].length]=new theitem(intitle,2,inkey);
outlookbar.itemlist[parentid][outlookbar.itemlist[parentid].length-1].otherclass=" nowrap align=left style='height:5' ";
return(outlookbar.itemlist[parentid].length-1);
}
else
additem=-1;
}
function outlook()
{
this.titlelist=new Array();
this.itemlist=new Array();
this.divstyle="style='height:100%;width:100%;overflow:auto' align=center";
this.otherclass="border=0 cellspacing='0' cellpadding='0' style='height:100%;width:100%'valign=middle align=center ";
this.addtitle=addtitle;
this.additem=additem;
this.starttitle=-1;
this.show=show;
this.getOutLine=getOutLine;
this.opentitle=this.starttitle;
this.reflesh=outreflesh;
this.timedelay=50;
this.inc=10;
}
function outreflesh()
{
document.all("outLookBarDiv").innerHTML=outlookbar.getOutLine();
}
function locatefold(foldname)
{
for (var i=0;i<outlookbar.titlelist.length;i++)
if(foldname==outlookbar.titlelist[i].title)
{
outlookbar.starttitle=i;
outlookbar.opentitle=i;
}
}
var outlookbar=new outlook();
var tempinnertext1,tempinnertext2,outlooksmoothstat
outlooksmoothstat = 0;
</SCRIPT>
在<Body>与</Body>中插入下面代码
<asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 208px; POSITION: absolute; TOP: 208px" runat="server">Label</asp:Label>
<TABLE id="mnuList" style="Z-INDEX: 102; LEFT: 8px; WIDTH: 140px; POSITION: absolute; TOP: 8px; HEIGHT: 100%"
cellSpacing="0" cellPadding="0" align="center" border="0">
<TBODY>
<TR>
<TD id="outLookBarShow" style="HEIGHT: 100%" vAlign="top" align="center" bgColor="#f0f0e5"
name="outLookBarShow">
<SCRIPT>locatefold("我的社区")
outlookbar.show()
</SCRIPT>
<FONT face="宋体"></FONT>
</TD>
</TR>
</TBODY>
</TABLE>
</form>
(4)转入WebForm1.aspx.cs页面
先定义一个变量
private string name;
在page_load中加入
if(!IsPostBack)
{
SqlConnection conn=new SqlConnection();
conn.ConnectionString=…//连接数据库
SqlDataAdapter adap=new SqlDataAdapter();
DataSet ds=new DataSet();
SqlCommand cmd=new SqlCommand(); cmd.Connection=conn;
cmd.CommandText="select Fun.ID,Fun.text,Fun.URL,Fun.ParentID from Fun,Roles,Users where Users.RoleName=Roles.RoleName and Roles.functionID=Fun.ID and Users.userName='"+name+"'";
conn.Open();
adap.SelectCommand=cmd;
adap.Fill(ds);
this.ViewState["ds"]=ds;
string[] str1=new string[6];
this.Label1.Text="<script>";
foreach(DataRow row in ds.Tables[0].Rows)
{
if (Convert.ToInt32(row["ParentID"].ToString())==0) {
int id=Convert.ToInt32(row["ID"].ToString());
this.Label1.Text+=@"var t; t=outlookbar.addtitle('"+row["text"].ToString()+"');";
addItem(id);
}
}
this.Label1.Text+="</script>";
}
private void addItem(int id)
{
DataSet ds=(DataSet)this.ViewState["ds"];
foreach (DataRow row in ds.Tables[0].Rows)
{
if (Convert.ToInt32(row["ParentID"].ToString())==id)
{
this.Label1.Text+="outlookbar.additem('"+row["text"].ToString()+"',t,'"+row["URL"].ToString()+"');";
}
}
}
(5) 此处需要注意的一项,就是最后一句中的row[“URL”]中为各菜单项所对应的连接,如果要令各小菜单项本身也是图片以美化菜单,则可以把最后一句改成
其中等于加入了<img src=…>这一句,这样就可以在小菜单项前加入一些小的图标来进行美化
(6)运行整个程序,首先会看到登陆页面,分别输入事先设计的三个用户名进行登陆就会看到不同的菜单项