+67
-72
@@ -1,2 +0,2 @@ | ||
| import { Router } from 'vue-router'; | ||
| import { Router } from "vue-router"; | ||
| import { App, DefineComponent, VNode } from "vue"; | ||
@@ -8,5 +8,9 @@ | ||
| export interface RuntimeConfig { | ||
| routes?: IMenuRoutes[]; | ||
| layout?: ILayout | ((option: GetInitialStateReturnType<RuntimeConfig['getInitialState']>) => LayoutConfig); | ||
| getInitialState?: () => (Record<string, any> | Promise<Record<string, any>>); | ||
| routes?: IMenuRoutes[]; | ||
| layout?: | ||
| | ILayout | ||
| | (( | ||
| option: GetInitialStateReturnType<RuntimeConfig["getInitialState"]>, | ||
| ) => LayoutConfig); | ||
| getInitialState?: (typeof import("src/app.ts"))["getInitialState"]|(typeof import("src/app.tsx"))["getInitialState"]; | ||
| } | ||
@@ -16,9 +20,9 @@ | ||
| export interface IMenuRoutes { | ||
| path: string; | ||
| /** | ||
| * 当前页面渲染的组件,must be a absolute path | ||
| */ | ||
| component?: string; | ||
| meta?: RouteMeta; | ||
| routes?: IMenuRoutes[]; | ||
| path: string; | ||
| /** | ||
| * 当前页面渲染的组件,must be a absolute path | ||
| */ | ||
| component?: string; | ||
| meta?: RouteMeta; | ||
| routes?: IMenuRoutes[]; | ||
| } | ||
@@ -28,73 +32,64 @@ | ||
| export interface RouteMeta { | ||
| /** | ||
| * 是否在菜单中隐藏 | ||
| */ | ||
| hideInMenu?: boolean; | ||
| /** | ||
| * 是否在菜单中隐藏其子节点 | ||
| */ | ||
| hideChildrenInMenu?: boolean; | ||
| /** | ||
| * 是否渲染菜单 | ||
| */ | ||
| menuRender?: boolean; | ||
| /** | ||
| * 是否渲染页脚 | ||
| */ | ||
| footerRender?: boolean; | ||
| /** | ||
| * 是否渲染头部 | ||
| */ | ||
| headerRender?: boolean; | ||
| /** | ||
| * 当前路由是否使用内置pro layout | ||
| */ | ||
| layout?: boolean; | ||
| /** | ||
| * 权限相关设置 | ||
| */ | ||
| access?: string; | ||
| /** | ||
| * 是否打平菜单 | ||
| */ | ||
| flatMenu?: boolean; | ||
| /** | ||
| * 当前菜单icon | ||
| */ | ||
| icon?: string; | ||
| /** | ||
| * 菜单或当前页面标题 | ||
| */ | ||
| title: string; | ||
| /** | ||
| * 是否在菜单中隐藏 | ||
| */ | ||
| hideInMenu?: boolean; | ||
| /** | ||
| * 是否在菜单中隐藏其子节点 | ||
| */ | ||
| hideChildrenInMenu?: boolean; | ||
| /** | ||
| * 是否渲染菜单 | ||
| */ | ||
| menuRender?: boolean; | ||
| /** | ||
| * 是否渲染页脚 | ||
| */ | ||
| footerRender?: boolean; | ||
| /** | ||
| * 是否渲染头部 | ||
| */ | ||
| headerRender?: boolean; | ||
| /** | ||
| * 当前路由是否使用内置pro layout | ||
| */ | ||
| layout?: boolean; | ||
| /** | ||
| * 权限相关设置 | ||
| */ | ||
| access?: string; | ||
| /** | ||
| * 是否打平菜单 | ||
| */ | ||
| flatMenu?: boolean; | ||
| /** | ||
| * 当前菜单icon | ||
| */ | ||
| icon?: string; | ||
| /** | ||
| * 菜单或当前页面标题 | ||
| */ | ||
| title: string; | ||
| } | ||
| export interface ILayout { | ||
| headerRender?: DefineComponent<{},{},any> | (() => VNode); | ||
| footerRender?: DefineComponent<{},{},any> | (() => VNode); | ||
| rightRender?: DefineComponent<{},{},any> | (() => VNode); | ||
| unAccessible?: DefineComponent<{},{},any> | (() => VNode); | ||
| noFound?: DefineComponent<{},{},any> | (() => VNode); | ||
| logout?: DefineComponent<{},{},any> | (() => VNode); | ||
| headerRender?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| footerRender?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| rightRender?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| unAccessible?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| noFound?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| logout?: DefineComponent<{}, {}, any> | (() => VNode); | ||
| } | ||
| // 定义布局配置接口 | ||
| export interface LayoutConfig extends ILayout { | ||
| menu?: { | ||
| request?: () => Promise<IMenuRoutes[]>; | ||
| }; | ||
| menu?: { | ||
| request?: () => Promise<IMenuRoutes[]>; | ||
| }; | ||
| } | ||
| // 定义权限检查函数的参数类型 | ||
| export interface CheckPermissionOptions { | ||
| to: IMenuRoutes; | ||
| routes: IMenuRoutes[]; | ||
| access?: Record<string, any>; | ||
| exclude?: string[]; | ||
| } | ||
| // 定义useProvider函数的参数类型 | ||
| export interface UseProviderOptions { | ||
| globalConfig: { layout: LayoutConfig,initialState?:Record<string, any>, menuRoutes: IMenuRoutes[], access?: Record<string, any> }; | ||
| router?: Router; | ||
| config: RuntimeConfig; | ||
| access?: (typeof import("src/access"))["default"]; | ||
| router?: Router; | ||
| } |
+47
-64
| import { App, inject } from "vue"; | ||
| import { UseProviderOptions, CheckPermissionOptions, IMenuRoutes, LayoutConfig } from './type'; // 假设type.ts和hooks文件在同一目录 | ||
| import {createStore} from './useStore'; | ||
| // core/access-provider.ts | ||
| const ACCESS_KEY = Symbol('access-context'); | ||
| const APP_CONFIG = Symbol('app-config'); | ||
| import { UseProviderOptions, IMenuRoutes, LayoutConfig } from "./type"; // 假设type.ts和hooks文件在同一目录 | ||
| const LAYOUT_CONFIG = Symbol('layout-config'); | ||
| const MENU_ROUTES = Symbol('menu-config'); | ||
| function findRouteByPath(routes: IMenuRoutes[], targetPath: string): [IMenuRoutes | null, IMenuRoutes] | null { | ||
| for (const route of routes) { | ||
| if (route.path === targetPath) { | ||
| return [null, route]; | ||
| } | ||
| if (route.routes && route.routes.length > 0) { | ||
| const foundRoute = findRouteByPath(route.routes, targetPath); | ||
| if (foundRoute) { | ||
| return [route, foundRoute[1]]; | ||
| } | ||
| } | ||
| } | ||
| return null; | ||
| let ACCESS_KEY: symbol; | ||
| export const getAppConfig = async (options: UseProviderOptions) => { | ||
| const { config, access = {} } = options; | ||
| const { routes = [], layout = {}, getInitialState } = config ?? {}; | ||
| const initialState = (await getInitialState?.()) ?? {}; | ||
| const accessConfig = access?.(initialState); | ||
| const layoutConfig = | ||
| typeof layout === "function" ? layout(initialState) : layout; | ||
| const menuRoutes = | ||
| (await (layoutConfig as LayoutConfig).menu?.request?.()) ?? routes; | ||
| return { routes: menuRoutes, access: accessConfig,layout:layoutConfig }; | ||
| }; | ||
| function checkPermision(options: CheckPermissionOptions) { | ||
| const { to, routes = [], access = {}, exclude = ['/user'] } = options; | ||
| // 递归函数,用于深度查询路由 | ||
| export const useProvider = (app: App, options: { accessInjectKey: symbol; routes: IMenuRoutes[],layout:LayoutConfig }) => { | ||
| // const { accessInjectKey, routesInjectKey } = options; | ||
| const { routes, accessInjectKey,layout } = options; | ||
| const hasNoPermision = (access: Record<string, any>, currAccess?: string) => { | ||
| return currAccess && !access[currAccess]; | ||
| } | ||
| const res = findRouteByPath(routes, to.path); | ||
| /** | ||
| * 注入菜单路由 | ||
| */ | ||
| app.provide(MENU_ROUTES, routes); | ||
| if (res) { | ||
| const [parentRoutes, route] = res; | ||
| const noPermission = (hasNoPermision(access, parentRoutes?.meta?.access) || hasNoPermision(access, route.meta?.access)) && !exclude.some(_ => to.path.includes(_)); | ||
| return noPermission && to.path !== '/403' | ||
| } else { | ||
| return false | ||
| } | ||
| } | ||
| /** | ||
| * 注入布局配置 | ||
| */ | ||
| export const useProvider = async (app: App, options: UseProviderOptions) => { | ||
| const { router, globalConfig } = options ?? {}; | ||
| const { access = [], layout = {}, menuRoutes = [],initialState={} } = globalConfig; | ||
| app.config.globalProperties.$access = access; | ||
| app.provide(ACCESS_KEY, access); | ||
| app.provide(APP_CONFIG, globalConfig); | ||
| app.provide(LAYOUT_CONFIG, layout); | ||
| app.provide(MENU_ROUTES, menuRoutes); | ||
| app.provide(LAYOUT_CONFIG,layout); | ||
| /** | ||
| * 获取插件的注入key | ||
| */ | ||
| ACCESS_KEY = accessInjectKey; | ||
| /** | ||
| * 注入全局store | ||
| */ | ||
| createStore('@@initialState',initialState); | ||
| // createStore('@@initialState',initialState); | ||
| }; | ||
| router?.addRoute({ | ||
| path: '/403', | ||
| component: layout.unAccessible ?? (() => import('@mooljs/plugin-layout/layouts/403.vue')) | ||
| }); | ||
| router?.beforeEach((to, from, next) => { | ||
| const exclude = menuRoutes.filter(_ => _.meta?.layout === false)?.map(_ => _.path); | ||
| if (checkPermision({ to, routes: menuRoutes, access, exclude })) { | ||
| next('/403'); | ||
| } else { | ||
| next(); | ||
| } | ||
| }); | ||
| } | ||
| export const useAccess = () => { | ||
| return inject(ACCESS_KEY) as ReturnType< | ||
| (typeof import("src/access"))["default"] | ||
| >; | ||
| }; | ||
| export const useAccess = () => { | ||
| return inject(ACCESS_KEY) as UseProviderOptions['globalConfig']['access'] | ||
| } | ||
| export const getAppConfig = () => { | ||
| return inject(APP_CONFIG) as UseProviderOptions['globalConfig'] | ||
| } | ||
| export const useMenuRoutes = () => { | ||
| return inject(MENU_ROUTES) as UseProviderOptions['globalConfig']['menuRoutes'] | ||
| } | ||
| return inject(MENU_ROUTES) as IMenuRoutes; | ||
| }; | ||
| export const useLayout = () => { | ||
| return inject(LAYOUT_CONFIG) as UseProviderOptions['globalConfig']['layout'] | ||
| return inject(LAYOUT_CONFIG) as LayoutConfig | ||
| } |
+1
-1
| { | ||
| "name": "mooljs", | ||
| "version": "0.8.0", | ||
| "version": "1.0.0-beta", | ||
| "description": "function tool library for mooljs", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.ts", |
41727
0.03%1379
-2.06%