feat(web): call the login name the account ID and list sign-up requirements
This commit is contained in:
1 parent
700be2ebae
commit
79bfd560cb
6 files changed
+49
-10
No files matched your search
@@ -150,6 +150,34 @@
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.rules {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
color: var(--text-dim);
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.rules li {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.rules li[data-met='true'] {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.srOnly {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip-path: inset(50%);
|
||||
}
|
||||
|
||||
.fieldError {
|
||||
color: var(--danger);
|
||||
font-size: 12px;
|
||||
|
||||
@@ -43,6 +43,14 @@ export function AccountPanel({ variant = 'default' }: { variant?: 'default' | 'a
|
||||
}, [account]);
|
||||
const creating = register && !unlockUsername;
|
||||
const mismatch = creating && confirm !== '' && password !== confirm;
|
||||
// 与服务端一致:ID 3–32 位,仅字母、数字、_、-
|
||||
const rules = [
|
||||
{ text: 'ID 为 3–32 个字符', met: username.length >= 3 && username.length <= 32 },
|
||||
{ text: 'ID 只能包含字母、数字、下划线 _ 和连字符 -', met: username !== '' && /^[A-Za-z0-9_-]+$/.test(username) },
|
||||
{ text: '密码至少 12 个字符', met: password.length >= 12 },
|
||||
{ text: '两次输入的密码一致', met: confirm !== '' && password === confirm },
|
||||
];
|
||||
const unmet = creating && rules.some((rule) => !rule.met);
|
||||
async function clearSaved() {
|
||||
edited.current = true;
|
||||
try { await clearSavedLogin(); setSaved(false); setRemember(false); setUsername(''); setPassword(''); setMessage(account ? '本机保存已清除,当前页面仍可使用;刷新后需要重新登录。' : '已清除本机保存的账号和密码。'); }
|
||||
@@ -81,14 +89,17 @@ export function AccountPanel({ variant = 'default' }: { variant?: 'default' | 'a
|
||||
<button type="button" aria-pressed={register} onClick={() => { edited.current = true; setRegister(true); setMessage(''); }}>创建账号</button>
|
||||
</div> : null}
|
||||
{unlockUsername ? <p className={styles.note}>已用Passkey确认账号,请输入账号密码解锁资源。</p> : null}
|
||||
<label>用户名<input name="username" autoComplete="username" minLength={3} maxLength={32} value={unlockUsername ?? username} disabled={Boolean(unlockUsername)} onChange={(event) => { edited.current = true; setUsername(event.target.value); }} required /></label>
|
||||
<label>账号 ID<input name="username" autoComplete="username" minLength={3} maxLength={32} value={unlockUsername ?? username} disabled={Boolean(unlockUsername)} onChange={(event) => { edited.current = true; setUsername(event.target.value); }} required /></label>
|
||||
<label>密码<input name="password" autoComplete={register ? 'new-password' : 'current-password'} type="password" minLength={register ? 12 : undefined} value={password} onChange={(event) => { edited.current = true; setPassword(event.target.value); }} required /></label>
|
||||
{creating ? <label>确认密码<input name="confirm-password" autoComplete="new-password" type="password" minLength={12} value={confirm} aria-invalid={mismatch} onChange={(event) => { edited.current = true; setConfirm(event.target.value); }} required />
|
||||
{mismatch ? <span className={styles.fieldError} role="alert">两次输入的密码不一致</span> : null}</label> : null}
|
||||
{creating ? <p className={styles.note}>密码至少 12 个字符。密码用于在本机加密你的资源保险库,<strong>忘记后无法找回</strong>,请妥善保管。</p> : null}
|
||||
</label> : null}
|
||||
{creating ? <ul className={styles.rules} aria-label="注册要求">
|
||||
{rules.map((rule) => <li key={rule.text} data-met={rule.met}><span aria-hidden="true">{rule.met ? '✓' : '○'}</span>{rule.text}<span className={styles.srOnly}>{rule.met ? ',已满足' : ',未满足'}</span></li>)}
|
||||
</ul> : null}
|
||||
{creating ? <p className={styles.note}>账号 ID 是登录用的唯一标识,不是显示名称;显示名称可在登录后的个人资料里设置。密码用于在本机加密你的资源保险库,<strong>忘记后无法找回</strong>,请妥善保管。</p> : null}
|
||||
<label className={styles.remember}><input type="checkbox" checked={remember} onChange={(event) => setRemember(event.target.checked)} />记住账号和密码(本机)</label>
|
||||
<div className={styles.actions}>
|
||||
<Button type="submit" variant="primary" disabled={busy || !channelsReady || !sharesReady || mismatch}>{busy ? '处理中…' : !channelsReady || !sharesReady ? '正在读取本机资源…' : unlockUsername ? '解锁资源' : register ? '创建账号' : '登录并同步'}</Button>
|
||||
<Button type="submit" variant="primary" disabled={busy || !channelsReady || !sharesReady || unmet}>{busy ? '处理中…' : !channelsReady || !sharesReady ? '正在读取本机资源…' : unlockUsername ? '解锁资源' : register ? '创建账号' : '登录并同步'}</Button>
|
||||
{variant !== 'auth' ? <Button variant="ghost" onClick={() => { edited.current = true; setRegister((value) => !value); setMessage(''); }}>{register ? '已有账号' : '创建账号'}</Button> : null}
|
||||
{saved ? <Button variant="ghost" disabled={busy} onClick={() => { void clearSaved(); }}>清除本机保存</Button> : null}
|
||||
{!register && !unlockUsername ? <Button variant="ghost" disabled={busy || !username || !passkeysAvailable()} onClick={() => {
|
||||
|
||||
Reference in new issue
Block a user