第六章:初始化后台首页左侧导航菜单nav,增加权限控制

第一章:后台管理系统 功能 简单梳理
第二章 数据库表的设计
第三章:对数据库权限相关的表进行重新设计
第四章:用idea 创建后台系统工程,并完成项目配置
第五章:实现后台登录,完成前后验证登录,并深入讲解captcha.js的使用方法和入‘坑‘指南

第六章:初始化后台首页左侧导航菜单nav,增加权限控制

需求分析:
用户登录后根据用户的主键id再利用mysql递归查询(根据用户挂接的角色去查询角色挂接的根菜单id,再根据根菜单id递归查询子菜单)
由于MySQL没有自己的递归函数,因此需要自己编写递归函数:
可以看我的这篇文章(有详细讲解):
mysql 实现树形递归查询 适合分级菜单、层级权限等查询

分级菜单的数据库表设计:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
前端源代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>layout 后台大布局 - Layui</title>
    <link rel="stylesheet" href="/future/util/layui/css/layui.css">
    <link rel="stylesheet" href="/future/css/index.css">
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin" id="page" v-cloak>
    <div class="layui-header">
        <div class="layui-logo">未来商城</div>
        <!-- 头部区域(可配合layui已有的水平导航) -->
        <ul class="layui-nav layui-layout-left">
            <li class="layui-nav-item"><a href="">控制台</a></li>
            <li class="layui-nav-item"><a href="">商品管理</a></li>
            <li class="layui-nav-item"><a href="">用户</a></li>
            <li class="layui-nav-item">
                <a href="javascript:;">其它系统</a>
                <dl class="layui-nav-child">
                    <dd><a href="">邮件管理</a></dd>
                    <dd><a href="">消息管理</a></dd>
                    <dd><a href="">授权管理</a></dd>
                </dl>
            </li>
        </ul>
        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item">
                <a href="javascript:;">
                    <img src="http://t.cn/RCzsdCq" class="layui-nav-img">
                    <text id="managername"></text>
                </a>
                <dl class="layui-nav-child">
                    <dd><a href="">基本资料</a></dd>
                    <dd><a href="">安全设置</a></dd>
                </dl>
            </li>
            <li class="layui-nav-item"><a href="">退了</a></li>
        </ul>
    </div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
            <ul id="leftNav" class="layui-nav layui-nav-tree" lay-filter="test">
                <li class="layui-nav-item" ref="model" v-for="(item,i) in menuList">
                    <a :class="item.htmlpath?'layui-nav-child':'layui-nav-title'" @click="setAframe(item.htmlpath,true,i)" href="javascript:;">{{item.menuname}}</a>
                    <dl class="layui-nav-child" v-for="(menu,j) in item.mm">
                        <dd><a @click="setAframe(menu.htmlpath,false,j)" href="javascript:;">{{menu.menuname}}</a></dd>
                    </dl>
                </li>
            </ul>
        </div>
    </div>

    <div class="layui-body">
        <!-- 内容主体区域 -->
        <iframe style="padding: 15px; width: 100%;height: 100%;" scrolling="false" id="framePage" :src="htmlpath"></iframe>
    </div>

    <div class="layui-footer">
        <!-- 底部固定区域 -->
    </div>
</div>

</body>
</html>

<script src="/future/util/layui/layui.js"></script>
<script src="/future/js/jquery.js"></script>
<script src="/future/vue/vue.min.js"></script>
<script src="/future/vue/vue.resource.js"></script>
<script src="/future/js/main.js"></script>

function getMid() {
    return JSON.parse(sessionStorage.getItem("manageInfo")).mid;
}

