Bläddra i källkod

feat: add permUtils (sort/group/search/delta)

BaiLuoYan 4 dagar sedan
förälder
incheckning
f6f933f9ab
1 ändrade filer med 88 tillägg och 0 borttagningar
  1. 88 0
      src/pages/Admin/_shared/PermTree/lib/permUtils.ts

+ 88 - 0
src/pages/Admin/_shared/PermTree/lib/permUtils.ts

@@ -0,0 +1,88 @@
+import { pinyin } from 'pinyin-pro';
+
+// ---- 类型 ----
+export interface PermGroup {
+  modelName: string;
+  apiPerms: API.PermItem[];
+  dataPerms: API.PermItem[]; // data:model:action(非字段)
+  fieldPerms: API.PermItem[]; // data:model:field:read|write
+}
+
+// ---- 排序 ----
+export const sortPerms = (perms: API.PermItem[]): API.PermItem[] =>
+  [...perms].sort((a, b) => {
+    const partsA = a.code.split(':');
+    const partsB = b.code.split(':');
+    const modelA = partsA[1] ?? '';
+    const modelB = partsB[1] ?? '';
+    if (modelA !== modelB) return modelA.localeCompare(modelB);
+    const isFieldA = partsA.length === 4;
+    const isFieldB = partsB.length === 4;
+    if (isFieldA !== isFieldB) return isFieldA ? 1 : -1;
+    return a.code.localeCompare(b.code);
+  });
+
+// ---- 分组 ----
+export const groupPerms = (perms: API.PermItem[]): PermGroup[] => {
+  const map = new Map<string, PermGroup>();
+  for (const p of perms) {
+    const parts = p.code.split(':');
+    const type = parts[0]; // api | data
+    const model = parts[1] ?? 'unknown';
+    if (!map.has(model)) {
+      map.set(model, { modelName: model, apiPerms: [], dataPerms: [], fieldPerms: [] });
+    }
+    const g = map.get(model)!;
+    if (type === 'api') {
+      g.apiPerms.push(p);
+    } else if (parts.length === 4) {
+      g.fieldPerms.push(p);
+    } else {
+      g.dataPerms.push(p);
+    }
+  }
+  return [...map.values()].sort((a, b) => a.modelName.localeCompare(b.modelName));
+};
+
+// ---- 搜索 ----
+const getPinyinStr = (text: string) => pinyin(text, { toneType: 'none', type: 'array' }).join('');
+
+const getPinyinInitials = (text: string) =>
+  pinyin(text, { pattern: 'first', toneType: 'none', type: 'array' }).join('');
+
+export const matchesPerm = (perm: API.PermItem, keyword: string): boolean => {
+  if (!keyword) return true;
+  const k = keyword.toLowerCase();
+  const code = perm.code.toLowerCase();
+  const name = perm.name.toLowerCase();
+  const namePy = getPinyinStr(perm.name).toLowerCase();
+  const nameInitials = getPinyinInitials(perm.name).toLowerCase();
+  return code.includes(k) || name.includes(k) || namePy.includes(k) || nameInitials.includes(k);
+};
+
+// ---- 用户权限 delta 计算 ----
+export const calcUserPermDelta = (
+  checkedIds: number[],
+  roleInheritedIds: number[],
+): API.UserPermItem[] => {
+  const checked = new Set(checkedIds);
+  const inherited = new Set(roleInheritedIds);
+  return [
+    ...checkedIds
+      .filter((id) => !inherited.has(id))
+      .map((id) => ({ permId: id, effect: 'ALLOW' as const })),
+    ...[...inherited]
+      .filter((id) => !checked.has(id))
+      .map((id) => ({ permId: id, effect: 'DENY' as const })),
+  ];
+};
+
+// ---- 获取权限对应的 pair id ----
+// api:model:action <-> data:model:action 互查
+export const getPairId = (perm: API.PermItem, allPerms: API.PermItem[]): number | undefined => {
+  const parts = perm.code.split(':');
+  if (parts.length !== 3) return undefined;
+  const [type, model, action] = parts;
+  const pairType = type === 'api' ? 'data' : 'api';
+  return allPerms.find((p) => p.code === `${pairType}:${model}:${action}`)?.id;
+};