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 クラスターの構築例

推薦する

linxu での Svn ワンクリック インストール シェル スクリプトの詳細な説明

#!/bin/bash #SVNをダウンロード yum -y サブバージョンをインストールします ...

MySQL 5.7.20 zip インストール チュートリアル

MySQL 5.7.20 zipインストール、具体的な内容は次のとおりです(1)圧縮パッケージを解凍...

Linux でスレッドを作成するための pthread_create の具体的な使用法

pthread_create関数機能紹介pthread_createはUNIX環境のスレッド作成関数...

Linux で最も頻繁に使用されるターミナル コマンドのトップ 10 のリストを取得します。

私が最も頻繁に使用するコマンドは次の通りです:選択肢CDギットls ssh須藤数週間前、私はこの R...

type=fileファイル変更フォームの名前が正常にエコーされない問題を解決

easyui フレームワークのコードは次のとおりです。 css: .ファイルボックス{ フロート:...

IE6 で幅と高さがおかしいバグ

図に示すように: しかし、IE6で表示すると、right:1px:になります。 IE6 には、幅と高...

HTMLテーブルで、各セルに異なる色と幅を設定します

設定が有効にならない場合が多いため、幅や高さなどをテーブル内で直接設定しないことをお勧めします。スタ...

Vueはファイルのアップロードとダウンロード機能を実装します

この記事では、ファイルのアップロードとダウンロード機能を実装するためのVueの具体的なコードを例とし...

初心者でもjsのtypeofとinstanceofの違いを理解できます

目次1. 型2. インスタンス3. 違い1. 型typeof 演算子は、評価されていないオペランドの...

MySQL 5.7.17 圧縮パッケージのインストール不要の構成プロセス図

MySQL データベース管理ソフトウェアには、エンタープライズ エディションとコミュニティ エディシ...

MySQL 5.7.23 winx64 のインストールと設定方法のグラフィックチュートリアル (win10 の場合)

この記事はMySQL 5.7.23 winx64のインストールチュートリアルを記録します。具体的な内...

MySQL 5.7.20 解凍版のインストールとルートパスワードの変更に関するチュートリアル

1. MySQL アーカイブ (解凍版) をダウンロードするURL: https://downloa...

MySQL の 3 つの Binlog 形式の概要と分析

1つ。 Mysql Binlog フォーマットの紹介 Mysql binlog ログには、State...

MySQL チュートリアル: サブクエリの例の詳細な説明

目次1. サブクエリとは何ですか? 2. サブクエリはどこに表示されますか? 3. Whereサブク...

VMware に Centos8 をインストールする詳細なチュートリアル

CentOS公式サイトアドレスhttps://www.centos.org/まず必要なファイルをダウ...