完善cms后台,完成管理员管理,菜单管理功能。
一、管理员管理功能
新建Admin类,添加index方法
在Baseadmin类中添加判断用户是否具有权限的功能和当前访问菜单功能
// 判断用户是否有权限
$this->db = new Sysdb;
$group = $this->db->table('admin_groups')->where(array('gid'=>$this->_admin['gid']))->item();
if(!$group){
$this->request_error('对不起,您没有权限');
}
$rights = json_decode($group['rights']);
// 当前访问菜单
$controller = request()->controller();
$action = request()->action();
$res = $this->db->table('admin_menus')->where(array('controller'=>$controller,'method'=>$action))->item();
if(!$res){
$this->request_error('对不起,您访问的功能不存在');
}
if($res['status']==1){
$this->request_error('对不起,该功能已禁止使用');
}
if(!in_array($res['mid'],$rights)){
$this->request_error('对不起,您没有权限');
}
admin类继承自BaseAdmin,用来获取权限控制功能
index方法主要是将所有管理员展示出来,查询出所有的管理员信息、查询出所有的角色信息(用gid作为自定义索引),发送给前端
//管理员列表
public function index() {
//13 查询管理员表admins 将所有信息都查询出来
$data['lists'] = $this->db->table('admins')->lists();
//13 加载所有角色
$data['group'] = $this->db->table('admin_groups')->cates('gid');
//将数据发送给前端
$this->assign('data', $data);
return $this->fetch();
}
然后新建前端页面 admin/index.php,通过表单把每个管理员的信息展示出来;需要对管理员进行添加、编辑、删除操作。
<!DOCTYPE html>
<html>
<head>
<title></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 span{background: #009688;margin-left: 30px;padding: 10px;color:#ffffff;}
.header div{border-bottom: solid 2px #009688;margin-top: 8px;}
.header button{float: right;margin-top: -5px;}
</style>
</head>
<body style="padding: 10px;">
<div class="header">
<span>管理员列表</span>
<button class="layui-btn layui-btn-sm" onclick="add()">添加</button>
<div></div>
</div>
<table class="layui-table">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>真实姓名</th>
<th>角色</th>
<th>状态</th>
<th>添加时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 循环出所有管理员 -->
{volist name="data.lists" id="vo"}
<tr>
<td>{$vo.id}</td>
<td>{$vo.username}</td>
<td>{$vo.truename}</td>
<!-- 三元运算 如果$data['group'][$vo.gid]有对应值那么就显示他的title 否则为空 -->
<td>{:isset($data['group'][$vo.gid]) ? $data['group'][$vo.gid]['title'] : ''}</td>
<!-- 三元运算 如果status为0 为绿色 -->
<td>{$vo.status == 0 ? '<span style="color: green">正常</span>' : '<span style="color: red">禁用</span>'}</td>
<td>{:date('Y-m-d H:i:s', $vo.add_time)}</td>
<td>
<button class="layui-btn layui-btn-xs" onclick="add({$vo.id})">编辑</button>
<button class="layui-btn layui-btn-danger layui-btn-xs" onclick="del({$vo.id})">删除</button>
</td>
</tr>
{/volist}
</tbody>
</table>
<script type="text/javascript">
layui.use(['layer'],function(){
layer = layui.layer;
$ = layui.jquery;
});
// 添加编辑
function add(id) {
layer.open({
type: 2,
title: id>0 ? '编辑管理员' : '添加管理员',
shade: 0.3,
area: ['480px', '420px'],
content: '/index.php/admins/Admin/add?id='+id
});
}
// 删除
function del(id) {
layer.confirm('确定要删除吗?', {
icon: 3,
btn: ['确定', '取消']
}, function () {
$.post('/index.php/admins/Admin/delete', {'id':id}, function (res) {
if (res.code > 0) {
layer.alert(res.msg, {icon:2});
} else {
layer.msg(res.msg);
setTimeout(function () {
window.location.reload();
}, 1000)
}
}, 'json');
});
}
</script>
</body>
</html>
编辑和添加功能都用add方法实现,用传过来的id区分,>0为编辑,否则就是添加。id值通过get方法传给Admin类下的add方法。add方法将此id的管理员信息和所有角色信息发给前端。这的编辑、添加,通过弹框一个新页面,这里新建前端页面admin/add.php。
public function add() {
//14 接收前端get过来的id值,确定是那个管理员,如果是0那么就是添加 ,大于0就是编辑
$id = (int)input('get.id');
// 14 加载管理员
// 14 用id在admins表中查询出该管理员的信息
$data['item'] = $this->db->table('admins')->where(array('id'=>$id))->item();
//加载出角色信息
$data['groups'] = $this->db->table('admin_groups')->cates('gid');
$this->assign('data', $data);
return $this->fetch();
}
前端页面根据传过来的id进行展示,如果是编辑里面的用户名不能更改,然后通过save方法将数据发送给Admin类下的save方法处理
<!DOCTYPE html>
<html>
<head>
<title></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>
</head>
<body style="padding: 10px;">
<form class="layui-form">
<!-- hidden 是把input框隐藏,它的作用是把一些隐藏信息传值到接口中 -->
<input type="hidden" name="id" value="{$data.item.id}">
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-inline">
<!-- value 是默认值 -->
<!-- 当添加时,传值是0,默认值是空 -->
<!-- readonly 是input里的一个参数,可以禁用input框,只有在修改用户时,才使用 -->
<input type="text" class="layui-input" name="username" value="{$data.item.username}" {$data.item.id>0?'readonly':''}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">角 色</label>
<div class="layui-input-inline">
<select name="gid">
<option value=0></option>
<!-- 循环角色数据 -->
<!-- value 是角色的ID -->
<!-- selected 是默认选中,用三元进行判断,判断条件是用户gid和角色gid -->
<!-- 用户gid和角色gid 只有一次相等的机会 -->
{volist name="data.groups" id="vo"}
<option value="{$vo.gid}" {$vo.gid == $data.item.gid ? 'selected' : ''}>{$vo.title}</option>
{/volist}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密 码</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="pwd">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">姓 名</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="truename" value="{$data.item.truename}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">状 态</label>
<div class="layui-input-inline">
<input type="checkbox" name="status" lay-skin="primary" title="禁用" value="1" {$data.item.status?'checked':''}>
</div>
</div>
</form>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" onclick="save()">保存</button>
</div>
</div>
<script type="text/javascript">
layui.use(['layer','form'],function(){
form = layui.form;
layer = layui.layer;
$ = layui.jquery;
});
// 保存管理员
function save(){
// 用js 获取id、用户名、密码、角色、真实姓名
var id = parseInt($('input[name="id"]').val());
var username = $.trim($('input[name="username"]').val());
var pwd = $.trim($('input[name="pwd"]').val());
var gid = $('select[name="gid"]').val();
var truename = $.trim($('input[name="truename"]').val());
var status = parseInt($('input[name="truename"]').val());
if(username==''){
layer.alert('请输入用户名',{icon:2});
return;
}
if(isNaN(id) && pwd==''){
layer.alert('请输入密码',{icon:2});
return;
}
if(gid==0){
layer.alert('请选择角色',{icon:2});
return;
}
if(truename==''){
layer.alert('请输入姓名',{icon:2});
return;
}
// 请求保存接口,把数据传值到接口中。
$.post('/index.php/admins/Admin/save',$('form').serialize(),function(res){
if(res.code>0){
layer.alert(res.msg,{icon:2});
}else{
layer.msg(res.msg);
setTimeout(function(){parent.window.location.reload();},1000);
}
},'json');
}
</script>
</body>
</html>
save方法接收post传过来的各种信息,经过控制判断,密码加密处理后,将id==0的是为添加,进行账号重复判断,将添加时间整合,进行insert操作,返回一个布尔值给$res;id不为0就进行编辑操作,update,返回一个$res;最后将$res为false的给到code:1 msg:保存失败,true的给到0和保存成功,发送给前端页面,前端页面进行展示
删除功能。
在admin/index页面有del方法,确认删除后将id值传给Admin类下的delete方法,然后执行delete操作
//保存管理员
public function save() {
// 15 将post传过来的ID 账号 角色id 密码 真实姓名状态保存在变量中
$id = (int)input('post.id');
$data['username'] = trim(input('post.username'));
$data['gid'] = (int)(input('post.gid'));
$password = trim(input('post.pwd'));
$data['truename'] = trim(input('post.truename'));
$data['status'] = (int)(input('post.status'));
//判空排除
if (!$data['username']) {
exit(json_encode(array('code'=>1, 'msg'=>'用户名不能为空')));
}
if (!$data['gid']) {
exit(json_encode(array('code'=>1, 'msg'=>'角色不能为空')));
}
if ($id==0 && !$password) {
exit(json_encode(array('code'=>1, 'msg'=>'密码不能为空')));
}
if (!$data['truename']) {
exit(json_encode(array('code'=>1, 'msg'=>'姓名不能为空')));
}
//给密码md5加密
if ($password) {
$data['password'] = md5($data['username'] . $password);
}
//初始化 数据库操作成功与否的变量 $res
$res = true;
// 15 判断用户id是否为0 0的话是添加 否则是修改
if ($id == 0) {
//检查账户是否重复 保证账号的唯一性
$item = $this->db->table('admins')->where(array('id'=>$id))->item();
if ($item) {
exit(json_encode(array('code'=>1, 'msg'=>'该用户已经存在')));
}
// 15 添加时间 给当前的时间戳
$data['add_time'] = time();
// 15 执行插入语句
$res = $this->db->table('admins')->insert($data);
}else {
// 15 不是0的情况执行修改语句
$res = $this->db->table('admins')->where(array('id'=>$id))->update($data);
}
if (!$res) {
exit(json_encode(array('code'=>1, 'msg'=>'保存失败')));
}
exit(json_encode(array('code'=>0, 'msg'=>'保存成功')));
}
二、菜单管理功能
新建Menu类index方法,新建menu/index.php页面。
通过get获得pid值,这里默认为0,然后通过pid找到所有pid为0的菜单信息,也就是一级菜单。初始化返回上一级的id即backid为0,然后当pid>0也就是进入二级菜单时,通过点击子菜单,获得的pid也就是上一级的mid,然后在找到他的pid,也就是二级菜单的爷爷辈菜单
public function index() {
//17 当点击菜单管理时 通过get得到pid 默认是管理pid为0的菜单
$pid = (int)input('get.pid');
//17 以得到的pid为条件查处与之相等的pid值的所有菜单信息
$data['lists'] = $this->db->table('admin_menus')->where(array('pid'=>$pid))->lists();
$backid = 0;
//19 如果是pid大于0 那就是二级菜单 再点击二级菜单就得到了pid也就是一级菜单的mid找到一级菜单 返回的id就是一级菜单的pid
if ($pid > 0) {
$parent = $this->db->table('admin_menus')->where(array('mid'=>$pid))->item();
$backid = $parent['pid'];
}
$this->assign('backid', $backid);
$this->assign('pid', $pid);
$this->assign('data', $data);
return $this->fetch();
}
将pid backid 和二级菜单内容(data)传给前端,前端页面menu/index.php,直接就是form表单,将菜单的mid ord title controller method status信息展示出来
<!DOCTYPE html>
<html>
<head>
<title></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 span{background: #009688;margin-left: 30px;padding: 10px;color:#ffffff;}
.header div{border-bottom: solid 2px #009688;margin-top: 8px;}
</style>
</head>
<body style="padding: 10px;">
<div class="header">
<span>菜单管理</span>
<div></div>
</div>
<form class="layui-form">
{if condition="$pid>0"}
<button class="layui-btn layui-btn-primary layui-btn-sm" style="float: right;margin:5px 0px;" onclick="back({$backid});return false;">返回上级</button>
{/if}
<!-- 隐藏pid -->
<input type="hidden" name="pid" value="{$pid}">
<table class="layui-table">
<thead>
<tr>
<th>ID</th>
<th>排序</th>
<th>菜单名称</th>
<th>controller</th>
<th>method</th>
<th>是否隐藏</th>
<th>是否禁用</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 循环菜单列表 -->
{volist name="data.lists" id="vo"}
<tr>
<td>{$vo.mid}</td>
<td><input type="text" class="layui-input" name="ords[{$vo.mid}]" value="{$vo.ord}"></td>
<td><input type="text" class="layui-input" name="titles[{$vo.mid}]" value="{$vo.title}"></td>
<td><input type="text" class="layui-input" name="controllers[{$vo.mid}]" value="{$vo.controller}"></td>
<td><input type="text" class="layui-input" name="methods[{$vo.mid}]" value="{$vo.method}"></td>
<td><input type="checkbox" lay-skin="primary" name="ishiddens[{$vo.mid}]" title="隐藏" {$vo.ishidden?'checked':''} value=1></td>
<td><input type="checkbox" lay-skin="primary" name="status[{$vo.mid}]" title="禁用" {$vo.status?'checked':''} value=1></td>
<td><button class="layui-btn layui-btn-xs" onclick="child({$vo.mid});return false;">子菜单</button></td>
</tr>
{/volist}
<!-- 这个是新增的空输入框 -->
<tr>
<td></td>
<td><input type="text" class="layui-input" name="ords[0]"></td>
<td><input type="text" class="layui-input" name="titles[0]"></td>
<td><input type="text" class="layui-input" name="controllers[0]"></td>
<td><input type="text" class="layui-input" name="methods[0]"></td>
<td><input type="checkbox" lay-skin="primary" name="ishiddens[0]" title="隐藏" value=1></td>
<td><input type="checkbox" lay-skin="primary" name="status[0]" title="禁用" value=1></td>
<td></td>
</tr>
</tbody>
</table>
</form>
<button class="layui-btn" onclick="save()">保存</button>
<script type="text/javascript">
layui.use(['layer','form'],function(){
$ = layui.jquery;
layer = layui.layer;
form = layui.form;
});
// 子菜单
function child(pid){
window.location.href="/index.php/admins/Menu/index?pid="+pid;
}
// 返回上一级
function back(pid){
window.location.href="/index.php/admins/Menu/index?pid="+pid;
}
// 保存
function save(){
$.post('/index.php/admins/Menu/save',$('form').serialize(),function(res){
if(res.code>0){
layer.alert(res.msg,{'icon':2});
}else{
layer.msg(res.msg,{'icon':1});
setTimeout(function(){window.location.reload();},1000);
}
},'json');
}
</script>
</body>
</html>
前端页面,有save child back 方法,child通过当前菜单的mid作为pid传递给menu类的index,back是将backid传给index方法。save是将所有信息传给menu的save方法,这里数据都是将当前的mid作为下标然后将所有的菜单分类组成数组,传递给后段menu下save方法。
public function save() {
//18 接收post传过来的 pid ords titles controllers methods ishidden status
$pid = (int)input('post.pid');
$ords = input('post.ords/a');
$titles = input('post.titles/a');
$controllers = input('post.controllers/a');
$methods = input('post.methods/a');
$ishiddens = input('post.ishiddens/a');
$status = input('post.status/a');
//18循环任何一个数组 因为前端的name值都是以菜单的mid作为下标的
foreach ($ords as $key => $value) {
//18将传过来的值组装成一个二维数组
$data['pid'] = $pid;
$data['ord'] = $value;
$data['title'] = $titles[$key];
$data['controller'] = $controllers[$key];
$data['method'] = $methods[$key];
$data['ishidden'] = isset($ishiddens[$key]) ? 1 : 0;
$data['status'] = isset($status[$key]) ? 1 : 0;
//18 $key为0 且 title有值 那么就是新增
if ($key==0 && $data['title']) {
$this->db->table('admin_menus')->insert($data);
}
//18 $key大于0 就是修改已经存在的菜单
if ($key > 0) {
//18 如果titles controllers methods都为空就是删除
if ($data['title'] == '' && $data['controller'] == '' && $data['method'] == '') {
//执行删除语句
$this->db->table('admin_menus')->where(array('mid'=>$key))->delete();
}else {
//修改语句
$this->db->table('admin_menus')->where(array('mid'=>$key))->update($data);
}
}
}
exit(json_encode(array('code'=>0, 'msg'=>'保存成功')));