一、準備條件javascript
(1)下載ztree,官網:http://www.ztree.me/css
(2)下載datatable,官網:http://www.datatables.net/html
二、開發java
(1)引入js和css代碼jquery
<%--樹形插件 --%> <link rel="stylesheet" href="${pageContext.request.contextPath}/static/zTree_v3/css/demo.css" type="text/css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/static/zTree_v3/css/zTreeStyle/zTreeStyle.css" type="text/css"> <%-- bootstarp tree Table插件 --%> <link href="${pageContext.request.contextPath}/static/admin/bootstarp/bower_components/datatables-plugins/dataTables.bootstrap.css" rel="stylesheet" /> <script type="text/javascript" src="${pageContext.request.contextPath}/static/admin/bootstarp/bower_components/jquery/dist/jquery.min.js"></script> <%--樹形插件 --%> <script type="text/javascript" src="${pageContext.request.contextPath}/static/zTree_v3/js/jquery.ztree.core-3.5.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/static/zTree_v3/js/jquery.ztree.excheck-3.5.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/static/zTree_v3/js/jquery.ztree.exedit-3.5.js"></script> <%-- bootstarp tree Table插件 --%> <script src="${pageContext.request.contextPath}/static/admin/bootstarp/bower_components/datatables-plugins/jquery.dataTables.js" type="text/javascript"></script> <script src="${pageContext.request.contextPath}/static/admin/bootstarp/bower_components/datatables-plugins/dataTables.bootstrap.js" type="text/javascript"></script>
(2)html代碼ios
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>管理員列表</title> <style type="text/css"> .ztree li span.button.add {margin-left:2px; margin-right: -1px; background-position:-144px 0; vertical-align:top; *vertical-align:middle} </style> </head> <body style="background-color:#fff;"> <form action="" id="tab" name="tab"> <div > <div> <h3>商品類型</h3> <div class="form-group form-inline well"> <div style="height:700px;"> <!-- 顯示屬性插件 --> <div style="height:700px;"> <ul id="treeDemo" style="height:700px;"></ul> </div> <div> <!-- 引入tableData數據 --> <table id="tableData" class="table table-striped table-bordered table-hover"> <thead> <tr> <th>類型名稱</th> <th>上級類型</th> <th>排序</th> <th>狀態</th> <th width="250px">操做</th> </tr> </thead> <tbody> <!-- <tr> <th>商品類型</th> <th>上級類型</th> <th>排序</th> <th>狀態</th> <th>刪除 修改</th> </tr> --> </tbody> </table> </div> </div> </div> </div> </div> <!-- 添加商品類型 --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div> <div> <div> <button type="button" data-dismiss="modal" aria-hidden="true">× </button> <h4 id="myModalLabel">添加商品類型</h4> </div> <div> <div> <label for="name">上級商品類型:</label> <input type="text" class="form-control disabled" id="disabledTextInput" readonly="readonly"> <input type="hidden" name="parentId" class="form-control disabled" id="pid" readonly="readonly"> </div> <div> <label for="name">類型名稱:</label> <input type="text" id="goodsTypeName" name="goodsTypeName" placeholder="請輸入商品類型名稱"> </div> <div> <label for="name">序號:</label> <input type="text" id="sort" name="sort" placeholder="請輸入排序序號"> </div> <div> <label> <input type="radio" name="status" id="optionsRadios3" value="1" checked="checked"> 啓用 </label> <label> <input type="radio" name="status" id="optionsRadios4" value="0"> 禁用 </label> </div> </div> <div> <button id="saveBtn" type="button" class="btn btn-primary">提交更改</button> <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button> </div> </div> </div> </div> </form> </body> <script type="text/javascript"> var setting = { edit: { enable: true }, data: { simpleData: { enable: true } }, callback: { beforeDrag: beforeDrag, beforeRemove: beforeRemove, onRemove: onRemove, /*onRename: onRename,*/ onClick: onClick } }; var zNodes =[ { id:1, pId:0, name:"父節點 1", open:true}, { id:11, pId:1, name:"葉子節點 1-1"}, { id:12, pId:1, name:"葉子節點 1-2"}, { id:13, pId:1, name:"葉子節點 1-3"}, { id:2, pId:0, name:"父節點 2", open:true}, { id:21, pId:2, name:"葉子節點 2-1"}, { id:22, pId:2, name:"葉子節點 2-2"}, { id:23, pId:2, name:"葉子節點 2-3"}, { id:3, pId:0, name:"父節點 3", open:true}, { id:31, pId:3, name:"葉子節點 3-1"}, { id:32, pId:3, name:"葉子節點 3-2"}, { id:33, pId:3, name:"葉子節點 3-3"} ]; setting.edit.showRenameBtn = false; function beforeDrag(treeId, treeNodes) { return true; } function showCode(str) { var code = $("#code"); code.empty(); for (var i=0, l=str.length; i<l; i++) { code.append("<li>"+str[i]+"</li>"); } } /*回調函數*/ /*添加*/ function onClick(e, treeId, treeNode) { $("#disabledTextInput").val(treeNode.name); $("#pid").val(treeNode.id); $('input[name="goodsTypeName"]').val(""); $('input[name="sort"]').val(""); //彈窗口開發 $('#myModal').modal({ keyboard: true }); } /*添加方法*/ $("#saveBtn").click(function(){ var pid = $('input[name="parentId"]').val(); var pName = $('input[name="goodsTypeName"]').val(); var sort = $('input[name="sort"]').val(); var status = $('input[name="status"]:checked').val(); var path = "${path}/admin/goods/saveGoodsType"; $.ajax({ type:"POST", url:path, dataType:"json", contentType: "application/json; charset=utf-8", beforeSend:function(xhr) { xhr.setRequestHeader("If-Modified-Since","0"); xhr.setRequestHeader("Cache-Control","no-cache"); }, data:JSON.stringify({"parentId":pid,"typeName":pName,"sort":sort,"status":status}), //接送格式 beforeSend:function(xhr) { xhr.setRequestHeader("If-Modified-Since","0"); xhr.setRequestHeader("Cache-Control","no-cache"); }, success:function(result) { if(result.status == "success"){ genGoodsTypes(); /*div隱藏*/ $('#myModal').modal('hide') } } }); }); /*移除回調函數*/ function beforeRemove(treeId, treeNode) { return confirm("確認刪除 " + treeNode.name + "嗎?"); } function onRemove(e, treeId, treeNode) { //樹狀Id treeNode.id var path = "${path}/admin/goods/deleteGoodsType/"+treeNode.id; deleteGoodsType(path); } /*拖拽事件*/ function onDrag(e, treeId, treeNodes){ alert(treeNodes); } /*生成表格數據*/ function genTableDatas(result){ $('#tableData').dataTable().fnClearTable(); $('#tableData').dataTable().fnDestroy(); var trs = ""; $.each(result, function(index,n) { trs = trs + "<tr><td class='cs_test edit'>" + n.name + "</td><td>" + n.pname + "</td><td>" + n.sort + "</td><td>"; if(n.status == 1){ trs = trs + "<span class='label label-success'>啓用</span></td>"; }else if(n.status == 0){ trs = trs + "<span class='btn btn-danger btn-xs'>禁用</span>"; } trs = trs + "</td><td>"+ "<a onclick='javascript:editGoodsType(this.name);' class='btn btn-info btn-xs' name='${path}/admin/goods/updateGoodsType/"+n.id+"'><i class='fa fa-pencil'></i> 修改</a> "+ "<a onclick='javascript:deleteGoodsType(this.name);' class='btn btn-danger btn-xs' name='${path}/admin/goods/deleteGoodsType/"+ n.id +"'><i class='fa fa-trash'></i> 刪除</a>"+ "</td></tr>"; }); $("#tableData tbody").html(trs); /*生成表格列表*/ $("#tableData").dataTable({ retrieve: true, paging: true, //分頁 ordering: true, //是否啓用排序 searching: true, //搜索 pageLength: 15, //首次加載的數據條數 bLengthChange: false,//屏蔽tables的一頁展現多少條記錄的下拉列表 language: { search: '<button type="button" class="btn btn-success btn-sm"><i class="fa fa-search"></i> 搜索:</button>',//右上角的搜索文本,能夠寫html標籤 paginate: {//分頁的樣式內容。 previous: "<<", next: ">>", first: "首頁", last: "尾頁" }, zeroRecords: "<font color='red'>沒有記錄...</font>",//table tbody內容爲空時,tbody的內容。 //下面三者構成了整體的左下角的內容。 info: "總共_PAGES_ 頁",//左下角的信息顯示,大寫的詞爲關鍵字。 infoEmpty: "0條記錄",//篩選爲空時左下角的顯示。 infoFiltered: ""//篩選以後的左下角篩選提示, }, paging: true, pagingType: "full_numbers",//分頁樣式的類型 }); } /*生成全部樹*/ function genGoodsTypes(){ var url = "${path}/admin/goods/showGoodsTypes" $.ajax({ type:"POST", url:url, dataType:"json", beforeSend:function(xhr) { xhr.setRequestHeader("If-Modified-Since","0"); xhr.setRequestHeader("Cache-Control","no-cache"); }, success:function(result) { if(result.data.length != 0){ /*初始化樹*/ $.fn.zTree.init($("#treeDemo"), setting, result.data); /*生成表格數據*/ genTableDatas(result.data); } } }); } /*修改商品類型*/ function editGoodsType(path){ $("#tab").attr("action",path); $("#tab").submit(); } /*刪除商品類型*/ function deleteGoodsType(path){ $.ajax({ type:"POST", url:path, dataType:"json", beforeSend:function(xhr) { xhr.setRequestHeader("If-Modified-Since","0"); xhr.setRequestHeader("Cache-Control","no-cache"); }, success:function(result) { if(result.status == "success"){ genGoodsTypes(); } } }); } $(document).ready(function(){ genGoodsTypes(); }); </script> </html>
(3)部分java代碼web
controller層代碼ajax
package com.xtxq.controller.goods; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.xtxq.common.SystemConstants; import com.xtxq.controller.base.BaseController; import com.xtxq.domain.goods.GoodsProperty; import com.xtxq.domain.goods.GoodsType; import com.xtxq.domain.goods.GoodsTypeProperty; import com.xtxq.service.goods.GoodsInfoService; import com.xtxq.service.goods.GoodsPropertyService; import com.xtxq.service.goods.GoodsTypePropertyService; import com.xtxq.service.goods.GoodsTypeService; /** * * @ClassName: GoodsTypeController * @Description: TODO(商品分類) * @author zwcheng 1054900400@qq.com * @date 2016年1月7日 下午8:47:36 * */ @Controller @RequestMapping("/admin/goods/") public class GoodsTypeController extends BaseController<GoodsType>{ private Logger logger = Logger.getLogger(GoodsTypeController.class); @Autowired private GoodsInfoService goodsInfoService ; @Autowired private GoodsPropertyService goodsPropertyService ; @Autowired private GoodsTypeService goodsTypeService ; @Autowired private GoodsTypePropertyService goodsTypePropertyService ; /** * 重定向路徑 */ private static String REDIRECT_PATH = "redirect:/admin/goods/goodsTypeList"; /** * 獲取子分類 * @param id * @param response * @return * @throws Exception */ @ResponseBody @RequestMapping(value="goodsInfo/getChildGoodsType/{id}",produces = "text/html;charset=UTF-8") public String getChildGoodsType(@PathVariable String id,HttpServletResponse response) throws Exception{ System.out.println(id); List<GoodsType> list = goodsTypeService.getChildrens(id) ; String msg = JSON.toJSONString(list) ; return msg ; } /** * 經過商品子類別查看該子類下面的全部公共屬性 * @param typeId * @param response * @return * @throws Exception */ @ResponseBody @RequestMapping(value="goodsInfo/getPropertyByTypeId/{typeId}",produces = "text/html;charset=UTF-8") public String getPropertyByTypeId(@PathVariable String typeId,HttpServletResponse response) throws Exception { List<GoodsTypeProperty> list = goodsTypePropertyService.getPropertyByTypeId(typeId); List<GoodsProperty> goodsProperties = new ArrayList<GoodsProperty>(); for(GoodsTypeProperty goodsTypeProperty:list) { GoodsProperty property = new GoodsProperty() ; String src= goodsTypeProperty.getPropertySrc() ; String[] values = goodsInfoService.splitPath(src) ; property = goodsTypeProperty.getGoodsProperty() ; goodsProperties.add(property) ; for(String value:values) { goodsProperties.add(goodsPropertyService.getById(value)) ; } } String msg = JSON.toJSONString(goodsProperties) ; System.out.println(msg); return msg ; } @RequestMapping(value="goodsTypeList") public String listGoodsType()throws Exception{ return genGoodsTypePath("goodsTypeList"); } /** * 顯示全部商品 * @return * @throws Exception */ @RequestMapping(value="showGoodsTypes",method=RequestMethod.POST) @ResponseBody public String showGoodsTypes() throws Exception { JSONObject json = new JSONObject(); JSONArray jsons = new JSONArray(); try { this.goodsTypeService.getAllChildsGoodsTypes("0", jsons); //頂級商品類型 json.put("data", jsons); } catch (Exception e) { this.logger.error("範問商品類型發生異常。。。"); } return json.toJSONString(); } /** * 刪除 */ @RequestMapping(value="deleteGoodsType/{id}",method=RequestMethod.POST) @ResponseBody public String deleteGoodsType(@PathVariable String id) throws Exception{ Map<String,Object> maps = new HashMap<String, Object>(); try { goodsTypeService.deleteGoodsType(id); maps = ajaxJsonMessage("success","刪除商品類型成功!"); } catch (Exception e) { logger.error("刪除發生錯誤!"); e.printStackTrace(); maps = ajaxJsonMessage("fail","刪除商品失敗!"); } return JSONObject.toJSONString(maps); } /** * 保存商品類型 * @param goodsType * @return * @throws Exception */ @RequestMapping(value="saveGoodsType",method=RequestMethod.POST) @ResponseBody public String saveGoodsType(@RequestBody GoodsType goodsType) throws Exception{ Map<String,Object> maps = new HashMap<String, Object>(); try { goodsTypeService.add(goodsType); maps = ajaxJsonMessage("success","添加商品類型成功!"); } catch (Exception e) { logger.error("添加商品類型發生錯誤!"); e.printStackTrace(); maps = ajaxJsonMessage("fail","添加商品失敗!"); } return JSONObject.toJSONString(maps); } /** * 修改商品類型頁面 */ @RequestMapping(value="updateGoodsType/{id}",method=RequestMethod.GET) public String editGoodsType(@PathVariable String id,Model model) throws Exception{ GoodsType goodsType = goodsTypeService.getById(id); GoodsType pgoodsType = goodsTypeService.getById(goodsType.getParentId()); goodsType.setPname(pgoodsType.getTypeName()); model.addAttribute("goodsType", goodsType); return genGoodsTypePath("editGoodsType"); } @RequestMapping(value="updateGoodsType",method=RequestMethod.POST) public String editGoodsType(GoodsType goodsType) throws Exception{ GoodsType goodsType_db = goodsTypeService.getById(goodsType.getId()); goodsType_db.setStatus(goodsType.getStatus()); goodsType_db.setSort(goodsType.getSort()); goodsType_db.setTypeName(goodsType.getTypeName()); goodsTypeService.update(goodsType_db); return REDIRECT_PATH; } /** * 生成商品類型路徑 * @param path * @return */ private String genGoodsTypePath(String path){ return SystemConstants.GoodsTypeConstant.GOODS_TYPE_ROOT_PATH + path; } }
service層代碼(涉及到遞歸方法)spring
package com.xtxq.service.impl.goods; import java.util.List; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.xtxq.basic.SystemException; import com.xtxq.basic.SystemPager; import com.xtxq.dao.goods.GoodsTypeMapper; import com.xtxq.domain.goods.GoodsType; import com.xtxq.domain.goods.GoodsTypeExample; import com.xtxq.service.goods.GoodsTypeService; import com.xtxq.utils.UUIDUtils; /** * @ClassName: GoodsTypeServiceImpl * @Description: TODO(商品分類的業務邏輯實現) * @author zwcheng 1054900400@qq.com * @date 2016年1月7日 下午8:50:03 */ @Service public class GoodsTypeServiceImpl implements GoodsTypeService{ @Autowired private GoodsTypeMapper goodsTypeDao; /** * 儲存商品大類 */ public void add(GoodsType t) throws Exception { GoodsType goodsType2 = getByName(t.getTypeName()); if(null != goodsType2){ throw new SystemException("這個商品的類型名稱已經存在!"); } t.setId(UUIDUtils.genUUID()); //生成主鍵 goodsTypeDao.insert(t); } /** * 刪除商品大類 */ public void deleteById(String id) throws Exception { goodsTypeDao.deleteByPrimaryKey(id); } /** * 更新商品大類 */ public void update(GoodsType t) throws Exception { goodsTypeDao.updateByPrimaryKey(t) ; } /** * 按照商品類別的id查詢 */ public GoodsType getById(String id) throws Exception { if(id!="" && id != null) { return goodsTypeDao.selectByPrimaryKey(id); } else { return null ; } } /** * 按照商品大類的姓名去查詢 */ public GoodsType getByName(String name) throws Exception { //按照名稱查找 GoodsTypeExample example = new GoodsTypeExample(); GoodsTypeExample.Criteria criteria = example.createCriteria(); criteria.andTypeNameEqualTo(name); List<GoodsType> goodsTypeList = goodsTypeDao.selectByExample(example); if(null != goodsTypeList && !goodsTypeList.isEmpty()){ return goodsTypeList.get(0); } return null; } /** *獲取全部的分類 */ public List<GoodsType> list() throws Exception { GoodsTypeExample example = new GoodsTypeExample() ; return goodsTypeDao.selectByExample(example); } /** * 分頁獲取全部的商品類型 */ public List<GoodsType> findNotices(int currentpage) throws Exception { GoodsTypeExample goodsTypeExample = new GoodsTypeExample() ; goodsTypeExample.setLimitStart(currentpage-1); goodsTypeExample.setLimitEnd(SystemPager.getPagesize()); List<GoodsType> list = goodsTypeDao.selectByExample(goodsTypeExample) ; return list; } /** * 獲取全部類型的計數 */ public int getCount() throws Exception { GoodsTypeExample example = new GoodsTypeExample() ; return goodsTypeDao.countByExample(example) ; } /** * 判斷是否有子節點 */ public boolean hasChildren(String id) throws Exception { int count = goodsTypeDao.hasChildren(id) ; if(count>0) { return true ; }else { return false ; } } /** * 獲取全部的大類 */ public List<GoodsType> getGoodsTypes() throws Exception{ return goodsTypeDao.getGoodsTypes() ; } /** * 得到某一個大類下面的全部子類 */ public List<GoodsType> getChildrens(String id) throws Exception{ GoodsTypeExample example = new GoodsTypeExample(); GoodsTypeExample.Criteria criteria = example.createCriteria(); System.out.println(id); criteria.andParentIdEqualTo(id); List<GoodsType> goodsTypeList = goodsTypeDao.selectByExample(example); if(goodsTypeList!=null) { return goodsTypeList; } else { return null ; } } /** * 經過父親Id獲取商品類型 * @param pid 父親Id * @return * @throws Exception */ public List<GoodsType> getChildsGoodsTypes(String pid) throws Exception{ GoodsTypeExample goodsTypeExample = new GoodsTypeExample(); GoodsTypeExample.Criteria criteria = goodsTypeExample.createCriteria(); criteria.andParentIdEqualTo(pid); return this.goodsTypeDao.selectByExample(goodsTypeExample); } public JSONArray getChildsGoodsTypes(String pid, JSONArray jsons) throws Exception { List<GoodsType> childs = getChildsGoodsTypes(pid); GoodsType pgoodsType = getById(pid); for (GoodsType goodsType : childs) { JSONObject jsonObject = new JSONObject(); jsonObject.put("id", goodsType.getId()); jsonObject.put("pId", pid); jsonObject.put("name", goodsType.getTypeName()); jsonObject.put("pname", pgoodsType.getTypeName()); jsonObject.put("sort", goodsType.getSort()); jsonObject.put("status", goodsType.getStatus()); jsonObject.put("open", Boolean.valueOf(true)); jsons.add(jsonObject); } return jsons; } /** * 獲取全部商品類型 * @param pid * @param jsons * @return * @throws Exception */ public JSONArray getAllChildsGoodsTypes(String pid, JSONArray jsons) throws Exception{ List<GoodsType> childs = getChildsGoodsTypes(pid); if ((childs != null) && (!childs.isEmpty())) for (GoodsType goodsType : childs) { jsons = getChildsGoodsTypes(goodsType.getId(), jsons); getAllChildsGoodsTypes(goodsType.getId(), jsons); } else { jsons = getChildsGoodsTypes(pid, jsons); } return jsons; } /** * 經過Id刪除全部商品(遞歸刪除) * @param id 主鍵 * @throws Exception */ public void deleteGoodsType(String id) throws Exception{ //TODO 查詢全部與商品類型關聯表 //遞歸刪除全部子節點 List<GoodsType> coodsTypes = getChildsGoodsTypes(id); if(null != coodsTypes && !coodsTypes.isEmpty()){ for(GoodsType goodsType : coodsTypes){ deleteGoodsType(goodsType.getId()); deleteById(goodsType.getId()); } }else{ deleteById(id); } deleteById(id); //刪除 } }
三、運行後效果圖apache