第一次提交
This commit is contained in:
134
auth-portal/src/app/register/page.tsx
Normal file
134
auth-portal/src/app/register/page.tsx
Normal file
@ -0,0 +1,134 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { buildFrontendHandoffUrl, register, withNext } from '@/lib/auth-client';
|
||||
|
||||
export default function RegisterPage() {
|
||||
const searchParams = useSearchParams();
|
||||
const nextPath = searchParams?.get('next') || '/mcp';
|
||||
|
||||
const [username, setUsername] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
if (password !== confirmPassword) {
|
||||
throw new Error('两次输入的密码不一致');
|
||||
}
|
||||
const response = await register(username, email, password);
|
||||
window.location.replace(buildFrontendHandoffUrl(response, nextPath));
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : '注册失败,请稍后重试');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="portal-page">
|
||||
<section className="portal-shell">
|
||||
<div className="portal-brand">
|
||||
<div className="portal-kicker">Auth Portal</div>
|
||||
<h1 className="portal-title">Create Runtime</h1>
|
||||
<p className="portal-copy">
|
||||
注册不仅建立登录账号,还会触发专属实例创建和 backend 身份分配。认证完成后会直接进入你的专属 URL。
|
||||
</p>
|
||||
<div className="portal-notes">
|
||||
<div className="portal-note">
|
||||
<strong>注册结果</strong>
|
||||
deploy-control 会创建实例,AuthZ 再补齐 backend 身份,auth portal 最后把你转交到该实例前端。
|
||||
</div>
|
||||
<div className="portal-note">
|
||||
<strong>目标页面</strong>
|
||||
当前注册完成后将回到:<code>{nextPath}</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="portal-panel">
|
||||
<div className="auth-card">
|
||||
<h1>注册</h1>
|
||||
<p>为当前容器创建登录账号,并完成 backend 身份初始化。</p>
|
||||
|
||||
<form className="auth-form" onSubmit={handleSubmit}>
|
||||
<div className="field">
|
||||
<label htmlFor="username">用户名</label>
|
||||
<input
|
||||
id="username"
|
||||
value={username}
|
||||
onChange={(event) => setUsername(event.target.value)}
|
||||
autoComplete="username"
|
||||
placeholder="例如:bwgdi"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label htmlFor="email">邮箱</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(event) => setEmail(event.target.value)}
|
||||
autoComplete="email"
|
||||
placeholder="例如:steven@example.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label htmlFor="password">密码</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
autoComplete="new-password"
|
||||
placeholder="设置密码"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label htmlFor="confirmPassword">确认密码</label>
|
||||
<input
|
||||
id="confirmPassword"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(event) => setConfirmPassword(event.target.value)}
|
||||
autoComplete="new-password"
|
||||
placeholder="再次输入密码"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="error-text">{error}</div>
|
||||
|
||||
<button className="primary-button" type="submit" disabled={loading}>
|
||||
{loading ? '注册中...' : '注册并进入容器'}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="auth-footer">
|
||||
已有账号? <Link href={withNext('/login', nextPath)}>去登录</Link>
|
||||
</div>
|
||||
|
||||
<div className="status-panel">
|
||||
Portal 会先调用部署机接口创建实例,再把浏览器跳到实例自己的 URL。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user