LayUI + Shiro 实现动态菜单并记住菜单收展

LayUI + Shiro 实现动态菜单 + 记住菜单收展

  • 一、Maven 依赖
  • 二、菜单相关的类
    • 1、主菜单
    • 2、子菜单
  • 三、Shiro 配置
    • 1、ShiroConfig
    • 2、自定义shiro密码校验
    • 3、MyRealm
  • 四、控制类
    • 1、LoginController
    • 2、PageController
    • 3、MenuController
  • 五、数据库
    • 1、user 表
    • 2、role 表
    • 3、user_role_list 表
  • 六、前端页面
    • 1、Ajax 请求菜单数据
    • 2、显示菜单栏
  • 七、完整代码

LayUI + Shiro + Thyemleaf 实现动态菜单并记住菜单收展

LayUI + Shiro 实现动态菜单并记住菜单收展_第1张图片
LayUI + Shiro 实现动态菜单并记住菜单收展_第2张图片


一、Maven 依赖

<dependencies>

        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.39version>
        dependency>
        
        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-spring-boot-starterartifactId>
            <version>1.4.0-RC2version>
        dependency>

        
        <dependency>
            <groupId>com.github.theborakompanionigroupId>
            <artifactId>thymeleaf-extras-shiroartifactId>
            <version>2.0.0version>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.1.4version>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <scope>runtimescope>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

二、菜单相关的类

1、主菜单

LayUI + Shiro 实现动态菜单并记住菜单收展_第3张图片

/**
 * @author wxhntmy
 */
@Getter
@Setter
public class Menu {
     
    private String name;
    private String icon;
    private String url;
    private Boolean hidden;
    private List<MenuList> list;
}

2、子菜单

LayUI + Shiro 实现动态菜单并记住菜单收展_第4张图片

/**
 * @author wxhntmy
 */
@Getter
@Setter
public class MenuList {
     
    private String name;
    private String url;

    public MenuList(String name, String url) {
     
        this.name = name;
        this.url = url;
    }
}

三、Shiro 配置

1、ShiroConfig

/**
 * @author wxhntmy
 */
@Configuration
public class ShiroConfig {
     
    /**
     * 配置拦截器
     * 

* 定义拦截URL权限,优先级从上到下 1). anon : 匿名访问,无需登录 2). authc : 登录后才能访问 3). logout: 登出 4). * roles : 角色过滤器 *

* URL 匹配风格 1). ?:匹配一个字符,如 /admin? 将匹配 /admin1,但不匹配 /admin 或 /admin/; 2). * *:匹配零个或多个字符串,如 /admin* 将匹配 /admin 或/admin123,但不匹配 /admin/1; 2). * **:匹配路径中的零个或多个路径,如 /admin/** 将匹配 /admin/a 或 /admin/a/b *

* 配置身份验证成功,失败的跳转路径 */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 静态资源匿名访问 filterChainDefinitionMap.put("/layui/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/admin/**", "anon"); filterChainDefinitionMap.put("/**/*.eot", "anon"); filterChainDefinitionMap.put("/**/*.svg", "anon"); filterChainDefinitionMap.put("/**/*.svgz", "anon"); filterChainDefinitionMap.put("/**/*.ttf", "anon"); filterChainDefinitionMap.put("/**/*.woff", "anon"); filterChainDefinitionMap.put("/**/*.woff2", "anon"); filterChainDefinitionMap.put("/**/*.gif", "anon"); filterChainDefinitionMap.put("/favicon.ico", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/menu", "anon"); filterChainDefinitionMap.put("/user/login", "anon"); // 用户退出 filterChainDefinitionMap.put("/logout", "logout"); // 其他路径均需要身份认证,一般位于最下面,优先级最低 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); //登录路径 shiroFilterFactoryBean.setLoginUrl("/login"); // 主页 //shiroFilterFactoryBean.setSuccessUrl("/index"); //验证失败跳转的路径 shiroFilterFactoryBean.setUnauthorizedUrl("/error"); return shiroFilterFactoryBean; } /** * SecurityManager安全管理器;shiro的核心 * * @return */ @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm()); return defaultWebSecurityManager; } /** * 自定义Realm * * @return */ @Bean public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); myRealm.setCredentialsMatcher(myCredentialsMatcher()); return myRealm; } /** * 配置加密方式 * @return */ @Bean public MyCredentialsMatcher myCredentialsMatcher() { return new MyCredentialsMatcher(); } /** * 配置Shiro生命周期处理器 */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 自动创建代理类,若不添加,Shiro的注解可能不会生效。 */ @Bean @DependsOn({ "lifecycleBeanPostProcessor" }) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } /** * 开启Shiro的注解 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } }

2、自定义shiro密码校验

/**
 * 自定义shiro密码校验
 * @author wxhntmy
 */
public class MyCredentialsMatcher implements CredentialsMatcher {
     

    @Resource
    private UserMapper userMapper;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
     

        UsernamePasswordToken utoken = (UsernamePasswordToken) token;

        String password = new String(utoken.getPassword());
        String username = utoken.getUsername();

        User user = userMapper.getUserById(username);

        return user.getPwd().equals(password);
    }
}

3、MyRealm

/**
 * @author wxhntmy
 */
public class MyRealm extends AuthorizingRealm {
     

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private UserRoleListMapper userRoleListMapper;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
     

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        User user = (User) principalCollection.getPrimaryPrincipal();
        if (user == null) {
     
            return null;
        }


