Files
gao-customer-h5/src/store/permissionSettingsStore.ts
T
2026-08-07 16:02:29 +08:00

342 lines
8.5 KiB
TypeScript

import { defineStore } from "pinia";
import {
PermissionAPI,
RoleAPI,
type ModuleCode,
type Permission as UserPermission,
type PermissionPayload,
type Role as UserRole,
type RolePayload
} from "timi-web";
export const moduleCode: ModuleCode = "GAO";
const pageSize = 1000;
export type Permission = UserPermission;
export type Role = Omit<UserRole, "id" | "permissionIdList" | "childRoleIdList"> & {
id: string;
permissionIdList: string[];
childRoleIdList: string[];
};
export type RoleDraft = {
id?: string;
code: string;
name: string;
description: string;
nameLangId?: string;
moduleCode?: ModuleCode;
permissionIdList: string[];
childRoleIdList: string[];
};
export type PermissionDraft = {
id?: string;
code: string;
name: string;
description: string;
nameLangId?: string;
moduleCode?: ModuleCode;
};
function normalizeRole(role: UserRole): Role {
return {
...role,
id: role.id || "",
moduleCode: role.moduleCode || moduleCode,
description: role.description || "",
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)) || []
};
}
function createEmptyRole(): Role {
return {
id: "",
moduleCode: moduleCode,
code: "",
name: "",
description: "",
permissionIdList: [],
childRoleIdList: []
};
}
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 loading = ref(false);
const loaded = ref(false);
let loadTask: Promise<void> | null = null;
const roleTree = computed<Array<Role & { level: number }>>(() => {
const childIdSet = new Set(roleList.value.flatMap(item => item.childRoleIdList));
const roots = roleList.value.filter(item => !childIdSet.has(item.id));
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 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);
return [{
...current,
level
}, ...current.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 allPermissionList = role.allPermissionList || [];
for (const permission of [...getRolePermissionList(role), ...allPermissionList]) {
permissionMap.set(permission.id, permission);
}
for (const childRole of getChildRoles(role)) {
for (const permission of getRolePermissionList(childRole)) {
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 payload: RolePayload = {
...draft,
moduleCode: moduleCode,
code: draft.code.trim(),
nameLangId: current?.nameLangId,
name: draft.name.trim(),
description: draft.description.trim(),
permissionIdList: [...draft.permissionIdList],
childRoleIdList: [...draft.childRoleIdList]
};
if (createMode) {
await RoleAPI.create({
moduleCode: payload.moduleCode,
code: payload.code,
name: payload.name,
description: payload.description,
permissionIdList: payload.permissionIdList,
childRoleIdList: payload.childRoleIdList
});
await loadAll(true);
return undefined;
}
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,
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> {
const role = await loadRoleDetail(roleId);
await upsertRole({
id: role.id,
moduleCode: moduleCode,
code: role.code,
name: role.name || "",
description: role.description || "",
permissionIdList: [...permissionIds],
childRoleIdList: [...role.childRoleIdList]
}, false);
}
return {
roleList,
permissionList,
roleTree,
loading,
loaded,
loadAll,
loadRoleDetail,
loadPermissionDetail,
getRoleById,
getPermissionById,
getChildRoles,
getRolePermissionList,
getInheritedPermissionList,
upsertRole,
removeRole,
upsertPermission,
removePermission,
setRolePermissionList
};
});