refactor(admin): 移除多身份绑定与切换 —— 只剩运营端/园区端单一身份登录
- 登录后直接以运营端进入(不再多身份选择弹窗/端口身份过滤) - 移除顶栏「切换身份」(IdentitySwitcher); 侧边/路由仍按 operator 域 - 园区端(园区账密)登录保持不变
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user