Correction status:Uncorrected
Teacher's comments:
今天学习了tp51框架下,构建的cms后台管理系统,主要实现了登陆功能,登陆后对管理员账号权限在左侧菜单的显示。
一、准备
首先要重新下载tp51框架,composer create-project topthink/think cms 5.1.37
配置:
//config下的app。php
// 默认模块名
'default_module' => 'admins',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Home',
// 默认操作名
'default_action' => 'index',
//config下的database.php
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => 'localhost',
// 数据库名
'database' => 'ouyang',
// 用户名
'username' => 'root',
// 密码
'password' => 'root',
//config下的template.php
// 模板后缀
'view_suffix' => 'php',
//public下的.htaccess index.php 后面加上问号 就可以省去入口文件
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
二、 页面登陆
use Util\Sysdb
class Account extends Controller
{
//后台登陆页面
//2、页面文件不能再继承公共的权限控制类BaseAdmin类,
//因为这是登陆页面,肯定没有登陆,那么BaseAdmin肯定让他跳转当前页面,造成无限循环
//3、页面需要显示登陆用户名 密码 验证码
//4、验证使用tp51自带的验证码插件
public function login () {
return $this->fetch();
}
}
cms composer require topthink/think-captcha=2.0.2
引用<img src="{:captcha_src()}" id="img">
reloadImg
刷新二维码
function dologin() {
var username = $.trim($('#username').val());
var pwd = $.trim($('#password').val());
var verifycode = $.trim($('#verifycode').val());
//验证输入内容为空
if (username == '') {
layer.alert('请输入用户名', {icon:2});
return;
}
if (pwd == '') {
layer.alert('请输入密码', {icon:2});
return;
}
if (verifycode == '') {
layer.alert('请输入验证码', {icon:2});
return;
}
//通过ajax方式交给后台dologin方法处理数据 并且返回相应的数据
$.post('/index.php/admins/Account/dologin', {'username':username,
'pwd':pwd, 'verifycode':verifycode}, function (res) {
if (res.code > 0) {
reloadImg();
layer.alert(res.msg, {icon:2});
}else{
layer.msg(res.msg);
setTimeout(function () {
window.location.href='/index.php/admins/Home/index'
}, 1000)
}
},'json');
}
input
方法获取传过来的值,然后验证都不为空,!captcha_check($verifycode)
验证验证码是否正确连接数据库 查询与账号相符的记录,验证账号是否存在,验证账号密码是否一致,验证账号状态,删除密码信息后存入session,
//5、登陆接口
public function dologin () {
//获取传过来的数据 然后赋给相应的变量
$username = trim(input('username'));
$pwd = trim(input('pwd'));
$verifycode = trim(input('verifycode'));
//验证数据空值,输出错误信息的code和msg
if ($username == '') {
exit(json_encode(array('code'=>1, 'msg'=>'账号不能为空')));
}
if ($pwd == '') {
exit(json_encode(array('code'=>1, 'msg'=>'密码不能为空')));
}
if ($verifycode == '') {
exit(json_encode(array('code'=>1, 'msg'=>'验证码不能为空')));
}
//验证验证码
if (!captcha_check($verifycode)) {
exit(json_encode(array('code'=>1, 'msg'=>'验证码错误')));
}
//验证用户
//连接数据库 引入数据库操作公用文件
$this->db = new Sysdb();
//按照账户查询数据库,不用(账户和密码)一起查询,因为那样的花出错不知谁错
$admin = $this->db->table('admins')->where(array('username'=>$username))->item();
//验证是否有该用户
if (!$admin) {
exit(json_encode(array('code'=>1, 'msg'=>'该用户不存在')));
}
//验证账号密码是否一致
if (md5($admin['username'].$pwd) != $admin['password']) {
exit(json_encode(array('code'=>1, 'msg'=>'密码错误')));
}
//验证账号状态
if ($admin['status'] == 1) {
exit(json_encode(array('code'=>1, 'msg'=>'该账号被禁用')));
}
//为了安全 将密码设为空然后再把用户信息存在session中
$admin['password'] = null;
session('admin', $admin);
exit(json_encode(array('code'=>0, 'msg'=>'登陆成功')));
}
三、后台首页
. 登陆成功后跳转到 Home.php下的index方法,home类需要继承BaseAdmin类
. BaseAdmin验证是否登陆,验证session里面的admin信息有就是登陆了,没有就跳转到登陆页面,所哟登陆页面不要继承BaseAdmin类,如果那样的花就循环跳转
class BaseAdmin extends Controller
{
public function __construct()
{
//Controller类里面就有魔术构造方法 继承调用
parent::__construct();
//1、判断是否登陆
//将session值赋给属性
$this->_admin = session('admin');
if (!$this->_admin) {
header('Location: /index.php/admins/Account/login');
exit;
}
$this->assign('admin', $this->_admin);
}
}
. 新建index方法,链接数据库,查询该账号权限下(这里没有验证权限所有开放所有权限)显示并且可用状态的所有左侧菜单,然后将二级菜单根据上级菜单所属进行分类
. 分类菜单,显示把左侧菜单全部遍历,然后分类是首先看他的父级id的下标,有没有该条记录,一级菜单的父id都是0,但是遍历的菜单记录理下标没有为0的,所有就把作为一级菜单赋给tree变量,然后二级的菜单父级id都有,然后把它的记录付费父记录下的children下,用来调用。
. 查询config表 把杂项查询出来
<?php
/**
* Created by PhpStorm.
* User: apple
* Date: 2020/1/2
* Time: 4:29 PM
*/
namespace app\admins\controller;
use think\Controller;
use Util\Sysdb;
class Home extends BaseAdmin
{
// 6、首页和左侧菜单的样式是后台共用的样式
// 7、退出登陆 确认后删除session
// 8、查询左侧菜单 遍历出来 渲染在前端
public function index(){
// $menus = false;
// $role = $this->db->table('admin_groups')->where(array('gid'=>$this->_admin['gid']))->item();
// if($role){
// $role['rights'] = (isset($role['rights']) && $role['rights']) ? json_decode($role['rights'],true) : [];
// }
// if($role['rights']){ mid in('.implode(',',$role['rights']).') and
// 9,查询左侧菜单。 在权限开启的情况下,可以直接把admin去掉,那admin就可以有全部权限了。
// 10,查询出来左侧菜单后,整理菜单分级
$this->db = new Sysdb;
// $where = ' ishidden=0 and status=0';
$where = array('ishidden'=>0, 'status'=>0);
$menus = $this->db->table('admin_menus')->where($where)->cates('mid');
print_r($menus);
$menus && $menus = $this->gettreeitems($menus);
// }
// 11,查询config表,这个是公用的表。 config表的目的,是存放一起零散的信息的。
$site = $this->db->table('config')->where(array('names'=>'site'))->item();
$site && $site['values'] = json_decode($site['values']);
$this->assign('site',$site);
// $this->assign('role',$role);
$this->assign('menus',$menus);
return $this->fetch();
}
// 把菜单分级处理。
private function gettreeitems($items){
$tree = array();
// 循环(菜单数组),查询菜单的数据。
foreach ($items as $item) {
// 循环数组, $item是 数组里的单条数据
// 单条数据,判断父ID,是否存在。
// 存在后,把就把它的父级ID,当做它的下标。
if(isset($items[$item['pid']])){
// 如果是二级或三级,就把它的父级ID,当做它的下标。
$items[$item['pid']]['children'][] = &$items[$item['mid']];
}else{
// 不存在,直接在数组第一层
// 如果是一级,直接在数组第一层
$tree[] = &$items[$item['mid']];
}
}
// 作业:看懂这个返回值
print_r($tree);
return $tree;
}
// 欢迎页面
public function welcome(){
return $this->fetch();
}
}
. 最后新建home下的index前端页面,做好渲染
<!DOCTYPE html>
<html>
<head>
<title>{$site.values}--后台管理系统</title>
<link rel="stylesheet" type="text/css" href="/static/plugins/layui/css/layui.css">
<script type="text/javascript" src="/static/plugins/layui/layui.js"></script>
<style type="text/css">
.header{width:100%;height: 50px;line-height: 50px;background: #2e6da4;color:#ffffff;}
.title{margin-left: 20px;font-size: 20px;}
.userinfo{float: right;margin-right: 10px;}
.userinfo a{color:#ffffff;}
.menu{width: 200px;background: #333744;position: absolute;}
.main{position: absolute;left: 200px;right: 0px;}
.layui-collapse{border: none;}
.layui-colla-item{border-top: none;}
.layui-colla-title{background: #42485b;color:#ffffff;}
.layui-colla-content{border-top: none;padding: 0px;}
</style>
</head>
<body>
<!--header-->
<div class="header">
<span class="title"><span style="font-size: 20px;">{$site.values}</span>--后台管理系统</span>
<span class="userinfo">{$admin.username} <span><a href="javascript:;" onclick="logout()">退出</a></span></span>
</div>
<!--菜单-->
<div class="menu" id="menu">
<div class="layui-collapse" lay-accordion>
{volist name="menus" id="vo"}
<div class="layui-colla-item">
<h2 class="layui-colla-title">{$vo.title}</h2>
<div class="layui-colla-content{$i==1?' layui-show':''}">
<?php if(isset($vo['children']) && $vo['children']){?>
<ul class="layui-nav layui-nav-tree" lay-filter="test">
{volist name="vo.children" id="cvo"}
<li class="layui-nav-item"><a href="javascript:;" onclick="menuFire(this)" src="/index.php/admins/{$cvo.controller}/{$cvo.method}">{$cvo.title}</a></li>
{/volist}
</ul>
<?php }?>
</div>
</div>
{/volist}
</div>
</div>
<!--主操作页面-->
<div class="main">
<iframe src="/index.php/admins/Home/welcome" onload="resetMainHeight(this)" style="width: 100%;height:100%;" frameborder="0" scrolling="0"></iframe>
</div>
<script>
layui.use(['element','layer'], function(){
var element = layui.element;
$ = layui.jquery;
layer = layui.layer;
resetMenuHeight();
});
// 重新设置菜单容器高度
function resetMenuHeight(){
var height = document.documentElement.clientHeight - 50;
$('#menu').height(height);
}
// 重新设置主操作页面高度
function resetMainHeight(obj){
var height = parent.document.documentElement.clientHeight - 53;
$(obj).parent('div').height(height);
}
// 菜单点击
function menuFire(obj){
// 获取url
var src = $(obj).attr('src');
// 设置iframe的src
$('iframe').attr('src',src);
}
// 退出
function logout(){
layer.confirm('确定要退出吗?', {
icon:3,
btn: ['确定','取消']
}, function(){
$.get('/index.php/admins/account/logout',function(res){
if(res.code>0){
layer.msg(res.msg,{'icon':2});
}else{
layer.msg(res.msg,{'icon':1});
setTimeout(function(){window.location.href="/index.php/admins/account/login";},1000);
}
},'json');
});
}
</script>
</body>
</html>