mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-05-17 17:49:23 +08:00
158 lines
4.0 KiB
Smarty
158 lines
4.0 KiB
Smarty
import { reactive, unref, computed, inject } from "vue";
|
||
import createDirective from "./createDirective";
|
||
import createComponent from "./createComponent";
|
||
import {isPlainObject} from "{{{ lodashPath }}}";
|
||
|
||
const accessKey = Symbol("plugin-access");
|
||
|
||
function isPromise(obj) {
|
||
return (
|
||
!!obj &&
|
||
(typeof obj === "object" || typeof obj === "function") &&
|
||
typeof obj.then === "function"
|
||
);
|
||
}
|
||
|
||
const state = reactive({
|
||
roles: {{{REPLACE_ROLES}}},
|
||
currentRoleId: "",
|
||
currentAccessIds: [],
|
||
});
|
||
|
||
const rolePromiseList = [];
|
||
const accessPromiseList = [];
|
||
|
||
const getAllowAccessIds = () => {
|
||
const roleAccessIds = state.roles[state.currentRoleId];
|
||
if (Array.isArray(roleAccessIds) && roleAccessIds.length > 0) {
|
||
return state.currentAccessIds.concat(roleAccessIds);
|
||
}
|
||
return state.currentAccessIds;
|
||
};
|
||
|
||
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);
|
||
}
|
||
});
|
||
};
|
||
|
||
const setAccess = (accessIds) => {
|
||
if (isPromise(accessIds)) {
|
||
return _syncSetAccessIds(accessIds);
|
||
}
|
||
if(isPlainObject(accessIds)){
|
||
if(accessIds.accessIds){
|
||
setAccess(accessIds.accessIds);
|
||
}
|
||
if(accessIds.roleId){
|
||
setRole(accessIds.roleId);
|
||
}
|
||
return
|
||
}
|
||
if (!Array.isArray(accessIds)) {
|
||
throw new Error("[plugin-access]: argument to the setAccess() must be array or promise or object");
|
||
}
|
||
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]: 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;
|
||
}
|
||
path = path.split("?")[0];
|
||
// 进入"/"路由时,此时path为“”
|
||
if (path === "") {
|
||
path = "/";
|
||
}
|
||
const len = accessIds.length;
|
||
for (let i = 0; i < len; i++) {
|
||
if (path === accessIds[i]) {
|
||
return true;
|
||
}
|
||
// 支持*匹配
|
||
const reg = new RegExp(`^${accessIds[i].replace("*", ".+")}$`);
|
||
if (reg.test(path)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
const isDataReady = () => {
|
||
return rolePromiseList.length || accessPromiseList.length;
|
||
};
|
||
|
||
const hasAccess = async (path) => {
|
||
if (!isDataReady()) {
|
||
return match(path, getAllowAccessIds());
|
||
}
|
||
await Promise.all(rolePromiseList.concat(accessPromiseList));
|
||
return match(path, getAllowAccessIds());
|
||
};
|
||
|
||
export const install = (app) => {
|
||
const allowPageIds = computed(getAllowAccessIds);
|
||
const useAccess = (path) => {
|
||
const result = computed(() => {
|
||
return match(unref(path), allowPageIds.value);
|
||
});
|
||
return result;
|
||
};
|
||
app.provide(accessKey, useAccess);
|
||
app.directive("access", createDirective(useAccess));
|
||
app.component("Access", createComponent(useAccess));
|
||
};
|
||
|
||
export const access = {
|
||
hasAccess,
|
||
isDataReady,
|
||
setRole,
|
||
setAccess,
|
||
getAccess: getAllowAccessIds,
|
||
};
|
||
|
||
export const useAccess = (path) => {
|
||
return inject(accessKey)(path);
|
||
};
|