系统后台的左侧菜单的使用解释

超级管理员后台的界面结构说明

表象

左侧菜单普通

先来看左侧这个导航条是怎么来的?

让我们点击后台菜单看看 (这里原先是菜单管理,为了更好的区分我设置成了后台菜单)
点击右侧列表中的系统 我们就可以看到下面的界面 为了更好的说明问题 我对属性管理的分组做了去除操作
大家可以通过查看这里的设置来配置新的菜单


左侧菜单对比说明

超级管理员的后台操作就是如此形成的,当大家在新建后台时就可以不用做太大的修改即可轻松的搞定模板
下面是一个模板展示 OT的Public/base模板的结构 将会对部分内容给大家作一些说明

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{$meta_title}|{:C('TIPINFO')}管理平台</title>
    <link href="__ROOT__/Public/favicon.ico" type="image/x-icon" rel="shortcut icon">
    <link rel="stylesheet" type="text/css" href="__CSS__/base.css" media="all">
    <link rel="stylesheet" type="text/css" href="__CSS__/common.css" media="all">
    <link rel="stylesheet" type="text/css" href="__CSS__/module.css">
    <link rel="stylesheet" type="text/css" href="__CSS__/style.css" media="all">
    <link rel="stylesheet" type="text/css" href="__CSS__/{$Think.config.COLOR_STYLE}.css" media="all">
     <!--[if lt IE 9]>
    <script type="text/javascript" src="__STATIC__/jquery-1.10.2.min.js"></script>
    <![endif]--><!--[if gte IE 9]><!-->
    <script type="text/javascript" src="__STATIC__/jquery-2.0.3.min.js"></script>
    <script type="text/javascript" src="__JS__/jquery.mousewheel.js"></script>
    <!--<![endif]-->
    <block name="style"></block>
