mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat(admin-ui): members panel, invite links, audit tab and role-aware console
- New MembersPanel: role switching, add/remove members, invite-link generation with copy/revoke, pending invite list - New Audit tab (AuditLog.vue) with group filter - Role-aware UI: viewer hides route/group edit actions (RouteCard readonly), owner-only controls, role badge + member count on group cards - GroupEditor: members managed via panel, owners field super-admin only - en/zh i18n and CSS for the new panels
This commit is contained in:
parent
252f6f181a
commit
11b74aa82a
11 changed files with 805 additions and 55 deletions
|
|
@ -1,12 +1,28 @@
|
|||
import type { Group } from "~/types";
|
||||
import type { Group, GroupRole } from "~/types";
|
||||
|
||||
export function useGroupsApi() {
|
||||
const groups = ref<Group[]>([]);
|
||||
const isSuper = ref(false);
|
||||
/** groupId → role of the signed-in user (absent for super admins). */
|
||||
const roles = ref<Record<string, GroupRole>>({});
|
||||
const loading = ref(false);
|
||||
const needLogin = ref(false);
|
||||
const error = ref("");
|
||||
|
||||
function roleOf(groupId: string): GroupRole | undefined {
|
||||
return isSuper.value ? "owner" : roles.value[groupId];
|
||||
}
|
||||
|
||||
function canEditGroup(groupId: string): boolean {
|
||||
const r = roleOf(groupId);
|
||||
return isSuper.value || r === "owner";
|
||||
}
|
||||
|
||||
function canEditRoutes(groupId: string): boolean {
|
||||
const r = roleOf(groupId);
|
||||
return isSuper.value || r === "owner" || r === "admin";
|
||||
}
|
||||
|
||||
async function load(): Promise<void> {
|
||||
loading.value = true;
|
||||
error.value = "";
|
||||
|
|
@ -21,9 +37,14 @@ export function useGroupsApi() {
|
|||
return;
|
||||
}
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
const data = (await res.json()) as { groups?: Group[]; isSuper?: boolean };
|
||||
const data = (await res.json()) as {
|
||||
groups?: Group[];
|
||||
isSuper?: boolean;
|
||||
roles?: Record<string, GroupRole>;
|
||||
};
|
||||
groups.value = data.groups ?? [];
|
||||
isSuper.value = data.isSuper ?? false;
|
||||
roles.value = data.roles ?? {};
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : String(err);
|
||||
} finally {
|
||||
|
|
@ -49,5 +70,5 @@ export function useGroupsApi() {
|
|||
groups.value = next;
|
||||
}
|
||||
|
||||
return { groups, isSuper, loading, needLogin, error, load, save };
|
||||
return { groups, isSuper, roles, roleOf, canEditGroup, canEditRoutes, loading, needLogin, error, load, save };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue