问题描述:
pro 后台在没有勾选二级菜单下的一个菜单时,用子管理员登录直接进入了 403 页面;
可能原因:
1. 后台没有返回对应的菜单权限(可行性较小,已经勾选对应菜单)
2. 后台登录后跳转问题(很有可能是跳转到了没有权限的菜单内导致直接进入了 403,可能性贴别大)
最终问题:
由于前台路由定义,大路由组上都自带有重定向到子路由上的功能,导致在进入某个大菜单下直接跳转进入重定向的路由上导致的。这个问题完全吻合问题 2 的可能性。
处理方式:
修改所有路由组的自动重定向功能,禁用掉;
这样修改后却出现了进入后台没有底部菜单,也没有左侧菜单的问题
那么这是由于什么问题导致的呢?
如下图,发现顶部菜单是在 main.js 中的 watch 监听路由中设置的。
注意:getHeaderName 方法时为了从当前路由找到当前顶部菜单到底是谁
而这时 headerName 却为 null 导致顶部菜单根本无法设置;
1.  没有找到顶部菜单,那么就是路由调整的地址有问题,没有在当前权限菜单的路由里面导致没有找到;
2.  登录的时候进行了跳转不会是,登录的时候跳转的路由地址有问题;
3.  如果调整登录的处理跳转地址,是否能解决此问题。答案是肯定的;
经过了如上分析,发现根本原因就是:登录跳转的路径不对。进入 403 页面后返回主页的跳转路由也是不对导致。进入 403 后,就成了死循环。
最终处理方式:
1. 修改路由组中的重定向,下图中的文件内,注释掉重定向
如下图
这样就处理掉了,没有勾选子菜单的第一个菜单导致出现的 403 问题
2. 修改登录写入订单和侧边菜单和返回主页条状路径
 import { getHeaderName, getHeaderSider, getMenuSider } from '@/libs/system';
getChilden(data) {
    if(data.length && data[0].children) {
        return this.getChilden(data[0].children)
    }
    return data[0].path
},
AccountLogin({
    account: this.formInline.username,
    pwd: this.formInline.password,
    imgcode: this.formInline.code}).then(async res => {
    msg();    
if (!res.data.unique_auth.length)
 return this.$Message.error('您暂无任何菜单权限');
    this.$store.dispatch('admin/account/setPageTitle')
    let expires = res.data.expires_time;
    // 记录用户登陆信息
    util.cookies.set('uuid', res.data.user_info.id, {
        expires: expires
    });
    util.cookies.set('token', res.data.token, {
        expires: expires
    });
    util.cookies.set('expires_time', res.data.expires_time, {
        expires: expires
    });
    const db = await this.$store.dispatch('admin/db/database', {
        user: true
    });
    // 保存菜单信息
    // db.set('menus', res.data.menus).set('unique_auth', res.data.unique_auth).set('user_info', res.data.user_info).write();
    db.set('unique_auth', res.data.unique_auth).set('user_info', res.data.user_info).write();
    const menuSider = res.data.menus;
    ### 写入菜单
    this.$store.commit('admin/menus/getmenusNav', menuSider);
    let headerSider = getHeaderSider(res.data.menus);
    ### 写入顶级菜单
    this.$store.commit('admin/menu/setHeader', headerSider);
    ### 找到当前菜单一个跳转的子菜单
    let toPath = this.getChilden(res.data.menus);
    // 获取侧边栏菜单
    const headerName = getHeaderName({
        path: toPath,
        query:{},
        params:{},
    }, menuSider);
    const filterMenuSider = getMenuSider(menuSider, headerName);
    // 指定当前显示的侧边菜单
    this.$store.commit('admin/menu/setSider', filterMenuSider[0].children);
    //设置首页path
    this.$store.commit('admin/menus/setIndexPath', toPath);
    // 记录用户信息
    this.$store.dispatch('admin/user/set', {
        name: res.data.user_info.account,
        avatar: res.data.user_info.head_pic,
        access: res.data.unique_auth,
        logo: res.data.logo,
        logoSmall: res.data.logo_square,
        version: res.data.version,
        newOrderAudioLink: res.data.newOrderAudioLink
    });
    // if (this.jigsaw) this.jigsaw.reset();
    ### 调整的地址也需要调整 toPath就是当前跳转的第一个子菜单
    return this.$router.replace({ path: this.$route.query.redirect || toPath || '/admin/' });}).catch(res => {    console.log(res);    msg();    let data = res === undefined ? {} : res;    this.errorNum++;    this.captchas();    this.$Message.error(data.msg || '登录失败');});
       复制代码
 手机号登录的时候需要修改成相同的逻辑
 
