LayUI+Shiroは動的なメニューを実装し、メニュー拡張の例を記憶します

LayUI+Shiroは動的なメニューを実装し、メニュー拡張の例を記憶します

LayUI + Shiro + Thyemleaf は動的メニューを実装し、メニューの拡張と縮小を記憶します

ここに画像の説明を挿入

ここに画像の説明を挿入

1. Maven 依存関係

<依存関係>

        <!--Ali FastJson 依存関係-->
        <依存関係>
            <グループID>com.alibaba</グループID>
            <artifactId>fastjson</artifactId>
            <バージョン>1.2.39</バージョン>
        </依存関係>
        <!--権限制御-->
        <依存関係>
            <グループID>org.apache.shiro</グループID>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <バージョン>1.4.0-RC2</バージョン>
        </依存関係>

        <!-- thymeleaf の shiro と互換性があります -->
        <依存関係>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <バージョン>2.0.0</バージョン>
        </依存関係>

        <依存関係>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </依存関係>
        <依存関係>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </依存関係>
        <依存関係>
            <グループ ID>org.mybatis.spring.boot</グループ ID>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <バージョン>2.1.4</バージョン>
        </依存関係>

        <依存関係>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>ランタイム</scope>
            <オプション>true</オプション>
        </依存関係>
        <依存関係>
            <グループID>mysql</グループID>
            <artifactId>mysql-コネクタ-java</artifactId>
            <scope>ランタイム</scope>
        </依存関係>
        <依存関係>
            <groupId>org.projectlombok</groupId>
            <artifactId>ロンボク</artifactId>
            <オプション>true</オプション>
        </依存関係>
        <依存関係>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>テスト</scope>
        </依存関係>
    </依存関係>

2. メニュー関連クラス

1. メインメニュー

ここに画像の説明を挿入

/**
 * @author wxhntmy
 */
@ゲッター
@セッター
パブリッククラスメニュー{
    プライベート文字列名;
    プライベート文字列アイコン;
    プライベート文字列 URL;
    プライベートブール値 hidden;
    プライベート List<MenuList> リスト;
}

2. サブメニュー

ここに画像の説明を挿入

/**
 * @author wxhntmy
 */
@ゲッター
@セッター
パブリッククラスMenuList {
    プライベート文字列名;
    プライベート文字列 URL;

    パブリックメニューリスト(文字列名、文字列URL) {
        this.name = 名前;
        this.url = url;
    }
}

3. Shiroの設定

1. シロコンフィグ

/**
 * @author wxhntmy
 */