</head>
<body>
    <!-- 头部 -->
    <div class="header">
        <!-- Logo -->
        <span class="logo"></span>
        <!-- /Logo -->

        <!-- 主导航 -->
        <ul class="main-nav">
            <volist name="__MENU__.main" id="menu">
                <li class="{$menu.class|default=''}"><a href="{$menu.url|U}">{$menu.title}</a></li>
            </volist>
        </ul>
        <!-- /主导航 -->

        <!-- 用户栏 -->
        <div class="user-bar">
            <a href="javascript:;" class="user-entrance"><i class="icon-user"></i></a>
            <ul class="nav-list user-menu hidden">
                <li class="manager">你好,<em title="{:session('user_auth.username')}">{:session('user_auth.username')}</em></li>
                <li><a href="{:U('User/updatePassword')}">修改密码</a></li>
                <li><a href="{:U('User/updateNickname')}">修改昵称</a></li>
                <li><a href="{:U('Public/logout')}">退出</a></li>
            </ul>
        </div>
    </div>
    <!-- /头部 -->

    <!-- 边栏 -->
    <div class="sidebar">
        <!-- 子导航 -->
        <block name="sidebar">
            <div id="subnav" class="subnav">
                <notempty name="_extra_menu">
                    {// 动态扩展菜单 //}
                    {:extra_menu($_extra_menu,$__MENU__)} 
                </notempty>
  <!-- 哈哈 这里开始就是左侧菜单啦。。。。。 -->
                <volist name="__MENU__.child" id="sub_menu">
                    <!-- 子导航 -->
                    <notempty name="sub_menu">
                        <notempty name="key"><h3><i class="icon icon-unfold"></i>{$key}</h3></notempty>
                        <ul class="side-sub-menu">
                            <volist name="sub_menu" id="menu">
                                <li>
                                    <a class="item" href="{$menu.url|U}">{$menu.title}</a>
                                </li>
                            </volist>
                        </ul>
                    </notempty>
                    <!-- /子导航 -->
                </volist>
            </div>
        </block>
        <!-- /子导航 -->
    </div>
    <!-- /边栏 -->

    <!-- 内容区 -->
    <div id="main-content">
        <div id="top-alert" class="fixed alert alert-error" style="display: none;">
            <button class="close fixed" style="margin-top: 4px;">&times;</button>
            <div class="alert-content">这是内容</div>
        </div>
        <div id="main" class="main">
            <block name="nav">
            <!-- nav -->
            <notempty name="_show_nav">
            <div class="breadcrumb">
                <span>您的位置:</span>
                <assign name="i" value="1" />
                <foreach name="_nav" item="v" key="k">
                    <if condition="$i eq count($_nav)">
                    <span>{$v}</span>
                    <else />
                    <span><a href="{$k}">{$v}</a>&gt;</span>
                    </if>
                    <assign name="i" value="$i+1" />
                </foreach>
            </div>
            </notempty>
            <!-- nav -->
            </block>

            <block name="body"> </block>
        </div>
        <div class="cont-ft">
            <div class="copyright">
                <div class="fl">感谢使用<a href="http://www.bluemark.cn" target="_blank">{:C('TIPINFO')}</a></div>
                <div class="fr">V{$Think.const.BP_VERSION}</div>
            </div>
        </div>
    </div>
    <!-- /内容区 -->
    <script type="text/javascript">
    (function(){
        var ThinkPHP = window.Think = {
            "ROOT"   : "__ROOT__", //当前网站地址
            "APP"    : "__APP__", //当前项目地址
            "PUBLIC" : "__PUBLIC__", //项目公共目录地址
            "DEEP"   : "{:C('URL_PATHINFO_DEPR')}", //PATHINFO分割符
            "MODEL"  : ["{:C('URL_MODEL')}", "{:C('URL_CASE_INSENSITIVE')}", "{:C('URL_HTML_SUFFIX')}"],
            "VAR"    : ["{:C('VAR_MODULE')}", "{:C('VAR_CONTROLLER')}", "{:C('VAR_ACTION')}"]
        }
    })();
    </script>
    <script type="text/javascript" src="__STATIC__/think.js"></script>
    <script type="text/javascript" src="__JS__/common.js"></script>
    <script type="text/javascript">
        +function(){
            var $window = $(window), $subnav = $("#subnav"), url;
            $window.resize(function(){
                $("#main").css("min-height", $window.height() - 80);
            }).resize();

            /* 左边菜单高亮 */
            url = window.location.pathname + window.location.search;
            url = url.replace(/(\/(p)\/\d+)|(&p=\d+)|(\/(id)\/\d+)|(&id=\d+)|(\/(group)\/\d+)|(&group=\d+)/, "");
            $subnav.find("a[href='" + url + "']").parent().addClass("current");

            /* 左边菜单显示收起 */
            $("#subnav").on("click", "h3", function(){
                var $this = $(this);
                $this.find(".icon").toggleClass("icon-fold");
                $this.next().slideToggle("fast").siblings(".side-sub-menu:visible").
                      prev("h3").find("i").addClass("icon-fold").end().end().hide();
            });

            $("#subnav h3 a").click(function(e){e.stopPropagation()});

            /* 头部管理员菜单 */
            $(".user-bar").mouseenter(function(){
                var userMenu = $(this).children(".user-menu ");
                userMenu.removeClass("hidden");
                clearTimeout(userMenu.data("timeout"));
            }).mouseleave(function(){
                var userMenu = $(this).children(".user-menu");
                userMenu.data("timeout") && clearTimeout(userMenu.data("timeout"));
                userMenu.data("timeout", setTimeout(function(){userMenu.addClass("hidden")}, 100));
            });

            /* 表单获取焦点变色 */
            $("form").on("focus", "input", function(){
                $(this).addClass('focus');
            }).on("blur","input",function(){
                        $(this).removeClass('focus');
                    });
            $("form").on("focus", "textarea", function(){
                $(this).closest('label').addClass('focus');
            }).on("blur","textarea",function(){
                $(this).closest('label').removeClass('focus');
            });

            // 导航栏超出窗口高度后的模拟滚动条
            var sHeight = $(".sidebar").height();
            var subHeight  = $(".subnav").height();
            var diff = subHeight - sHeight; //250
            var sub = $(".subnav");
            if(diff > 0){
                $(window).mousewheel(function(event, delta){
                    if(delta>0){
                        if(parseInt(sub.css('marginTop'))>-10){
                            sub.css('marginTop','0px');
                        }else{
                            sub.css('marginTop','+='+10);
                        }
                    }else{
                        if(parseInt(sub.css('marginTop'))<'-'+(diff-10)){
                            sub.css('marginTop','-'+(diff-10));
                        }else{
                            sub.css('marginTop','-='+10);
                        }
                    }
                });
            }
        }();
    </script>
    <block name="script"></block>
</body>
</html>

左侧菜单的生成就是通过

                <volist name="__MENU__.child" id="sub_menu">
                    <!-- 子导航 -->
                    <notempty name="sub_menu">
                        <notempty name="key"><h3><i class="icon icon-unfold"></i>{$key}</h3></notempty>
                        <ul class="side-sub-menu">
                            <volist name="sub_menu" id="menu">
                                <li>
                                    <a class="item" href="{$menu.url|U}">{$menu.title}</a>
                                </li>
                            </volist>
                        </ul>
                    </notempty>
                    <!-- /子导航 -->
                </volist>

通过这里可以看到官方在构建OneThink时候也是下了很大的功夫的。

原理跟踪

至于官方是如何生成tree 并获取到的可以通过对extra_menu这个方法进行debug来查看
这个方法的位置是 /Application/Admin/Common/function.phg 第253行
朱亚杰也对这个方法做了简单说明,但最主要的还是那个tree的生成。那么$__MENU__参数是在哪里设置的呢?
可以参见 /Application/Admin/Controller/AdminController.class.php 第65行
这里的get_menu方法便是这个东东了

动态扩展(假的啊)

大家在看代码的时候会看到这样的东东

 {// 动态扩展菜单 //}
{:extra_menu($_extra_menu,$__MENU__)} 

咦,这个东东是做什么用的?
让我们再来看个别的图

内容区域的左侧导航配置
内容左侧实际情况

哈哈 傻眼了吧,我刚开始的时候看到这里的也是傻了。这里是怎么弄的呢?
看程序源码吧

#Application\Admin\Controller\ArticleController.class.php 第154行   
        $this->getMenu();
#然后查看getMenu()内容
    /**
     * 显示左边菜单,进行权限控制
     * @author huajie <banhuajie@163.com>
     */
    protected function getMenu(){
        //获取动态分类
        $cate_auth  =   AuthGroupModel::getAuthCategories(UID); //获取当前用户所有的内容权限节点
        $cate_auth  =   $cate_auth == null ? array() : $cate_auth;
        $cate       =   M('Category')->where(array('status'=>1))->field('id,title,pid,allow_publish')->order('pid,sort')->select();

        //没有权限的分类则不显示
        if(!IS_ROOT){
            foreach ($cate as $key=>$value){
                if(!in_array($value['id'], $cate_auth)){
                    unset($cate[$key]);
                }
            }
        }

        $cate           =   list_to_tree($cate);    //生成分类树

        //获取分类id
        $cate_id        =   I('param.cate_id');
        $this->cate_id  =   $cate_id;

        //是否展开分类
        $hide_cate = false;
        if(ACTION_NAME != 'recycle' && ACTION_NAME != 'draftbox' && ACTION_NAME != 'mydocument'){
            $hide_cate  =   true;
        }

        //生成每个分类的url
        foreach ($cate as $key=>&$value){
            $value['url']   =   'Article/index?cate_id='.$value['id'];
            if($cate_id == $value['id'] && $hide_cate){
                $value['current'] = true;
            }else{
                $value['current'] = false;
            }
            if(!empty($value['_child'])){
                $is_child = false;
                foreach ($value['_child'] as $ka=>&$va){
                    $va['url']      =   'Article/index?cate_id='.$va['id'];
                    if(!empty($va['_child'])){
                        foreach ($va['_child'] as $k=>&$v){
                            $v['url']   =   'Article/index?cate_id='.$v['id'];
                            $v['pid']   =   $va['id'];
                            $is_child = $v['id'] == $cate_id ? true : false;
                        }
                    }
                    //展开子分类的父分类
                    if($va['id'] == $cate_id || $is_child){
                        $is_child = false;
                        if($hide_cate){
                            $value['current']   =   true;
                            $va['current']      =   true;
                        }else{
                            $value['current']   =   false;
                            $va['current']      =   false;
                        }
                    }else{
                        $va['current']      =   false;
                    }
                }
            }
        }
        $this->assign('nodes',      $cate);
        $this->assign('cate_id',    $this->cate_id);

        //获取面包屑信息
        $nav = get_parent_category($cate_id);
        $this->assign('rightNav',   $nav);

        //获取回收站权限
        $this->assign('show_recycle', IS_ROOT || $this->checkRule('Admin/article/recycle'));
        //获取草稿箱权限
        $this->assign('show_draftbox', C('OPEN_DRAFTBOX'));
        //获取审核列表权限
        $this->assign('show_examine', IS_ROOT || $this->checkRule('Admin/article/examine'));
    }

这就出来了吗 ? 纳尼!? 怎么没看到个人中心的字样呢?
还是再看看模板吧

<div id="subnav" class="subnav">
    <notempty name="_extra_menu">
        {// 动态扩展菜单 //}
        {:extra_menu($_extra_menu,$__MENU__)}
    </notempty>
    <volist name="__MENU__.child" id="sub_menu">
        <!-- 子导航 -->
        <notempty name="sub_menu">
            <notempty name="key"><h3><i class="icon icon-unfold"></i>{$key}</h3></notempty>
            <ul class="side-sub-menu">
                <volist name="sub_menu" id="menu">
                    <li>
                        <a class="item" href="{$menu.url|U}">{$menu.title}</a>
                    </li>
                </volist>
            </ul>
        </notempty>
        <!-- /子导航 -->
    </volist>
 <h3>
    <i class="icon <notin name="Think.ACTION_NAME"  value="mydocument,draftbox,examine">icon-fold</notin>"></i>
    个人中心
 </h3>
    <ul class="side-sub-menu <notin name="Think.ACTION_NAME"  value="mydocument,draftbox,examine">subnav-off</notin>">
        <li <eq name="Think.ACTION_NAME" value="mydocument">class="current"</eq>><a class="item" href="{:U('article/mydocument')}">我的文档</a></li>
        <eq name="show_draftbox" value="1">
        <li <eq name="Think.ACTION_NAME" value="draftbox">class="current"</eq>><a class="item" href="{:U('article/draftbox')}">草稿箱</a></li>
        </eq>
        <eq name="show_examine" value="1">
        <li <eq name="Think.ACTION_NAME" value="examine">class="examine"</eq>><a class="item" href="{:U('article/examine')}">待审核</a></li>
        </eq>
    </ul>

    <volist name="nodes" id="sub_menu">
        <!-- 子导航 -->
        <notempty name="sub_menu">
            <h3>
                <i class="icon <neq name="sub_menu['current']" value="1">icon-fold</neq>"></i>
                <gt name="sub_menu['allow_publish']" value="0"><a class="item" href="{$sub_menu.url|U}">{$sub_menu.title}</a><else/>{$sub_menu.title}</gt>
            </h3>
            <ul class="side-sub-menu <neq name='sub_menu["current"]' value="1">subnav-off</neq>">
                <volist name="sub_menu['_child']" id="menu">
                    <li <if condition="$menu['id'] eq $cate_id or $menu['current'] eq 1">class="current"</if>>
                        <gt name="menu['allow_publish']" value="0"><a class="item" href="{$menu.url|U}">{$menu.title}</a><else/><a class="item" href="javascript:void(0);">{$menu.title}</a></gt>

                        <!-- 一级子菜单 -->
                        <present name="menu['_child']">
                        <ul class="subitem">
                            <foreach name="menu['_child']" item="three_menu">
                            <li>
                                <gt name="three_menu['allow_publish']" value="0"><a class="item" href="{$three_menu.url|U}">{$three_menu.title}</a><else/><a class="item" href="javascript:void(0);">{$three_menu.title}</a></gt>
                                <!-- 二级子菜单 -->
                                <present name="three_menu['_child']">
                                <ul class="subitem">
                                    <foreach name="three_menu['_child']" item="four_menu">
                                    <li>
                                        <gt name="four_menu['allow_publish']" value="0"><a class="item" href="{:U('index','cate_id='.$four_menu['id'])}">{$four_menu.title}</a><else/><a class="item" href="javascript:void(0);">{$four_menu.title}</a></gt>
                                        <!-- 三级子菜单 -->
                                        <present name="four_menu['_child']">
                                        <ul class="subitem">
                                            <volist name="four_menu['_child']" id="five_menu">
                                            <li>
                                                <gt name="five_menu['allow_publish']" value="0"><a class="item" href="{:U('index','cate_id='.$five_menu['id'])}">{$five_menu.title}</a><else/><a class="item" href="javascript:void(0);">{$five_menu.title}</a></gt>
                                            </li>
                                            </volist>
                                        </ul>
                                        </present>
                                        <!-- end 三级子菜单 -->
                                    </li>
                                     </foreach>
                                </ul>
                                </present>
                                <!-- end 二级子菜单 -->
                            </li>
                            </foreach>
                        </ul>
                        </present>
                        <!-- end 一级子菜单 -->
                    </li>
                </volist>
            </ul>
        </notempty>
        <!-- /子导航 -->
    </volist>
    <!-- 回收站 -->
    <eq name="show_recycle" value="1">
    <h3>
        <em class="recycle"></em>
        <a href="{:U('article/recycle')}">回收站</a>
    </h3>
    </eq>
</div>
<script>
    $(function(){
        $(".side-sub-menu li").hover(function(){
            $(this).addClass("hover");
        },function(){
            $(this).removeClass("hover");
        });
    })
</script>

卧槽,,竟然不是真正的 动态扩展这里是手动拼出来的。
不过也得感激官方这种想法也能够给出实例。。。

那么真正的动态扩展在哪里?

真正的动态扩展

再来看图

没错,这就是扩展页面
扩展菜单是这样设置第

咦 有戏,赶紧去看代码

#Application\Admin\Controller\AddonsController.class.php   就在开头不用写行号了
 */
class AddonsController extends AdminController {

    public function _initialize(){
        $this->assign('_extra_menu',array(
            '已装插件后台'=> D('Addons')->getAdminList(),
        ));
        parent::_initialize();
    }

看到了已安装插件,看到了_extra_menu 一切ok。。。
本章完

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 回首页 第一部分 Drupal简介 Drupal overview A tour of Drupal fundam...
    王乂阅读 1,918评论 0 9
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,614评论 4 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 产品小白,最近做产品的时候发现了一个非常有趣的现象。 我们在做产品的时候,需求的收集,产品的设计,还是产品的实现,...
    XiaoluFrank阅读 357评论 0 0
  • 齐鲁软件大赛 队伍信息 队名:山东大学ing21:10组成员:翁清涛,曲岩松,郭卓强,冯嘉伟, 刘鹏昊 项目背景 ...
    z轴阅读 305评论 0 0