修复手机号注册登录密码页与成功清理
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
getAutoRunStatusPayload,
|
||||
getErrorMessage,
|
||||
getFirstUnfinishedNodeId,
|
||||
getNodeIdsForState,
|
||||
getPendingAutoRunTimerPlan,
|
||||
getRunningNodeIds,
|
||||
getState,
|
||||
@@ -65,6 +66,77 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
const EMPTY_REGISTRATION_EMAIL_STATE = Object.freeze({
|
||||
current: '',
|
||||
previous: '',
|
||||
source: '',
|
||||
updatedAt: 0,
|
||||
});
|
||||
const DONE_NODE_STATUSES = new Set(['completed', 'manual_completed', 'skipped']);
|
||||
|
||||
function isPhoneSignupFlow(state = {}) {
|
||||
const resolvedSignupMethod = String(state?.resolvedSignupMethod || '').trim().toLowerCase();
|
||||
if (resolvedSignupMethod === 'phone' || resolvedSignupMethod === 'email') {
|
||||
return resolvedSignupMethod === 'phone';
|
||||
}
|
||||
const signupMethod = String(state?.signupMethod || '').trim().toLowerCase();
|
||||
return signupMethod === 'phone';
|
||||
}
|
||||
|
||||
function getFullWorkflowNodeIds(state = {}) {
|
||||
if (typeof getNodeIdsForState === 'function') {
|
||||
const nodeIds = getNodeIdsForState(state);
|
||||
if (Array.isArray(nodeIds) && nodeIds.length) {
|
||||
return Array.from(new Set(
|
||||
nodeIds
|
||||
.map((nodeId) => String(nodeId || '').trim())
|
||||
.filter(Boolean)
|
||||
));
|
||||
}
|
||||
}
|
||||
return getKnownNodeIdsFromState(state);
|
||||
}
|
||||
|
||||
function isFullWorkflowDone(state = {}) {
|
||||
const nodeIds = getFullWorkflowNodeIds(state);
|
||||
if (!nodeIds.length) {
|
||||
return false;
|
||||
}
|
||||
const nodeStatuses = state?.nodeStatuses || {};
|
||||
return nodeIds.every((nodeId) => DONE_NODE_STATUSES.has(String(nodeStatuses[nodeId] || 'pending').trim()));
|
||||
}
|
||||
|
||||
async function clearPhoneSignupRuntimeAfterRoundSuccess() {
|
||||
const currentState = await getState();
|
||||
if (!isPhoneSignupFlow(currentState) || !isFullWorkflowDone(currentState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await setState({
|
||||
accountIdentifierType: null,
|
||||
accountIdentifier: '',
|
||||
currentPhoneActivation: null,
|
||||
phoneNumber: '',
|
||||
signupPhoneNumber: '',
|
||||
signupPhoneActivation: null,
|
||||
signupPhoneCompletedActivation: null,
|
||||
signupPhoneVerificationRequestedAt: null,
|
||||
signupPhoneVerificationPurpose: '',
|
||||
currentPhoneVerificationCode: '',
|
||||
currentPhoneVerificationCountdownEndsAt: 0,
|
||||
currentPhoneVerificationCountdownWindowIndex: 0,
|
||||
currentPhoneVerificationCountdownWindowTotal: 0,
|
||||
email: null,
|
||||
registrationEmailState: { ...EMPTY_REGISTRATION_EMAIL_STATE },
|
||||
step8VerificationTargetEmail: '',
|
||||
lastEmailTimestamp: null,
|
||||
lastSignupCode: '',
|
||||
lastLoginCode: '',
|
||||
bindEmailSubmitted: false,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
async function waitForRunningWorkflowNodesToFinish(payload = {}) {
|
||||
if (typeof waitForRunningNodesToFinish === 'function') {
|
||||
return waitForRunningNodesToFinish(payload);
|
||||
@@ -698,6 +770,7 @@
|
||||
attemptRuns: attemptRun,
|
||||
continued: useExistingProgress,
|
||||
});
|
||||
await clearPhoneSignupRuntimeAfterRoundSuccess();
|
||||
|
||||
roundSummary.status = 'success';
|
||||
roundSummary.finalFailureReason = '';
|
||||
|
||||
@@ -523,6 +523,109 @@
|
||||
|| status === 'skipped';
|
||||
}
|
||||
|
||||
function isPhoneSignupStepPayload(payload = {}, state = {}) {
|
||||
const payloadIdentifierType = String(payload?.accountIdentifierType || '').trim().toLowerCase();
|
||||
if (payloadIdentifierType === 'email') {
|
||||
return false;
|
||||
}
|
||||
const stateIdentifierType = String(state?.accountIdentifierType || '').trim().toLowerCase();
|
||||
return payloadIdentifierType === 'phone'
|
||||
|| Boolean(resolveSignupPhonePayload(payload))
|
||||
|| stateIdentifierType === 'phone'
|
||||
|| Boolean(String(state?.signupPhoneNumber || '').trim())
|
||||
|| Boolean(state?.signupPhoneActivation)
|
||||
|| Boolean(state?.signupPhoneCompletedActivation);
|
||||
}
|
||||
|
||||
function isLoginPasswordPagePayload(payload = {}) {
|
||||
const mode = String(payload?.passwordPageMode || '').trim().toLowerCase();
|
||||
if (mode === 'login') {
|
||||
return true;
|
||||
}
|
||||
const path = String(payload?.passwordPagePath || '').trim();
|
||||
if (/\/log-in\/password(?:[/?#]|$)/i.test(path)) {
|
||||
return true;
|
||||
}
|
||||
const rawUrl = String(payload?.passwordPageUrl || '').trim();
|
||||
if (!rawUrl) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return /\/log-in\/password(?:[/?#]|$)/i.test(new URL(rawUrl).pathname || '');
|
||||
} catch {
|
||||
return /\/log-in\/password(?:[/?#]|$)/i.test(rawUrl);
|
||||
}
|
||||
}
|
||||
|
||||
function isSignupPasswordPagePayload(payload = {}) {
|
||||
const mode = String(payload?.passwordPageMode || '').trim().toLowerCase();
|
||||
if (mode === 'signup') {
|
||||
return true;
|
||||
}
|
||||
const path = String(payload?.passwordPagePath || '').trim();
|
||||
if (/\/(?:create-account|u\/signup|signup)\/password(?:[/?#]|$)/i.test(path)) {
|
||||
return true;
|
||||
}
|
||||
const rawUrl = String(payload?.passwordPageUrl || '').trim();
|
||||
if (!rawUrl) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return /\/(?:create-account|u\/signup|signup)\/password(?:[/?#]|$)/i.test(new URL(rawUrl).pathname || '');
|
||||
} catch {
|
||||
return /\/(?:create-account|u\/signup|signup)\/password(?:[/?#]|$)/i.test(rawUrl);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldSkipPhoneSignupRegistrationTailAfterPassword(payload = {}, state = {}) {
|
||||
if (!isPhoneSignupStepPayload(payload, state) || isSignupPasswordPagePayload(payload) || !isLoginPasswordPagePayload(payload)) {
|
||||
return false;
|
||||
}
|
||||
const nextState = String(payload?.state || payload?.successState || '').trim().toLowerCase();
|
||||
return Boolean(payload?.ready)
|
||||
|| Boolean(payload?.alreadyVerified)
|
||||
|| nextState === 'verification'
|
||||
|| nextState === 'verification_page'
|
||||
|| nextState === 'phone_verification_page'
|
||||
|| nextState === 'oauth_consent_page'
|
||||
|| nextState === 'logged_in_home';
|
||||
}
|
||||
|
||||
async function skipPhoneSignupRegistrationTailAfterPassword(currentStep, payload = {}) {
|
||||
const latestState = await getState();
|
||||
const skippedSteps = [];
|
||||
for (const stepKey of ['fetch-signup-code', 'fill-profile', 'wait-registration-success']) {
|
||||
const skippedStep = findStepByKeyAfter(currentStep, stepKey, latestState);
|
||||
if (!skippedStep) {
|
||||
continue;
|
||||
}
|
||||
const status = getNodeStatusByStep(skippedStep, latestState);
|
||||
if (isStepProtectedFromAutoSkip(status)) {
|
||||
continue;
|
||||
}
|
||||
await setNodeStatusByStep(skippedStep, 'skipped', latestState);
|
||||
skippedSteps.push(skippedStep);
|
||||
}
|
||||
|
||||
await setState({ signupVerificationRequestedAt: null });
|
||||
if (skippedSteps.length) {
|
||||
await addLog(
|
||||
`步骤 ${currentStep}:手机号密码提交后已确认账号进入登录后续状态,已自动跳过步骤 ${skippedSteps.join('/')},流程将直接进入 OAuth 后续节点。`,
|
||||
'warn',
|
||||
{ step: currentStep, stepKey: 'fill-password' }
|
||||
);
|
||||
}
|
||||
payload.signupVerificationRequestedAt = null;
|
||||
payload.passwordLoginFlow = true;
|
||||
payload.skipRegistrationFlow = true;
|
||||
return {
|
||||
...payload,
|
||||
signupVerificationRequestedAt: null,
|
||||
passwordLoginFlow: true,
|
||||
skipRegistrationFlow: true,
|
||||
};
|
||||
}
|
||||
|
||||
function findStepByKeyAfter(currentOrder, targetKey, state = {}) {
|
||||
const activeStepIds = typeof getStepIdsForState === 'function'
|
||||
? getStepIdsForState(state)
|
||||
@@ -847,6 +950,13 @@
|
||||
break;
|
||||
case 3:
|
||||
await syncStepAccountIdentityFromPayload(payload);
|
||||
{
|
||||
const latestState = await getState();
|
||||
if (shouldSkipPhoneSignupRegistrationTailAfterPassword(payload, latestState)) {
|
||||
await skipPhoneSignupRegistrationTailAfterPassword(step, payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (payload.signupVerificationRequestedAt) {
|
||||
await setState({ signupVerificationRequestedAt: payload.signupVerificationRequestedAt });
|
||||
}
|
||||
@@ -967,9 +1077,16 @@
|
||||
notifyNodeError(nodeId, '流程已被用户停止。');
|
||||
return { ok: true };
|
||||
}
|
||||
let completionPayload = message.payload || {};
|
||||
try {
|
||||
if (nodeId === 'fill-password' && typeof finalizeStep3Completion === 'function') {
|
||||
await finalizeStep3Completion(message.payload || {});
|
||||
const finalizedPayload = await finalizeStep3Completion(message.payload || {});
|
||||
if (finalizedPayload && typeof finalizedPayload === 'object') {
|
||||
completionPayload = {
|
||||
...completionPayload,
|
||||
...finalizedPayload,
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (typeof isCloudflareSecurityBlockedError === 'function' && isCloudflareSecurityBlockedError(error)) {
|
||||
@@ -1004,11 +1121,11 @@
|
||||
stepKey: nodeId,
|
||||
});
|
||||
}
|
||||
await handleStepData(resolvedStep, message.payload);
|
||||
await handleStepData(resolvedStep, completionPayload);
|
||||
if (isFinalNode && typeof appendAccountRunRecord === 'function') {
|
||||
await appendAccountRunRecord('success', completionState);
|
||||
}
|
||||
notifyNodeComplete(nodeId, message.payload);
|
||||
notifyNodeComplete(nodeId, completionPayload);
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user