@構成
パブリッククラスShiroConfig{
    /**
     * インターセプターを構成する * <p>
     * インターセプト URL 権限を定義します。上から下の優先順位は 1)。anon: 匿名アクセス、ログイン不要 2)。authc: ログインが必要 3)。logout: ログアウト 4)。
     * ロール: ロールフィルター * <p>
     * URL マッチング スタイル 1)。?: は文字に一致します。たとえば、/admin? は /admin1 に一致しますが、/admin や /admin/ には一致しません。2)。
     * *: 0 個以上の文字列に一致します。たとえば、/admin* は /admin または /admin123 に一致しますが、/admin/1 には一致しません。2)。
     * **: パス内の0個以上のパスに一致します。たとえば、/admin/** は /admin/a または /admin/a/b に一致します。
     * <p>
     * 認証成功と認証失敗のジャンプパスを設定する*/
    @ビーン
    パブリック ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = 新しい ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

        // 静的リソースへの匿名アクセス filterChainDefinitionMap.put("/layui/**", "anon");
        フィルターチェーン定義マップ.put("/js/**", "anon");
        フィルターチェーン定義マップ.put("/admin/**", "anon");

        フィルターチェーン定義マップ.put("/**/*.eot", "anon");
        フィルターチェーン定義マップ.put("/**/*.svg", "anon");
        フィルターチェーン定義マップ.put("/**/*.svgz", "anon");
        フィルターチェーン定義マップ.put("/**/*.ttf", "anon");
        フィルターチェーン定義マップ.put("/**/*.woff", "anon");
        フィルターチェーン定義マップ.put("/**/*.woff2", "anon");
        フィルターチェーン定義マップ.put("/**/*.gif", "anon");

        filterChainDefinitionMap.put("/favicon.ico", "anon");

        フィルターチェーン定義マップ.put("/login", "anon");
        filterChainDefinitionMap.put("/menu", "anon");
        filterChainDefinitionMap.put("/user/login", "anon");

        // ユーザーログアウト filterChainDefinitionMap.put("/logout", "logout");


        // 他のパスは ID 認証を必要とし、通常は最も優先順位の低い一番下にあります。filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        //ログインパス shiroFilterFactoryBean.setLoginUrl("/login");
        // ホームページ //shiroFilterFactoryBean.setSuccessUrl("/index");
        //検証失敗のジャンプパス shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean を返します。
    }

    /**
     * SecurityManager セキュリティマネージャ。shiro の中核* 
     * @戻る
     */
    @ビーン
    パブリックDefaultWebSecurityManagerセキュリティマネージャ() {
        デフォルトの Web セキュリティ マネージャー defaultWeb セキュリティ マネージャー = 新しい DefaultWeb セキュリティ マネージャー (myRealm())。
        defaultWebSecurityManager を返します。
    }

    /**
     * カスタムレルム
     * 
     * @戻る
     */
    @ビーン
    パブリックMyRealm myRealm() {
        MyRealm myRealm = 新しい MyRealm();
        myRealm.setCredentialsMatcher(myCredentialsMatcher());
        myRealm を返します。
    }

    /**
     * 暗号化方式を設定する * @return
     */
    @ビーン
    パブリック MyCredentialsMatcher myCredentialsMatcher() {
        新しい MyCredentialsMatcher() を返します。
    }

    /**
     * Shiro ライフサイクルプロセッサを構成する */
    @ビーン
    パブリックライフサイクルBeanPostProcessorライフサイクルBeanPostProcessor() {
        新しい LifecycleBeanPostProcessor() を返します。
    }

    /**
     * プロキシクラスを自動的に作成します。追加しないと、Shiro のアノテーションが有効にならない場合があります。
     */
    @ビーン
    @DependsOn({ "ライフサイクルBeanポストプロセッサ" })
    パブリックDefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator アドバイザーAutoProxyCreator = 新しい DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        advisorAutoProxyCreator を返します。
    }

    /**
     * Shiro注釈を有効にする*/
    @ビーン
    パブリック AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor の authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        authorizationAttributeSourceAdvisor を返します。
    }

    @ビーン
    パブリック ShiroDialect shiroDialect() {
        新しい ShiroDialect() を返します。
    }
}

2. Shiroのパスワード認証をカスタマイズする

/**
 * カスタム shiro パスワード検証 * @author wxhntmy
 */
パブリッククラス MyCredentialsMatcher は CredentialsMatcher を実装します {

    @リソース
    プライベート UserMapper userMapper;

    @オーバーライド
    パブリックブールdoCredentialsMatch(AuthenticationTokenトークン、AuthenticationInfo情報) {

        ユーザー名パスワードトークン utoken = (ユーザー名パスワードトークン) トークン;

        文字列パスワード = 新しい文字列(utoken.getPassword());
        文字列ユーザー名 = utoken.getUsername();

        ユーザー user = userMapper.getUserById(username);

        user.getPwd().equals(password) を返します。
    }
}

3. マイレルム

/**
 * @author wxhntmy
 */
