diff --git a/.fatherrc.js b/.fatherrc.js index 365d43bd..3aa9c308 100644 --- a/.fatherrc.js +++ b/.fatherrc.js @@ -4,7 +4,7 @@ import { join } from 'path'; // utils must build before core // runtime must build before renderer-react -const headPkgs = ['fes-runtime', 'fes-core', 'fes', 'fes-plugin-built-in', 'fes-plugin-request', 'fes-plugin-access']; +const headPkgs = ['fes-runtime', 'fes-core', 'fes', 'fes-plugin-built-in', 'fes-plugin-request', 'fes-plugin-access', 'fes-plugin-initstate']; const tailPkgs = []; // const otherPkgs = readdirSync(join(__dirname, 'packages')).filter( // (pkg) => @@ -18,4 +18,4 @@ export default { cjs: { type: 'babel', lazy: false }, disableTypeCheck: true, pkgs: [...headPkgs, ...otherPkgs, ...tailPkgs], -}; +}; \ No newline at end of file diff --git a/packages/fes-plugin-access/src/index.js b/packages/fes-plugin-access/src/index.js index b3e645a2..0868f041 100644 --- a/packages/fes-plugin-access/src/index.js +++ b/packages/fes-plugin-access/src/index.js @@ -109,12 +109,12 @@ export default (api) => { }); }); - // api.addPluginExports(() => [ - // { - // exportAll: true, - // source: absoluteFilePath - // } - // ]); + api.addPluginExports(() => [ + { + specifiers: ['access', 'useAccess'], + source: absoluteFilePath + } + ]); api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`); }; diff --git a/packages/fes-plugin-access/src/runtime.js b/packages/fes-plugin-access/src/runtime.js deleted file mode 100644 index dba2aa7e..00000000 --- a/packages/fes-plugin-access/src/runtime.js +++ /dev/null @@ -1,18 +0,0 @@ -import { hasAccess } from './core'; - -export function onRouterCreated({ router }) { - router.beforeEach(async (to, from, next) => { - let path; - if (to.matched.length === 1) { - path = to.matched[0].path; - } else { - path = to.path; - } - const canRoute = await hasAccess(path); - if (canRoute) { - next(); - } else { - next(false); - } - }); -} diff --git a/packages/fes-plugin-access/src/template/core.tpl b/packages/fes-plugin-access/src/template/core.tpl index 723a63aa..0a95b79e 100644 --- a/packages/fes-plugin-access/src/template/core.tpl +++ b/packages/fes-plugin-access/src/template/core.tpl @@ -1,48 +1,137 @@ -const roles = {{{REPLACE_ROLES}}}; +import { reactive, computed } from "vue"; -let allowPageIds = []; +function isPromise(obj) { + return ( + !!obj && + (typeof obj === "object" || typeof obj === "function") && + typeof obj.then === "function" + ); +} -const get = () => Promise.all(allowPageIds).then(data => data.reduce((merge, cur) => merge.concat(cur), [])); +const state = reactive({ + roles: {{{REPLACE_ROLES}}}, + currentRoleId: "", + currentAccessIds: ["/"], +}); -export const setPageIds = (pageIds) => { - if (Array.isArray(pageIds)) { - allowPageIds = pageIds.map(id => Promise.resolve(id)); - } else { - allowPageIds = [Promise.resolve(pageIds)]; +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 []; }; -export const setRoleId = async (roleId) => { - console.log('setRole'); - const _roleId = await Promise.resolve(roleId); - if (typeof _roleId !== 'string') { - throw new Error( - '[plugin-access]: roleId必须是string或者Promise的结果必须是string', - ); - } - setPageIds(roles[_roleId]); +const _syncSetAccessIds = (promise) => { + accessPromiseList.push(promise); + promise + .then((accessIds) => { + setAccess(accessIds); + }) + .catch((e) => { + console.error(e); + }) + .then(() => { + const index = accessPromiseList.indexOf(promise); + if (index !== -1) { + accessPromiseList.splice(index, 1); + } + }); }; -export const hasAccess = async (path) => { - const allowPage = await get(); - if (!Array.isArray(allowPage) || allowPage.length === 0) { +const setAccess = (accessIds) => { + if (isPromise(accessIds)) { + return _syncSetAccessIds(accessIds); + } + if (!Array.isArray(accessIds)) { + throw new Error("[plugin-access]: pageIds必须是array"); + } + state.currentAccessIds = accessIds; +}; + +const _syncSetRoleId = (promise) => { + rolePromiseList.push(promise); + promise + .then((roleId) => { + setRole(roleId); + }) + .catch((e) => { + console.error(e); + }) + .then(() => { + const index = rolePromiseList.indexOf(promise); + if (index !== -1) { + rolePromiseList.splice(index, 1); + } + }); +}; + +const setRole = async (roleId) => { + if (isPromise(roleId)) { + return _syncSetRoleId(roleId); + } + if (typeof roleId !== "string") { + throw new Error("[plugin-access]: roleId必须是string"); + } + state.currentRoleId = roleId; +}; + +const match = (path, accessIds) => { + if (!Array.isArray(accessIds) || accessIds.length === 0) { return false; } - path = path.split('?')[0]; + path = path.split("?")[0]; // 进入"/"路由时,此时path为“” - if (path === '') { - path = '/'; + if (path === "") { + path = "/"; } - const len = allowPage.length; + const len = accessIds.length; for (let i = 0; i < len; i++) { - if (path === allowPage[i]) { + if (path === accessIds[i]) { return true; } // 支持*匹配 - const reg = new RegExp(`^${allowPage[i].replace('*', '.+')}$`); + const reg = new RegExp(`^${accessIds[i].replace("*", ".+")}$`); if (reg.test(path)) { return true; } } return false; -}; \ No newline at end of file +} + +const hasLoading = ()=>{ + return rolePromiseList.length || accessPromiseList.length +} + +const hasAccess = async (path) => { + if(!hasLoading()){ + return match(path, getAllowAccessIds()) + } + await Promise.all(rolePromiseList.concat(accessPromiseList)); + return match(path, getAllowAccessIds()) +}; + +const allowPageIds = computed(getAllowAccessIds); + +export const access = { + hasAccess, + hasLoading, + setRole, + setAccess +} + +export const useAccess = (path) => { + const result = computed(() => { + return match(path, allowPageIds.value); + }); + return result; +} \ No newline at end of file diff --git a/packages/fes-plugin-access/src/template/runtime.tpl b/packages/fes-plugin-access/src/template/runtime.tpl index dba2aa7e..c40500a3 100644 --- a/packages/fes-plugin-access/src/template/runtime.tpl +++ b/packages/fes-plugin-access/src/template/runtime.tpl @@ -1,4 +1,4 @@ -import { hasAccess } from './core'; +import { access } from './core'; export function onRouterCreated({ router }) { router.beforeEach(async (to, from, next) => { @@ -8,11 +8,11 @@ export function onRouterCreated({ router }) { } else { path = to.path; } - const canRoute = await hasAccess(path); + const canRoute = await access.hasAccess(path); if (canRoute) { next(); } else { next(false); } }); -} +} \ No newline at end of file diff --git a/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/index.js b/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/index.js index 64515db1..c68c907f 100644 --- a/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/index.js +++ b/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/index.js @@ -21,4 +21,11 @@ export default function (api) { }) }); }); + + api.addExports(() => [ + { + specifiers: ['router'], + source: absoluteFilePath + } + ]); } diff --git a/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/routes.tpl b/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/routes.tpl index cbf32ff7..631f2c2c 100644 --- a/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/routes.tpl +++ b/packages/fes-plugin-built-in/src/plugins/generateFiles/core/routes/routes.tpl @@ -31,3 +31,5 @@ export const createRouter = () => { return router; }; + +export { router } \ No newline at end of file diff --git a/packages/fes-plugin-initstate/.fatherrc.js b/packages/fes-plugin-initstate/.fatherrc.js new file mode 100644 index 00000000..332f1bff --- /dev/null +++ b/packages/fes-plugin-initstate/.fatherrc.js @@ -0,0 +1,3 @@ +export default { + disableTypeCheck: false, +}; diff --git a/packages/fes-plugin-initstate/package.json b/packages/fes-plugin-initstate/package.json new file mode 100644 index 00000000..5878d8dc --- /dev/null +++ b/packages/fes-plugin-initstate/package.json @@ -0,0 +1,19 @@ +{ + "name": "@webank/fes-plugin-initstate", + "version": "1.0.0", + "description": "", + "main": "lib/index.js", + "files": [ + "lib" + ], + "module": "dist/index.esm.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "MIT", + "peerDependencies": { + "@webank/fes": "^2.0.0" + } +} diff --git a/packages/fes-plugin-initstate/src/index.js b/packages/fes-plugin-initstate/src/index.js new file mode 100644 index 00000000..5d48e800 --- /dev/null +++ b/packages/fes-plugin-initstate/src/index.js @@ -0,0 +1,21 @@ + +import { readFileSync } from 'fs'; +import { join } from 'path'; + +const namespace = 'plugin-initstate'; + +export default (api) => { + api.addRuntimePluginKey(() => 'initstate'); + + const absRuntimeFilePath = join(namespace, 'runtime.js'); + + api.onGenerateFiles(() => { + api.writeTmpFile({ + path: absRuntimeFilePath, + content: readFileSync(join(__dirname, 'template/runtime.tpl'), 'utf-8') + }); + }); + + + api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`); +}; diff --git a/packages/fes-plugin-initstate/src/template/runtime.tpl b/packages/fes-plugin-initstate/src/template/runtime.tpl new file mode 100644 index 00000000..1793aaab --- /dev/null +++ b/packages/fes-plugin-initstate/src/template/runtime.tpl @@ -0,0 +1,28 @@ +import { defineComponent } from 'vue' + +export function rootContainer(childComponent, args){ + console.log(childComponent, args) + const App = { + setup() { + const state = reactive({ + loading: true + }) + onMounted(()=>{ + setTimeout(() => { + state.loading = false + }, 3000); + }) + return () => { + if(state.loading){ + return ( + <> +
loading
+ + ) + } + return + } + } + } + return App +} \ No newline at end of file diff --git a/packages/fes-template/package.json b/packages/fes-template/package.json index e6ccfee6..aa65f4fa 100644 --- a/packages/fes-template/package.json +++ b/packages/fes-template/package.json @@ -34,7 +34,6 @@ "dependencies": { "vue": "^3.0.2", "@webank/fes": "^2.0.0", - "@webank/fes-plugin-request": "^1.0.0", "@webank/fes-plugin-access": "^1.0.0" } } diff --git a/packages/fes-template/src/app.js b/packages/fes-template/src/app.js index 958e212f..e69de29b 100644 --- a/packages/fes-template/src/app.js +++ b/packages/fes-template/src/app.js @@ -1,2 +0,0 @@ -// 配置fes-plugin-request -export const request = {}; diff --git a/packages/fes-template/src/pages/index.vue b/packages/fes-template/src/pages/index.vue index 18ec9dae..2ed28aec 100644 --- a/packages/fes-template/src/pages/index.vue +++ b/packages/fes-template/src/pages/index.vue @@ -1,17 +1,32 @@