3. 修改获取顶部菜单条状的 path 路径,文件路径:/src/store/modules/admin/modules/menu.js
 /**
 * @description 根据 user 里登录用户权限,对顶栏菜单进行鉴权过滤
 *
 */
filterHeader(state, getters, rootState) {
    function getChilden(data) {
        if(data.children) {
            return getChilden(data.children[0])
        }
        return data.path
    }
    // 之前是获取了一级跳转路径,现在改为获取子菜单的第一个菜单路径,
    // 这样在点击顶部菜单的时候,跳转路径保证正确
    //  调用递归函数
    state.header.forEach(item => {
        item.path = getChilden(item)
    })
    // @权限
    const userInfo = rootState.admin.user.info;
    const access = userInfo.access;
    if (access && access.length) {
        return state.header.filter(item => {
            let state = true;
            if (item.auth && !includeArray(item.auth, access)) state = false;
            return state;
        });
    } else {
        return state.header.filter(item => {
            let state = true;
            if (item.auth && item.auth.length) state = false;
            return state;
        });
    }
},
       复制代码
 4. 修改进入 403 页面返回首页的路径
 /src/store/modules/admin/modules/menus.js
export default {
    namespaced: true,
    state: {
        menusName: getMenusName(),
        //返回首页path
        indexPath: '',
    },
    mutations: {
        getmenusNav (state, menuList) {
            state.menusName = menuList;
            let storage = window.localStorage;
            storage.setItem('menuList', JSON.stringify(menuList));
        },
        /**
         * @description 设置返回首页path
         * @param {Object} state vuex state
         * @param {Array} menu menu
         */
        setIndexPath(state, data) {
            state.indexPath = data;
        },
    },
    getters:{
        //增加了返回首页的条状路径获取,在登录的页面已经设置过。
        indexPath(state, getters) {
            const menus = state.menusName;
            if (menus.length && !state.indexPath) {
                let getChilden = function(data) {
                    if(data.length && data[0].children) {
                        return getChilden(data[0].children)
                    }
                    return data[0].path
                }
                let toPath = getChilden(menus);
                state.indexPath = toPath;
            } else if (!menus.length && !state.indexPath) {
                return '/admin/home'
            }
            return state.indexPath;
        },
    },
}
       复制代码
 然后可以修改 403 页面的跳转路径
 /src/pages/system/error/403/index.vue
<template>
    <div>
        <Exception type="403" img-color :desc="$t('page.exception.e403')" :back-text="$t('page.exception.btn')" :redirect="indexPath"/>
    </div>
</template>
<script>
    import { mapGetters } from "vuex";
    export default {
        data(){
            return {
            }
        },
        computed: {
            ...mapGetters('admin/menus', [
                'indexPath'
            ])
        },
    }
</script>
       复制代码
 修改完成后大功告成,设置的子菜单第一个菜单不用设置也能进入后台了。
 
源码附件已经打包好上传到百度云了,大家自行下载即可~
 链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27提取码: yu27
       复制代码
 百度云链接不稳定,随时可能会失效,大家抓紧保存哈。
如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~
开源地址
码云地址:http://github.crmeb.net/u/defu
Github 地址:http://github.crmeb.net/u/defu
评论