パブリッククラスMyRealmはAuthorizingRealmを拡張します{

    @リソース
    プライベート RoleMapper roleMapper;
    @リソース
    プライベート UserRoleListMapper userRoleListMapper;

    // 承認 @Override
    保護された AuthorizationInfo doGetAuthorizationInfo(プリンシパルコレクション プリンシパルコレクション) {

        SimpleAuthorizationInfo の authorizationInfo = 新しい SimpleAuthorizationInfo();

        ユーザー user = (User) principalCollection.getPrimaryPrincipal();
        (ユーザー == null)の場合{
            null を返します。
        }


        リスト<UserRoleList> roleLists = userRoleListMapper.getUserRoleByUserId(user.getId());

        リスト<Role> roles = roleMapper.getAllRoles();

        (roleLists != null && !roleLists.isEmpty())の場合 {
            (UserRoleList ロールリスト: ロールリスト) {
                (ロール ロール: ロール) {
                    (Objects.equals(roleList.getRole_id(), role.getId())) の場合 {
                        認可情報にロールを追加します(ロールを取得します)。
                    }
                }
            }
        }
        authorizationInfo を返します。
    }

    //認証@オーバーライド
    保護されたAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) はAuthenticationExceptionをスローします {
        //ログインユーザーアカウントを取得します。UsernamePasswordToken utoken = (UsernamePasswordToken) authenticationToken;

        //ユーザーが入力したパスワードを取得します。String password = new String(utoken.getPassword());
        文字列ユーザー名 = utoken.getUsername();

        ユーザー user = new User();

        user.setId(ユーザー名);
        user.setPwd(パスワード);

        //現在のレルム オブジェクトの一意の名前。親クラスの getName() メソッドを呼び出します。String realmName = getName();

        // ソルト値、つまりユーザー名を取得します。ByteSource salt = ByteSource.Util.bytes(password);

        SimpleAuthenticationInfo 情報 = 新しい SimpleAuthenticationInfo(ユーザー、パスワード、ソルト、レルム名);

        情報を返します。

    }

}

4. コントロール

1. ログインコントローラ

@レストコントローラ
パブリッククラスLoginController {

    @リソース
    プライベート RoleMapper roleMapper;
    @リソース
    プライベート UserRoleListMapper userRoleListMapper;
    @リソース
    プライベート UserMapper userMapper;

    @RequestMapping(値 = "/user/login", メソッド = RequestMethod.GET)
    パブリックMsg<String> getUserByName(@RequestParam String user,
                                     @RequestParam 文字列 pwd、
                                     @RequestParam 文字列 ユーザータイプ、
                                     @RequestParam 文字列ボックス) {


        ロール role = roleMapper.getRoleByRoleName(usertype);
        ユーザー uUser = userMapper.getUserById(user);
        (uUser == null)の場合{
            Msg.fail("UserUnexit"); を返します。
        }
        //ログイン認証 UsernamePasswordToken token = new UsernamePasswordToken(user, pwd);
        件名 subject = SecurityUtils.getSubject();
        試す {
            subject.login(トークン);
        } キャッチ (認証例外 e) {
            Msg.fail("PasswordError"); を返します。
        }
        //ログインの有効期限をミリ秒単位で設定します。ここでは 30 分に設定されています。SecurityUtils.getSubject().getSession().setTimeout(1800000);
        Msg.ok("成功") を返します。
    }
}

2. ページコントローラ

@コントローラ
パブリッククラス PageController {

    @リソース
    プライベート UserMapper userMapper;

    @RequestMapping(値 = "/login", メソッド = RequestMethod.GET)
    パブリック文字列ログイン(){
        「ログイン」を返します。
    }

    @RequestMapping(値 = "/user/index", メソッド = RequestMethod.GET)
    パブリック文字列インデックス(モデルモデル){

        ユーザー user = (User) SecurityUtils.getSubject().getPrincipal();

        ユーザー uuser = userMapper.getUserById(user.getId());

        StringUtils.isEmpty(ユーザー)の場合{
            「redirect:/login」を返します。
        }

        モデルに属性を追加します("user", uuser);

        「インデックス」を返します。
    }
}

3. メニューコントローラー

