refactor(auth): 管理端清除多身份残留(identities/currentIdentity/selectIdentity/Identity)
- auth.tsx/type 去 identities/currentIdentity 状态与 Identity 类型,role 恒取 user.role - api/auth.ts 删 selectIdentity、getSavedUser/saveUser 去 identity 字段 - types.ts LoginResponse 去 identities/identity_id/port/identity_name 字段 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+3
-11
@@ -1,5 +1,5 @@
|
||||
import { api, setToken } from "@/api/client";
|
||||
import type { Identity, LoginResponse } from "@/types";
|
||||
import type { LoginResponse } from "@/types";
|
||||
|
||||
export async function login(username: string, password: string): Promise<LoginResponse> {
|
||||
const res = await api.post<LoginResponse>("/auth/login", { username, password });
|
||||
@@ -7,14 +7,6 @@ export async function login(username: string, password: string): Promise<LoginRe
|
||||
return res;
|
||||
}
|
||||
|
||||
export async function selectIdentity(identityId: string): Promise<LoginResponse> {
|
||||
const res = await api.post<LoginResponse>("/auth/select-identity", {
|
||||
identity_id: identityId,
|
||||
});
|
||||
setToken(res.token);
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---- 四种登录:短信验证码 / 微信扫码 / 小程序扫码 ----
|
||||
|
||||
export async function sendCode(phone: string): Promise<{ sent: boolean; message: string; stub_code?: string }> {
|
||||
@@ -64,7 +56,7 @@ export async function fetchMe(): Promise<Record<string, unknown>> {
|
||||
return api.get("/auth/me");
|
||||
}
|
||||
|
||||
export function getSavedUser(): { username?: string; role?: string; identity?: Identity } | null {
|
||||
export function getSavedUser(): { username?: string; role?: string } | null {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem("@cloud-opc-admin/user") || "null");
|
||||
} catch {
|
||||
@@ -72,7 +64,7 @@ export function getSavedUser(): { username?: string; role?: string; identity?: I
|
||||
}
|
||||
}
|
||||
|
||||
export function saveUser(user: { username?: string; role?: string; identity?: Identity } | null) {
|
||||
export function saveUser(user: { username?: string; role?: string } | null) {
|
||||
if (user) localStorage.setItem("@cloud-opc-admin/user", JSON.stringify(user));
|
||||
else localStorage.removeItem("@cloud-opc-admin/user");
|
||||
}
|
||||
|
||||
+4
-22
@@ -2,13 +2,11 @@ import * as React from "react";
|
||||
import { api, setToken as persistToken } from "@/api/client";
|
||||
import * as authApi from "@/api/auth";
|
||||
import { clearParkAuth } from "@/lib/parkAuth";
|
||||
import type { Identity, LoginResponse } from "@/types";
|
||||
import type { LoginResponse } from "@/types";
|
||||
|
||||
interface AuthState {
|
||||
token: string | null;
|
||||
user: LoginResponse | null;
|
||||
identities: Identity[];
|
||||
currentIdentity: Identity | null;
|
||||
}
|
||||
|
||||
interface AuthContextValue extends AuthState {
|
||||
@@ -28,29 +26,20 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
typeof window === "undefined" ? null : (localStorage.getItem("cloud_opc_admin_token") ?? null),
|
||||
);
|
||||
const [user, setUser] = React.useState<LoginResponse | null>(null);
|
||||
const [identities, setIdentities] = React.useState<Identity[]>([]);
|
||||
const [currentIdentity, setCurrentIdentity] = React.useState<Identity | null>(null);
|
||||
|
||||
// 启动/刷新时若有 token:先本地还原 saved user(立即有 role,避免「无权限」闪屏),
|
||||
// 再调 /auth/me 从后端还原权威身份(identities / 当前身份 / permissions)。
|
||||
// 再调 /auth/me 从后端还原权威身份(role / permissions,账号单一角色)。
|
||||
React.useEffect(() => {
|
||||
if (!token) return;
|
||||
const saved = authApi.getSavedUser();
|
||||
if (saved?.username) {
|
||||
setUser((u) => ({ ...(u ?? {}), username: saved.username, role: saved.role } as LoginResponse));
|
||||
if (saved.identity) setCurrentIdentity(saved.identity);
|
||||
}
|
||||
authApi
|
||||
.fetchMe()
|
||||
.then((res) => {
|
||||
const r = res as unknown as LoginResponse;
|
||||
const identities = r.identities ?? [];
|
||||
setUser((u) => ({ ...(u ?? {}), username: r.username ?? u?.username, role: r.role ?? u?.role, ...r }));
|
||||
if (identities.length) setIdentities(identities);
|
||||
const current = identities.find((i) => i.id === r.identity_id);
|
||||
if (current) setCurrentIdentity(current);
|
||||
else if (saved?.identity) setCurrentIdentity(saved.identity);
|
||||
else if (identities[0]) setCurrentIdentity(identities[0]);
|
||||
})
|
||||
.catch(() => { /* 401 时 api client 已触发 auth:expired → 登出 */ });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -81,17 +70,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
if (res.token) persistToken(res.token);
|
||||
setToken(res.token);
|
||||
setUser(res);
|
||||
setIdentities(res.identities ?? []);
|
||||
const current = res.identities?.find((i) => i.id === res.identity_id) || null;
|
||||
setCurrentIdentity(current || (res.identities?.[0] ?? null));
|
||||
authApi.saveUser({ username: res.username, role: current?.role || res.role, identity: current || undefined });
|
||||
authApi.saveUser({ username: res.username, role: res.role });
|
||||
}
|
||||
|
||||
function logout() {
|
||||
setToken(null);
|
||||
setUser(null);
|
||||
setIdentities([]);
|
||||
setCurrentIdentity(null);
|
||||
localStorage.removeItem("cloud_opc_admin_token");
|
||||
authApi.saveUser(null);
|
||||
clearParkAuth(); // 一并清除园区端(园区账密)登录态,避免回跳 /park 死循环
|
||||
@@ -101,10 +85,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
const value: AuthContextValue = {
|
||||
token,
|
||||
user,
|
||||
identities,
|
||||
currentIdentity,
|
||||
isAuthed: !!token,
|
||||
// 账号单一角色:role 恒取账号真实类型(user.role),不再多身份/currentIdentity。
|
||||
// 账号单一角色:role 恒取账号真实类型(user.role)。
|
||||
role: user?.role || null,
|
||||
permissions: user?.permissions ?? [],
|
||||
username: user?.username ?? null,
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
export interface Identity {
|
||||
id: string;
|
||||
port: string;
|
||||
role: string;
|
||||
sub_role?: string | null;
|
||||
name?: string;
|
||||
org_id?: string | null;
|
||||
region_id?: string | null;
|
||||
org_name?: string | null;
|
||||
region_name?: string | null;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
token: string;
|
||||
identities: Identity[];
|
||||
username?: string;
|
||||
nickname?: string;
|
||||
avatar?: string;
|
||||
@@ -24,9 +10,6 @@ export interface LoginResponse {
|
||||
permissions?: string[];
|
||||
scope_region_ids?: string[];
|
||||
scope_level?: string;
|
||||
identity_id?: string;
|
||||
port?: string;
|
||||
identity_name?: string;
|
||||
}
|
||||
|
||||
// ---- 管理业务模型(server-core /admin/* 端点,部分端点尚未实现)----
|
||||
|
||||
Reference in New Issue
Block a user