EasyUI基于easyUI实现权力管理体系(二)——菜单导航

此文章是根据  EasyUI+Knockout实现藏表单的查、编辑

 

一. 系文书介绍

  1. menu.jsp:菜单导航主界面

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>菜单导航</title>
    <%@ include file="/common/head.jsp"%>
 </head>
 <body>
     <div class="toolbar">
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-arrow_refresh" title="刷新" data-bind="click:refreshClick">刷新</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-add" title="新增" data-bind="click:addClick">新增</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-edit" title="编辑" data-bind="click:editClick">编辑</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-cross" title="删除" data-bind="click:deleteClick">删除</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-save" title="保存" data-bind="click:saveClick">保存</a>       
    </div>

    <table id="gridlist" data-bind="treegrid:grid">
        <thead>  
            <tr>  
                <th field="id"  hidden="true"></th>  
                <th field="menuName"    align="left"        width="150" editor="{type:'validatebox',options:{required: true }}">菜单名称   </th>  
                <th field="parentId"  align="left"        width="150"  editor="combotree" formatter="formatterParent">上级菜单   </th>
                <th field="iconClass"   align="left"        width="180" editor="{type:'lookup'}">图标     </th> 
                <th field="url"         align="left"        width="180" editor="text">链接地址   </th> 
                <th field="isVisible"   align="center"      width="60" editor="{type: 'checkbox',options: {on: 1,off: 0}}" formatter="formatterEnable" >是否可见</th> 
                <th field="isEnable"    align="center"      width="60" editor="{type: 'checkbox',options: {on: 1,off: 0}}" formatter="formatterEnable" >是否启用</th> 
                <th field="menuSeq"     align="right"       width="50"  editor="text">排序</th> 
                <th field="button"      align="center"      width="100" formatter="formatterButton">页面按钮 </th> 
            </tr>                            
        </thead>      
    </table>

    <script type="text/html" id="button-template">
        <div style="margin:5px;height:320px;overflow:auto;">
            <style type="text/css">
                .listview{ margin:0 !important;}
                .listview li{width:100px !important;background-color:#ECECFF !important;float:left;margin:3px;overflow:hidden;}
                .listview span{ font-size:14px !important;height:auto !important; white-space: nowrap;}
                .listview .icon:before{content:"" !important}
            </style>

            <div style="border-bottom:1px solid #CCC; margin-bottom:5px;">
                请选择页面按钮 
            </div>

            <div class="metrouicss">
                <label class="input-control checkbox" style="margin-top:6px;margin-left:3px;">
                    <input type="checkbox" data-bind="checked:checkAll">全选
                </label>
                <button class="image-button standart fg-color-white" style="float:right" data-bind="click:manageClick">
                    <i class="icon-grid-view bg-color-green"></i>
                    管理按钮库
                </button>
                <ul class="listview" data-bind="foreach: buttons" style="clear:both">
                    <li data-bind="click:$parent.buttonClick,css:{selected:selected()>0}"></li>
                </ul>
            </div> 
        </div>
        <div style="text-align:center;">
            <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" data-bind="click:confirmClick" href="javascript:void(0)"  >确定</a>  
            <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" data-bind="click:cancelClick" href="javascript:void(0)">取消</a> 
        </div>
    </script>

    <script type="text/html" id="manage-template">
        <style type="text/css">
            .datagrid-wrap{border-width:0 0 1px 0;}
            .datagrid-toolbar{background-color:#E0ECFF !important}
        </style>

        <table data-bind="datagrid:grid">
            <thead>
                <th field="id"  hidden="true"></th>
                <th field="buttonCode"    align="left" editor="{type:'validatebox',options:{required:true}}"    width="80"  >编码   </th>  
                <th field="buttonName"    align="left" editor="{type:'validatebox',options:{required:true}}"    width="70"  >名称   </th>  
                <th field="buttonIcon"    align="left" editor="{type:'validatebox',options:{required:true}}"    width="120" >图标   </th> 
                <th field="buttonSeq"     align="left" editor="text"    width="50"  >排序   </th> 
                <th field="description"   align="left" editor="text"    width="200" >备注说明   </th> 
            </thead>
        </table>

        <div style="text-align:center;margin:5px;">
            <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" data-bind="click:confirmClick" href="javascript:void(0)"  >确定</a>  
            <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" data-bind="click:cancelClick" href="javascript:void(0)">取消</a> 
        </div>
    </script> 

    <%@ include file="/common/foot.jsp"%>
    <script src="viewModel/sys/menu.js"></script>
    <script type="text/javascript">
        using(['lookup', 'numberspinner'], easyuifix.datagrid_editor_extend);
        ko.bindingViewModel(new viewModel());
        using(['validatebox','combotree','dialog','messager']);
        var formatterEnable = function (value,row) {return '<img src="content' + ((value||'').toString()=="1" ? "checkmark.gif" : "checknomark.gif") + '"/>';};
        var formatterParent = function (value, row) { return row.parentName };
        var formatterButton = function (value, row) { return (row.url&&row.url!='#')?'<a href="javascript:;" onclick="setButton(\'' + row.id + '\')">&nbsp;[设置按钮]</a>':''; };
    </script>
 </body>
</html>

View Code

  

  2. menu.js:实现菜单导航功能、列表,设置按钮功能

function viewModel() {
    var self = this;

    this.editClick = function () {
        var row = self.grid.treegrid('getSelected');
        if (row) {
            //取得父节点数据
            var treeData = JSON.parse(JSON.stringify(self.grid.treegrid('getData')).replace(/menuName/g, "text"));
            treeData.unshift({ "id": 0, "text": "" });

            //设置上级菜单下拉树
            var gridOpt = $.data(self.grid.$element()[0], "datagrid").options;
            var col = $.grep(gridOpt.columns[0], function (n) { return n.field == 'parentId' })[0];
            col.editor = { type: 'combotree', options: { data: treeData } };
            col.editor.options.onBeforeSelect = function (node) {
                var isChild = utils.isInChild(treeData, row.id, node.id);
                com.messageif(isChild, 'warning', '不能将自己或下级设为上级节点');
                return !isChild;
            };

            //开始编辑行数据
            self.grid.treegrid('beginEdit', row.id);
            self.edit_id = row.id;
            var eds = self.grid.treegrid('getEditors', row.id);
            var edt = function (field) { return $.grep(eds, function (n) { return n.field == field })[0]; };
            self.afterCreateEditors(edt);
        }
    };

    this.grid = {
        size: { w: 4, h: 40 },
        url: rootPath+'/sys/menu!getAll.do',
        idField: 'id',
        queryParams: ko.observable(),
        treeField: 'menuName',
        loadFilter: function (d) {
            d = utils.copyProperty(d.rows || d, ["iconClass"], ["iconCls"], false);
            return utils.toTreeData(d, 'id', 'parentId', "children");
        } 
    };

    this.grid.onClickRow = function () {
        var edit_id = self.edit_id;
        if (!!edit_id) {
            if (self.grid.treegrid('validateRow', edit_id)) { //通过验证
                self.grid.treegrid('endEdit', edit_id);
                self.edit_id = undefined;
            }
            else { //未通过验证
                self.grid.treegrid('select', edit_id);
                return false;
            }
        }
        return true;
    };

    this.grid.onDblClickRow = self.editClick;

    this.grid.OnBeforeDestroyEditor = function (editors, row) {
        row.parentName = editors['parentId'].target.combotree('getText');
        row.iconClass = editors["iconClass"].target.lookup('textbox').val();
    };

    this.refreshClick = function () {
        window.location.reload();
    };

    this.addClick = function () {
        if (self.grid.onClickRow()) {
            var row = { id: '0', menuName:''};
            self.grid.treegrid('append', { parent: '', data: [row] });
            self.grid.treegrid('select', row.id);
            self.grid.$element().data("datagrid").insertedRows.push(row);
            self.editClick();
        }
    };

    this.afterCreateEditors = function (editors) {
        var iconInput = editors("iconClass").target;
        var onShowPanel = function () {
            iconInput.lookup('hidePanel');
            com.dialog({
                title: "&nbsp;选择图标",
                iconCls: 'icon-node_tree',
                width: 700,
                height: 500,
                url: rootPath+"/view/sys/icon.html",
                viewModel: function (w) {
                    w.find('#iconlist').css("padding", "5px");
                    w.find('#iconlist li').attr('style', 'float:left;border:1px solid #fff; line-height:20px; margin-right:4px;width:16px;cursor:pointer')
                     .click(function () {
                         iconInput.lookup('setValue',$(this).find('span').attr('class').split(" ")[1]);
                         w.dialog('close');
                     }).hover(function () {
                         $(this).css({ 'border': '1px solid red' });
                     }, function () {
                         $(this).css({ 'border': '1px solid #fff' });
                     });
                }
            });
        };
        iconInput.lookup({ customShowPanel: true, onShowPanel: onShowPanel, editable: true });
        iconInput.lookup('resize', iconInput.parent().width());
        iconInput.lookup('textbox').unbind();
    };

    this.deleteClick = function () {
        var row = self.grid.treegrid('getSelected');
        if (row) {
            var childNodes = self.grid.treegrid('getChildren', row.id);
            if(childNodes.length>0){
                com.message('warning', '请先删除子菜单!');
                return;
            }
            self.grid.$element().treegrid('remove', row.id);
            self.grid.$element().data("datagrid").deletedRows.push(row);
        }
    };

    this.saveClick = function () {
        self.grid.onClickRow();
        var post = {};
        post.list = new com.editTreeGridViewModel(self.grid).getChanges(['id', 'menuName', 'parentId', 'iconClass', 'url', 'isVisible', 'isEnable', 'menuSeq']);
        if (self.grid.onClickRow() && post.list._changed) {
            com.ajax({
                url: rootPath+'/sys/menu!edit.do',
                contentType: 'application/json',
                data: ko.toJSON(post),
                success: function (d) {
                    com.message('success', '保存成功!');
                    self.grid.treegrid('acceptChanges');
                    self.grid.queryParams({});
                }
            });
        }
    };
}


var setButton = function (menuId) {
    com.dialog({
        title: "设置按钮",
        width: 555,
        height: 400,
        html: "#button-template",
        viewModel: function (w) {
            var self = this;
            com.loadCss(rootPath+'/content/css/metro/css/modern.css', parent.document);
            this.buttons = ko.observableArray();
            this.refresh = function () {
                com.ajax({
                    url: rootPath+'/sys/button!getMenuButtons.do?menuId=' + menuId,
                    type: 'GET',
                    async: false,
                    success: function (d) {
                        self.buttons(ko.mapping.fromJS(d)());
                    }
                });
            };
            this.refresh();
            this.checkAll = ko.observable(false);
            this.checkAll.subscribe(function (value) {
                $.each(self.buttons(), function () {
                    this.selected(value ? 1 : 0);
                });
            });
            this.buttonClick = function (row) {
                row.selected(row.selected() ? 0 : 1);
            };
            this.confirmClick = function () {
                var data = utils.filterProperties($.grep(self.buttons(), function (row) {
                    return row.selected() > 0;
                }), ['id']);
                com.ajax({
                    url: rootPath+'/sys/button!editMenuButtons.do?menuId=' + menuId,
                    data: ko.toJSON(data),
                    success: function (d) {
                        com.message('success', '保存成功!');
                        self.cancelClick();
                    }
                });
            };
            this.manageClick = function () {
                com.dialog({
                    title: "管理按钮库",
                    width: 600,
                    height: 410,
                    html: "#manage-template",
                    viewModel: function (w_sub) {
                        var that = this;
                        this.grid = {
                            width: 586,
                            height: 340,
                            pagination: false,
                            pageSize: 10,
                            url: rootPath+"/sys/button!getButtons.do",
                            queryParams: ko.observable()
                        };
                        this.cancelClick = function () {
                            w_sub.dialog('close');
                        };
                        this.gridEdit = new com.editGridViewModel(this.grid);
                        this.grid.OnAfterCreateEditor =