feat: complete login and user management flow

This commit is contained in:
hectorzhao
2026-07-02 16:28:48 +08:00
parent 9c639d54b9
commit e26d8324c3
22 changed files with 1320 additions and 300 deletions
+9 -1
View File
@@ -24,15 +24,23 @@ import {
Users,
UserX,
} from 'lucide-react';
import { Navigate } from 'react-router-dom';
import { readSession } from '@/api/session';
import { AppShell } from '@/layouts/AppShell';
export function AdminLayout() {
const session = readSession();
if (session?.portal !== 'admin') {
return <Navigate to="/admin/login" replace />;
}
return (
<AppShell
title="CMPP 运营端"
subtitle="平台运营管理中心"
workspaceName="平台运营工作区"
userName="运营"
loginPath="/admin/login"
userName={session.user.displayName}
userRole="平台管理员"
auditNotifications={[
{ label: '企业认证审核', count: 3, to: '/admin/enterprise-audit' },
+10 -2
View File
@@ -12,7 +12,8 @@ import {
Search,
Sparkles,
} from 'lucide-react';
import { NavLink, Outlet } from 'react-router-dom';
import { NavLink, Outlet, useNavigate } from 'react-router-dom';
import { clearSession } from '@/api/session';
export type ShellNavItem = {
label: string;
@@ -37,6 +38,7 @@ type AppShellProps = {
title: string;
subtitle: string;
workspaceName: string;
loginPath: string;
userName: string;
userRole: string;
navSections: ShellNavSection[];
@@ -47,6 +49,7 @@ export function AppShell({
title,
subtitle,
workspaceName,
loginPath,
userName,
userRole,
navSections,
@@ -56,6 +59,7 @@ export function AppShell({
const [closedSections, setClosedSections] = useState<Record<string, boolean>>({});
const [userMenuOpen, setUserMenuOpen] = useState(false);
const [noticeOpen, setNoticeOpen] = useState(false);
const navigate = useNavigate();
const ToggleIcon = collapsed ? PanelLeftOpen : PanelLeftClose;
const auditTotal = useMemo(
() => auditNotifications.reduce((sum, item) => sum + item.count, 0),
@@ -205,7 +209,11 @@ export function AppShell({
<KeyRound size={16} />
</button>
<button onClick={() => setUserMenuOpen(false)} role="menuitem" type="button">
<button onClick={() => {
clearSession();
setUserMenuOpen(false);
navigate(loginPath, { replace: true });
}} role="menuitem" type="button">
<LogOut size={16} />
退
</button>
+10 -2
View File
@@ -10,15 +10,23 @@ import {
ShieldCheck,
Users,
} from 'lucide-react';
import { Navigate } from 'react-router-dom';
import { readSession } from '@/api/session';
import { AppShell } from '@/layouts/AppShell';
export function ClientLayout() {
const session = readSession();
if (session?.portal !== 'client') {
return <Navigate to="/client/login" replace />;
}
return (
<AppShell
title="CMPP 客户端"
subtitle="短信服务控制台"
workspaceName="华东一区客户空间"
userName="赵先生"
workspaceName={session.user.tenantName ?? '企业客户空间'}
loginPath="/client/login"
userName={session.user.displayName}
userRole="企业管理员"
navSections={[
{