feat(web): 增加单点登录分流与本地应急入口

开启统一认证后,正常登录入口直接跳转认证中心,并将本地账号入口收敛到 /login 应急页;未开启统一认证时继续保留工作台内原有登录方式。

影响范围仅限 Web 登录路由、认证入口展示和相关测试,不修改认证接口或 OpenAPI。风险主要在运行时身份状态判断,已通过 141 项前端测试、生产构建、无缓存类型检查及浏览器分支验证。
This commit is contained in:
2026-07-31 13:43:06 +08:00
parent cae97b6f77
commit 88c971564a
10 changed files with 169 additions and 14 deletions
@@ -0,0 +1,24 @@
import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it, vi } from 'vitest';
import { EmergencyLoginPage } from './EmergencyLoginPage';
describe('EmergencyLoginPage', () => {
it('renders only the local account form for emergency access', () => {
const html = renderToStaticMarkup(
<EmergencyLoginPage
loginForm={{ account: '', password: '' }}
state="idle"
onLoginChange={vi.fn()}
onSubmitLogin={vi.fn()}
/>,
);
expect(html).toContain('本地应急登录');
expect(html).toContain('统一认证中心不可用');
expect(html).toContain('用户名或邮箱');
expect(html).toContain('current-password');
expect(html).not.toContain('注册账号');
expect(html).not.toContain('外部 Token');
expect(html).not.toContain('使用统一认证中心登录');
});
});
+35
View File
@@ -0,0 +1,35 @@
import type { FormEvent } from 'react';
import { LocalLoginForm } from '../components/AuthPanel';
import { Card, CardContent, CardDescription, CardHeader } from '../components/ui';
import type { LoadState, LoginForm } from '../types';
export function EmergencyLoginPage(props: {
loginForm: LoginForm;
state: LoadState;
onLoginChange: (value: LoginForm) => void;
onSubmitLogin: (event: FormEvent<HTMLFormElement>) => void;
}) {
return (
<div className="loginRequiredPage">
<div className="loginRequiredCopy">
<p className="eyebrow">Emergency Access</p>
<h1></h1>
<p>使</p>
</div>
<section className="authShell" aria-label="本地应急登录">
<Card className="authCard">
<CardHeader>
<div>
<p className="eyebrow">Gateway Identity</p>
<h2 className="shCardTitle">使</h2>
<CardDescription> Manager Admin </CardDescription>
</div>
</CardHeader>
<CardContent className="authContent">
<LocalLoginForm {...props} />
</CardContent>
</Card>
</section>
</div>
);
}