        List<UserRoleList> roleLists = userRoleListMapper.getUserRoleByUserId(user.getId());

        List<Role> roles = roleMapper.getAllRoles();

        if (roleLists != null && !roleLists.isEmpty()) {
     
            for (UserRoleList roleList : roleLists) {
     
                for (Role role : roles) {
     
                    if (Objects.equals(roleList.getRole_id(), role.getId())) {
     
                        authorizationInfo.addRole(role.getRole());
                    }
                }
            }
        }
        return authorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
     
        //获取登录用户账号
        UsernamePasswordToken utoken = (UsernamePasswordToken) authenticationToken;

        //获得用户输入的密码
        String password = new String(utoken.getPassword());
        String username = utoken.getUsername();

        User user = new User();

        user.setId(username);
        user.setPwd(password);

        //当前realm对象的唯一名字,调用父类的getName()方法
        String realmName = getName();

        // 获取盐值,即用户名
        ByteSource salt = ByteSource.Util.bytes(password);

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, salt, realmName);

        return info;

    }

}

四、控制类

1、LoginController

@RestController
public class LoginController {
     

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private UserRoleListMapper userRoleListMapper;
    @Resource
    private UserMapper userMapper;

    @RequestMapping(value = "/user/login", method = RequestMethod.GET)
    public Msg<String> getUserByName(@RequestParam String user,
                                     @RequestParam String pwd,
                                     @RequestParam String usertype,
                                     @RequestParam String box) {
     


        Role role = roleMapper.getRoleByRoleName(usertype);
        User uUser = userMapper.getUserById(user);
        if (uUser == null){
     
            return Msg.fail("UserUnexit");
        }
        //登录验证
        UsernamePasswordToken token = new UsernamePasswordToken(user, pwd);
        Subject subject = SecurityUtils.getSubject();
        try {
     
            subject.login(token);
        } catch (AuthenticationException e) {
     
            return Msg.fail("PasswordError");
        }
        //设置登陆过期时间,单位毫秒,这里设置30分钟
        SecurityUtils.getSubject().getSession().setTimeout(1800000);
        return Msg.ok("Success");
    }
}

2、PageController

@Controller
public class PageController {
     

    @Resource
    private UserMapper userMapper;

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String Login(){
     
        return "login";
    }

    @RequestMapping(value = "/user/index", method = RequestMethod.GET)
    public String Index(Model model){
     

        User user = (User) SecurityUtils.getSubject().getPrincipal();

        User uuser = userMapper.getUserById(user.getId());

        if (StringUtils.isEmpty(user)) {
     
            return "redirect:/login";
        }

        model.addAttribute("user", uuser);

        return "index";
    }
}

3、MenuController

/**
 * @author wxhntmy
 */
@RestController
public class MenuController {
     

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private UserRoleListMapper userRoleListMapper;

    //记住用户菜单收展
    private Map<String, Map> menu_map = new HashMap<>();