layui.use(['layer', 'form', 'element'], function () {
    var layer = layui.layer;
    var element = layui.element;
    var form = layui.form;

    // (function ($) {
    // 	funObj = {
    // 		timeUserFun: 'timeUserFun',
    // 	}
    // 	$[funObj.timeUserFun] = function (time) {
    // 		var time = time || 2;    // 默认参数
    // 		var userTime = time * 60;
    // 		var objTime = {
    // 			init: 0,
    // 			time: function () {
    // 				objTime.init += 1;
    // 				if (objTime.init == userTime) {
    // 					// 用户到达未操作事件 做一些处理
    // 					update();
    // 				}
    // 			},
    // 			eventFun: function () {
    // 				clearInterval(testUser);
    // 				objTime.init = 0;
    // 				testUser = setInterval(objTime.time, 1000);
    // 			}
    // 		}
    //
    // 		var testUser = setInterval(objTime.time, 1000);
    //
    // 		var body = document.querySelector('html');
    // 		body.addEventListener("click", objTime.eventFun);
    // 		body.addEventListener("keydown", objTime.eventFun);
    // 		body.addEventListener("mousemove", objTime.eventFun);
    // 		body.addEventListener("mousewheel", objTime.eventFun);
    // 	}
    // })(window)
    function update() {
        let mid = getMid();
        $.ajax({
            url: "/future/manager/saveLoginStatus/" + mid,
            type: "POST",
            contentType: "application/json;charset=utf-8",
            dataType: "json",
            async: false,
            success(res) {
                if (res.code == "200") {
                    sessionStorage.setItem("manageInfo", "null");
                    layer.msg("由于您长时间未操作页面,请重新登录", {icon: 2, time: 2000});
                    setTimeout(function () {
                        window.location.reload();
                    }, 2000);
                }
            }
        })
    }

    // 直接调用 参数代表分钟数,可以有一位小数,不传参默认2分钟
    // timeUserFun(0.2);

    let vm = new Vue({
        el: "#page",
        data: {
            manageInfo: {},
            menuList: [],
            htmlpath: "welcome.html",
        },
        ready() {
        },
        mounted() {
            this.manageInfo = JSON.parse(sessionStorage.getItem("manageInfo"));
            if (undefined == this.manageInfo || null == this.manageInfo) {
                layer.msg("登录状态已过期,请重新登录", {icon: 2, time: 2000});
                window.location.href = "login.html";
            } else {
                $("#managername").html(this.manageInfo.mno);
                this.manageInfo.mrole === 0 ? layer.msg("欢迎管理员" + this.manageInfo.mno + "登录", {
                    icon: 1,
                    time: 2000
                }) : layer.msg("欢迎超级管理员:" + this.manageInfo.mno + "登录", {icon: 1, time: 2000});
            }
            this.getMenuList(this.manageInfo.mid);
        },
        destroy() {
        },
        methods: {
            getMenuList(managerid) {
                var that = this;
                $.ajax({
                    url: "/future/manager/getMenuTree/" + managerid,
                    dataType: "json",
                    async: false,
                    success(res) {
                        that.menuList = res.objList;
                    }
                })
            },
         
        }
    })
});

但是渲染出来会发现导航菜单无法展开,经过分析发现,控制展示和隐藏下级菜单的主要是 样式类
名为layui-nav-itemed,因此通过判断这个类名是否存在来实现菜单的显示与隐藏:

  setAframe(path, isTitle, i) {
                if (isTitle) {
                    let navTitle = this.$refs.model[i];
                    if ("" != path && null != path && undefined != path) {
                        this.htmlpath = path;
                    }
                    if (navTitle.className.indexOf("layui-nav-itemed") > -1) {
                        $(navTitle).removeClass("layui-nav-itemed");
                    } else {
                        $(navTitle).addClass("layui-nav-itemed");
                    }
                } else {
                    this.htmlpath = path;
                }
            }

这里再说一下vue的 v-cloak,主要是为了解决在页面加载出来前,出现小胡子语法的闪现
将v-cloak放在body内最外层的标签上,并编写css:
[v-cloak]{
display:none;
}
这条css应该写在link引用的样式表文件中。
实现效果:

20220109_220541

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前后端杂货铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值