修改注册功能问题
This commit is contained in:
+20
-10
@@ -6,29 +6,35 @@
|
||||
.login-mode-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
margin: 18px 0 16px;
|
||||
gap: 4px;
|
||||
margin: 18px 0 18px;
|
||||
padding: 4px;
|
||||
border: 1px solid rgba(138, 64, 42, .14);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, .72);
|
||||
border: 1px solid rgba(200, 59, 50, .16);
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 250, 241, .88);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .78);
|
||||
}
|
||||
|
||||
/* 登录方式按钮只负责状态呈现,切换逻辑在 auth-pages.js */
|
||||
.login-mode-tab {
|
||||
min-height: 38px;
|
||||
min-height: 42px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
font: inherit;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: color .22s ease, background .22s ease, box-shadow .22s ease;
|
||||
}
|
||||
|
||||
.login-mode-tab.is-active {
|
||||
background: var(--brand);
|
||||
color: #fff;
|
||||
box-shadow: 0 8px 20px rgba(138, 64, 42, .18);
|
||||
background: rgba(200, 59, 50, .11);
|
||||
color: var(--red);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(200, 59, 50, .16),
|
||||
0 8px 18px rgba(138, 64, 42, .08);
|
||||
}
|
||||
|
||||
.login-mode-panel[hidden] {
|
||||
@@ -41,6 +47,10 @@
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.page-login .auth-links {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.page-login .auth-layout {
|
||||
align-items: start;
|
||||
|
||||
+137
-46
@@ -15,6 +15,28 @@
|
||||
'use strict';
|
||||
|
||||
var documentRef = root.document;
|
||||
var FORM_CONFIG = {
|
||||
login: {
|
||||
selector: '#login-password-form',
|
||||
captchaScene: 'WEB_H5_LOGIN',
|
||||
successUrl: 'profile.html'
|
||||
},
|
||||
'sms-login': {
|
||||
selector: '#login-sms-form',
|
||||
captchaScene: 'WEB_H5_LOGIN',
|
||||
successUrl: 'profile.html'
|
||||
},
|
||||
register: {
|
||||
selector: '#register-form',
|
||||
captchaScene: 'WEB_H5_REGISTER',
|
||||
successUrl: 'login.html'
|
||||
},
|
||||
'password-reset': {
|
||||
selector: '#password-reset-form',
|
||||
captchaScene: 'WEB_H5_FORGOT_PASSWORD',
|
||||
successUrl: 'login.html'
|
||||
}
|
||||
};
|
||||
|
||||
function hashPassword(value) {
|
||||
// 接口文档要求密码传 32 位 MD5;没有加载 md5.js 时保留原值,便于测试定位。
|
||||
@@ -77,20 +99,22 @@
|
||||
|
||||
function getCaptchaScene(formType) {
|
||||
// PC/H5 认证场景来自后台验证码配置,客户端 Key 为 web_pc。
|
||||
var map = {
|
||||
login: 'WEB_H5_LOGIN',
|
||||
register: 'WEB_H5_REGISTER',
|
||||
'password-reset': 'WEB_H5_FORGOT_PASSWORD'
|
||||
};
|
||||
var config = FORM_CONFIG[formType] || {};
|
||||
|
||||
return map[formType] || '';
|
||||
return config.captchaScene || '';
|
||||
}
|
||||
|
||||
function getSuccessUrl(formType) {
|
||||
var config = FORM_CONFIG[formType] || {};
|
||||
|
||||
return config.successUrl || '';
|
||||
}
|
||||
|
||||
function getFormCaptchaScene(form, formType) {
|
||||
// 页面可通过 data-captcha-scene 显式声明后台配置的验证码场景。
|
||||
var sceneCode = form && form.getAttribute && form.getAttribute('data-captcha-scene');
|
||||
// 场景码由当前脚本统一管理,避免散落在 HTML 属性中。
|
||||
var sceneCode = getCaptchaScene(formType);
|
||||
|
||||
return sceneCode || getCaptchaScene(formType);
|
||||
return sceneCode;
|
||||
}
|
||||
|
||||
async function ensureCaptcha(form, sceneCode, subject) {
|
||||
@@ -142,8 +166,73 @@
|
||||
if (root.console && root.console.warn) root.console.warn(message);
|
||||
}
|
||||
|
||||
function requireValue(value, message) {
|
||||
if (value) return true;
|
||||
function isPhone(value) {
|
||||
return /^1\d{10}$/.test(value || '');
|
||||
}
|
||||
|
||||
function isSmsCode(value) {
|
||||
return /^\d{4,6}$/.test(value || '');
|
||||
}
|
||||
|
||||
function validatePassword(value, message) {
|
||||
if (!value) return message;
|
||||
if (value.length < 6) return '密码至少需要 6 位';
|
||||
return '';
|
||||
}
|
||||
|
||||
function validateAuthValues(formType, values) {
|
||||
var data = values || {};
|
||||
|
||||
if (!data.phone) return '请填写手机号';
|
||||
if (!isPhone(data.phone)) return '请输入正确的手机号';
|
||||
|
||||
if (formType === 'login') {
|
||||
return validatePassword(data.password, '请填写密码');
|
||||
}
|
||||
|
||||
if (formType === 'sms-login') {
|
||||
if (!data.smsCode) return '请填写短信验证码';
|
||||
if (!isSmsCode(data.smsCode)) return '请输入正确的短信验证码';
|
||||
return '';
|
||||
}
|
||||
|
||||
if (formType === 'register') {
|
||||
return validatePassword(data.password, '请填写密码');
|
||||
}
|
||||
|
||||
if (formType === 'password-reset') {
|
||||
if (!data.smsCode) return '请填写验证码';
|
||||
if (!isSmsCode(data.smsCode)) return '请输入正确的短信验证码';
|
||||
|
||||
var passwordMessage = validatePassword(data.newPassword, '请填写新密码');
|
||||
if (passwordMessage) return passwordMessage;
|
||||
if (!data.confirmPassword) return '请再次输入新密码';
|
||||
if (data.newPassword !== data.confirmPassword) return '两次输入的新密码不一致';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function validateBeforeSubmit(formType, values) {
|
||||
var message = validateAuthValues(formType, values);
|
||||
|
||||
if (!message) return true;
|
||||
showMessage(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
function validatePhoneOnly(values) {
|
||||
var data = values || {};
|
||||
|
||||
if (!data.phone) return '请填写手机号';
|
||||
if (!isPhone(data.phone)) return '请输入正确的手机号';
|
||||
return '';
|
||||
}
|
||||
|
||||
function validateBeforeSendCode(values) {
|
||||
var message = validatePhoneOnly(values);
|
||||
|
||||
if (!message) return true;
|
||||
showMessage(message);
|
||||
return false;
|
||||
}
|
||||
@@ -159,30 +248,29 @@
|
||||
});
|
||||
}
|
||||
|
||||
function setLoginMode(activeMode) {
|
||||
function setLoginMode(activePanelId) {
|
||||
// 登录方式切换只更新状态,具体样式由 login.css 控制。
|
||||
queryAll('[data-login-mode-tab]').forEach(function (button) {
|
||||
var isActive = button.getAttribute('data-login-mode-tab') === activeMode;
|
||||
queryAll('.login-mode-tab').forEach(function (button) {
|
||||
var isActive = button.getAttribute('aria-controls') === activePanelId;
|
||||
|
||||
button.classList.toggle('is-active', isActive);
|
||||
button.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
||||
});
|
||||
|
||||
queryAll('[data-login-mode-panel]').forEach(function (panel) {
|
||||
var isActive = panel.getAttribute('data-login-mode-panel') === activeMode;
|
||||
queryAll('.login-mode-panel').forEach(function (panel) {
|
||||
var isActive = panel.id === activePanelId;
|
||||
|
||||
panel.hidden = !isActive;
|
||||
});
|
||||
}
|
||||
|
||||
async function submitLogin(form, button) {
|
||||
// 登录成功后跳转地址由 HTML 的 data-success-url 控制,页面可单独调整。
|
||||
// 登录成功后跳转地址由 FORM_CONFIG 统一控制,HTML 只保留表单结构。
|
||||
var api = getApi();
|
||||
var values = readForm(form);
|
||||
|
||||
if (!api) return;
|
||||
if (!requireValue(values.phone, '请填写手机号')) return;
|
||||
if (!requireValue(values.password, '请填写密码')) return;
|
||||
if (!validateBeforeSubmit('login', values)) return;
|
||||
if (!await ensureCaptcha(form, getFormCaptchaScene(form, 'login'), values.phone)) return;
|
||||
|
||||
values = readForm(form);
|
||||
@@ -190,7 +278,7 @@
|
||||
setBusy(button, true);
|
||||
try {
|
||||
await api.login(buildLoginBody(values));
|
||||
root.location.href = form.getAttribute('data-success-url') || 'profile.html';
|
||||
root.location.href = getSuccessUrl('login');
|
||||
} catch (error) {
|
||||
showMessage(error.message || '登录失败');
|
||||
} finally {
|
||||
@@ -204,16 +292,15 @@
|
||||
var values = readForm(form);
|
||||
|
||||
if (!api) return;
|
||||
if (!requireValue(values.phone, '请填写手机号')) return;
|
||||
if (!requireValue(values.smsCode, '请填写短信验证码')) return;
|
||||
if (!await ensureCaptcha(form, getFormCaptchaScene(form, 'login'), values.phone)) return;
|
||||
if (!validateBeforeSubmit('sms-login', values)) return;
|
||||
if (!await ensureCaptcha(form, getFormCaptchaScene(form, 'sms-login'), values.phone)) return;
|
||||
|
||||
values = readForm(form);
|
||||
|
||||
setBusy(button, true);
|
||||
try {
|
||||
await api.loginBySms(buildSmsLoginBody(values));
|
||||
root.location.href = form.getAttribute('data-success-url') || 'profile.html';
|
||||
root.location.href = getSuccessUrl('sms-login');
|
||||
} catch (error) {
|
||||
showMessage(error.message || '短信登录失败');
|
||||
} finally {
|
||||
@@ -222,13 +309,12 @@
|
||||
}
|
||||
|
||||
async function submitRegister(form, button) {
|
||||
// 注册成功后默认进入创建家谱流程。
|
||||
// 注册完成后回到登录页,创建家谱必须在登录后进行。
|
||||
var api = getApi();
|
||||
var values = readForm(form);
|
||||
|
||||
if (!api) return;
|
||||
if (!requireValue(values.phone, '请填写手机号')) return;
|
||||
if (!requireValue(values.password, '请填写密码')) return;
|
||||
if (!validateBeforeSubmit('register', values)) return;
|
||||
if (!await ensureCaptcha(form, getFormCaptchaScene(form, 'register'), values.phone)) return;
|
||||
|
||||
values = readForm(form);
|
||||
@@ -236,7 +322,7 @@
|
||||
setBusy(button, true);
|
||||
try {
|
||||
await api.register(buildRegisterBody(values));
|
||||
root.location.href = form.getAttribute('data-success-url') || 'create-genealogy.html';
|
||||
root.location.href = getSuccessUrl('register');
|
||||
} catch (error) {
|
||||
showMessage(error.message || '注册失败');
|
||||
} finally {
|
||||
@@ -245,14 +331,15 @@
|
||||
}
|
||||
|
||||
async function sendCode(button) {
|
||||
// 当前只接找回密码验证码;后续注册短信可复用 data-scene-code 扩展。
|
||||
// 短信验证码场景由表单配置决定,不在按钮属性中重复声明。
|
||||
var api = getApi();
|
||||
var form = button.closest('form');
|
||||
var values = readForm(form);
|
||||
var sceneCode = button.getAttribute('data-scene-code') || getFormCaptchaScene(form, 'password-reset');
|
||||
var formType = getFormType(form);
|
||||
var sceneCode = getFormCaptchaScene(form, formType);
|
||||
|
||||
if (!api) return;
|
||||
if (!requireValue(values.phone, '请填写手机号')) return;
|
||||
if (!validateBeforeSendCode(values)) return;
|
||||
if (!await ensureCaptcha(form, sceneCode, values.phone)) return;
|
||||
|
||||
values = readForm(form);
|
||||
@@ -278,13 +365,7 @@
|
||||
var values = readForm(form);
|
||||
|
||||
if (!api) return;
|
||||
if (!requireValue(values.phone, '请填写手机号')) return;
|
||||
if (!requireValue(values.smsCode, '请填写验证码')) return;
|
||||
if (!requireValue(values.newPassword, '请填写新密码')) return;
|
||||
if (values.newPassword !== values.confirmPassword) {
|
||||
showMessage('两次输入的新密码不一致');
|
||||
return;
|
||||
}
|
||||
if (!validateBeforeSubmit('password-reset', values)) return;
|
||||
if (!await ensureCaptcha(form, getFormCaptchaScene(form, 'password-reset'), values.phone)) return;
|
||||
|
||||
values = readForm(form);
|
||||
@@ -293,7 +374,7 @@
|
||||
try {
|
||||
await api.resetPassword(buildPasswordResetBody(values));
|
||||
showMessage('密码已重设,请重新登录');
|
||||
root.location.href = form.getAttribute('data-success-url') || 'login.html';
|
||||
root.location.href = getSuccessUrl('password-reset');
|
||||
} catch (error) {
|
||||
showMessage(error.message || '重设密码失败');
|
||||
} finally {
|
||||
@@ -311,21 +392,29 @@
|
||||
}
|
||||
|
||||
function bindLoginModeTabs() {
|
||||
queryAll('[data-login-mode-tab]').forEach(function (button) {
|
||||
queryAll('.login-mode-tab').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
setLoginMode(button.getAttribute('data-login-mode-tab'));
|
||||
setLoginMode(button.getAttribute('aria-controls'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getFormType(form) {
|
||||
if (!form) return '';
|
||||
|
||||
return Object.keys(FORM_CONFIG).find(function (formType) {
|
||||
return FORM_CONFIG[formType].selector === '#' + form.id;
|
||||
}) || '';
|
||||
}
|
||||
|
||||
function init() {
|
||||
// 每个页面只会命中自己的 data-auth-form,不需要拆多个入口文件。
|
||||
// 每个页面只会命中自己的表单 id,不需要拆多个入口文件。
|
||||
if (!documentRef) return;
|
||||
|
||||
bindSubmit('[data-auth-form="login"]', submitLogin);
|
||||
bindSubmit('[data-auth-form="sms-login"]', submitSmsLogin);
|
||||
bindSubmit('[data-auth-form="register"]', submitRegister);
|
||||
bindSubmit('[data-auth-form="password-reset"]', submitPasswordReset);
|
||||
bindSubmit(FORM_CONFIG.login.selector, submitLogin);
|
||||
bindSubmit(FORM_CONFIG['sms-login'].selector, submitSmsLogin);
|
||||
bindSubmit(FORM_CONFIG.register.selector, submitRegister);
|
||||
bindSubmit(FORM_CONFIG['password-reset'].selector, submitPasswordReset);
|
||||
bindLoginModeTabs();
|
||||
bindCodeButtons();
|
||||
}
|
||||
@@ -337,6 +426,8 @@
|
||||
buildPasswordResetBody: buildPasswordResetBody,
|
||||
getCaptchaScene: getCaptchaScene,
|
||||
getFormCaptchaScene: getFormCaptchaScene,
|
||||
getSuccessUrl: getSuccessUrl,
|
||||
validateAuthValues: validateAuthValues,
|
||||
init: init
|
||||
};
|
||||
});
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
// requestData 是 TAC 拖动完成后的轨迹数据;context 保存本次挑战的接口字段。
|
||||
var settings = context || {};
|
||||
var source = requestData || {};
|
||||
var track = normalizeVerifyTrack(source.data || {});
|
||||
|
||||
return {
|
||||
tenantId: settings.tenantId || api.tenantId,
|
||||
@@ -80,12 +81,35 @@
|
||||
providerCode: settings.providerCode || 'tianai',
|
||||
captchaType: settings.captchaType || 'SLIDER',
|
||||
payload: {
|
||||
id: source.id,
|
||||
data: source.data || {}
|
||||
track: track
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeVerifyTrack(data) {
|
||||
// 后端 /captcha/verify 要求轨迹统一放在 payload.track,并显式携带 left/top。
|
||||
var track = Object.assign({}, data || {});
|
||||
var trackList = Array.isArray(track.trackList) ? track.trackList : [];
|
||||
var first = trackList[0] || {};
|
||||
var last = trackList[trackList.length - 1] || {};
|
||||
|
||||
if (typeof track.left === 'undefined') {
|
||||
track.left = toNumber(last.x) - toNumber(first.x);
|
||||
}
|
||||
|
||||
if (typeof track.top === 'undefined') {
|
||||
track.top = toNumber(last.y) - toNumber(first.y);
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
function toNumber(value) {
|
||||
var numberValue = Number(value);
|
||||
|
||||
return Number.isFinite(numberValue) ? numberValue : 0;
|
||||
}
|
||||
|
||||
function normalizeVerifyResponse(response) {
|
||||
// TAC 只看 code 是否为 200;接口通过 passed 表示业务验证结果。
|
||||
var payload = response || {};
|
||||
@@ -299,6 +323,7 @@
|
||||
buildChallengeBody: buildChallengeBody,
|
||||
adaptChallengeResponse: adaptChallengeResponse,
|
||||
buildVerifyBody: buildVerifyBody,
|
||||
normalizeVerifyTrack: normalizeVerifyTrack,
|
||||
createCaptchaLayer: createCaptchaLayer,
|
||||
closeCaptchaLayer: closeCaptchaLayer,
|
||||
extractValidToken: extractValidToken,
|
||||
|
||||
Reference in New Issue
Block a user