fix: refine settings dialog layout

This commit is contained in:
2026-07-03 01:03:34 -07:00
parent b5e2aa6df1
commit d2404616bc
6 changed files with 76 additions and 11 deletions

View File

@@ -1,11 +1,11 @@
"use client";
import { FormEvent, useState } from "react";
import { Globe2, Save, ShieldCheck } from "lucide-react";
import { Building2, Globe2, KeyRound, Save, ShieldCheck, UserPlus } from "lucide-react";
import { useRouter } from "next/navigation";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Button, LinkButton } 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";
@@ -13,17 +13,22 @@ import type { ApiResult } from "@/modules/core/server/api";
import type { SystemSettings } from "@/modules/core/types";
type GlobalSettingsClientProps = {
organizationSettingsHref: string;
settings: SystemSettings;
};
type SettingsTab = "registration" | "oidc";
type SettingsTab = "registration" | "invitation" | "oidc";
const tabs: Array<{ label: string; value: SettingsTab }> = [
{ label: "注册入口", value: "registration" },
{ label: "邀请注册", value: "invitation" },
{ label: "OIDC 默认配置", value: "oidc" },
];
export function GlobalSettingsClient({ settings }: GlobalSettingsClientProps): React.ReactElement {
export function GlobalSettingsClient({
organizationSettingsHref,
settings,
}: GlobalSettingsClientProps): React.ReactElement {
const router = useRouter();
const [activeTab, setActiveTab] = useState<SettingsTab>("registration");
const [registrationEnabled, setRegistrationEnabled] = useState(settings.registrationEnabled);
@@ -135,6 +140,58 @@ export function GlobalSettingsClient({ settings }: GlobalSettingsClientProps): R
</div>
</CardContent>
</div>
<div hidden={activeTab !== "invitation"} role="tabpanel">
<CardHeader>
<div className="flex items-center gap-2">
<KeyRound className="size-5 text-primary" aria-hidden="true" />
<CardTitle></CardTitle>
</div>
<CardDescription></CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-3 lg:grid-cols-3">
<section className="rounded-md border p-3">
<div className="flex items-center gap-2">
<Globe2 className="size-4 text-primary" aria-hidden="true" />
<h3 className="text-sm font-semibold"></h3>
</div>
<p className="mt-2 text-sm text-muted-foreground">
{registrationEnabled
? "访客可以从注册页创建账号,并选择申请加入开放注册的机构。"
: "普通注册入口关闭;用户需要通过邀请链接或管理员创建账号。"}
</p>
</section>
<section className="rounded-md border p-3">
<div className="flex items-center gap-2">
<UserPlus className="size-4 text-primary" aria-hidden="true" />
<h3 className="text-sm font-semibold"></h3>
</div>
<p className="mt-2 text-sm text-muted-foreground">
`/register?invite=...`
</p>
</section>
<section className="rounded-md border p-3">
<div className="flex items-center gap-2">
<Building2 className="size-4 text-primary" aria-hidden="true" />
<h3 className="text-sm font-semibold"></h3>
</div>
<p className="mt-2 text-sm text-muted-foreground">
</p>
</section>
</div>
<div className="flex flex-col gap-3 rounded-md border bg-secondary/25 p-3 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0 text-sm">
<p className="font-medium"></p>
<p className="mt-1 text-muted-foreground"></p>
</div>
<LinkButton href={organizationSettingsHref} variant="outline">
<UserPlus className="size-4" aria-hidden="true" />
</LinkButton>
</div>
</CardContent>
</div>
<div hidden={activeTab !== "oidc"} role="tabpanel">
<CardHeader>
<div className="flex items-center gap-2">

View File

@@ -166,7 +166,7 @@ export function OrganizationRowActions({
}
return (
<div className="flex items-center justify-end gap-2">
<div className="flex flex-wrap items-center justify-end gap-2">
<Button onClick={() => setIsEditOpen(true)} size="sm" type="button" variant="outline">
<Pencil className="size-4" aria-hidden="true" />
@@ -195,6 +195,7 @@ export function OrganizationRowActions({
</Button>
)}
<Dialog
className="max-w-lg"
description="编辑机构名称、唯一标识和启停状态。"
onClose={() => setIsEditOpen(false)}
open={isEditOpen}
@@ -223,7 +224,7 @@ export function OrganizationRowActions({
{message}
</p>
) : null}
<div className="flex justify-end gap-2">
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
<Button onClick={() => setIsEditOpen(false)} type="button" variant="outline">
</Button>

View File

@@ -204,7 +204,7 @@ export function RoleManagementClient({ permissions }: RoleManagementClientProps)
</Button>
<Dialog
className="max-w-5xl"
className="w-[min(calc(100vw-1.5rem),64rem)]"
description="角色由系统注册权限点组合而成。"
onClose={closeCreateDialog}
open={isCreateOpen}
@@ -345,7 +345,7 @@ export function RoleRowActions({ permissions, role }: RoleRowActionsProps): Reac
</Button>
)}
<Dialog
className="max-w-5xl"
className="w-[min(calc(100vw-1.5rem),64rem)]"
description="编辑自定义角色的名称、说明、状态和权限点。"
onClose={closeEditDialog}
open={isEditOpen}