"use client"; import { FormEvent, useState } from "react"; import { Copy, LinkIcon, Save, Send } from "lucide-react"; import { useRouter } from "next/navigation"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; import { Table } from "@/components/ui/table"; import type { ApiResult } from "@/modules/core/server/api"; import type { Organization, OrganizationInvitation, RoleDefinition } from "@/modules/core/types"; import { getInviteHref, OrganizationInviteDialog } from "@/modules/settings/components/OrganizationInviteDialog"; type OrganizationDetailClientProps = { invitations: OrganizationInvitation[]; organization: Organization; roles: RoleDefinition[]; }; export function OrganizationDetailClient({ invitations, organization, roles, }: OrganizationDetailClientProps): React.ReactElement { const router = useRouter(); const [isInviteOpen, setIsInviteOpen] = useState(false); const [settingsMessage, setSettingsMessage] = useState(""); const [isPending, setIsPending] = useState(false); async function handleSettingsSubmit(event: FormEvent): Promise { event.preventDefault(); setSettingsMessage(""); setIsPending(true); const formData = new FormData(event.currentTarget); const response = await fetch(`/api/organizations/${organization.id}`, { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ registrationEnabled: formData.get("registrationEnabled") === "on", oidcEnabled: formData.get("oidcEnabled") === "on", oidcIssuerUrl: String(formData.get("oidcIssuerUrl") ?? ""), oidcClientId: String(formData.get("oidcClientId") ?? ""), oidcClientSecret: String(formData.get("oidcClientSecret") ?? ""), oidcScopes: String(formData.get("oidcScopes") ?? ""), oidcRedirectUri: String(formData.get("oidcRedirectUri") ?? ""), oidcAvatarClaim: String(formData.get("oidcAvatarClaim") ?? ""), oidcAutoProvision: formData.get("oidcAutoProvision") === "on", }), }); const result = (await response.json()) as ApiResult<{ organization: Organization }>; setIsPending(false); if (!result.success) { setSettingsMessage(result.reason); return; } setSettingsMessage(result.reason); router.refresh(); } return (
机构访问配置 控制公开注册、OIDC 登录入口和自动开户策略。
开放公开注册 关闭后,注册页不再展示该机构;邀请链接仍可使用。 } name="registrationEnabled" />
启用 OIDC 登录 保存标准 OIDC 配置,后续登录入口按该开关展示。 } name="oidcEnabled" />
OIDC 自动开户 首次 OIDC 登录时自动创建账号并进入本机构。 } name="oidcAutoProvision" />
{settingsMessage ? (

{settingsMessage}

) : null}
机构邀请 生成邀请链接后发送给成员;可限定邮箱,也可生成通用邀请。
对象 角色 状态 有效期 链接 {invitations.map((invitation) => ( {invitation.email || "通用邀请"} {invitation.roleLabel} {invitation.status} {new Date(invitation.expiresAt).toLocaleString("zh-CN")} ))} {invitations.length === 0 ? ( 暂无邀请 ) : null}
setIsInviteOpen(false)} open={isInviteOpen} organization={organization} roles={roles} />
); }