/**
 * @author wxhntmy
 */
@レストコントローラ
パブリッククラスMenuController{

    @リソース
    プライベート RoleMapper roleMapper;
    @リソース
    プライベート UserRoleListMapper userRoleListMapper;

    //ユーザー メニュー コレクションを記憶します private Map<String, Map> menu_map = new HashMap<>();

    @RequestMapping(値 = "/menu", メソッド = RequestMethod.GET)
    パブリック Msg<List<Menu>> getMenu() {
        ユーザー user = (User) SecurityUtils.getSubject().getPrincipal();

        リスト<メニュー> リスト = 新しい ArrayList<>();

        StringUtils.isEmpty(ユーザー)の場合{
            return Msg.fail(list, "ログイン情報の有効期限が切れています。もう一度ログインしてください!");
        }

        // Map<String, Boolean> を収集することを忘れないでください。map_store = new HashMap<>();

        (menu_map.containsKey(user.getId()))の場合{
            map_store = menu_map.get(user.getId());
        }

        Map<String, String> map = new HashMap();
        リスト<UserRoleList> roleLists = userRoleListMapper.getUserRoleByUserId(user.getId());
        (UserRoleList ロールリスト: ロールリスト) {
            ロール role = roleMapper.getRoleByRoleId(roleList.getRole_id());
            ロールの取得ロール()、ロールリストの取得ユーザーID() をマップします。
        }
        メニュー menu1 = new Menu();
        menu1.setName("ホーム");
        menu1.setIcon("&#xe68e;");
        menu1.setUrl("/user/index");
        menu1.setHidden(false);

        リスト<MenuList> menuLists2 = 新しいArrayList<>();
        メニュー1.setList(メニューリスト2);
        リストに追加(メニュー1)


        map.containsKey("学生")の場合{
            メニュー menu2 = new Menu();
            メニュー menu3 = new Menu();

            menu2.setName("コース管理");
            menu2.setIcon("&#xe609;");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("コース管理", false));
            リスト<MenuList> menuLists = 新しいArrayList<>();
            MenuList menuList1 = new MenuList("選択したコース", "");
            MenuList menuList2 = new MenuList("オプションコース", "");
            MenuList menuList22 = new MenuList("コースフォーラム", "");
            メニューリストを追加します(メニューリスト1)。
            メニューリストを追加します(メニューリスト2)。
            メニューリストを追加します(メニューリスト22);
            menu2.setList(メニューリスト);

            menu3.setName("パフォーマンス管理");
            menu3.setIcon("&#xe609;");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("パフォーマンス管理", false));
            リスト<MenuList> menuLists3 = 新しいArrayList<>();
            MenuList menuList3 = new MenuList("コース結果の送信", "");
            MenuList menuList33 = new MenuList("コースログの送信", "");
            MenuList menuList4 = new MenuList("実習コースの結果", "");
            MenuList menuList5 = new MenuList("コースアンケート", "");
            メニューリスト3を追加します。
            メニューリスト3.add(メニューリスト33);
            メニューリスト3.add(メニューリスト4);
            メニューリスト3.add(メニューリスト5);
            メニュー3.setList(メニューリスト3);

            リストに追加(メニュー2)
            リストに追加します(メニュー3)。
        }

        map.containsKey("先生"){
            メニュー menu2 = new Menu();
            メニュー menu3 = new Menu();

            menu2.setName("コース管理");
            menu2.setIcon("&#xe609;");
            メニュー2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("コース管理", false));
            リスト<MenuList> menuLists = 新しいArrayList<>();
            MenuList menuList1 = new MenuList("教授のトレーニングコース", "");
            MenuList menuList2 = new MenuList("コースフォーラム", "");
            メニューリストを追加します(メニューリスト1)。
            メニューリストを追加します(メニューリスト2)。
            menu2.setList(メニューリスト);

            menu3.setName("パフォーマンス管理");
            menu3.setIcon("&#xe609;");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("パフォーマンス管理", false));
            リスト<MenuList> menuLists3 = 新しいArrayList<>();
            MenuList menuList3 = new MenuList("コース達成度チェック", "");
            MenuList menuList33 = new MenuList("コースログ承認", "");
            MenuList menuList4 = new MenuList("実習コースの結果", "");
            メニューリスト3を追加します。
            メニューリスト3.add(メニューリスト33);
            メニューリスト3.add(メニューリスト4);
            メニュー3.setList(メニューリスト3);

            リストに追加(メニュー2)
            リストに追加します(メニュー3)。
        }
        if (map.containsKey("専門家")){
            メニュー menu2 = new Menu();
            メニュー menu3 = new Menu();

            menu2.setName("実習コース運営");
            menu2.setIcon("&#xe609;");
            メニュー2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("実習コース運営", false));
            リスト<MenuList> menuLists = 新しいArrayList<>();
            MenuList menuList1 = new MenuList("認定対象となる実習コース", "");
            MenuList menuList2 = new MenuList("トレーニングコースの追加", "");
            MenuList menuList3 = new MenuList("実習コース運営", "");
            メニューリストを追加します(メニューリスト1)。
            メニューリストを追加します(メニューリスト2)。
            メニューリストを追加します(メニューリスト3)。
            menu2.setList(メニューリスト);

            menu3.setName("アンケートを公開");
            menu3.setIcon("&#xe609;");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("アンケートを公開", false));
            リスト<MenuList> menuLists1 = 新しいArrayList<>();
            MenuList menuList11 = new MenuList("アンケートを公開", "");
            MenuList menuList21 = new MenuList("回復アンケート", "");
            メニューリスト1.add(メニューリスト11);
            メニューリスト1.add(メニューリスト21);
            メニュー3.setList(メニューリスト1);

            リストに追加(メニュー2)
            リストに追加します(メニュー3)。
        }
        map.containsKey("admin") の場合{
            メニュー menu2 = new Menu();
            メニュー menu3 = new Menu();

            menu2.setName("ユーザー管理");
            menu2.setIcon("&#xe612;");
            menu2.setUrl("");
            menu2.setHidden(map_store.getOrDefault("ユーザー管理", false));
            リスト<MenuList> menuLists = 新しいArrayList<>();
            MenuList menuList0 = new MenuList("ユーザーの追加", "");
            MenuList menuList1 = new MenuList("学生アカウント", "");
            MenuList menuList2 = new MenuList("教師アカウント", "");
            MenuList menuList3 = new MenuList("研修担当者アカウント", "");
            メニューリストを追加します(メニューリスト0)。
            メニューリストを追加します(メニューリスト1)。
            メニューリストを追加します(メニューリスト2)。
            メニューリストを追加します(メニューリスト3)。
            menu2.setList(メニューリスト);

            menu3.setName("データベース管理");
            menu3.setIcon("&#xe857;");
            menu3.setUrl("");
            menu3.setHidden(map_store.getOrDefault("データベース管理", false));
            リスト<MenuList> menuLists3 = 新しいArrayList<>();
            MenuList menuList4 = new MenuList("データベースのバックアップ", "");
            MenuList menuList5 = new MenuList("データベースを復元", "");
            メニューリスト3.add(メニューリスト4);
            メニューリスト3.add(メニューリスト5);
            メニュー3.setList(メニューリスト3);

            リストに追加(メニュー2)
            リストに追加します(メニュー3)。
        }

        メニュー menu4 = new Menu();
        menu4.setName("システム設定");
        menu4.setIcon("&#xe620;");
        menu4.setUrl("");
        menu4.setHidden(map_store.getOrDefault("システム設定", false));
        リスト<MenuList> menuLists4 = 新しいArrayList<>();
        MenuList menuList5 = new MenuList("個人情報の変更", "");
        MenuList menuList6 = new MenuList("パスワードの変更", "");
        MenuList menuList7 = new MenuList("キャッシュをクリア", "");
        メニューリスト4.add(メニューリスト5);
        メニューリスト4.add(メニューリスト6);
        メニューリスト4.add(メニューリスト7);
        メニュー4.setList(メニューリスト4);

        メニュー menu5 = new Menu();
        menu5.setName("ログアウト");
        menu5.setIcon("&#xe65c;");
        menu5.setUrl("/ログアウト");
        menu5.setHidden(false);
        リスト<MenuList> menuLists5 = 新しいArrayList<>();
        メニュー5.setList(メニューリスト5);

        リストに追加(メニュー4)
        リストに追加(メニュー5)

        map.containsKey("学生")の場合{
            Msg.ok(リスト、"STU")を返します。
        }
        文字列メッセージ = null;
        map.containsKey("先生")の場合{
            メッセージ = "TEA";
        }
        if (map.containsKey("専門家")){
            メッセージ = "PRI";
        }
        map.containsKey("admin") の場合{
            メッセージ = "ADM";

        }
        Msg.ok(リスト、メッセージ)を返します。
    }

    @RequestMapping(値 = "/menu_storage", メソッド = RequestMethod.GET)
    パブリックMsg<String> menu_storage(@RequestParam String data) {

        JSONArray の jsonArray を JSONArray.parseArray(data) に変換します。
        ユーザー user = (User) SecurityUtils.getSubject().getPrincipal();

        StringUtils.isEmpty(ユーザー)の場合{
            return Msg.fail("ログイン情報の有効期限が切れています。再度ログインしてください!");
        }
        // Map<String, Boolean> を収集することを忘れないでください。map_store = new HashMap<>();

        (オブジェクト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);

        Msg.ok() を返します。
    }
}

