410 lines
11 KiB
TypeScript
410 lines
11 KiB
TypeScript
import { defineStore } from "pinia";
|
|
import {
|
|
PermissionAPI,
|
|
RoleAPI,
|
|
type ModuleCode,
|
|
type PermissionPayload,
|
|
type Role as UserRole
|
|
} from "timi-web";
|
|
import type {
|
|
Permission,
|
|
PermissionDraft,
|
|
Role,
|
|
RoleDraft,
|
|
RolePayload
|
|
} from "@/types/PermissionSettings";
|
|
|
|
export const moduleCode: ModuleCode = "GAO";
|
|
const pageSize = 1000;
|
|
|
|
export type {
|
|
Permission,
|
|
PermissionDraft,
|
|
Role,
|
|
RoleDraft,
|
|
RolePayload
|
|
} from "@/types/PermissionSettings";
|
|
|
|
function normalizeRole(role: UserRole): Role {
|
|
return {
|
|
...role,
|
|
id: role.id || "",
|
|
moduleCode: role.moduleCode || moduleCode,
|
|
description: role.description || "",
|
|
parentRoleId: role.parentRoleId || role.parentRole?.id,
|
|
permissionIdList: role.permissionIdList || role.permissionList?.map(item => item.id) || [],
|
|
childRoleIdList: role.childRoleIdList || role.childRoleList?.map(item => item.id).filter((id): id is string => Boolean(id)) || [],
|
|
delegationPermissionIdList: role.delegationPermissionIdList || role.delegationPermissionList?.map((item: Permission) => item.id) || []
|
|
};
|
|
}
|
|
|
|
function createEmptyRole(): Role {
|
|
return {
|
|
id: "",
|
|
moduleCode: moduleCode,
|
|
code: "",
|
|
name: "",
|
|
description: "",
|
|
permissionIdList: [],
|
|
childRoleIdList: [],
|
|
delegationPermissionIdList: []
|
|
};
|
|
}
|
|
|
|
function createEmptyPermission(): Permission {
|
|
return {
|
|
id: "",
|
|
moduleCode: moduleCode,
|
|
code: "",
|
|
name: "",
|
|
description: ""
|
|
};
|
|
}
|
|
|
|
export const usePermissionSettingsStore = defineStore("permission-settings", () => {
|
|
const roleList = ref<Role[]>([]);
|
|
const permissionList = ref<Permission[]>([]);
|
|
const manageableRoleList = ref<Role[]>([]);
|
|
const grantablePermissionList = ref<Permission[]>([]);
|
|
const loading = ref(false);
|
|
const loaded = ref(false);
|
|
let loadTask: Promise<void> | null = null;
|
|
|
|
const roleTree = computed<Array<Role & { level: number }>>(() => {
|
|
const roleIdSet = new Set(roleList.value.map(item => item.id));
|
|
const roots = roleList.value.filter(item => !item.parentRoleId || !roleIdSet.has(item.parentRoleId));
|
|
return roots.flatMap(item => buildRoleTree(item.id, 0, new Set<string>()));
|
|
});
|
|
|
|
// ---------- 基础数据 ----------
|
|
|
|
async function loadAll(force = false): Promise<void> {
|
|
if (loaded.value && !force) {
|
|
return;
|
|
}
|
|
|
|
if (loadTask && !force) {
|
|
await loadTask;
|
|
return;
|
|
}
|
|
|
|
loading.value = true;
|
|
loadTask = (async () => {
|
|
const [roleResult, permissionResult] = await Promise.all([
|
|
RoleAPI.list({
|
|
index: 0,
|
|
size: pageSize,
|
|
equalsExample: {
|
|
moduleCode: moduleCode
|
|
},
|
|
orderMap: {
|
|
code: "ASC"
|
|
}
|
|
}),
|
|
PermissionAPI.list({
|
|
index: 0,
|
|
size: pageSize,
|
|
equalsExample: {
|
|
moduleCode: moduleCode
|
|
},
|
|
orderMap: {
|
|
code: "ASC"
|
|
}
|
|
})
|
|
]);
|
|
roleList.value = roleResult.list.map(normalizeRole);
|
|
permissionList.value = permissionResult.list;
|
|
loaded.value = true;
|
|
})();
|
|
|
|
try {
|
|
await loadTask;
|
|
} finally {
|
|
loadTask = null;
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
async function loadRoleDetail(id: string): Promise<Role> {
|
|
if (!id) {
|
|
return createEmptyRole();
|
|
}
|
|
|
|
const role = normalizeRole(await RoleAPI.detail(id));
|
|
upsertLocalRole(role);
|
|
return role;
|
|
}
|
|
|
|
// ---------- 授权范围 ----------
|
|
|
|
async function loadManageableRoles(): Promise<Role[]> {
|
|
manageableRoleList.value = [];
|
|
const list = await RoleAPI.manageableList(moduleCode);
|
|
manageableRoleList.value = (list || []).map(normalizeRole);
|
|
return manageableRoleList.value;
|
|
}
|
|
|
|
async function loadGrantablePermissions(targetModuleCode: ModuleCode = moduleCode): Promise<Permission[]> {
|
|
grantablePermissionList.value = [];
|
|
const list = await PermissionAPI.grantableList(targetModuleCode);
|
|
grantablePermissionList.value = list || [];
|
|
return grantablePermissionList.value;
|
|
}
|
|
|
|
async function loadGrantableRolePermissions(roleId: string): Promise<Permission[]> {
|
|
return await RoleAPI.grantablePermissionList(roleId);
|
|
}
|
|
|
|
async function loadDelegationPermissions(roleId: string): Promise<Permission[]> {
|
|
return await RoleAPI.delegationList(roleId);
|
|
}
|
|
|
|
async function loadGrantableDelegationPermissions(roleId: string): Promise<Permission[]> {
|
|
return await RoleAPI.grantableDelegationList(roleId);
|
|
}
|
|
|
|
async function loadParentGrantableRoles(roleId: string): Promise<Role[]> {
|
|
return (await RoleAPI.parentGrantableList(roleId)).map(normalizeRole);
|
|
}
|
|
|
|
async function loadPermissionDetail(id: string): Promise<Permission> {
|
|
if (!id) {
|
|
return createEmptyPermission();
|
|
}
|
|
|
|
const permission = permissionList.value.find(item => item.id === id);
|
|
if (!permission) {
|
|
throw new Error("权限不存在");
|
|
}
|
|
upsertLocalPermission(permission);
|
|
return permission;
|
|
}
|
|
|
|
function upsertLocalRole(role: Role): void {
|
|
const index = roleList.value.findIndex(item => item.id === role.id);
|
|
if (-1 < index) {
|
|
roleList.value.splice(index, 1, role);
|
|
return;
|
|
}
|
|
roleList.value.unshift(role);
|
|
}
|
|
|
|
function upsertLocalPermission(permission: Permission): void {
|
|
const index = permissionList.value.findIndex(item => item.id === permission.id);
|
|
if (-1 < index) {
|
|
permissionList.value.splice(index, 1, permission);
|
|
return;
|
|
}
|
|
permissionList.value.unshift(permission);
|
|
}
|
|
|
|
// ---------- 查询 ----------
|
|
|
|
function buildRoleTree(roleId: string, level: number, visitedRoleIds: Set<string>): Array<Role & { level: number }> {
|
|
const current = getRoleById(roleId);
|
|
if (!current || visitedRoleIds.has(roleId)) {
|
|
return [];
|
|
}
|
|
|
|
const nextVisitedRoleIds = new Set(visitedRoleIds);
|
|
nextVisitedRoleIds.add(roleId);
|
|
|
|
const childRoleIdList = roleList.value
|
|
.filter(item => item.parentRoleId === roleId)
|
|
.map(item => item.id);
|
|
return [{
|
|
...current,
|
|
level
|
|
}, ...childRoleIdList.flatMap(childRoleId => buildRoleTree(childRoleId, level + 1, nextVisitedRoleIds))];
|
|
}
|
|
|
|
function getRoleById(id: string): Role | undefined {
|
|
return roleList.value.find(item => item.id === id);
|
|
}
|
|
|
|
function getPermissionById(id: string): Permission | undefined {
|
|
return permissionList.value.find(item => item.id === id);
|
|
}
|
|
|
|
function getChildRoles(role: Role): Role[] {
|
|
return role.childRoleIdList.map(getRoleById).filter(Boolean) as Role[];
|
|
}
|
|
|
|
function getRolePermissionList(role: Role): Permission[] {
|
|
return role.permissionIdList.map(getPermissionById).filter(Boolean) as Permission[];
|
|
}
|
|
|
|
function getInheritedPermissionList(role: Role): Permission[] {
|
|
const permissionMap = new Map<string, Permission>();
|
|
const permissionList = role.allPermissionList?.length
|
|
? role.allPermissionList
|
|
: getRolePermissionList(role);
|
|
for (const permission of permissionList) {
|
|
permissionMap.set(permission.id, permission);
|
|
}
|
|
|
|
return Array.from(permissionMap.values());
|
|
}
|
|
|
|
// ---------- 写入 ----------
|
|
|
|
async function upsertRole(draft: RoleDraft, createMode: boolean): Promise<Role | undefined> {
|
|
const current = getRoleById(draft.id || "");
|
|
const code = draft.code.trim();
|
|
const name = draft.name.trim();
|
|
const description = draft.description.trim();
|
|
const payload: RolePayload = {
|
|
...draft,
|
|
moduleCode: moduleCode,
|
|
code,
|
|
nameLangId: current?.nameLangId,
|
|
name,
|
|
description
|
|
};
|
|
if (draft.permissionIdList !== undefined) {
|
|
payload.permissionIdList = [...draft.permissionIdList];
|
|
}
|
|
if (draft.childRoleIdList !== undefined) {
|
|
payload.childRoleIdList = [...draft.childRoleIdList];
|
|
}
|
|
|
|
if (createMode) {
|
|
await RoleAPI.create({
|
|
moduleCode: moduleCode,
|
|
code,
|
|
name,
|
|
description,
|
|
parentRoleId: payload.parentRoleId,
|
|
ownerType: payload.ownerType,
|
|
ownerId: payload.ownerId,
|
|
permissionIdList: payload.permissionIdList,
|
|
childRoleIdList: payload.childRoleIdList
|
|
});
|
|
await loadAll(true);
|
|
return roleList.value.find(item => item.code === payload.code && item.moduleCode === moduleCode);
|
|
}
|
|
|
|
await RoleAPI.update(payload);
|
|
const role = await loadRoleDetail(payload.id || "");
|
|
await loadAll(true);
|
|
return role;
|
|
}
|
|
|
|
async function removeRole(id: string): Promise<void> {
|
|
await RoleAPI.remove(id);
|
|
roleList.value = roleList.value
|
|
.filter(item => item.id !== id)
|
|
.map(item => ({
|
|
...item,
|
|
parentRoleId: item.parentRoleId === id ? undefined : item.parentRoleId,
|
|
childRoleIdList: item.childRoleIdList.filter(childId => childId !== id)
|
|
}));
|
|
}
|
|
|
|
async function upsertPermission(draft: PermissionDraft, createMode: boolean): Promise<Permission | undefined> {
|
|
const current = getPermissionById(draft.id || "");
|
|
const payload: PermissionPayload = {
|
|
...draft,
|
|
moduleCode: moduleCode,
|
|
code: draft.code.trim(),
|
|
nameLangId: current?.nameLangId,
|
|
name: draft.name.trim(),
|
|
description: draft.description.trim()
|
|
};
|
|
|
|
if (createMode) {
|
|
await PermissionAPI.create({
|
|
moduleCode: payload.moduleCode,
|
|
code: payload.code,
|
|
name: payload.name,
|
|
description: payload.description
|
|
});
|
|
await loadAll(true);
|
|
return undefined;
|
|
}
|
|
|
|
await PermissionAPI.update(payload);
|
|
const permission = await loadPermissionDetail(payload.id || "");
|
|
await loadAll(true);
|
|
return permission;
|
|
}
|
|
|
|
async function removePermission(id: string): Promise<void> {
|
|
await PermissionAPI.remove(id);
|
|
permissionList.value = permissionList.value.filter(item => item.id !== id);
|
|
roleList.value = roleList.value.map(item => ({
|
|
...item,
|
|
permissionIdList: item.permissionIdList.filter(permissionId => permissionId !== id)
|
|
}));
|
|
}
|
|
|
|
async function setRolePermissionList(roleId: string, permissionIds: string[]): Promise<void> {
|
|
await RoleAPI.update({
|
|
id: roleId,
|
|
permissionIdList: [...permissionIds]
|
|
});
|
|
const role = await loadRoleDetail(roleId);
|
|
upsertLocalRole(role);
|
|
}
|
|
|
|
async function setRoleChildRoleList(roleId: string, childRoleIds: string[]): Promise<void> {
|
|
await RoleAPI.update({
|
|
id: roleId,
|
|
childRoleIdList: [...childRoleIds]
|
|
});
|
|
const role = await loadRoleDetail(roleId);
|
|
upsertLocalRole(role);
|
|
}
|
|
|
|
async function setRoleDelegationPermissionList(roleId: string, permissionIds: string[]): Promise<void> {
|
|
await RoleAPI.updateDelegation({
|
|
id: roleId,
|
|
delegationPermissionIdList: permissionIds
|
|
});
|
|
const role = await loadRoleDetail(roleId);
|
|
upsertLocalRole(role);
|
|
}
|
|
|
|
async function setRoleParentRole(roleId: string, parentRoleId: string): Promise<void> {
|
|
await RoleAPI.updateParent({
|
|
id: roleId,
|
|
parentRoleId
|
|
});
|
|
const role = await loadRoleDetail(roleId);
|
|
upsertLocalRole(role);
|
|
}
|
|
|
|
return {
|
|
roleList,
|
|
permissionList,
|
|
manageableRoleList,
|
|
grantablePermissionList,
|
|
roleTree,
|
|
loading,
|
|
loaded,
|
|
loadAll,
|
|
loadManageableRoles,
|
|
loadGrantablePermissions,
|
|
loadGrantableRolePermissions,
|
|
loadDelegationPermissions,
|
|
loadGrantableDelegationPermissions,
|
|
loadParentGrantableRoles,
|
|
loadRoleDetail,
|
|
loadPermissionDetail,
|
|
getRoleById,
|
|
getPermissionById,
|
|
getChildRoles,
|
|
getRolePermissionList,
|
|
getInheritedPermissionList,
|
|
upsertRole,
|
|
removeRole,
|
|
upsertPermission,
|
|
removePermission,
|
|
setRolePermissionList,
|
|
setRoleChildRoleList,
|
|
setRoleDelegationPermissionList,
|
|
setRoleParentRole
|
|
};
|
|
});
|
|
|