    @RequestMapping(value = "/menu", method = RequestMethod.GET)
    public Msg<List<Menu>> getMenu() {
     
        User user = (User) SecurityUtils.getSubject().getPrincipal();

        List<Menu> list = new ArrayList<>();

        if (StringUtils.isEmpty(user)) {
     
            return Msg.fail(list, "登录信息已过期!请重新登录!");
        }

        //记住收展
        Map<String, Boolean> map_store = new HashMap<>();

        if (menu_map.containsKey(user.getId())){
     
            map_store = menu_map.get(user.getId());
        }

        Map<String, String> map = new HashMap();
        List<UserRoleList> roleLists = userRoleListMapper.getUserRoleByUserId(user.getId());
        for (UserRoleList roleList : roleLists) {
     
            Role role = roleMapper.getRoleByRoleId(roleList.getRole_id());
            map.put(role.getRole(), roleList.getUser_id());
        }
        Menu menu1 = new Menu();
        menu1.setName("首页");
        menu1.setIcon("");
        menu1.setUrl("/user/index");
        menu1.setHidden(false);

        List<MenuList> menuLists2 = new ArrayList<>();
        menu1.setList(menuLists2);
        list.add(menu1);


        if (map.containsKey("student")){
     
            Menu menu2 = new Menu();
            Menu menu3 = new Menu();

            menu2.setName("课程管理");
            menu2.setIcon("");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("课程管理", false));
            List<MenuList> menuLists = new ArrayList<>();
            MenuList menuList1 = new MenuList("已选课程", "");
            MenuList menuList2 = new MenuList("可选课程", "");
            MenuList menuList22 = new MenuList("课程论坛", "");
            menuLists.add(menuList1);
            menuLists.add(menuList2);
            menuLists.add(menuList22);
            menu2.setList(menuLists);

            menu3.setName("成果管理");
            menu3.setIcon("");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("成果管理", false));
            List<MenuList> menuLists3 = new ArrayList<>();
            MenuList menuList3 = new MenuList("提交课程成果", "");
            MenuList menuList33 = new MenuList("提交课程日志", "");
            MenuList menuList4 = new MenuList("实训课程成绩", "");
            MenuList menuList5 = new MenuList("课程调查问卷", "");
            menuLists3.add(menuList3);
            menuLists3.add(menuList33);
            menuLists3.add(menuList4);
            menuLists3.add(menuList5);
            menu3.setList(menuLists3);

            list.add(menu2);
            list.add(menu3);
        }

        if (map.containsKey("teacher")){
     
            Menu menu2 = new Menu();
            Menu menu3 = new Menu();

            menu2.setName("授课课程管理");
            menu2.setIcon("");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("授课课程管理", false));
            List<MenuList> menuLists = new ArrayList<>();
            MenuList menuList1 = new MenuList("教授的实训课程", "");
            MenuList menuList2 = new MenuList("课程论坛", "");
            menuLists.add(menuList1);
            menuLists.add(menuList2);
            menu2.setList(menuLists);

            menu3.setName("成果管理");
            menu3.setIcon("");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("成果管理", false));
            List<MenuList> menuLists3 = new ArrayList<>();
            MenuList menuList3  = new MenuList("课程成果检查", "");
            MenuList menuList33 = new MenuList("课程日志批复", "");
            MenuList menuList4  = new MenuList("实训课程成绩", "");
            menuLists3.add(menuList3);
            menuLists3.add(menuList33);
            menuLists3.add(menuList4);
            menu3.setList(menuLists3);

            list.add(menu2);
            list.add(menu3);
        }
        if (map.containsKey("professionor")){
     
            Menu menu2 = new Menu();
            Menu menu3 = new Menu();

            menu2.setName("实训课程管理");
            menu2.setIcon("");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("实训课程管理", false));
            List<MenuList> menuLists = new ArrayList<>();
            MenuList menuList1 = new MenuList("待批准实训课程", "");
            MenuList menuList2 = new MenuList("添加实训课程", "");
            MenuList menuList3 = new MenuList("实训课程管理", "");
            menuLists.add(menuList1);
            menuLists.add(menuList2);
            menuLists.add(menuList3);
            menu2.setList(menuLists);

            menu3.setName("发布调查问卷");
            menu3.setIcon("");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("发布调查问卷", false));
            List<MenuList> menuLists1 = new ArrayList<>();
            MenuList menuList11 = new MenuList("发布调查问卷", "");
            MenuList menuList21 = new MenuList("回收调查问卷", "");
            menuLists1.add(menuList11);
            menuLists1.add(menuList21);
            menu3.setList(menuLists1);

            list.add(menu2);
            list.add(menu3);
        }
        if (map.containsKey("admin")){
     
            Menu menu2 = new Menu();
            Menu menu3 = new Menu();

            menu2.setName("用户管理");
            menu2.setIcon("");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("用户管理", false));
            List<MenuList> menuLists = new ArrayList<>();
            MenuList menuList0 = new MenuList("添加用户", "");
            MenuList menuList1 = new MenuList("学生账号", "");
            MenuList menuList2 = new MenuList("教师账号", "");
            MenuList menuList3 = new MenuList("实训负责人账号", "");
            menuLists.add(menuList0);
            menuLists.add(menuList1);
            menuLists.add(menuList2);
            menuLists.add(menuList3);
            menu2.setList(menuLists);

            menu3.setName("数据库管理");
            menu3.setIcon("");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("数据库管理", false));
            List<MenuList> menuLists3 = new ArrayList<>();
            MenuList menuList4  = new MenuList("备份数据库", "");
            MenuList menuList5 = new MenuList("还原数据库", "");
            menuLists3.add(menuList4);
            menuLists3.add(menuList5);
            menu3.setList(menuLists3);

            list.add(menu2);
            list.add(menu3);
        }

        Menu menu4 = new Menu();
        menu4.setName("系统设置");
        menu4.setIcon("");
        menu4.setUrl("");
        menu4.setHidden(map_store.getOrDefault("系统设置", false));
        List<MenuList> menuLists4 = new ArrayList<>();
        MenuList menuList5 = new MenuList("修改个人信息", "");
        MenuList menuList6 = new MenuList("修改密码", "");
        MenuList menuList7 = new MenuList("清除缓存", "");
        menuLists4.add(menuList5);
        menuLists4.add(menuList6);
        menuLists4.add(menuList7);
        menu4.setList(menuLists4);

        Menu menu5 = new Menu();
        menu5.setName("退出登录");
        menu5.setIcon("");
        menu5.setUrl("/logout");
        menu5.setHidden(false);
        List<MenuList> menuLists5 = new ArrayList<>();
        menu5.setList(menuLists5);

        list.add(menu4);
        list.add(menu5);

        if (map.containsKey("student")){
     
            return Msg.ok(list, "STU");
        }
        String message = null;
        if (map.containsKey("teacher")){
     
            message = "TEA";
        }
        if (map.containsKey("professionor")){
     
            message = "PRI";
        }
        if (map.containsKey("admin")){
     
            message = "ADM";

        }
        return Msg.ok(list, message);
    }

    @RequestMapping(value = "/menu_storage", method = RequestMethod.GET)
    public Msg<String> menu_storage(@RequestParam String data) {
     

        JSONArray jsonArray = JSONArray.parseArray(data);
        User user = (User) SecurityUtils.getSubject().getPrincipal();

        if (StringUtils.isEmpty(user)) {
     
            return Msg.fail("登录信息已过期!请重新登录!");
        }
        //记住收展
        Map<String, Boolean> map_store = new HashMap<>();

        for (Object o : jsonArray) {
     
            JSONObject jsonObject = JSONObject.parseObject(o.toString());
            map_store.put(jsonObject.getString("name"), Boolean.valueOf(jsonObject.getString("hidden")));
        }

        menu_map.put(user.getId(), map_store);

        return Msg.ok();
    }
}