5. データベース

1. ユーザーテーブル

ここに画像の説明を挿入

2. 役割表

ここに画像の説明を挿入

3. user_role_list テーブル

ここに画像の説明を挿入

6. フロントエンドページ

1. Ajaxリクエストメニューデータ

		config = {} とします。
        関数set_menu() {
            //ajax 情報を送信$.ajax({
                タイプ: "get",
                非同期: false、
                url: "/menu", // リクエストはLoginServletに送信されます dataType: 'json',
                成功: 関数 (メッセージ) {
                    msg.ok === true の場合、msg.data は次のようになります。
                        config["name"] = msg.message;
                        config["メニュー"] = msg.data;
                    }
                    msg.ok が false の場合
                        window.location.href = "/ログアウト";
                    }
                    if (!msg.data) {
                        window.location.href = "/ログアウト";
                    }
                },
                エラー: 関数 (メッセージ) {
                    // リクエストが失敗したときにこの関数を実行します。layer.alert('メニューデータのリクエストに失敗しました!!!', function (index) {
                        //何かをする
                        レイヤーを閉じます(インデックス);
                    });
                }
            });
        }

        set_menu();


        $(ドキュメント).ready(関数() {
            //削除$(".del").click(function() {
                var url = $(this).attr("href");
                var id = $(this).attr("データID");

                layer.confirm('本当に削除しますか?', {
                    ボタン: ['OK', 'キャンセル']
                }、 関数 () {
                    $.get(url, 関数(データ) {
                        (データコード === 1)の場合{
                            $(id).fadeOut();
                            レイヤー.msg(データ.msg、{アイコン: 1});
                        } それ以外 {
                            レイヤー.msg(data.msg, {アイコン: 2});
                        }
                    });
                }、 関数 () {
                    layer.msg("削除をキャンセルしました!");
                });
                false を返します。
            });
        })

        layui.use('form', 関数() {
            var フォーム = layui.form,
                レイヤー = layui.layer;
        });

        var vue = 新しい Vue({
            el: '#app',
            データ: {
                ウェブ名: config.name、
                メニュー: [],
                住所: []
            },
            作成: 関数 () {
                config.menu をカスタマイズします。
                this.thisActive();
                this.thisAttr();
            },
            メソッド: {
                // onActiveを閉じることを忘れないでください: function (pid, id = false) {
                    データを入力します。
                    id === falseの場合{
                        データ = this.menu[pid];
                        (data.url.length > 0) の場合 {
                            this.menu.forEach((v, k) => {
                                v.active = false;
                                v.list.forEach((v2, k2) => {
                                    アクティブ = false;
                                })
                            })
                            データアクティブ = true;
                        }
                        データ.hidden = !データ.hidden;
                    } それ以外 {
                        this.menu.forEach((v, k) => {
                            v.active = false;
                            v.list.forEach((v2, k2) => {
                                アクティブ = false;
                            })
                        })
                        データ = this.menu[pid].list[id];
                    }

                    this.updateStorage();
                    (data.url.length > 0) の場合 {
                        if (データ.ターゲット) {
                            (data.target === '_blank')の場合{
                                ウィンドウを開きます(data.url);
                            } それ以外 {
                                データURLをコピーします。
                            }
                        } それ以外 {
                            データURLをコピーします。
                        }
                    }
                },

                //メニューキャッシュを更新する updateStorage() {
                    //sessionStorage.menu = JSON.stringify(this.menu);
                    $.ajax({
                        タイプ: "get",
                        非同期: false、
                        url: "/menu_storage", // リクエストはLoginServletに送信されます data: {
                            "データ": JSON.stringify(this.menu)
                        },
                        データ型: 'json',
                        成功: 関数 (メッセージ) {

                        },
                        エラー: 関数 (メッセージ) {
                            // リクエストが失敗したときにこの関数を実行します var index = layer.load();
                            レイヤーを閉じます(インデックス);
                            layer.alert('メニューデータの要求に失敗しました!!!', function (index) {
                                //何かをする
                                レイヤーを閉じます(インデックス);
                            });
                        }
                    });
                },
                //メニューのハイライト thisActive: function () {
                    pathname = window.location.pathname; とします。
                    ホストを window.location.host とします。
                    pid = false とします。
                    id = false とします。
                    this.menu.forEach((v, k) => {
                        url = v.url; とします。
                        url.length > 0 の場合 {
                            url[0] !== '/' && url.substr(0, 4) !== 'http' の場合 {
                                url = '/' + url;
                            }
                        }
                        if (パス名 === URL) {
                            pid = k;
                        }
                        v.list.forEach((v2, k2) => {
                            url = v2.url; とします。

                            url.length > 0 の場合 {
                                url[0] !== '/' && url.substr(0, 4) !== 'http' の場合 {
                                    url = '/' + url;
                                }
                            }
                            if (パス名 === URL) {
                                pid = k;
                                id = k2;
                            }
                        })
                    })


                    id !== false の場合 {
                        this.menu[pid].list[id].active = true;
                    } それ以外 {
                        pid !== false の場合 {
                            this.menu[pid].active = true;
                        }
                    }

                    this.updateStorage();

                },
                //現在の位置 thisAttr: function () {
                    //現在の位置 let address = [{
                        名前: 'ホームページ',
                        URL: '/user/index'
                    }];
                    this.menu.forEach((v, k) => {
                        v.list.forEach((v2, k2) => {
                            (v2.active) の場合 {
                                アドレス.push({
                                    名前: v.name、
                                    url: 'javascript:;'
                                })
                                アドレス.push({
                                    名前: v2.name、
                                    URL: v2.url、
                                })
                                this.address = アドレス;
                            }
                        })
                    })
                }
            }
        })

