代码下载
热衷于开源框架探索的我发现ASP.NET MVC与jQuery easyUI的组合很给力。由于原先一直受Ext JS框架的licence所苦恼,于是痛下决心寻找一个完全免费的js框架——easyUI。它有完整的demo和强大AIP手册,使我在开发过程中得心应手。以下是这篇博文Demo程序的演示效果:
解决方案如图1所示
图1
Domain:领域模型
Dao:持久层
Service:服务层
WebSite:表示层
Common:通用类
首页如图2所示,可以选择中文和English。
图2
英文首页如图3所示
图3
公司简介效果如图4所示
图4
后台登陆页面如图5所示
图5
后台首页如图6所示
图6
后台首页的代码html为:
function
showChangePasswordWin() {
$(
'
#winPassword
'
).window(
'
open
'
);
}
function
changePassword() {
var
oldPassword
=
$(
"
#iptOldPassword
"
).val();
if
(oldPassword
==
""
) {
$.messager.alert(
'
提示
'
,
'
请输入旧密码!
'
);
return
;
}
var
password
=
$(
"
#iptPassword
"
).val();
if
(password
==
""
) {
$.messager.alert(
'
提示
'
,
'
请输入新密码!
'
);
return
;
}
var
newPassword
=
$(
"
#iptNewPassword
"
).val();
if
(newPassword
==
""
) {
$.messager.alert(
'
提示
'
,
'
请确认密码!
'
);
return
;
}
if
(newPassword
!=
password) {
$.messager.alert(
'
提示
'
,
'
两次密码不一致,请重新输入!
'
);
return
;
}
var
parm
=
{ password: password, oldPassword: oldPassword };
$.ajax({
type:
"
POST
"
,
url:
"
/Home/ChangedPassword/
"
,
data: parm,
success:
function
(msg) {
if
(msg.IsSuccess) {
$.messager.alert(
'
提示
'
,
'
修改成功!
'
,
"
info
"
,
function
() {
$(
'
#winPassword
'
).window(
'
close
'
);
$(
"
#iptOldPassword
"
).val(
""
);
$(
"
#iptPassword
"
).val(
""
);
$(
"
#iptNewPassword
"
).val(
""
);
});
}
else
{
$.messager.alert(
'
提示
'
,
'
密码错误,请重新输入!
'
,
"
info
"
);
}
},
error:
function
() {
$.messager.alert(
'
错误
'
,
'
修改失败!
'
,
"
error
"
);
}
});
}
function
showTab(url, title) {
var
tab
=
$(
'
#tab
'
);
if
(tab.tabs(
'
exists
'
, title)) {
tab.tabs(
'
select
'
, title);
}
else
{
tab.tabs(
'
add
'
, {
title: title,
content:
"
<iframe scrolling='yes' frameborder='0' src='/
"
+
url
+
"
/Index/' style='width:100%;height:100%;'/>
"
,
closable:
true
});
}
}
function
showArticle(id, title) {
var
tab
=
$(
'
#tab
'
);
if
(tab.tabs(
'
exists
'
, title)) {
tab.tabs(
'
select
'
, title);
}
else
{
tab.tabs(
'
add
'
, {
title: title,
content:
"
<iframe scrolling='yes' frameborder='0' src='/Article/Admin/
"
+
id
+
"
/' style='width:100%;height:100%;'/>
"
,
closable:
true
});
}
}
<
body
class
="easyui-layout"
>
<
div
region
="north"
border
="false"
style
="height: 100px; background-color: #E0ECFF;"
>
<
div
style
="height: 80px; clear: both;"
>
<
div
style
="width: 150px;"
>
</
div
>
<
div
style
="text-align: center; width: 150px; line-height: 80px;"
>
<
img
alt
="logo"
src
="/Images/logo_small.jpg"
onclick
="window.open('/Index.html')"
/>
</
div
>
</
div
>
<
div
style
="height: 20px;text-align:right"
>
<
div
>
登陆用户:
<
a
href
="#"
onclick
=""
>
<%
=
((dynamic)ViewData[
"
User
"
]).Name
%>
</
a
>
<
a
href
="#"
onclick
="showChangePasswordWin();"
>
修改密码
</
a
>
<
a
href
="/Home/LogOut/"
>
退出系统
</
a
>
<
a
href
="http://member.webweb.com/"
target
="_blank"
>
空间管理
</
a
>
<
a
href
="http://new.cnzz.com/"
target
="_blank"
>
站长在线
</
a
>
</
div
>
</
div
>
</
div
>
<
div
region
="west"
split
="true"
title
="<font color='#993333'>系统菜单</font>"
style
="width: 150px;"
>
<
div
class
="easyui-accordion"
fit
="true"
border
="false"
style
="background-color: #E0ECFF;
background-repeat: repeat-x;"
>
<
div
title
="资料管理"
style
="overflow: auto;"
>
<
table
border
="0"
cellspacing
="1"
cellpadding
="1"
align
="center"
>
<
tr
>
<
td
height
="23"
>
<
a
href
="#"
onclick
="showTab('Forum',$(this).html());"
>
版块管理
</
a
>
</
td
>
</
tr
>
<
tr
>
<
td
height
="23"
>
<
a
href
="#"
onclick
="showTab('Category',$(this).html());"
>
分类管理
</
a
>
</
td
>
</
tr
>
</
table
>
</
div
>
<%
foreach (var item in (this.ViewData[
"
CategoryList
"
]
as
IList
<
Domain.Category
>
).GroupBy(g
=>
g.Forum))
{
%>
<
div
title
="<%= item.Key.Name %>"
style
="overflow: auto;"
>
<
table
border
="0"
cellspacing
="1"
cellpadding
="1"
align
="center"
>
<%
foreach (var value in item)
{
%>
<
tr
>
<
td
height
="23"
>
<
a
href
="#"
onclick
="showArticle('<%= value.ID %>',$(this).html());"
>
<%
=
value.Name
%>
</
a
>
</
td
>
</
tr
>
<%
}
%>
</
table
>
</
div
>
<%
}
%>
<
div
title
="系统管理"
style
="overflow: auto;"
>
<
table
border
="0"
cellspacing
="1"
cellpadding
="1"
align
="center"
>
<
tr
>
<
td
height
="23"
>
<
a
href
="#"
onclick
="showTab('UserInfo',$(this).html());"
>
管理员用户管理
</
a
>
</
td
>
</
tr
>
</
table
>
</
div
>
</
div
>
</
div
>
<
div
region
="south"
border
="false"
style
="height: 20px; background: #A9FACD; text-align: center;
line-height: 20px; background-image: url(/Images/bg_bottom.gif);"
>
Copy Right ®2010-2011
</
div
>
<
div
region
="center"
>
<
div
id
="tab"
class
="easyui-tabs"
fit
="true"
border
="false"
>
<
div
title
="首页"
style
="padding: 20px; overflow: hidden;"
>
<
table
width
="98%"
border
="0"
cellpadding
="3"
align
="center"
cellspacing
="0"
bgcolor
="#F1EAE0"
>
<
tr
>
<
td
width
="100%"
bgcolor
="#cccccc"
height
="5"
>
</
td
>
</
tr
>
<
tr
>
<
td
width
="100%"
class
="change_td"
style
="cursor: hand"
>
服务器参数
</
td
>
</
tr
>
</
table
>
<
table
cellspacing
="1"
cellpadding
="3"
width
="98%"
align
="center"
bgcolor
="#ffffff"
border
="0"
>
<
tbody
>
<
tr
>
<
td
class
="th1"
align
="center"
colspan
="2"
style
="height: 25px"
>
服务器信息统计
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
width
="50%"
style
="height: 24px"
>
<
strong
>
服务器名
</
strong
>
:
<%
=
System.Environment.MachineName
%>
</
td
>
<
td
width
="50%"
style
="height: 24px"
>
<
b
>
服务器端口:
</
b
>
<%
=
HttpContext.Current.Request.ServerVariables[
"
Server_Port
"
].ToString()
%>
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
width
="50%"
style
="height: 23px"
>
<
b
>
脚本解释引擎:
</
b
>
<%
=
System.Environment.Version
%>
</
td
>
<
td
width
="50%"
style
="height: 23px"
>
<
b
>
站点物理路径:
</
b
>
<%
=
HttpContext.Current.Request.PhysicalApplicationPath.ToString()
%>
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
width
="50%"
style
="height: 23px"
>
<
b
>
服务器CPU个数:
</
b
>
<%
=
System.Environment.ProcessorCount
%>
</
td
>
<
td
width
="50%"
style
="height: 23px"
>
<
b
>
服务器IIS版本:
</
b
>
<%
=
Request.ServerVariables[
"
SERVER_SOFTWARE
"
]
%>
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
width
="50%"
>
<
b
>
开机运行时长
</
b
>
:
<%
=
(System.Environment.TickCount
/
3600000
).ToString(
"
N2
"
)
%>
小时
</
td
>
<
td
width
="50%"
>
<
b
>
服务器时间:
</
b
>
<%
=
DateTime.Now.ToString()
%>
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
colspan
="2"
>
<
b
>
服务器操作系统:
</
b
><
span
>
<%
=
System.Environment.OSVersion.ToString()
%>
</
span
>
</
td
>
</
tr
>
<
tr
bgcolor
="#f9fbf0"
>
<
td
colspan
="2"
>
</
td
>
</
tr
>
</
tbody
>
</
table
>
</
div
>
</
div
>
</
div
>
<
div
id
="winPassword"
class
="easyui-window"
closed
="true"
modal
="true"
title
="修改密码"
style
="width: 280px; height: 160px;"
collapsible
="false"
minimizable
="false"
maximizable
="false"
>
<
div
class
="easyui-layout"
fit
="true"
>
<
div
region
="center"
border
="false"
style
="padding: 10px; background: #fff; border: 1px solid #ccc;"
>
<
table
>
<
tr
>
<
td
>
旧密码:
</
td
>
<
td
>
<
input
type
="password"
id
="iptOldPassword"
/>
</
td
>
</
tr
>
<
tr
>
<
td
>
新密码:
</
td
>
<
td
>
<
input
type
="password"
id
="iptPassword"
/>
</
td
>
</
tr
>
<
tr
>
<
td
>
确认密码:
</
td
>
<
td
>
<
input
type
="password"
id
="iptNewPassword"
/>
</
td
>
</
tr
>
</
table
>
</
div
>
<
div
region
="south"
border
="false"
style
="text-align: right; height: 30px; line-height: 30px;"
>
<
a
class
="easyui-linkbutton"
iconcls
="icon-ok"
href
="javascript:void(0)"
onclick
="changePassword()"
>
确定
</
a
>
<
a
class
="easyui-linkbutton"
iconcls
="icon-cancel"
href
="javascript:void(0)"
onclick
="$('#winPassword').window('close');"
>
取消
</
a
>
</
div
>
</
div
>
</
div
>
</
body
>
可以进行版块和分类的管理,如图7和图8所示。
图7
图8
选择列表模式的分类可以添加列表内容,如图9所示。
图9
easyUI的datagrid代码如下:
$(
'
#grid
'
).datagrid({
title:
'
<%= ((Domain.Category)this.ViewData["entity"]).Name %>信息
'
,
iconCls:
'
icon-save
'
,
nowrap:
false
,
striped:
true
,
url:
'
/Article/LoadAllByPage/
'
,
sortName:
'
CreateDate
'
,
sortOrder:
'
desc
'
,
remoteSort:
true
,
fitColumns:
true
,
fit:
true
,
idField:
'
ID
'
,
queryParams: { categoryId:
'
<%= ((Domain.Category)this.ViewData["entity"]).ID %>
'
},
frozenColumns: [[
{ field:
'
ID
'
, checkbox:
true
}
]],
columns: [[
{ field:
'
CreateDate
'
, title:
'
建立日期
'
, width:
100
,
formatter:
function
(value, rec) {
return
eval(
"
new
"
+
value.substr(
1
, value.length
-
2
)).toLocaleDateString();
}
},
{ field:
'
Name
'
, title:
'
中文标题
'
, width:
80
, align:
'
right
'
},
{ field:
'
NameEn
'
, title:
'
英文标题
'
, width:
80
, align:
'
right
'
},
{ field:
'
IsFirst
'
, title:
'
是否置顶
'
, width:
40
, align:
'
right
'
,
formatter:
function
(value, rec) {
return
value
?
'
是
'
:
'
否
'
;
}
},
{ field:
'
IsEnabled
'
, title:
'
状态
'
, width:
40
, align:
'
right
'
,
formatter:
function
(value, rec) {
return
value
?
'
显示
'
:
'
隐藏
'
;
}
},
{ field:
'
From
'
, title:
'
来源
'
, width:
80
, align:
'
right
'
},
{ field:
'
ViewCount
'
, title:
'
浏览次数
'
, width:
40
, align:
'
left
'
},
{ field:
'
UpdateDate
'
, title:
'
最后更新日期
'
, width:
100
,
formatter:
function
(value, rec) {
return
eval(
"
new
"
+
value.substr(
1
, value.length
-
2
)).toLocaleDateString();
}
}
]],
pagination:
true
,
rownumbers:
true
,
toolbar: [
'
-
'
, {
id:
'
btnSave
'
,
text:
'
添加
'
,
iconCls:
'
icon-add
'
,
handler:
function
() {
this
.href
=
'
/Article/View/?categoryId=<%= ((Domain.Category)this.ViewData["entity"]).ID %>
'
;
}
},
'
-
'
, {
id:
'
btnUpdate
'
,
text:
'
修改
'
,
iconCls:
'
icon-save
'
,
handler:
function
() {
var
row
=
$(
'
#grid
'
).datagrid(
'
getSelected
'
);
if
(row) {
this
.href
=
'
/Article/View/
'
+
row.ID
+
'
/?categoryId=<%= ((Domain.Category)this.ViewData["entity"]).ID %>
'
;
}
else
{
$.messager.alert(
'
提示
'
,
'
请选择要修改的数据
'
);
return
;
}
}
},
'
-
'
, {
id:
'
btnDelete
'
,
text:
'
删除
'
,
disabled:
false
,
iconCls:
'
icon-cut
'
,
handler:
function
() {
var
rows
=
$(
'
#grid
'
).datagrid(
'
getSelections
'
);
if
(
!
rows
||
rows.length
==
0
) {
$.messager.alert(
'
提示
'
,
'
请选择要删除的数据
'
);
return
;
}
var
parm;
$.each(rows,
function
(i, n) {
if
(i
==
0
) {
parm
=
"
idList=
"
+
n.ID;
}
else
{
parm
+=
"
&idList=
"
+
n.ID;
}
});
$.messager.confirm(
'
提示
'
,
'
是否删除这些数据?
'
,
function
(r) {
if
(
!
r) {
return
;
}
$.ajax({
type:
"
POST
"
,
url:
"
/Article/Delete/
"
,
data: parm,
success:
function
(msg) {
if
(msg.IsSuccess) {
$.messager.alert(
'
提示
'
,
'
删除成功!
'
,
"
info
"
,
function
() {
$(
'
#grid
'
).datagrid(
"
reload
"
);
});
}
},
error:
function
() {
$.messager.alert(
'
错误
'
,
'
删除失败!
'
,
"
error
"
);
}
});
});
}
},
'
-
'
]
Controller的载入JSON数据的代码为:
[Authorize]
public
ActionResult LoadAllByPage(Guid categoryId,
int
page,
int
rows,
string
order,
string
sort)
{
long
total
=
0
;
var list
=
this
.ArticleManager.LoadAllByPage(
out
total, categoryId, page, rows, order, sort).Select(entity
=>
new
{
entity.Name,
entity.NameEn,
entity.ID,
entity.CreateDate,
entity.UpdateDate,
entity.IsEnabled,
entity.IsFirst,
entity.ViewCount,
entity.From,
CategoryId
=
entity.Category.ID,
CategoryName
=
entity.Category.Name
});
var result
=
new
{ total
=
total, rows
=
list.ToList() };
return
Json(result);
}
开发环境为VS2010,数据库是根据NHibernate的方言任意配置,我使用的是SQLite数据库。
<!--
SQLite
-->
<
add
key
="provider"
value
="System.Data.SQLite"
/>
<
add
key
="connectionString"
value
="Data Source=|DataDirectory|DataBase.db;Version=3;FailIfMissing=False;"
/>
<
add
key
="dialect"
value
="NHibernate.Dialect.SQLiteDialect"
/>
<
add
key
="driver_class"
value
="NHibernate.Driver.SQLite20Driver"
/>
<!--
自动建表
-->
<
add
key
="hbm2ddl.auto"
value
="update"
/>