[{"data":1,"prerenderedAt":83},["ShallowReactive",2],{"content:\u002Fposts\u002F2023\u002Fvue-project-permission-control":3,"surround:\u002Fposts\u002F2023\u002Fvue-project-permission-control":72},{"id":4,"title":5,"body":6,"canonical":40,"categories":41,"date":43,"description":44,"draft":45,"extension":46,"image":47,"meta":48,"navigation":49,"path":50,"permalink":40,"readingTime":51,"recommend":40,"references":56,"seo":66,"sitemap":67,"stem":68,"tags":69,"type":40,"updated":43,"__hash__":71},"content\u002Fposts\u002F2023\u002Fvue-project-permission-control.md","Vue项目权限控制",{"type":7,"value":8,"toc":37},"minimark",[9,21,30],[10,11,17],"pre",{"className":12,"code":14,"language":15,"meta":16},[13],"language-ts","import { createRouter, createWebHashHistory, RouteRecordRaw } from \"vue-router\"\n\n\u002F\u002F 静态路由\nconst routes: RouteRecordRaw[] = [\n    {\n        name: \"home\",\n        path: \"\u002F\",\n        meta: { label: \"首页\" },\n        component: () => import(\"..\u002Fpages\u002Fhome.vue\"),\n    },\n    {\n        name: \"login\",\n        path: \"\u002Flogin\",\n        meta: { label: \"登录\" },\n        component: () => import(\"..\u002Fpages\u002Flogin.vue\"),\n    },\n\n    {\n        name: \"disboard\",\n        path: \"\u002Fdisboard\",\n        meta: { label: \"工作台\" },\n        component: () => import(\"..\u002Fpages\u002Fdisboard.vue\"),\n    },\n]\n\n\u002F\u002F 动态路由\nconst dynamicRoutes: RouteRecordRaw[] = [\n    {\n        name: \"list\",\n        path: \"\u002Flist\",\n        meta: { label: \"列表\", roles: [\"admin\", \"user\"] },\n        component: () => import(\"..\u002Fpages\u002Flist.vue\"),\n    },\n    {\n        name: \"about\",\n        path: \"\u002Fabout\",\n        meta: { label: \"关于\", roles: [\"admin\", \"user\"] },\n        component: () => import(\"..\u002Fpages\u002Fabout.vue\"),\n    },\n    {\n        name: \"user\",\n        path: \"\u002Fuser\",\n        meta: { label: \"用户\", roles: [\"admin\", \"user\"] },\n        component: () => import(\"..\u002Fpages\u002Fuser.vue\"),\n        children: [\n            {\n                name: \"user-info\",\n                path: \"\u002Fuser\u002Finfo\",\n                meta: { label: \"用户info\", roles: [\"admin\", \"user\"] },\n                component: () => import(\"..\u002Fpages\u002Fuser-info.vue\"),\n                children: [\n                    {\n                        name: \"user-info.a\",\n                        path: \"\u002Fuser\u002Finfo\u002Fa\",\n                        meta: { label: \"用户info.a\", roles: [\"admin\", \"user\"] },\n                        component: () => import(\"..\u002Fpages\u002Fuser-info-a.vue\"),\n                    },\n                    {\n                        name: \"user-info.b\",\n                        path: \"\u002Fuser\u002Finfo\u002Fb\",\n                        meta: { label: \"用户info.b\", roles: [\"admin\", \"user\"] },\n                        component: () => import(\"..\u002Fpages\u002Fuser-info-b.vue\"),\n                    },\n                ],\n            },\n            {\n                name: \"user-orders\",\n                path: \"\u002Fuser\u002Forders\",\n                meta: { label: \"用户orders\", roles: [\"user\"] },\n                component: () => import(\"..\u002Fpages\u002Fuser-orders.vue\"),\n            },\n        ],\n    },\n]\n\n\u002F\u002F routes 扁平化处理\nfunction loopRoutes(routes: RouteRecordRaw[], role: string = \"\") {\n    const result: RouteRecordRaw[] = []\n    const loopChildren = (children: RouteRecordRaw[] = [], parent: string = \"\") => {\n        children.forEach((item) => {\n            if (item.children) {\n                const { children, ...rest } = item\n                if (!rest.meta?.roles || (rest.meta?.roles as string[]).includes(role)) {\n                    result.push(rest)\n                    if (!router.hasRoute(item.name!)) {\n                        if (parent) {\n                            router.addRoute(parent, rest)\n                        }\n                        else {\n                            router.addRoute(rest)\n                        }\n                    }\n                }\n                loopChildren(children, rest.name as string)\n            }\n            else {\n                \u002F\u002F meta信息中没有roles或者meta信息中roles包含当前登录用户的role\n                if (!item.meta?.roles || (item.meta?.roles as string[]).includes(role)) {\n                    result.push(item)\n                    if (!router.hasRoute(item.name!)) {\n                        if (parent) {\n                            \u002F\u002F 有父级\n                            router.addRoute(parent, item)\n                        }\n                        else {\n                            router.addRoute(item)\n                        }\n                    }\n                }\n            }\n        })\n    }\n    loopChildren(dynamicRoutes)\n    console.log(result)\n    return [...routes, ...result].filter(item => item.name !== \"login\")\n}\n\nconst router = createRouter({\n    history: createWebHashHistory(),\n    routes,\n})\n\nexport default router\n\nexport { loopRoutes, routes }\n","ts","router\u002Findex.ts",[18,19,14],"code",{"__ignoreMap":20},"",[10,22,28],{"className":23,"code":25,"language":26,"meta":27},[24],"language-html","\u003Cscript setup lang=\"ts\">\n  import { provide, ref, watch } from \"vue\"\n  import router, { routes } from \".\u002Frouter\"\n  const showRoutes = ref(routes)\n  provide(\"showRoutes\", showRoutes)\n  const logout = () => {\n    location.href = \"\u002F\"\n  }\n  watch(showRoutes, () => {\n    console.log(router.getRoutes()) \u002F\u002F 查看当前路由列表\n  })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Crouter-link v-for=\"route in showRoutes\" :key=\"route.name\" :to=\"{ name: route.name }\">\n    【{{ route.meta?.label }}】\n  \u003C\u002Frouter-link>\n  \u003Cbutton @click=\"logout\">退出登录\u003C\u002Fbutton>\n  \u003Chr \u002F>\n  \u003Crouter-view>\u003C\u002Frouter-view>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\u003C\u002Fstyle>\n","html","App.vue",[18,29,25],{"__ignoreMap":20},[10,31,35],{"className":32,"code":33,"language":26,"meta":34},[24],"\u003Cscript lang=\"ts\" setup>\n  import { inject, Ref } from \"vue\"\n  import { loopRoutes, routes } from \"..\u002Frouter\"\n\n  const showRoutes = inject(\"showRoutes\") as unknown as Ref\n  const login = (userType: string) => {\n    showRoutes.value = loopRoutes(routes, userType)\n  }\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  login.vue\n  \u003Cbutton @click=\"login('user')\">用户登录\u003C\u002Fbutton>\n  \u003Cbutton @click=\"login('admin')\">admin登录\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped lang=\"scss\">\u003C\u002Fstyle>\n","login.vue",[18,36,33],{"__ignoreMap":20},{"title":20,"searchDepth":38,"depth":38,"links":39},4,[],null,[42],"代码","2023-01-03 22:25:15","实现 vue 动态路由的测试，登录 user 和 admin 可以访问不同的菜单",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002F679ad72e4f05d-78.webp",{},true,"\u002Fposts\u002F2023\u002Fvue-project-permission-control",{"text":52,"minutes":53,"time":54,"words":55},"3 min read",2.575,154500,515,[57,60,63],{"title":58,"link":59},"Vue动态路由权限控制","https:\u002F\u002Fwww.bilibili.com\u002Fvideo\u002FBV1gR4y1f7tb\u002F?vd_source=6e32730b05dc719c9f21598867bef69d",{"title":61,"link":62},"addRoute","https:\u002F\u002Frouter.vuejs.org\u002Fzh\u002Fapi\u002F#addroute",{"title":64,"link":65},"hasRoute","https:\u002F\u002Frouter.vuejs.org\u002Fzh\u002Fapi\u002F#hasroute",{"title":5,"description":44},{"loc":50},"posts\u002F2023\u002Fvue-project-permission-control",[70],"Vue","XvUPE9O5NGlp-NgttCdcvnxBf0zoeO5nE_V_w7-iInI",[73,78],{"title":74,"path":75,"stem":76,"date":77,"type":40,"children":-1},"rest client插件使用","\u002Fposts\u002F2023\u002Frest-client-plugin-use","posts\u002F2023\u002Frest-client-plugin-use","2023-01-03 20:13:52",{"title":79,"path":80,"stem":81,"date":82,"type":40,"children":-1},"给vitepress添加algolia搜索","\u002Fposts\u002F2023\u002Fvitepress-add-algolia","posts\u002F2023\u002Fvitepress-add-algolia","2023-01-11 21:32:22",1789642595385]