2. メニューバーを表示する

<ul class="cl">
        <!--トップカテゴリー-->
        <li v-for="vo,メニュー内のインデックス" :class="{hidden:vo.hidden}">
            <a href="javascript:;" rel="外部nofollow" rel="外部nofollow" :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">&#xe61a;</i> <i v-show="vo.active"
                                                                                      class="layui-icon active">&#xe623;</i>
            </a>
            <!--サブカテゴリ-->
            <div v-for="vo2,vo.list のインデックス2">
                <a href="javascript:;" rel="外部 nofollow" rel="外部 nofollow" :class="{active:vo2.active}" @click="onActive(index,index2)"
                   v-text="vo2.name"></a>
                <i v-show="vo2.active" class="layui-icon active">&#xe623;</i>
            </div>
        </li>
    </ul>

7. 完全なコード

コード転送を完了しました Gitee: wxhntmy/SpringBootLayuiMenu

これで、LayUI+Shiro の動的メニューの実装例とメニューの拡大と縮小を記憶する例についての記事は終了です。LayUI Shiro の動的メニューに関するその他の関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • SpringBoot 構成 shiro セキュリティ フレームワークの実装
  • SpringBoot は、Shiro パスワード ログインと電子メール検証コード ログイン機能を統合します (マルチレルム認証)
  • Springbootがshiroを統合する際に静的リソースが傍受される問題を解決する
  • Shiro を springboot と統合する手順
  • Shiro+Redis でログイン時間を凍結する例
  • Springboot は Shiro 統合 JWT サンプル コードを実装します
  • Springmvc 統合 shiro ログイン失敗処理操作
  • Swagger と shiro の統合に関する注意事項

