feat(admin): Phase 2 邀请码发放管理 — apps/adminpanel 跨团队端点 + Admin 邀请码页

后端:新建 apps/adminpanel(跨团队后台容器,/api/admin/);GET/POST invitations(列跨团队码+筛选分页 /
平台发 create_team 开团队码,写审计)+ revoke(写审计),全程 IsPlatformAdmin。
前端:adminApi 分层;Admin 邀请码页(类型筛选段控 + 表格 + 发码弹窗 + 复制邀请链接 + 撤销)接入 AdminApp toast;
Invitation 类型补 kind/team_name;admin-page.css 补段控/表格/弹窗(仅 token)。
测试:adminpanel 9 + accounts 22 = 31 单测过;无头 e2e _admin-p2.mjs 6 断言过 + 0 console error
+ 端到端凭 UI 发的码注册开团队 201;tsc+build 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 21:29:55 +08:00
co-authored by Claude Opus 4.8
parent 3f8547564c
commit 45a4ceae51
14 changed files with 589 additions and 6 deletions
+20
View File
@@ -513,3 +513,23 @@ export const api = {
return request<void>(`/api/ops/notifications/${id}/archive/`, { method: "POST" });
}
};
// 平台超管后台 API(/api/admin/*,全程 IsPlatformAdmin)。与团队级 api 分层,便于权限收敛。
export const adminApi = {
invitations(params?: { kind?: string; status?: string; search?: string; page?: number; page_size?: number }) {
const qs = new URLSearchParams();
if (params?.kind) qs.set("kind", params.kind);
if (params?.status) qs.set("status", params.status);
if (params?.search) qs.set("search", params.search);
if (params?.page) qs.set("page", String(params.page));
if (params?.page_size) qs.set("page_size", String(params.page_size));
const q = qs.toString();
return request<Paginated<Invitation>>(`/api/admin/invitations/${q ? `?${q}` : ""}`);
},
createInvite(payload?: { email?: string }) {
return request<Invitation>("/api/admin/invitations/", { method: "POST", body: JSON.stringify(payload || {}) });
},
revokeInvite(id: string) {
return request<Invitation>(`/api/admin/invitations/${id}/revoke/`, { method: "POST" });
}
};