20260803225403
This commit is contained in:
1 parent
efd5a2bc93
commit
e17bbe9db3
40 files changed
+5516
-3910
No files matched your search
@@ -1,80 +1,75 @@
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import { loadDataApi } from "@/services/api";
|
||||
import { hasPageComponent } from "@/router/pageComponents";
|
||||
import { useAuthStore } from "./auth";
|
||||
|
||||
export const usePermissionStore = defineStore("permissions", () => {
|
||||
const authStore = useAuthStore();
|
||||
const loadedPrincipalKey = ref("");
|
||||
const modules = ref([]);
|
||||
const grantedPageIds = ref([]);
|
||||
const moduleCodes = ref([]);
|
||||
const powerCodes = ref([]);
|
||||
const functionNodes = ref([]);
|
||||
const pageNodes = ref([]);
|
||||
const actions = ref([]);
|
||||
const grantedFunctionNodeIds = ref([]);
|
||||
const grantedPageNodeIds = ref([]);
|
||||
const grantedActionIds = ref([]);
|
||||
let loadingPromise = null;
|
||||
let loadingPrincipalKey = "";
|
||||
let loadVersion = 0;
|
||||
|
||||
const moduleByCode = computed(
|
||||
() => new Map(modules.value.map((module) => [String(module.b_code || ""), module])),
|
||||
const functionNodeById = computed(
|
||||
() => new Map(functionNodes.value.map((node) => [String(node.b_id), node])),
|
||||
);
|
||||
const grantedPageSet = computed(() => new Set(grantedPageIds.value));
|
||||
const powerSet = computed(() => new Set(powerCodes.value));
|
||||
const isG3soft = computed(() => {
|
||||
return (
|
||||
String(authStore.user?.account || "")
|
||||
.trim()
|
||||
.toLowerCase() === "g3soft"
|
||||
);
|
||||
});
|
||||
const grantedFunctionSet = computed(() => new Set(grantedFunctionNodeIds.value));
|
||||
const grantedPageSet = computed(() => new Set(grantedPageNodeIds.value));
|
||||
const grantedActionSet = computed(() => new Set(grantedActionIds.value));
|
||||
|
||||
async function load() {
|
||||
const userId = String(authStore.user?.id || "");
|
||||
const principalKey = `${String(authStore.orgId || "")}:${userId}`;
|
||||
if (isG3soft.value) {
|
||||
const elevatedKey = `g3soft:${principalKey}`;
|
||||
if (loadedPrincipalKey.value === elevatedKey) return;
|
||||
loadVersion++;
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
loadedPrincipalKey.value = elevatedKey;
|
||||
modules.value = [];
|
||||
grantedPageIds.value = [];
|
||||
moduleCodes.value = [];
|
||||
powerCodes.value = [];
|
||||
return;
|
||||
}
|
||||
if (!/^\d+$/.test(userId)) throw new Error("登录用户 ID 无效,请重新登录");
|
||||
const principalKey = `${String(authStore.orgId || "")}:${userId}`;
|
||||
if (loadedPrincipalKey.value === principalKey) return;
|
||||
if (loadingPromise && loadingPrincipalKey === principalKey) return loadingPromise;
|
||||
|
||||
const requestVersion = ++loadVersion;
|
||||
loadingPrincipalKey = principalKey;
|
||||
const request = Promise.all([
|
||||
loadDataApi("s_module", "b_canuse = 1", "b_id ASC"),
|
||||
loadDataApi("b_user_module", `b_user_id = ${userId}`, "b_id ASC"),
|
||||
loadDataApi("b_user_power", `b_user_id = ${userId}`, "b_id ASC"),
|
||||
loadDataApi("s_module_power", "b_canuse = 1", "b_id ASC"),
|
||||
loadDataApi("v_s_function_node", "b_canuse = 1", "b_xh ASC, b_id ASC"),
|
||||
loadDataApi("v_s_page_node", "b_canuse = 1", "b_xh ASC, b_id ASC"),
|
||||
loadDataApi("v_s_module_action", "b_canuse = 1", "b_xh ASC, b_id ASC"),
|
||||
loadDataApi(
|
||||
"v_s_user_function_permission",
|
||||
`b_user_id = ${userId}`,
|
||||
"b_function_node_id ASC",
|
||||
),
|
||||
loadDataApi("v_s_user_page_permission", `b_user_id = ${userId}`, "b_page_node_id ASC"),
|
||||
loadDataApi("v_s_user_action_permission", `b_user_id = ${userId}`, "b_action_id ASC"),
|
||||
])
|
||||
.then(([moduleResponse, userModules, userPowers, powers]) => {
|
||||
if (requestVersion !== loadVersion) return;
|
||||
const activeModules = moduleResponse.data || [];
|
||||
const moduleById = new Map(activeModules.map((module) => [String(module.b_id), module]));
|
||||
const powerById = new Map(powers.data.map((power) => [String(power.b_id), power]));
|
||||
const pageIds = userModules.data
|
||||
.map((item) => String(item.b_module_id || ""))
|
||||
.filter(Boolean);
|
||||
modules.value = activeModules;
|
||||
grantedPageIds.value = pageIds;
|
||||
moduleCodes.value = userModules.data
|
||||
.map((item) => moduleById.get(String(item.b_module_id))?.b_code)
|
||||
.filter(Boolean);
|
||||
powerCodes.value = userPowers.data
|
||||
.map((item) => powerById.get(String(item.b_power_id)))
|
||||
.filter(Boolean)
|
||||
.map((power) => `${String(power.b_module_id)}.${power.b_code}`)
|
||||
.filter(Boolean);
|
||||
loadedPrincipalKey.value = principalKey;
|
||||
})
|
||||
.then(
|
||||
([
|
||||
functionResponse,
|
||||
pageResponse,
|
||||
actionResponse,
|
||||
functionGrants,
|
||||
pageGrants,
|
||||
actionGrants,
|
||||
]) => {
|
||||
if (requestVersion !== loadVersion) return;
|
||||
functionNodes.value = functionResponse.data || [];
|
||||
pageNodes.value = pageResponse.data || [];
|
||||
actions.value = actionResponse.data || [];
|
||||
grantedFunctionNodeIds.value = (functionGrants.data || []).map((item) =>
|
||||
String(item.b_function_node_id),
|
||||
);
|
||||
grantedPageNodeIds.value = (pageGrants.data || []).map((item) =>
|
||||
String(item.b_page_node_id),
|
||||
);
|
||||
grantedActionIds.value = (actionGrants.data || []).map((item) =>
|
||||
String(item.b_action_id),
|
||||
);
|
||||
loadedPrincipalKey.value = principalKey;
|
||||
},
|
||||
)
|
||||
.finally(() => {
|
||||
if (requestVersion !== loadVersion) return;
|
||||
loadingPromise = null;
|
||||
@@ -84,26 +79,50 @@ export const usePermissionStore = defineStore("permissions", () => {
|
||||
return request;
|
||||
}
|
||||
|
||||
function resolvePageId(code) {
|
||||
const module = moduleByCode.value.get(String(code || ""));
|
||||
if (!module) return "";
|
||||
if (module.b_module_type === "page") return String(module.b_id || "");
|
||||
if (module.b_module_type === "data") return String(module.b_parent_id || "");
|
||||
return "";
|
||||
function hasGrantedDescendant(nodeId) {
|
||||
const ancestorIds = new Set();
|
||||
for (const grantedId of grantedFunctionSet.value) {
|
||||
let current = functionNodeById.value.get(grantedId);
|
||||
while (current?.b_parent_id != null) {
|
||||
const parentId = String(current.b_parent_id);
|
||||
ancestorIds.add(parentId);
|
||||
current = functionNodeById.value.get(parentId);
|
||||
}
|
||||
}
|
||||
return ancestorIds.has(String(nodeId));
|
||||
}
|
||||
|
||||
function canAccess(moduleId) {
|
||||
if (isG3soft.value || !moduleId) return true;
|
||||
const pageId = resolvePageId(moduleId);
|
||||
return !!pageId && grantedPageSet.value.has(pageId);
|
||||
function canAccessFunctionNode(nodeId) {
|
||||
const id = String(nodeId || "");
|
||||
if (!id) return false;
|
||||
const node = functionNodeById.value.get(id);
|
||||
if (!node) return false;
|
||||
if (node.b_node_type === "directory") return hasGrantedDescendant(id);
|
||||
if (node.b_page_mode === "custom" && !hasPageComponent(node.b_component_key)) return false;
|
||||
return grantedFunctionSet.value.has(id);
|
||||
}
|
||||
|
||||
function canPower(scopeCode, powerCode) {
|
||||
if (isG3soft.value) return true;
|
||||
const pageId = resolvePageId(scopeCode);
|
||||
return (
|
||||
!!pageId && grantedPageSet.value.has(pageId) && powerSet.value.has(`${pageId}.${powerCode}`)
|
||||
function canAccessRoute(path) {
|
||||
if (path === "/dashboard") return true;
|
||||
const node = functionNodes.value.find(
|
||||
(item) => item.b_node_type === "entry" && String(item.b_route || "") === String(path || ""),
|
||||
);
|
||||
return node ? canAccessFunctionNode(node.b_id) : false;
|
||||
}
|
||||
|
||||
function canViewPageNode(nodeId, permissionRequired = true) {
|
||||
if (!permissionRequired) return true;
|
||||
return grantedPageSet.value.has(String(nodeId || ""));
|
||||
}
|
||||
|
||||
function canAction(moduleIdOrCode, actionCode) {
|
||||
const action = actions.value.find(
|
||||
(item) =>
|
||||
(String(item.b_module_id) === String(moduleIdOrCode) ||
|
||||
String(item.b_module_code) === String(moduleIdOrCode)) &&
|
||||
String(item.b_code) === String(actionCode),
|
||||
);
|
||||
return action ? grantedActionSet.value.has(String(action.b_id)) : false;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
@@ -111,26 +130,30 @@ export const usePermissionStore = defineStore("permissions", () => {
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
loadedPrincipalKey.value = "";
|
||||
modules.value = [];
|
||||
grantedPageIds.value = [];
|
||||
moduleCodes.value = [];
|
||||
powerCodes.value = [];
|
||||
functionNodes.value = [];
|
||||
pageNodes.value = [];
|
||||
actions.value = [];
|
||||
grantedFunctionNodeIds.value = [];
|
||||
grantedPageNodeIds.value = [];
|
||||
grantedActionIds.value = [];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [authStore.orgId, authStore.user?.id, authStore.user?.account, authStore.token],
|
||||
clear,
|
||||
);
|
||||
watch(() => [authStore.orgId, authStore.user?.id, authStore.token], clear);
|
||||
|
||||
return {
|
||||
load,
|
||||
canAccess,
|
||||
canPower,
|
||||
clear,
|
||||
modules,
|
||||
grantedPageIds,
|
||||
moduleCodes,
|
||||
powerCodes,
|
||||
isG3soft,
|
||||
canAccessFunctionNode,
|
||||
canAccessRoute,
|
||||
canViewPageNode,
|
||||
canAction,
|
||||
canAccess: canAccessRoute,
|
||||
canPower: canAction,
|
||||
functionNodes,
|
||||
pageNodes,
|
||||
actions,
|
||||
grantedFunctionNodeIds,
|
||||
grantedPageNodeIds,
|
||||
grantedActionIds,
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user