257 lines
7.9 KiB
JavaScript
257 lines
7.9 KiB
JavaScript
(function () {
|
|
var root = document.querySelector("[data-register-pop]");
|
|
if (!root) return;
|
|
|
|
var form = root.querySelector("[data-register-form]");
|
|
var password = root.querySelector("[data-register-password]");
|
|
var confirm = root.querySelector("[data-register-password-confirm]");
|
|
var submitBtn = root.querySelector("[data-register-submit]") || (form && form.querySelector('button[type="submit"]'));
|
|
var previousOverflow = "";
|
|
|
|
function closeLogin() {
|
|
if (typeof window.closeLoginPop === "function") {
|
|
window.closeLoginPop();
|
|
return;
|
|
}
|
|
var login = document.querySelector("[data-login-pop]");
|
|
if (login) login.classList.remove("is-open");
|
|
}
|
|
|
|
function closeUserMenu() {
|
|
var menu = document.querySelector("[data-user-menu].is-open");
|
|
if (menu) {
|
|
menu.classList.remove("is-open");
|
|
var t = menu.querySelector("[data-user-menu-toggle]");
|
|
if (t) t.setAttribute("aria-expanded", "false");
|
|
}
|
|
}
|
|
|
|
function clearFieldError(name) {
|
|
var field = root.querySelector('[data-field="' + name + '"]');
|
|
var err = root.querySelector('[data-field-error="' + name + '"]');
|
|
if (field) field.classList.remove("is-error");
|
|
if (err) {
|
|
err.hidden = true;
|
|
var text = err.querySelector("[data-field-error-text]");
|
|
if (text) text.textContent = "";
|
|
}
|
|
}
|
|
|
|
function clearAllErrors() {
|
|
root.querySelectorAll("[data-field]").forEach(function (el) {
|
|
el.classList.remove("is-error");
|
|
});
|
|
root.querySelectorAll("[data-field-error]").forEach(function (err) {
|
|
err.hidden = true;
|
|
var text = err.querySelector("[data-field-error-text]");
|
|
if (text) text.textContent = "";
|
|
});
|
|
}
|
|
|
|
function setFieldError(name, message) {
|
|
var field = root.querySelector('[data-field="' + name + '"]');
|
|
var err = root.querySelector('[data-field-error="' + name + '"]');
|
|
if (field) field.classList.add("is-error");
|
|
if (err) {
|
|
err.hidden = false;
|
|
var text = err.querySelector("[data-field-error-text]");
|
|
if (text) text.textContent = message || "";
|
|
}
|
|
}
|
|
|
|
function isAccountNo(value) {
|
|
return /^[A-Za-z0-9]{6,20}$/.test(String(value || ""));
|
|
}
|
|
|
|
function isPassword(value) {
|
|
var pwd = String(value || "");
|
|
if (pwd.length < 8) return false;
|
|
return /[A-Za-z]/.test(pwd) && /[0-9]/.test(pwd);
|
|
}
|
|
|
|
function bindingMessage(message, fallback) {
|
|
return String(message || fallback || "").replace(/注册/g, "绑定");
|
|
}
|
|
|
|
function validateForm() {
|
|
clearAllErrors();
|
|
var fd = new FormData(form);
|
|
var account = String(fd.get("account") || "").trim();
|
|
var pwd = String(fd.get("password") || "");
|
|
var pwd2 = String(fd.get("passwordConfirm") || "");
|
|
var agree = form.querySelector('input[name="agree"]');
|
|
var valid = true;
|
|
|
|
if (!account) {
|
|
setFieldError("account", "请输入账号");
|
|
valid = false;
|
|
} else if (!isAccountNo(account)) {
|
|
setFieldError("account", "账号需为 6 到 20 位字母或数字");
|
|
valid = false;
|
|
}
|
|
|
|
if (!pwd) {
|
|
setFieldError("password", "请输入密码");
|
|
valid = false;
|
|
} else if (!isPassword(pwd)) {
|
|
setFieldError("password", "密码需 8 位以上,且同时包含字母与数字");
|
|
valid = false;
|
|
}
|
|
|
|
if (!pwd2) {
|
|
setFieldError("passwordConfirm", "请再次输入密码");
|
|
valid = false;
|
|
} else if (pwd2 !== pwd) {
|
|
setFieldError("passwordConfirm", "两次输入的密码不一致");
|
|
valid = false;
|
|
}
|
|
|
|
if (agree && !agree.checked) {
|
|
setFieldError("agree", "请先同意用户条款与隐私政策");
|
|
valid = false;
|
|
}
|
|
|
|
if (!valid) return null;
|
|
return { accountNo: account, password: pwd };
|
|
}
|
|
|
|
function mapServerError(err) {
|
|
var tip = bindingMessage(err && err.message, "绑定失败,请稍后重试");
|
|
var code = err && err.code;
|
|
if (code === 5005 || /已存在|重复|占用/.test(tip)) {
|
|
setFieldError("account", tip);
|
|
return;
|
|
}
|
|
if (/密码|password/i.test(tip)) {
|
|
setFieldError("password", tip);
|
|
return;
|
|
}
|
|
setFieldError("account", tip);
|
|
}
|
|
|
|
function open(event) {
|
|
if (event) event.preventDefault();
|
|
closeLogin();
|
|
closeUserMenu();
|
|
clearAllErrors();
|
|
root.classList.add("is-open");
|
|
previousOverflow = document.body.style.overflow;
|
|
document.body.style.overflow = "hidden";
|
|
var first = root.querySelector(".register-pop__input");
|
|
if (first) {
|
|
window.setTimeout(function () {
|
|
first.focus();
|
|
}, 0);
|
|
}
|
|
}
|
|
|
|
function close() {
|
|
root.classList.remove("is-open");
|
|
document.body.style.overflow = previousOverflow;
|
|
clearAllErrors();
|
|
}
|
|
|
|
window.openRegisterPop = open;
|
|
window.closeRegisterPop = close;
|
|
|
|
function bindToggle(key, input) {
|
|
var btn = root.querySelector('[data-register-toggle="' + key + '"]');
|
|
var icon = root.querySelector('[data-register-toggle-icon="' + key + '"]');
|
|
if (!btn || !input || !icon) return;
|
|
btn.addEventListener("click", function () {
|
|
var show = input.getAttribute("type") === "password";
|
|
input.setAttribute("type", show ? "text" : "password");
|
|
icon.setAttribute("src", show ? "/static/images/eye-off.svg" : "/static/images/eye.svg");
|
|
btn.setAttribute("aria-label", show ? "隐藏密码" : "显示密码");
|
|
});
|
|
}
|
|
|
|
document.addEventListener("click", function (event) {
|
|
var opener = event.target.closest("[data-register-open]");
|
|
if (opener) {
|
|
open(event);
|
|
return;
|
|
}
|
|
|
|
// 站内注册入口统一使用绑定账号弹窗
|
|
var registerLink = event.target.closest('a[href="/register"], a[href="/register/"], a[href="#register"]');
|
|
if (registerLink) {
|
|
open(event);
|
|
return;
|
|
}
|
|
|
|
if (!root.classList.contains("is-open")) return;
|
|
if (event.target.closest("[data-register-close]")) {
|
|
close();
|
|
}
|
|
});
|
|
|
|
bindToggle("password", password);
|
|
bindToggle("confirm", confirm);
|
|
|
|
function setSubmitting(loading) {
|
|
if (!submitBtn) return;
|
|
submitBtn.disabled = !!loading;
|
|
submitBtn.classList.toggle("is-loading", !!loading);
|
|
submitBtn.textContent = loading ? "绑定中…" : "绑定";
|
|
}
|
|
|
|
if (form) {
|
|
form.querySelectorAll("input").forEach(function (input) {
|
|
input.addEventListener("input", function () {
|
|
var name = input.getAttribute("name");
|
|
if (name === "agree") clearFieldError("agree");
|
|
else if (name) clearFieldError(name);
|
|
});
|
|
if (input.type === "checkbox") {
|
|
input.addEventListener("change", function () {
|
|
clearFieldError("agree");
|
|
});
|
|
}
|
|
});
|
|
|
|
form.addEventListener("submit", function (event) {
|
|
event.preventDefault();
|
|
if (!window.AuthAPI || !window.HttpRequest) {
|
|
setFieldError("account", "认证脚本未加载,请刷新页面");
|
|
return;
|
|
}
|
|
if (submitBtn && submitBtn.classList.contains("is-loading")) return;
|
|
|
|
var payload = validateForm();
|
|
if (!payload) return;
|
|
|
|
setSubmitting(true);
|
|
AuthAPI.register(payload)
|
|
.then(function (res) {
|
|
AuthAPI.toast(bindingMessage(res && res.tip, "绑定成功"), "success");
|
|
window.setTimeout(function () {
|
|
close();
|
|
window.location.reload();
|
|
}, 400);
|
|
})
|
|
.catch(function (err) {
|
|
setSubmitting(false);
|
|
mapServerError(err);
|
|
AuthAPI.toast(bindingMessage(err && err.message, "绑定失败"), "error");
|
|
});
|
|
});
|
|
}
|
|
|
|
document.addEventListener("keydown", function (event) {
|
|
if (event.key === "Escape" && root.classList.contains("is-open")) {
|
|
close();
|
|
}
|
|
});
|
|
|
|
try {
|
|
var params = new URLSearchParams(window.location.search || "");
|
|
if (params.get("auth") === "register") {
|
|
params.delete("auth");
|
|
var qs = params.toString();
|
|
window.history.replaceState(null, "", window.location.pathname + (qs ? "?" + qs : "") + window.location.hash);
|
|
open();
|
|
}
|
|
} catch (e) {}
|
|
})();
|