超级管理员后台的界面结构说明
表象
左侧菜单普通
先来看左侧这个导航条是怎么来的?
让我们点击后台菜单看看 (这里原先是菜单管理,为了更好的区分我设置成了后台菜单)
点击右侧列表中的系统 我们就可以看到下面的界面 为了更好的说明问题 我对属性管理的分组做了去除操作
大家可以通过查看这里的设置来配置新的菜单
左侧菜单对比说明
超级管理员的后台操作就是如此形成的,当大家在新建后台时就可以不用做太大的修改即可轻松的搞定模板
下面是一个模板展示 OT的Public/base模板的结构 将会对部分内容给大家作一些说明
{$meta_title}|{:C('TIPINFO')}管理平台(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')}"]
}
})();
+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'))
sub.css('marginTop','-'+(diff-10));
}else{
sub.css('marginTop','-='+10);
}
}
});
}
}();
左侧菜单的生成就是通过
{$key}
通过这里可以看到官方在构建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
*/
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'));
}
这就出来了吗 ? 纳尼!? 怎么没看到个人中心的字样呢?
还是再看看模板吧
$(function(){
$(".side-sub-menu li").hover(function(){
$(this).addClass("hover");
},function(){
$(this).removeClass("hover");
});
})
卧槽,,竟然不是真正的 动态扩展这里是手动拼出来的。
不过也得感激官方这种想法也能够给出实例。。。
那么真正的动态扩展在哪里?
真正的动态扩展
再来看图
没错,这就是扩展页面
扩展菜单是这样设置第
咦 有戏,赶紧去看代码
#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。。。
本章完