refactor(admin): 移除多身份绑定与切换 —— 只剩运营端/园区端单一身份登录

- 登录后直接以运营端进入(不再多身份选择弹窗/端口身份过滤)
- 移除顶栏「切换身份」(IdentitySwitcher); 侧边/路由仍按 operator 域
- 园区端(园区账密)登录保持不变
This commit is contained in:
Pine
2026-08-26 12:42:35 +08:00
parent 044ec4bb81
commit 71620f85b7
2 changed files with 7 additions and 85 deletions
+2 -42
View File
@@ -16,12 +16,11 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { hasPermission } from "@/lib/rbac";
export function AppShell() {
const { role, user, identities, currentIdentity, selectIdentity, logout } = useAuth();
const { role, user, logout } = useAuth();
const groups = navForRole(role);
const roleLabel = currentIdentity?.name || role || "未选择";
const roleLabel = role || "运营";
return (
<div className="flex min-h-screen">
@@ -77,7 +76,6 @@ export function AppShell() {
<span className="ml-1 font-medium text-foreground">{roleLabel}</span>
</div>
<IdentitySwitcher identities={identities} current={currentIdentity} onSelect={selectIdentity} />
</header>
<main className="p-6">
<Outlet />
@@ -121,41 +119,3 @@ function UserMenu({
</DropdownMenu>
);
}
function IdentitySwitcher({
identities,
current,
onSelect,
}: {
identities: { id: string; name?: string; role: string }[];
current: { id: string } | null;
onSelect: (id: string) => void;
}) {
if (!identities || identities.length <= 1) return null;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-1.5">
<ChevronsUpDown className="h-3.5 w-3.5 opacity-60" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuLabel></DropdownMenuLabel>
<DropdownMenuSeparator />
{identities.map((i) => (
<DropdownMenuItem
key={i.id}
disabled={i.id === current?.id || !hasPermission(undefined, i.role)}
onSelect={() => onSelect(i.id)}
>
<span className="truncate">
{i.name || i.role}
<span className="ml-1 text-muted-foreground">({i.role})</span>
</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}
+5 -43
View File
@@ -10,7 +10,7 @@ import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { QRCodeSVG } from "@rc-component/qrcode";
import { Loader2, ShieldCheck, Lock, Smartphone, QrCode } from "lucide-react";
import type { Identity, LoginResponse } from "@/types";
import type { LoginResponse } from "@/types";
/** 二维码轮询登录(微信扫码 / 小程序扫码共用) */
function PollingQr({
@@ -91,7 +91,7 @@ function PollingQr({
}
export default function LoginPage() {
const { isAuthed, login, loginWithResponse, selectIdentity } = useAuth();
const { isAuthed, login, loginWithResponse } = useAuth();
const navigate = useNavigate();
const [mode, setMode] = React.useState<"platform" | "park">("platform");
const [pmode, setPmode] = React.useState<"account" | "sms" | "miniprogram">("account");
@@ -101,20 +101,17 @@ export default function LoginPage() {
const [smsCode, setSmsCode] = React.useState("");
const [smsCountdown, setSmsCountdown] = React.useState(0);
const [smsStub, setSmsStub] = React.useState("");
const [pendingIds, setPendingIds] = React.useState<Identity[]>([]);
const [error, setError] = React.useState<string | null>(null);
const [loading, setLoading] = React.useState(false);
if (isAuthed && pendingIds.length === 0) return <Navigate to="/" replace />;
if (isAuthed) return <Navigate to="/" replace />;
if (isParkUser()) return <Navigate to="/park" replace />;
/** 平台登录结果统一处理:只保留运营(operator)角色身份 */
/** 平台登录结果:登录即以运营端进入(单一身份,无需选择/切换身份) */
async function applyPlatformResult(res: LoginResponse | null) {
if (!res) return;
clearParkAuth();
const operatorIds = (res?.identities ?? []).filter((i) => i.role === "operator");
if (operatorIds.length > 1) setPendingIds(operatorIds);
else navigate("/", { replace: true });
navigate("/", { replace: true });
}
async function onAccountSubmit(e: React.FormEvent) {
@@ -168,41 +165,6 @@ export default function LoginPage() {
} finally { setLoading(false); }
}
async function onPick(id: string) {
setLoading(true);
try {
await selectIdentity(id);
navigate("/", { replace: true });
} catch (err) {
setError(err instanceof Error ? err.message : "切换身份失败");
} finally {
setLoading(false);
}
}
if (pendingIds.length > 0) {
return (
<Centered>
<Card className="w-full max-w-sm">
<CardHeader>
<CardTitle className="text-lg"></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent className="space-y-2">
{pendingIds.map((i) => (
<Button key={i.id} variant="outline" className="w-full justify-between" onClick={() => onPick(i.id)} disabled={loading}>
<span>
{i.name || i.role}
<span className="ml-1 text-muted-foreground">({i.role})</span>
</span>
</Button>
))}
</CardContent>
</Card>
</Centered>
);
}
return (
<Centered>
<Card className="w-full max-w-sm">