总体效果:
一、前台:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>CheckBox Tree - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="assets/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="assets/themes/icon.css">
<script type="text/javascript" src="assets/jquery.min.js"></script>
<script type="text/javascript" src="assets/jquery.easyui.min.js"></script>
<title>可编辑的表格树</title>
</head>
<!-- //treegrid主表 -->
<table id="tg" class="easyui-treegrid" title="菜单管理"
style="width: 700px; height: 600px" toolbar="#toolbar"
data-options="
iconCls: 'icon-ok',
rownumbers: true,
animate: true,
fitColumns: true,
url: 'getmenutree',
method: 'get',
idField: 'id',
treeField: 'name',
onContextMenu: onContextMenu,
collapsible: true,
showFooter: true
">
<thead>
<tr>
<th data-options="field:'name',width:180,editor:'text'"> Name</th>
<th data-options="field:'urls',width:60,align:'right',editor:'text'">url</th>
</tr>
</thead>
</table>
<div id="toolbar">
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit'" οnclick="beginEdit()">编辑</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-save'"
οnclick="saveUpdate()">保存编辑</a>
<a href="javascript:void(0)" class="easyui-linkbutton" οnclick="cancel()">取消编辑</a>
<a href="#" class="easyui-linkbutton"
data-options="iconCls:'icon-add'" οnclick="appendRoot()">新增根目录</a> <a
href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add'"
οnclick="append()">新增目录</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-save'"
οnclick="saveEdit()">保存新增</a>
<a href="#" class="easyui-linkbutton"
data-options="iconCls:'icon-cancel'" οnclick="removeIt()">删除</a>
</div>
<!-- //右键菜单选项 -->
<div id="mm" class="easyui-menu" style="width: 120px;">
<div οnclick="append()" data-options="iconCls:'icon-add'">新增</div>
<div οnclick="removeIt()" data-options="iconCls:'icon-remove'">删除</div>
<div class="menu-sep"></div>
<div οnclick="collapse()">收起</div>
<div οnclick="expand()">展开</div>
</div>
<script type="text/javascript">
//treegrid 的js代码
//编辑目录
var editingId=null;
var editid;
var flag=1;//新增子菜单,flag为0表示新增父级菜单
function ff(row) {
/* $('#tg').treegrid('options').url ='/courseType/getCourseType?parentId='+row.id; */
}
function formatProgress(value) {
if (value) {
var s = '<div style="width:100%;border:1px solid #ccc">'
+ '<div style="width:' + value
+ '%;background:#cc0000;color:#fff">' + value + '%' + '</div>'
'</div>';
return s;
} else {
return '';
}
}
function onContextMenu(e, row) {
if (row) {
e.preventDefault();
$(this).treegrid('select', row.id);
$('#mm').menu('show', {
left : e.pageX,
top : e.pageY
});
}
}
//生成节点ID
function uuid() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "";
var uuid = s.join("");
return uuid;
}
//添加节点,新增目录
function append() {
if (editingId != null){
$.messager.alert("提示信息", "请先保存未保存的信息");
return;
}
var uid=uuid();//新增菜单的id
var node = $('#tg').treegrid('getSelected');//选中的节点
expand();
var parentId;
if(node.pid!=0){
//不是父级菜单
$.messager.alert("提示信息","此菜单不可以有子菜单,请在父级菜单中新增");
}else{
if(node) parentId=node.id;
//flag=1;
else parentId=null;
$('#tg').treegrid('append', {
parent : parentId,
data : [ {
id : uid,
name : '',
sort :'1'
} ]
})
editingId=uid;
if (editingId != null){
$('#tg').treegrid('select', editingId);
}
$('#tg').treegrid('beginEdit', editingId);
editid=node.id;
}//else结束
}
//添加跟节点
function appendRoot() {
if (editingId != null){
$.messager.alert("提示信息", "请先保存");
return;
}
flag=0;
var uid=uuid();
var node = $('#tg').treegrid('getSelected');
expand();
$('#tg').treegrid('append', {
parent : null,
data : [ {
id : uid,
typeName : '',
sort :'1'
} ]
})
editingId=uid;
if (editingId != null){
$('#tg').treegrid('select', editingId);
}
$('#tg').treegrid('beginEdit', editingId);
}
//移除节点
function removeIt() {
if (editingId != null){
$.messager.alert("提示信息", "请先保存");
return;
}
var node = $('#tg').treegrid('getSelected');
if (node==null)
$.messager.alert("提示信息", "请选择一个节点");
if (node) {
var id=node.id;
var pid=node.pid;
var a;
if(id<=20){
//不可以删除
$.messager.alert("提示信息", "此为系统原生功能,不可以删除");
}else{
//可以删除
if(pid==0){
//删除的为根节点
a=confirm('确定删除此菜单及其子菜单吗');
}else{
//删除的为子节点
a=confirm('确定删除此菜单吗');
}
if(a){
//删除的ajax
var dt="&id="+id+"&pid="+pid;
$.post("deletemenu",dt,function(data){
alert(data);
if(data.endsWith("成功")){
$('#tg').treegrid('remove', node.id);
}
})
}
}
}
}
function collapse() {
var node = $('#tg').treegrid('getSelected');
if (node) {
$('#tg').treegrid('collapse', node.id);
}
}
//展开节点
function expand() {
var node = $('#tg').treegrid('getSelected');
if (node) {
$('#tg').treegrid('expand', node.id);
}
}
//开始编辑
function beginEdit(){
if (editingId != null){
$('#tg').treegrid('cancelEdit', editingId);
$('#tg').treegrid('select', editingId);
editingId = null;
return;
}
var row = $('#tg').treegrid('getSelected');
if (row){
editingId = row.id
$('#tg').treegrid('beginEdit', editingId);
}
}
//保存新增的编辑
function saveEdit(){
if (editingId != null){
var t = $('#tg');
t.treegrid('endEdit', editingId);
$('#tg').treegrid('select', editingId);
var row = $('#tg').treegrid('getSelected');
if(flag==0){
editid=0;
}
var name=row.name;
var urls=row.urls;
var dt="&name="+name+"&urls="+urls+"&pid="+editid;
$.post("addmenu",dt,function(data){
alert(data);
})
editingId = null;
}
}
function cancel(){
if (editingId != undefined){
$('#tg').treegrid('cancelEdit', editingId);
editingId = undefined;
}
$(".actionbtn").toggleClass("l-btn-disabled");
}
</script>
</html>
二、后台:
1、获取表格数据:
(1、)首先需要遵循reasyui treegrid API的规范,实体类有id、pid、children属性。实体类
package com.ifytek.domain;
import java.io.Serializable;
import java.util.ArrayList;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name="menu")
public class Menu implements Serializable{
@Id
int id;
int pid;
String urls;
String name;
@Transient
ArrayList<Menu> children = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getUrls() {
return urls;
}
public void setUrls(String urls) {
this.urls = urls;
}
public ArrayList<Menu> getChildren() {
return children;
}
public void setChildren(ArrayList<Menu> children) {
this.children = children;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Menu() {
super();
// TODO Auto-generated constructor stub
}
public Menu(int id, int pid, String urls, String name) {
//super();
this.id = id;
this.pid = pid;
this.urls = urls;
this.name = name;
}
}
(2、)servlet:
package com.ifytek.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.ifytek.service.MenuService;
import com.ifytek.service.UserService;
@WebServlet("/getmenutree")
public class GetMenuTreeServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
//得到所有菜单
MenuService service=new MenuService();
String menujson=service.getMenuJson();
//System.out.println(menujson);
resp.getWriter().write(menujson);
}
}
(3、)service:
public String getMenuJson() {
MenuDao dao=new MenuDao();
ArrayList<Menu> menus = dao.getMenuJson();
ArrayList<Menu> fmenu = new ArrayList<>();
for (Menu menu : menus) {
if (menu.getPid() == 0) {
// 一级菜单
//System.out.println("..." + menu.getId());
//System.out.println("一级菜单: " + menu.getName());
fmenu.add(menu);
} else {
// 非一级菜单
}
}
for (Menu menu : menus) {
if (menu.getPid() != 0) {
//System.out.println("。。。" + menu.getId());
for (Menu fm : fmenu) {
if (menu.getPid() == fm.getId()) {
fm.getChildren().add(menu);
}
}
}
}
return JSON.toJSONString(fmenu,true);
}
(4、)dao:
public ArrayList<Menu> getMenuJson() {
Session session=HibernateUtil.getSessionFactory().openSession();
String hql = "select new Menu(m.id,m.pid,m.urls,m.name) from Menu m ";
/*String sql = "select Menu(m.id,m.pid,m.urls,m.name) from Menu m left join RoleMenu rm "
+ " on m.id=rm.mid left join LoginRole lr on lr.rid=rm.rid where lr.lid=?";*/
Query query=session.createQuery(hql);
ArrayList<Menu> list= (ArrayList<Menu>) query.list();
//System.out.println("list为"+list);
session.close();
return list;
}
2、新增菜单:我这里简化了一下,只有父级菜单可以添加子菜单,子菜单不可以再添加子菜单:
(1、)servlet:
package com.ifytek.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ifytek.domain.Menu;
import com.ifytek.domain.Message;
import com.ifytek.service.MenuService;
@WebServlet("/addmenu")
public class AddMenuServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("新增菜单");
MenuService service=new MenuService();
String name=req.getParameter("name");
String urls=req.getParameter("urls");
int pid=Integer.parseInt(req.getParameter("pid"));
int id=service.getMenuMaxId();
Menu menu=new Menu();
menu.setId(id+1);
menu.setName(name);
menu.setPid(pid);
menu.setUrls(urls);
Message message=service.addMenu(menu);
resp.getWriter().write(message.getMsg());
}
}
(2、)service:
public Message addMenu(Menu menu) {
MenuDao dao=new MenuDao();
int a=dao.addMenu(menu);
Message message=new Message();
if(a>0){
message.setCode(200);
message.setMsg("添加菜单成功");
message.setRes(true);
}else{
message.setCode(300);
message.setMsg("添加菜单失败");
message.setRes(false);
}
return message;
}
(3、)dao:
public int addMenu(Menu menu) {
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction transaction=session.getTransaction();
int a=-1;
transaction.begin();
try{
session.save(menu);
transaction.commit();
a=1;
}catch (Exception e) {
a=-1;
transaction.rollback();
}
session.close();
return a;
}
3、删除菜单:考虑删除父级菜单和子级菜单两种情况:
(1、)servlet:
package com.ifytek.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ifytek.domain.Message;
import com.ifytek.service.MenuService;
@WebServlet("/deletemenu")
public class DeleteMenu extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
int id=Integer.parseInt(req.getParameter("id"));
int pid=Integer.parseInt(req.getParameter("pid"));
MenuService service=new MenuService();
Message message=service.deleteMenu(id,pid);
resp.getWriter().write(message.getMsg());
}
}
(2、)service:
public Message deleteMenu(int id, int pid) {
MenuDao dao=new MenuDao();
Message message=new Message();
int a=-1;
if(pid==0){
//父级菜单
a=dao.deleteFatherMenu(id);
}else{
//子级菜单
a=dao.deleteMenu(id);
}
if(a>=0){
message.setCode(200);
message.setMsg("删除菜单成功");
message.setRes(true);
}else{
message.setCode(300);
message.setMsg("删除菜单失败");
message.setRes(false);
}
return message;
}
(3、)dao:
//删除子级菜单
public int deleteMenu(int id) {
int a=-1;
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction transaction=session.getTransaction();
transaction.begin();
try{
//删除Menu表
String hql="delete from Menu m where m.id=?";
Query query=session.createQuery(hql);
query.setInteger(0, id);
a=query.executeUpdate();
//删除RoleMenu表
String hql1="delete from RoleMenu r where r.mid=?";
Query query1=session.createQuery(hql1);
query1.setInteger(0, id);
a=query1.executeUpdate();
transaction.commit();
}catch (Exception e) {
transaction.rollback();
a=-1;
}
session.close();
return a;
}
//删除父级菜单
public int deleteFatherMenu(int id) {
int a=-1;
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction transaction=session.getTransaction();
transaction.begin();
try{
//删除RoleMenu表
String hql1="delete from RoleMenu r where r.mid in(select m.id from Menu m where m.id=? or m.pid=?)";
Query query1=session.createQuery(hql1);
query1.setInteger(0, id);
query1.setInteger(1, id);
a=query1.executeUpdate();
System.out.println("删除rolemenu表"+a);
//删除Menu表
String hql="delete from Menu m where m.id=? or m.pid=?";
Query query=session.createQuery(hql);
query.setInteger(0, id);
query.setInteger(1, id);
a=query.executeUpdate();
System.out.println("删除menu表"+a);
transaction.commit();
System.out.println("已提交");
}catch (Exception e) {
transaction.rollback();
a=-1;
}
session.close();
return a;
}