<<:  Linux で nginx を起動および再起動する方法

>>:  docker ベースの redis-sentinel クラスターの構築例

推薦する

nginx を介して方向プロキシを実装するプロセスの図

この記事は主に、nginx を介して方向プロキシを実装するプロセスを紹介します。この記事のサンプル ...

MySQLカスタム変数の概念と特徴

MySQL カスタム値は、値を保存するための一時的なコンテナです。サーバーへの接続がアクティブである...

複数の画像を切り替えるJavaScript

この記事では、複数の画像を切り替えるJavaScriptの具体的なコードを参考までに紹介します。具体...

Linux で libudev を使用して USB デバイスの VID と PID を取得する方法

この記事では、libudev ライブラリを使用して hidraw デバイスにアクセスします。 lib...

LinuxでIPを表示する方法の例

ネットワークの問題のトラブルシューティング、新しい接続のセットアップ、ファイアウォールの構成を行うと...

Django+mysql の設定と簡単な操作データベースのサンプルコード

ステップ1: MySQLドライバをダウンロードするcmdは作成されたDjangoプロジェクトディレク...

JavaScript 以外の静的リソースのバンドルの詳細

目次1. パッケージングツールでのカスタムインポート2. ブラウザとバンドラの共通インポート構文3....

MySQL B-Tree インデックスの簡単な分析

Bツリーインデックス異なるストレージ エンジンでは、異なるストレージ構造を使用する場合もあります。た...

MySQL における explain の役割の詳細な説明

1. MYSQLインデックスインデックス: MySQL がデータを効率的に取得するのに役立つデータ構...

バッチモードでtopコマンドを実行する方法

top コマンドは、Linux システムのパフォーマンスを監視するために誰もが使用している最適なコマ...

高速レイアウトのための CSS ビューポート単位

CSS ビューポート ユニットはここ数年登場しており、時が経つにつれて、ますます多くの開発者が使用し...

タブバーの切り替え効果を実現するJavaScript

タブバー: 異なるタブをクリックすると異なるコンテンツが表示され、クリックしたタブのスタイルが変更さ...

MySQLでconcat関数を使用する方法

以下のように表示されます。 //managefee_managefee テーブルの年と月を照会し、c...

Vue で Baidu Map を呼び出して経度と緯度を取得する

プロジェクトでは、現在地の緯度経度を取得したり、場所を検索して緯度経度情報を取得したりする必要があり...

Linux でファイルプレフィックスを一括で追加する方法

フォルダー内のすべての txt ファイルのファイル名の前に「gt_」を追加する必要があります。つまり...