feat(space): 全员空间(tenant-kind) —— 整租户共享的"开关",自动纳入全部成员
补齐 Space 三类型的最后一种:tenant-kind「全员空间」= 用户最初想要的"共享工作区开关"。 与 project 空间的本质区别:自动纳入全租户成员(含之后新加入的),而非手动逐个邀请。 后端: - EnableTenantSpace(幂等):建 kind=tenant 空间 + 把全部 active 租户成员按租户角色纳入 (owner→owner…billing_admin→viewer);tenantSpaceID 查询;spaceRoleFromTenant 角色映射 - AddMemberByEmail 加租户成员时 autoJoinTenantSpace:若已启用全员空间则自动补纳新成员 - SpaceCreate handler:kind=tenant 路由到 EnableTenantSpace,且须租户 admin/owner(inline 403) 桌面端: - 空间切换器加"启用全员空间"入口(Globe 图标):仅租户 admin/owner 且尚未启用时显示, 带二次确认;启用后该按钮自动隐藏(hasTenantSpace),全员空间进切换器 验证(gateway+docker):member 启用 403 / owner 启用纳入全部现有成员(owner·member·viewer 按租户角色映射) / 新加租户成员自动纳入 / 幂等(再启用返回同一个不重复建) / viewer 在全员空间 入库 403(只读) / owner 建库 200;浏览器实机:启用后全员空间进切换器 + 启用按钮消失 至此 Space 三类型(个人/项目/全员)全部落地。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -139,6 +139,16 @@ export default function App() {
|
||||
},
|
||||
[refreshTenant],
|
||||
);
|
||||
// 启用全员空间(整租户共享;幂等纳入全部成员)——须租户 admin。
|
||||
const onEnableTenantSpace = useCallback(async () => {
|
||||
try {
|
||||
const { id } = await createSpace("全员空间", "tenant");
|
||||
await switchSpace(id);
|
||||
refreshTenant();
|
||||
} catch (e) {
|
||||
window.alert((e as Error).message);
|
||||
}
|
||||
}, [refreshTenant]);
|
||||
useEffect(() => {
|
||||
if (!user) {
|
||||
setTenant(null);
|
||||
@@ -288,7 +298,7 @@ export default function App() {
|
||||
style={{ background: "radial-gradient(60% 100% at 50% 0%, rgba(124,92,246,0.10), transparent 70%)" }}
|
||||
/>
|
||||
<UpdateBanner />
|
||||
<TopBar user={user} tenant={tenant} tenants={tenants} onSwitchTenant={onSwitchTenant} space={space} spaces={spaces} onSwitchSpace={onSwitchSpace} onCreateSpace={onCreateSpace} onLogout={onLogout} onCommand={() => setCmdOpen(true)} onOpenUsage={() => setView("usage")} />
|
||||
<TopBar user={user} tenant={tenant} tenants={tenants} onSwitchTenant={onSwitchTenant} space={space} spaces={spaces} onSwitchSpace={onSwitchSpace} onCreateSpace={onCreateSpace} onEnableTenantSpace={onEnableTenantSpace} tenantRole={tenant?.role ?? ""} onLogout={onLogout} onCommand={() => setCmdOpen(true)} onOpenUsage={() => setView("usage")} />
|
||||
<ApprovalBar run={run} />
|
||||
<div className="relative flex min-h-0 flex-1">
|
||||
<LeftNav active={view} onSelect={setView} />
|
||||
|
||||
Reference in New Issue
Block a user