五、数据库

1、user 表

LayUI + Shiro 实现动态菜单并记住菜单收展_第5张图片

2、role 表

LayUI + Shiro 实现动态菜单并记住菜单收展_第6张图片

3、user_role_list 表

LayUI + Shiro 实现动态菜单并记住菜单收展_第7张图片

六、前端页面

1、Ajax 请求菜单数据

		let config = {
     };
        function set_menu() {
     
            //ajax提交信息
            $.ajax({
     
                type: "get",
                async: false,
                url: "/menu",// 请求发送到LoginServlet处
                dataType: 'json',
                success: function (msg) {
     
                    if (msg.ok === true && msg.data) {
     
                        config["name"] = msg.message;
                        config["menu"] = msg.data;
                    }
                    if (msg.ok === false) {
     
                        window.location.href = "/logout";
                    }
                    if (!msg.data) {
     
                        window.location.href = "/logout";
                    }
                },
                error: function (msg) {
     
                    // 请求失败时执行该函数
                    layer.alert('请求菜单数据失败!!!', function (index) {
     
                        //do something
                        layer.close(index);
                    });
                }
            });
        }

        set_menu();


        $(document).ready(function () {
     
            //删除
            $(".del").click(function () {
     
                var url = $(this).attr("href");
                var id = $(this).attr("data-id");

                layer.confirm('你确定要删除么?', {
     
                    btn: ['确定', '取消']
                }, function () {
     
                    $.get(url, function (data) {
     
                        if (data.code === 1) {
     
                            $(id).fadeOut();
                            layer.msg(data.msg, {
     icon: 1});
                        } else {
     
                            layer.msg(data.msg, {
     icon: 2});
                        }
                    });
                }, function () {
     
                    layer.msg("您取消了删除!");
                });
                return false;
            });
        })

        layui.use('form', function () {
     
            var form = layui.form,
                layer = layui.layer;
        });

        var vue = new Vue({
     
            el: '#app',
            data: {
     
                webname: config.name,
                menu: [],
                address: []
            },
            created: function () {
     
                this.menu = config.menu;
                this.thisActive();
                this.thisAttr();
            },
            methods: {
     
                //记住收展
                onActive: function (pid, id = false) {
     
                    let data;
                    if (id === false) {
     
                        data = this.menu[pid];
                        if (data.url.length > 0) {
     
                            this.menu.forEach((v, k) => {
     
                                v.active = false;
                                v.list.forEach((v2, k2) => {
     
                                    v2.active = false;
                                })
                            })
                            data.active = true;
                        }
                        data.hidden = !data.hidden;
                    } else {
     
                        this.menu.forEach((v, k) => {
     
                            v.active = false;
                            v.list.forEach((v2, k2) => {
     
                                v2.active = false;
                            })
                        })
                        data = this.menu[pid].list[id];
                    }

                    this.updateStorage();
                    if (data.url.length > 0) {
     
                        if (data.target) {
     
                            if (data.target === '_blank') {
     
                                window.open(data.url);
                            } else {
     
                                window.location.href = data.url;
                            }
                        } else {
     
                            window.location.href = data.url;
                        }
                    }
                },

                //更新菜单缓存
                updateStorage() {
     
                    //sessionStorage.menu = JSON.stringify(this.menu);
                    $.ajax({
     
                        type: "get",
                        async: false,
                        url: "/menu_storage",// 请求发送到LoginServlet处
                        data: {
     
                            "data": JSON.stringify(this.menu)
                        },
                        dataType: 'json',
                        success: function (msg) {
     

                        },
                        error: function (msg) {
     
                            // 请求失败时执行该函数
                            var index = layer.load();
                            layer.close(index);
                            layer.alert('请求菜单数据失败!!!', function (index) {
     
                                //do something
                                layer.close(index);
                            });
                        }
                    });
                },
                //菜单高亮
                thisActive: function () {
     
                    let pathname = window.location.pathname;
                    let host = window.location.host;
                    let pid = false;
                    let id = false;
                    this.menu.forEach((v, k) => {
     
                        let url = v.url;
                        if (url.length > 0) {
     
                            if (url[0] !== '/' && url.substr(0, 4) !== 'http') {
     
                                url = '/' + url;
                            }
                        }
                        if (pathname === url) {
     
                            pid = k;
                        }
                        v.list.forEach((v2, k2) => {
     
                            let url = v2.url;

                            if (url.length > 0) {
     
                                if (url[0] !== '/' && url.substr(0, 4) !== 'http') {
     
                                    url = '/' + url;
                                }
                            }
                            if (pathname === url) {
     
                                pid = k;
                                id = k2;
                            }
                        })
                    })


                    if (id !== false) {
     
                        this.menu[pid].list[id].active = true;
                    } else {
     
                        if (pid !== false) {
     
                            this.menu[pid].active = true;
                        }
                    }

                    this.updateStorage();

                },
                //当前位置
                thisAttr: function () {
     
                    //当前位置
                    let address = [{
     
                        name: '首页',
                        url: '/user/index'
                    }];
                    this.menu.forEach((v, k) => {
     
                        v.list.forEach((v2, k2) => {
     
                            if (v2.active) {
     
                                address.push({
     
                                    name: v.name,
                                    url: 'javascript:;'
                                })
                                address.push({
     
                                    name: v2.name,
                                    url: v2.url,
                                })
                                this.address = address;
                            }
                        })
                    })
                }
            }
        })

2、显示菜单栏

<ul class="cl">
        
        <li v-for="vo,index in menu" :class="{hidden:vo.hidden}">
            <a href="javascript:;" :class="{active:vo.active}" @click="onActive(index)">
                <i class="layui-icon" v-html="vo.icon">i>
                <span v-text="vo.name">span>
                <i class="layui-icon arrow" v-show="vo.url.length==0">i> <i v-show="vo.active"
                                                                                      class="layui-icon active">i>
            a>
            
            <div v-for="vo2,index2 in vo.list">
                <a href="javascript:;" :class="{active:vo2.active}" @click="onActive(index,index2)"
                   v-text="vo2.name">a>
                <i v-show="vo2.active" class="layui-icon active">i>
            div>
        li>
    ul>

七、完整代码

完整代码转 Gitee:wxhntmy / SpringBootLayuiMenu

你可能感兴趣的:(前后端相关,layui,shiro,spring)