From 35f659249e07f86dfd4c35ffe0eadf6397f9eba3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 6 Sep 2026 00:46:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B3=A8=E5=86=8C=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E4=B8=8D=E5=86=99=E5=85=A5=E6=8C=81=E4=B9=85=E5=8C=96?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=80=81=E3=80=81=E6=B3=A8=E5=86=8C=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5500=E9=94=99=E8=AF=AF=E6=98=BE=E7=A4=BA=E5=8E=9F?= =?UTF-8?q?=E5=A7=8B=E8=8B=B1=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register组件缺少Login同款的keep-logged-in挂载副作用,导致注册产生的 新账号在下一次刷新时静默丢失会话(无报错、无跳转登录页)。 另外注册走原生WS {acc}协议而非REST,未接入CTRL_ERROR_TEXT_CN翻译表, "internal error (500)"等错误会原样展示给用户。 第十轮最小粒度测试 Ch1-2 发现。 Co-Authored-By: Claude Sonnet 5 --- src/views/auth-onboarding-view.jsx | 18 ++++++++++++++++-- src/views/tinode-web.jsx | 13 +++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/views/auth-onboarding-view.jsx b/src/views/auth-onboarding-view.jsx index 10e7cb9e..36ca7a09 100644 --- a/src/views/auth-onboarding-view.jsx +++ b/src/views/auth-onboarding-view.jsx @@ -383,7 +383,7 @@ function VerificationButton({phone, scene = 'register', onChallenge, onError}) { // no phone-vs-username mode toggle. "Phone takes precedence" (per the spec text) is validation-only: // if a phone is filled it must be verified; the invite code is only required for a username-only // signup (matching the mock's original submit-time validation, now with real backend calls behind it). -function Register({errorText, errorLevel, onImRegisterRequest}) { +function Register({errorText, errorLevel, persist, onImRegisterRequest, onPersistenceChange}) { const [form, setForm] = React.useState({username: '', phone: '', code: '', password: '', invite: ''}); const [challengeId, setChallengeId] = React.useState(''); const [agreed, setAgreed] = React.useState(false); @@ -392,6 +392,19 @@ function Register({errorText, errorLevel, onImRegisterRequest}) { const change = key => e => setForm({...form, [key]: e.target.value}); const usingPhone = !!form.phone; + // Same silent "stay logged in" opt-in Login has (see its own copy of this effect for why there's + // no visible checkbox) -- missing here meant every account created by registering (as opposed to + // logging in) never had keep-logged-in/auth-token set, so handleLoginSuccessful() never persisted + // the session: the very next refresh silently lost myUserId with no redirect to the login page + // and no error, just a permanently empty messages-home shell. Every fresh registration hit this on + // its first reload. + React.useEffect(() => { + if (!persist) { + onPersistenceChange(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + // onImRegisterRequest (tinode-web.jsx's handleImRegisterRequest -> a WS connect+createAccountBasic // chain) isn't awaited and doesn't return a promise -- on the username/invite-code path (no // verifyRegisterCode await ahead of it) `submit` returns and its `finally` clears `submitting` @@ -795,7 +808,8 @@ export default function AuthOnboardingView({ errorText={errorText} errorLevel={errorLevel} onLoginRequest={onLoginRequest} onPersistenceChange={onPersistenceChange} onError={onError} />; case 'enterprise-register': return ; case 'enterprise-feedback': return ; - case 'register': return ; + case 'register': return ; case 'reset': return ; case 'identity-check': return ; case 'realname': return ; diff --git a/src/views/tinode-web.jsx b/src/views/tinode-web.jsx index 3ddab793..1651048f 100644 --- a/src/views/tinode-web.jsx +++ b/src/views/tinode-web.jsx @@ -177,7 +177,8 @@ const CTRL_ERROR_TEXT_CN = { 'authentication required': '请先登录', 'unknown authentication scheme': '登录方式不受支持,请刷新页面重试', 'policy violation': '当前操作不符合安全策略要求', - 'permission denied': '没有权限执行此操作,请重新登录' + 'permission denied': '没有权限执行此操作,请重新登录', + 'internal error': '服务器繁忙,请稍后重试' }; function translateCtrlError(err) { const raw = err && err.message; @@ -1517,7 +1518,15 @@ class TinodeWeb extends React.Component { this.handleLoginSuccessful(this); } }).catch(err => { - this.handleError(err.message, 'err'); + // Registration goes over the native WS {acc} protocol, not REST, so im-api.js's + // REASON_MESSAGES translation table (REST-only) never sees this error -- it was showing + // raw SDK text like "internal error (500)" verbatim (confirmed live: retrying a phone + // number that's already registered). CTRL_ERROR_TEXT_CN already translates this same class + // of {ctrl} error for login; reused here with a registration-appropriate fallback instead + // of loginErrorMessage's own (its 401/403 fallback is "账号或密码错误", which doesn't fit a + // failed registration). + const known = translateCtrlError(err); + this.handleError(known || (err && err.message) || '注册失败,请稍后重试', 'err'); }); }