diff --git a/packages/fes-plugin-access/README.md b/packages/fes-plugin-access/README.md new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/packages/fes-plugin-access/README.md @@ -0,0 +1,2 @@ + + diff --git a/packages/fes-plugin-access/src/index.js b/packages/fes-plugin-access/src/index.js index aeb3b601..b01fb9e8 100644 --- a/packages/fes-plugin-access/src/index.js +++ b/packages/fes-plugin-access/src/index.js @@ -23,6 +23,7 @@ export default (api) => { const absRuntimeFilePath = join(namespace, 'runtime.js'); + const generatedOnce = false; api.onGenerateFiles(() => { // 文件写出 const { roles = {} } = api.config.access || {}; @@ -37,12 +38,10 @@ export default (api) => { ) }); - api.writeTmpFile({ - path: absRuntimeFilePath, - content: readFileSync( - join(__dirname, 'runtime/runtime.tpl'), - 'utf-8' - ) + api.copyTmpFiles({ + namespace, + path: join(__dirname, 'runtime'), + ignore: ['.tpl'] }); }); diff --git a/packages/fes-plugin-access/src/runtime/core.tpl b/packages/fes-plugin-access/src/runtime/core.tpl index 0a286aa3..15d44688 100644 --- a/packages/fes-plugin-access/src/runtime/core.tpl +++ b/packages/fes-plugin-access/src/runtime/core.tpl @@ -1,4 +1,6 @@ import { reactive, computed, inject } from "vue"; +import createDirective from "./createDirective"; +import createComponent from "./createComponent"; const accessKey = Symbol("plugin-access"); @@ -20,17 +22,11 @@ const rolePromiseList = []; const accessPromiseList = []; const getAllowAccessIds = () => { - if ( - Array.isArray(state.currentAccessIds) && - state.currentAccessIds.length > 0 - ) { - return state.currentAccessIds; - } const roleAccessIds = state.roles[state.currentRoleId]; if (Array.isArray(roleAccessIds) && roleAccessIds.length > 0) { - return roleAccessIds; + return state.currentAccessIds.concat(roleAccessIds); } - return []; + return state.currentAccessIds; }; const _syncSetAccessIds = (promise) => { @@ -55,11 +51,18 @@ const setAccess = (accessIds) => { return _syncSetAccessIds(accessIds); } if (!Array.isArray(accessIds)) { - throw new Error("[plugin-access]: pageIds必须是array"); + throw new Error("[plugin-access]: argument to the setAccess() must be array or promise"); } state.currentAccessIds = accessIds; }; +const addAccess = (accessId) => { + if (typeof accessId !== 'string') { + throw new Error("[plugin-access]: argument to the addAccess() must be string"); + } + state.currentAccessIds.push(accessId); +}; + const _syncSetRoleId = (promise) => { rolePromiseList.push(promise); promise @@ -82,12 +85,15 @@ const setRole = async (roleId) => { return _syncSetRoleId(roleId); } if (typeof roleId !== "string") { - throw new Error("[plugin-access]: roleId必须是string"); + throw new Error("[plugin-access]: argument to the setRole() must be string or promise"); } state.currentRoleId = roleId; }; const match = (path, accessIds) => { + if(path === null || path === undefined) { + return false; + } if (!Array.isArray(accessIds) || accessIds.length === 0) { return false; } @@ -131,6 +137,8 @@ export const install = (app) => { return result; }; app.provide(accessKey, useAccess); + app.directive("access", createDirective(useAccess)); + app.component("Access", createComponent(useAccess)); }; export const access = { @@ -138,6 +146,7 @@ export const access = { hasLoading, setRole, setAccess, + addAccess }; export const useAccess = (path) => { diff --git a/packages/fes-plugin-access/src/runtime/createComponent.js b/packages/fes-plugin-access/src/runtime/createComponent.js new file mode 100644 index 00000000..00b7c83e --- /dev/null +++ b/packages/fes-plugin-access/src/runtime/createComponent.js @@ -0,0 +1,7 @@ +export default function createComponent(useAccess) { + return (props, { slots }) => { + const access = useAccess(props.id); + if (!access.value || !slots.default) return null; + return slots.default(); + }; +} diff --git a/packages/fes-plugin-access/src/runtime/createDirective.js b/packages/fes-plugin-access/src/runtime/createDirective.js new file mode 100644 index 00000000..2a693fb5 --- /dev/null +++ b/packages/fes-plugin-access/src/runtime/createDirective.js @@ -0,0 +1,46 @@ +import { watch } from 'vue'; + +const cache = new WeakMap(); +const setDispaly = (el, access) => { + if (access.value) { + el.style.display = el._display; + } else { + el.style.display = 'none'; + } +}; +export default function createDirective(useAccess) { + return { + beforeMount(el) { + const ctx = {}; + ctx.watch = (path) => { + el._display = el._display || el.style.display; + const access = useAccess(path); + setDispaly(el, access); + return watch(access, () => { + setDispaly(el, access); + }); + }; + cache.set(el, ctx); + }, + mounted(el, binding) { + const ctx = cache.get(el); + if (ctx.unwatch) { + ctx.unwatch(); + } + ctx.unwatch = ctx.watch(binding.value); + }, + updated(el, binding) { + const ctx = cache.get(el); + if (ctx.unwatch) { + ctx.unwatch(); + } + ctx.unwatch = ctx.watch(binding.value); + }, + beforeUnmount(el) { + const ctx = cache.get(el); + if (ctx.unwatch) { + ctx.unwatch(); + } + } + }; +} diff --git a/packages/fes-plugin-access/src/runtime/runtime.tpl b/packages/fes-plugin-access/src/runtime/runtime.js similarity index 75% rename from packages/fes-plugin-access/src/runtime/runtime.tpl rename to packages/fes-plugin-access/src/runtime/runtime.js index d99fa95a..85da5720 100644 --- a/packages/fes-plugin-access/src/runtime/runtime.tpl +++ b/packages/fes-plugin-access/src/runtime/runtime.js @@ -1,5 +1,5 @@ -import { access, install } from "./core"; -import { plugin, ApplyPluginsType } from "@@/core/coreExports"; +import { plugin, ApplyPluginsType } from '@@/core/coreExports'; +import { access, install } from './core'; export function onRouterCreated({ router }) { router.beforeEach(async (to, from, next) => { @@ -14,11 +14,11 @@ export function onRouterCreated({ router }) { next(); } else { const runtimeConfig = plugin.applyPlugins({ - key: "access", + key: 'access', type: ApplyPluginsType.modify, - initialValue: null, + initialValue: {} }); - if (runtimeConfig.noAccessHandler && typeof runtimeConfig.noAccessHandler === "function") { + if (runtimeConfig.noAccessHandler && typeof runtimeConfig.noAccessHandler === 'function') { runtimeConfig.noAccessHandler(router, to, from); } next(false); @@ -27,5 +27,5 @@ export function onRouterCreated({ router }) { } export function onAppCreated({ app }) { - install(app) + install(app); } diff --git a/packages/fes-plugin-layout/src/index.js b/packages/fes-plugin-layout/src/index.js index 62d43f2e..b4e8efcf 100644 --- a/packages/fes-plugin-layout/src/index.js +++ b/packages/fes-plugin-layout/src/index.js @@ -26,6 +26,10 @@ export default (api) => { api.onGenerateFiles(() => { const { name } = api.pkg; + const HAS_LOCALE = api.hasPlugins(['@webank/fes-plugin-locale']); + + const HAS_ACCESS = api.hasPlugins(['@webank/fes-plugin-access']); + // .fes配置 const userConfig = { title: name, @@ -38,7 +42,7 @@ export default (api) => { readFileSync(join(__dirname, 'runtime/index.tpl'), 'utf-8'), { REPLACE_USER_CONFIG: JSON.stringify(userConfig), - HAS_LOCALE: api.pkg.dependencies?.['@webank/fes-plugin-locale'] + HAS_LOCALE } ) }); diff --git a/packages/fes-plugin-layout/src/runtime/helpers/addAccessTag.js b/packages/fes-plugin-layout/src/runtime/helpers/addAccessTag.js index feedb371..ec962335 100644 --- a/packages/fes-plugin-layout/src/runtime/helpers/addAccessTag.js +++ b/packages/fes-plugin-layout/src/runtime/helpers/addAccessTag.js @@ -1,9 +1,9 @@ import { unref, computed } from 'vue'; -import { useAccess } from '@webank/fes'; +import { useAccess } from '../../plugin-access/core'; if (!useAccess) { throw new Error( - '[plugin-layout]: pLugin-layout依赖plugin-access,请先安装plugin-access!' + '[plugin-layout]: pLugin-layout depends on plugin-access,please install plugin-access first!' ); } diff --git a/packages/fes-template/src/pages/index.vue b/packages/fes-template/src/pages/index.vue index d04a2acf..96c6bb93 100644 --- a/packages/fes-template/src/pages/index.vue +++ b/packages/fes-template/src/pages/index.vue @@ -2,7 +2,8 @@
国际化: {{t("test")}}
fes & 拉夫德鲁
- accessOnepicess: {{accessOnepicess}} + accessOnepicess1 +
accessOnepicess2
@@ -15,27 +16,33 @@