电影网站权重怎么做,wordpress 没有远程发布,wordpress 商城 支付宝,万全网站建设GitHub Demo 地址 在线预览 前言 关于动态获取路由已在这里给出方案 Vue - vue-admin-template模板项目改造#xff1a;动态获取菜单路由 这里是在此基础上升级成vue3和ts#xff0c;数据和网络请求是通过mock实现的 具体代码请看demo!!! 本地权限控制#xff0c;具体是通过… GitHub Demo 地址 在线预览 前言 关于动态获取路由已在这里给出方案 Vue - vue-admin-template模板项目改造动态获取菜单路由 这里是在此基础上升级成vue3和ts数据和网络请求是通过mock实现的 具体代码请看demo!!! 本地权限控制具体是通过查询用户信息获取用户角色在路由守卫中通过角色过滤本地配置的路由把符合角色权限的路由生成一个路由数组 动态获取菜单路由其实思路是一样的只不过路由数组变成从服务器获取通过查询某个角色的菜单列表然后在路由守卫中把获取到的菜单数组转成路由数组 动态路由实现是参考vue-element-admin的issues写的相关issues vue-element-admin/issues/167 vue-element-admin/issues/293 vue-element-admin/issues/3326#issuecomment-832852647
关键点 主要在接口菜单列表中把父component的Layout 改为字符串 ‘Layout’ children的component: () import(‘/views/system/user/index.vue’), 改成 字符串’system/user/index’然后在获取到数据后再转回来 !!!!!!!!!!!! 接口格式可以根据项目需要自定义不一定非得按照这里的来 vue3 中component使用和vue略有差异需要加上完整路径并且从字符串换成组件的方式也有不同 !!!!!!!!!注意文件路径
import { defineAsyncComponent } from vue
const modules import.meta.glob(../../views/**/**.vue)// 加载路由
const loadView (view: string) {// 路由懒加载// return defineAsyncComponent(() import(/src/views/${view}.vue))return modules[../../views/${view}.vue]
}调用
loadView(route.component)本地路由格式
import { AppRouteType } from /router/typesconst Layout () import(/layout/index.vue)const systemRouter: AppRouteType {path: /system,name: system,component: Layout,meta: { title: SystemSetting, icon: ep:setting, roles: [admin] },children: [{path: user,name: user,component: () import(/views/system/user/index.vue),meta: {title: SystemUser,icon: user,buttons: [user-add, user-edit, user-look, user-export, user-delete, user-assign, user-resetPwd]}},{path: role,name: role,component: () import(/views/system/role/index.vue),meta: {title: SystemRole,icon: role,buttons: [role-add, role-edit, role-look, role-delete, role-setting]}},{path: menu,name: menu,component: () import(/views/system/menu/index.vue),meta: {title: SystemMenu,icon: menu,buttons: [menu-add, menu-edit, menu-look, menu-delete]}},{path: dict,name: dict,component: () import(/views/system/dict/index.vue),meta: {title: SystemDict,icon: dict,buttons: [dict-type-add, dict-type-edit, dict-type-delete, dict-item-add, dict-item-edit, dict-item-delete]}}]
}
export default systemRouterts路由类型定义
import type { RouteRecordRaw, RouteMeta, RouteRecordRedirectOption } from vue-routerexport type ComponentT any ReturnTypetypeof defineComponent | (() Promisetypeof import(*.vue)) | (() PromiseT)// element-plus图标
// https://icon-sets.iconify.design/ep/
// 其他的
// https://icon-sets.iconify.design/
// 动态图标
// https://icon-sets.iconify.design/line-md/
// https://icon-sets.iconify.design/svg-spinners/export interface AppRouteMetaType extends RouteMeta {title?: stringicon?: string // 设置svg图标和通过iconify使用的element-plus图标根据 : 判断是否是iconify图标hidden?: booleanaffix?: booleankeepAlive?: booleanroles?: string[]buttons?: string[]
}export interface AppRouteType extends OmitRouteRecordRaw, props {path: stringname?: stringcomponent?: Component | stringcomponents?: Componentchildren?: AppRouteType[]fullPath?: stringmeta?: AppRouteMetaTyperedirect?: stringalias?: string | string[]
}// 动态路由类型
export interface AppDynamicRouteType extends AppRouteType {id: stringcode: stringtitle: stringparentId: stringparentTitle: stringmenuType: stringcomponent: string | Componenticon: stringsort: numberhidden: booleanlevel: numberchildren?: AppDynamicRouteType[]buttons?: string[]
}接口路由格式
{id: 22,code: /system,title: 系统设置,parentId: ,parentTitle: ,menuType: catalog, // catalog | menu | buttoncomponent: Layout, // Layout | system/menu (文件路径: src/views/) | // component: Layout,icon: ep:setting,sort: 1,hidden: false,level: 1,children: [{id: 22-1,code: user,title: 用户管理,parentId: 22,parentTitle: 系统设置,menuType: menu,component: system/user/index,// component: () import(/views/system/user),icon: user,sort: 2,hidden: false,level: 2,children: [],buttons: [user-add, user-edit, user-look, user-export, user-delete, user-assign, user-resetPwd]},{id: 22-2,code: role,title: 角色管理,parentId: 22,parentTitle: 系统设置,menuType: menu,component: system/role/index,icon: role,sort: 3,hidden: false,level: 2,children: [],buttons: [role-add, role-edit, role-look, role-delete, role-setting]},{id: 22-3,code: menu,title: 菜单管理,parentId: 22,parentTitle: 系统设置,menuType: menu,component: system/menu/index,icon: menu,sort: 4,hidden: false,level: 2,children: [],buttons: [menu-add, menu-edit, menu-look, menu-delete]},{id: 22-4,code: dict,title: 字典管理,parentId: 22,parentTitle: 系统设置,menuType: menu,component: system/dict/index,icon: dict,sort: 5,hidden: false,level: 2,children: [],buttons: [dict-type-add, dict-type-edit, dict-type-delete, dict-item-add, dict-item-edit, dict-item-delete]}]}我这里在mock中加了个角色editor2当editor2登录使用的从服务器获取动态路由其他角色从本地获取路由 permission.ts 实现其中filterAsyncRoutes2方法就是格式化菜单路由的方法 import { defineAsyncComponent } from vue
import { cloneDeep } from lodash-es
import { defineStore } from pinia
import { store } from /store
import { asyncRoutes, constantRoutes } from /routerimport { AppRouteType, AppDynamicRouteType } from /router/typesconst modules import.meta.glob(../../views/**/**.vue)
const Layout () import(/layout/index.vue)/*** Use meta.role to determine if the current user has permission* param roles* param route*/
const hasPermission (roles: string[], route: AppRouteType) {if (route.meta route.meta.roles) {return roles.some((role) {if (route.meta?.roles ! undefined) {return (route.meta.roles as string[]).includes(role)}})}return true
}/*** Filter asynchronous routing tables by recursion* param routes asyncRoutes* param roles*/
const filterAsyncRoutes (routes: AppRouteType[], roles: string[]) {const res: AppRouteType[] []routes.forEach((route) {const tmp cloneDeep(route)// const tmp { ...route }if (hasPermission(roles, tmp)) {if (tmp.children) {tmp.children filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
}// 加载路由
const loadView (view: string) {// 路由懒加载// return defineAsyncComponent(() import(/src/views/${view}.vue))return modules[../../views/${view}.vue]
}/*** 通过递归格式化菜单路由 (配置项规则https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/router-and-nav.html#配置项)* param routes*/
export function filterAsyncRoutes2(routes: AppDynamicRouteType[]) {const res: AppDynamicRouteType[] []routes.forEach((route) {const tmp cloneDeep(route)// const tmp { ...route }tmp.id route.idtmp.path route.codetmp.name route.codetmp.meta { title: route.title, icon: route.icon, buttons: route.buttons }if (route.component Layout) {tmp.component Layout} else if (route.component) {tmp.component loadView(route.component)}if (route.children route.children.length 0) {tmp.children filterAsyncRoutes2(route.children)}res.push(tmp)})return res
}// setup
export const usePermissionStore defineStore(permission, () {// stateconst routes refAppRouteType[]([])// actionsfunction setRoutes(newRoutes: AppRouteType[]) {routes.value constantRoutes.concat(newRoutes)}function generateRoutes(roles: string[]) {return new PromiseAppRouteType[]((resolve, reject) {let accessedRoutes: AppRouteType[] []if (roles.includes(admin)) {accessedRoutes asyncRoutes || []} else {accessedRoutes filterAsyncRoutes(asyncRoutes, roles)}setRoutes(accessedRoutes)resolve(accessedRoutes)})}function generateDynamicRoutes(menus: AppDynamicRouteType[]) {return new PromiseAppRouteType[]((resolve, reject) {const accessedRoutes filterAsyncRoutes2(menus)setRoutes(accessedRoutes) // Todo: 内部拼接constantRoutes所以查出来的菜单不用包含constantRoutesresolve(accessedRoutes)})}return { routes, setRoutes, generateRoutes, generateDynamicRoutes }
})// 非setup
export function usePermissionStoreHook() {return usePermissionStore(store)
}
按钮权限控制 directive文件夹创建permission.ts指令设置路由内的按钮权限 import { useUserStoreHook } from /store/modules/user
import { Directive, DirectiveBinding } from vue
import router from /router/index/*** 按钮权限 eg: v-hasPerm[user-add,user-edit]*/
export const hasPerm: Directive {mounted(el: HTMLElement, binding: DirectiveBinding) {// 「超级管理员」拥有所有的按钮权限const { roles, perms } useUserStoreHook()if (roles.includes(admin)) {return true}// 「其他角色」按钮权限校验const buttons router.currentRoute.value.meta.buttons as string[]const { value } bindingif (value) {const requiredPerms value // DOM绑定需要的按钮权限标识const hasPerm buttons?.some((perm) {return requiredPerms.includes(perm)})if (!hasPerm) {el.parentNode el.parentNode.removeChild(el)}} else {throw new Error(need perms! Like v-has-perm\[user-add,user-edit]\)}}
}创建index.ts文件全局注册 directive import type { App } from vueimport { hasPerm } from ./permission// 全局注册 directive
export function setupDirective(app: AppElement) {// 使 v-hasPerm 在所有组件中都可用app.directive(hasPerm, hasPerm)
} 在main.ts注册自定义指令 import { setupDirective } from /directiveconst app createApp(App)
// 全局注册 自定义指令(directive)
setupDirective(app)使用
el-button v-hasPerm[user-item-add] 新增 /el-button