预览地址:http://padmin.easys.ltd/admin/account/login
后台管理页面效果预览
界面部署流程
新建控制器Home.php
<?php
namespace app\admin\controller;
use app\BaseController;
use think\facade\Session;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Request;
/**
* 后台首页
*/
class Home
{
public function index(){
// 用户信息
$data['admin'] = Session::get('admin');
// 获取继承父类Base的属性
// 用户角色(根据用户信息的角色gid查询对应的角色名称)
$data['group'] = Db::table('admin_group')->where('id',$data['admin']['gid'])->find();
View::assign([
'data'=>$data
]);
return View::fetch('/home/index');
}
public function welcome(){
return View::fetch('/home/welcome');
}
}
新建后台主体页面视图 Home/index.php
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="/static/layui/css/layui.css">
<script type="text/javascript" src="/static/layui/layui.js"></script>
<style type="text/css">
body{padding:0;margin: 0;}
.myheader{background: #009688;height: 50px;padding: 0 10px;line-height: 50px;color: #fff;display: flex;justify-content: space-between;}
.myheader .title .logo{width: 30px;vertical-align: sub;border-radius: 8px;margin-right: 12px;}
.myheader .title{font-size: 18px;cursor: pointer;}
.admin-info a{color: #fff;margin-left:6px;}
.main-menus{width: 200px;position:absolute;height: calc(100% - 50px)}
.main-menus .layui-inline{height: 100%;overflow: auto;}
.main-contain{position: absolute;left: 200px;right: 0;height: calc(100% - 50px);}
.main-contain iframe{width: 100%;height: 100%;background: #ececec;}
/* 设置滚动条的样式 */
::-webkit-scrollbar {
width:12px;
}
/* 滚动槽 */
::-webkit-scrollbar-track {
-webkit-box-shadow:inset006pxrgba(0,0,0,0.3);
border-radius:10px;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
border-radius:10px;
background:rgba(0,0,0,0.1);
-webkit-box-shadow:inset006pxrgba(0,0,0,0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
background:rgba(255,0,0,0.4);
}
</style>
</head>
<body>
<!-- 顶部提示条 -->
<div class="myheader">
<span class="title" onclick="goIndex()"><img src="/favicon.ico" class="logo">商城后台管理系统</span>
<span class="admin-info">
<i class="layui-icon layui-icon-user"></i> {$data['admin']['username']}【{$data['group']['title']}】
<a href="javascript:;" onclick="logout()"><i class="layui-icon layui-icon-logout"></i> 退出</a>
</span>
</div>
<!-- 侧边导航菜单 -->
<div class="main-menus">
</div>
<!-- 主操作内容区域 -->
<div class="main-contain">
<iframe src="/admin/home/welcome" frameborder="0"></iframe>
</div>
</body>
</html>
<script>
$ = layui.jquery;
/*function reset_height(obj){
// 当前页面高度-顶部信息条高度 = 主体区域高度
var height = (document.documentElement.clientHeight)-$('.myheader').height();
// 设置主体区域的高度
$(obj).parent('div').height(height);
}*/
// 返回首页
function goIndex(){
window.location.href = '/';
}
// 退出登陆
function logout(){
layer.confirm('确定要退出登陆吗?',{
icon:3,
btn: ['确定','取消']
},function(){
$.get('admin/account/logout',function(res){
layer.msg(res.msg,{icon:1});
setTimeout(function(){
window.location.href = "/admin/home/login";
},1000)
},'json');
});
}
</script>
欢迎页面视图文件 Home/welcom.php
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body style="background: url(http://api.easys.ltd/api/api/api.php);">
<div style="width:100%;height:360px;background: rgba(0,0,0,.6);margin:auto;position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
<p style="text-align:center;line-height: 360px;margin:0;color: #fff;font-size: 32px;">
<span style="font-size: 120px;vertical-align: bottom;">☺</span>
欢迎使用phpAdmin后台管理系统 <br>
</p>
<p style="text-align: center;color: #03a9f4;font-size: 24px;position: absolute;bottom: 0;left: 0;right: 0;">当前时间:<span id="curTime"></span> </p>
</div>
</body>
</html>
<script type="text/javascript">
/**
* 如:需求日期格式为:2018-08-28 星期二 21:53:40
* $timeWrapper:dom容器
*/
var timeWrapper = document.querySelector('#curTime');
timeWrapper.innerHTML = getCurTime();
setInterval(()=>{
timeWrapper.innerHTML = getCurTime();
}, 1000);
function getCurTime() {
var oDate = new Date();
var weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var y = oDate.getFullYear(),
m = String(oDate.getMonth()+ 1).padStart(2,0),
d = String(oDate.getDate()).padStart(2,0),
hour = String(oDate.getHours()).padStart(2,0),
min = String(oDate.getMinutes()).padStart(2,0),
sec = String(oDate.getSeconds()).padStart(2,0),
weekIndex = oDate.getDay(),
week = weekArr[weekIndex];
return y + '-' + m + '-' + d + ' ' + week + ' ' + hour + ':' + min + ':' + sec;
}
</script>
<?php
namespace app\admin\controller;
use app\BaseController;
use think\facade\Session;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Request;
/**
* 后台首页
*/
class Home
{
public function index(){
// 用户信息
// $data['admin'] = Session::get('admin');
// 获取继承父类Base的属性
$data['admin'] = $this->admin;
// 用户角色(根据用户信息的角色gid查询对应的角色名称)
// $data['group'] = Db::table('admin_group')->where('id',$data['admin']['gid'])->find();
$data['group'] = $this->mygroup;
//方案一:直接读数据库 根据一级菜单循环读取二级菜单
// 查询一级菜单(pid==0)
$data['menuList'] = Db::table('admin_menu')->where([['pid','=','0'],['status','=','0']])->select()->toArray();
// 根据一级菜单mid 查询对应的pid二级菜单
foreach ($data['menuList'] as $key => $menu) {
$data['menuList'][$key]['children'] = Db::table('admin_menu')->where('pid','=',$menu['mid'])->select();
}
View::assign([
'data'=>$data
]);
return View::fetch('/home/index');
}
public function welcome(){
return View::fetch('/home/welcome');
}
public function logout(){
// 删除session中admin
Session::delete('admin');
echo (json_encode(['code'=>0,'msg'=>'退出成功~']));
}
}
视图中循环渲染无限极菜单
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="/static/layui/css/layui.css">
<script type="text/javascript" src="/static/layui/layui.js"></script>
<style type="text/css">
body{padding:0;margin: 0;}
.myheader{background: #009688;height: 50px;padding: 0 10px;line-height: 50px;color: #fff;display: flex;justify-content: space-between;}
.myheader .title .logo{width: 30px;vertical-align: sub;border-radius: 8px;margin-right: 12px;}
.myheader .title{font-size: 18px;cursor: pointer;}
.admin-info a{color: #fff;margin-left:6px;}
.main-menus{width: 200px;position:absolute;height: calc(100% - 50px)}
.main-menus .layui-inline{height: 100%;overflow: auto;}
.main-contain{position: absolute;left: 200px;right: 0;height: calc(100% - 50px);}
.main-contain iframe{width: 100%;height: 100%;background: #ececec;}
/* 设置滚动条的样式 */
::-webkit-scrollbar {
width:12px;
}
/* 滚动槽 */
::-webkit-scrollbar-track {
-webkit-box-shadow:inset006pxrgba(0,0,0,0.3);
border-radius:10px;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
border-radius:10px;
background:rgba(0,0,0,0.1);
-webkit-box-shadow:inset006pxrgba(0,0,0,0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
background:rgba(255,0,0,0.4);
}
</style>
</head>
<body>
<!-- 顶部提示条 -->
<div class="myheader">
<span class="title" onclick="goIndex()"><img src="/favicon.ico" class="logo">商城后台管理系统</span>
<span class="admin-info">
<i class="layui-icon layui-icon-user"></i> {$data['admin']['username']}【{$data['group']['title']}】
<a href="javascript:;" onclick="logout()"><i class="layui-icon layui-icon-logout"></i> 退出</a>
</span>
</div>
<!-- 侧边导航菜单 -->
<div class="main-menus">
<ul class="layui-nav layui-nav-tree layui-inline layui-bg-cyan">
{foreach $data['menuList'] as $k=>$menu}
<li class="layui-nav-item {if($k==0)}layui-nav-itemed{/if}">
<a href="javascript:;"><i class="layui-icon {$menu['icon']}"></i> {$menu['title']}</a>
{if $menu['children']}
<dl class="layui-nav-child">
{foreach $menu['children'] as $k=>$chd}
<dd><a href="javascript:;" onclick="firemenu(this)" controller="{$chd['controller']}" action="{$chd['action']}">{$chd['title']}</a><dd>
{/foreach}
</dl>
{/if}
</li>
{/foreach}
</ul>
</div>
<!-- 主操作内容区域 -->
<div class="main-contain">
<iframe src="/admin/home/welcome" frameborder="0"></iframe>
</div>
</body>
</html>
<script>
$ = layui.jquery;
/*function reset_height(obj){
// 当前页面高度-顶部信息条高度 = 主体区域高度
var height = (document.documentElement.clientHeight)-$('.myheader').height();
// 设置主体区域的高度
$(obj).parent('div').height(height);
}*/
// 返回首页
function goIndex(){
window.location.href = '/';
}
// 退出登陆
function logout(){
layer.confirm('确定要退出登陆吗?',{
icon:3,
btn: ['确定','取消']
},function(){
$.get('admin/account/logout',function(res){
layer.msg(res.msg,{icon:1});
setTimeout(function(){
window.location.href = "/admin/account/login";
},1000)
},'json');
});
}
</script>
优化无限极菜单查询操作,避免频繁的从数据库中查询操作,我们将第一次查询出来的菜单数据进行文件保存处理、Cacheh缓存处理、分别查询出所有一级和二级菜单,在分别遍历循环处理等优化方案。
<?php
namespace app\admin\controller;
use app\BaseController;
use think\facade\Session;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Request;
use app\admin\controller\Base;
/**
* 后台首页
*/
class Home extends Base
{
public function index(){
// 用户信息
// $data['admin'] = Session::get('admin');
// 获取继承父类Base的属性
$data['admin'] = $this->admin;
// 用户角色(根据用户信息的角色gid查询对应的角色名称)
// $data['group'] = Db::table('admin_group')->where('id',$data['admin']['gid'])->find();
$data['group'] = $this->mygroup;
/*** 方案一:直接读数据库 根据一级菜单循环读取二级菜单
// 查询一级菜单(pid==0)
$data['menuList'] = Db::table('admin_menu')->where([['pid','=','0'],['status','=','0']])->select()->toArray();
// 根据一级菜单mid 查询对应的pid二级菜单
foreach ($data['menuList'] as $key => $menu) {
$data['menuList'][$key]['children'] = Db::table('admin_menu')->where('pid','=',$menu['mid'])->select();
}
**/
/*** 方案二:优化数据读取 将一级和二级分别都读取出来,根据一级的循环遍历查找对应二级
// 查询出所有一级菜单 (pid==0)
$data['menuList'] = Db::table('admin_menu')->where([['pid','=','0'],['status','=','0']])->select()->toArray();
// 查询出所有二级菜单 (pid > 0)
$secondLists = Db::table('admin_menu')->where([['pid','>','0'],['status','=','0']])->select()->toArray();
// 遍历一级菜单
foreach ($data['menuList'] as $key => $menu) {
// 遍历二级菜单
$data['menuList'][$key]['children'] = [];
foreach ($secondLists as $chd) {
// 根据一级菜单mid找出所有自己的二级菜单pid放到自己children的数组下面 二级pid == 一级mid
if($menu['mid']==$chd['pid']){
$data['menuList'][$key]['children'][] = $chd;
}
}
}
**/
/*** 方案一:优化 原生PHP操作文件 将第一次读取的数据存储到文件中
$cache_file = 'menuData.txt';
// 检查文件是否存在,不存在则创建
if(!file_exists($cache_file)){
touch($cache_file);
}
// 读取文件数据
$menus = file_get_contents($cache_file);
// 判断是否读取到数据
if(empty($menus)){
$menus = Db::table('admin_menu')->where([['pid','=','0'],['status','=','0']])->select()->toArray();
// 根据一级菜单mid 查询对应的pid二级菜单
foreach ($menus as $key => $menu) {
$menus[$key]['children'] = Db::table('admin_menu')->where('pid','=',$menu['mid'])->select();
}
// 将读取的数据存储起来
file_put_contents($cache_file,json_encode($menus));
}else{
// 如果读取到了数据,我们将其转化为数组
$menus = json_decode($menus,true);
}
$data['menuList'] = $menus;
**/
/*** 方案二: 使用tp的cache缓存机制存储 */
$menus = Cache::get('menus');
$where= [
['status','=','0'], // 筛选没有被禁用的菜单
['ishidden','=','0'], // 筛选可用显示的菜单
['mid','in',$this->mygroup['rights']] // 过滤有权限的菜单才显示
];
if(empty($menus)){
$menus = Db::table('admin_menu')->where('pid','=','0')->where($where)->select()->toArray();
foreach ($menus as $key => $menu) {
$menus[$key]['children'] = Db::table('admin_menu')->where('pid','=',$menu['mid'])->where($where)->select()->toArray();
}
Cache::set('menus',$menus);
}
$data['menuList'] = $menus;
// 注意:以上两种方式虽然我们将数据存到了缓存文件中,避免了数据重复读取,但是当缓存文件存在时,他永远不会再从数据库中读取数据,这时在修改导航的数据时,需要先清除缓存文件,不然他不会被更新到页面中,此时的缓存数据还是第一次读取的旧数据。
View::assign([
'data'=>$data
]);
return View::fetch('/home/index');
}
public function welcome(){
return View::fetch('/home/welcome');
}
}