Files
jiapu/public/js/security-pages.js
T
2026-07-09 17:30:10 +08:00

255 lines
6.5 KiB
JavaScript

(function (root, factory) {
// 账号安全模块同时支持浏览器页面和 Node 单元测试。
if (typeof module === 'object' && module.exports) {
module.exports = factory(root);
return;
}
root.SecurityPages = factory(root);
if (root.document) {
root.document.addEventListener('DOMContentLoaded', function () {
root.SecurityPages.init();
});
}
})(typeof globalThis !== 'undefined' ? globalThis : window, function (root) {
'use strict';
var documentRef = root.document;
function hashPassword(value) {
// 接口文档要求密码提交 32 位 MD5,测试环境可传入 hashFn 替代。
if (root.hex_md5) return root.hex_md5(value);
if (root.md5) return root.md5(value);
return value;
}
function trimOrUndefined(value) {
var text = String(value === undefined || value === null ? '' : value).trim();
return text || undefined;
}
function buildPasswordChangeBody(values, hashFn) {
var source = values || {};
var hash = hashFn || hashPassword;
return {
oldPassword: hash(String(source.oldPassword || '').trim()),
newPassword: hash(String(source.newPassword || '').trim())
};
}
function buildPhoneChangeBody(values) {
var source = values || {};
return {
newPhone: String(source.newPhone || '').trim(),
smsCode: String(source.smsCode || '').trim(),
validToken: trimOrUndefined(source.validToken)
};
}
function buildSmsLoginBody(values) {
var source = values || {};
return {
phone: String(source.phone || '').trim(),
smsCode: String(source.smsCode || '').trim(),
validToken: trimOrUndefined(source.validToken)
};
}
function buildDeactivateBody(values, hashFn) {
var source = values || {};
var hash = hashFn || hashPassword;
return {
password: hash(String(source.password || '').trim()),
reason: trimOrUndefined(source.reason)
};
}
function isDangerConfirmed(value) {
return String(value || '').trim() === '确认注销';
}
function getApi() {
return root.GenealogyApi && root.GenealogyApi.defaultClient;
}
function query(selector, rootNode) {
return (rootNode || documentRef).querySelector(selector);
}
function queryAll(selector, rootNode) {
return Array.prototype.slice.call((rootNode || documentRef).querySelectorAll(selector));
}
function showMessage(message) {
if (root.layui && root.layui.layer) {
root.layui.layer.msg(message);
return;
}
root.alert(message);
}
function getFormValues(form) {
var values = {};
queryAll('[name]', form).forEach(function (field) {
values[field.name] = field.value;
});
return values;
}
function setStatus(form, message) {
var status = query('[data-security-status]', form);
if (status) status.textContent = message;
}
async function submitPassword(form) {
var api = getApi();
var values = getFormValues(form);
if (!api) return;
if (!values.oldPassword || !values.newPassword) {
showMessage('请填写原密码和新密码');
return;
}
if (values.newPassword !== values.confirmPassword) {
showMessage('两次新密码不一致');
return;
}
try {
await api.changePassword(buildPasswordChangeBody(values));
setStatus(form, '密码已修改');
showMessage('密码已修改');
form.reset();
} catch (error) {
showMessage(error.message || '密码修改失败');
}
}
async function submitPhone(form) {
var api = getApi();
var body = buildPhoneChangeBody(getFormValues(form));
if (!api) return;
if (!body.newPhone || !body.smsCode) {
showMessage('请填写新手机号和验证码');
return;
}
try {
await api.changePhone(body);
setStatus(form, '手机号已换绑');
showMessage('手机号已换绑');
form.reset();
} catch (error) {
showMessage(error.message || '手机号换绑失败');
}
}
async function submitSmsLogin(form) {
var api = getApi();
var body = buildSmsLoginBody(getFormValues(form));
if (!api) return;
if (!body.phone || !body.smsCode) {
showMessage('请填写手机号和验证码');
return;
}
try {
await api.smsLogin(body);
setStatus(form, '短信登录已通过');
showMessage('短信登录已通过');
} catch (error) {
showMessage(error.message || '短信登录失败');
}
}
async function submitDeactivate(form) {
var api = getApi();
var values = getFormValues(form);
if (!api) return;
if (!values.password) {
showMessage('请填写当前密码');
return;
}
if (!isDangerConfirmed(values.confirmText)) {
showMessage('请完整输入“确认注销”');
return;
}
if (root.confirm && !root.confirm('账号注销后将退出登录,确认继续?')) return;
try {
await api.deactivateAccount(buildDeactivateBody(values));
showMessage('账号已提交注销');
root.location.href = 'login.html';
} catch (error) {
showMessage(error.message || '账号注销失败');
}
}
async function logout() {
var api = getApi();
if (!api) return;
if (root.confirm && !root.confirm('确认退出当前账号?')) return;
try {
await api.logout();
root.location.href = 'login.html';
} catch (error) {
showMessage(error.message || '退出登录失败');
}
}
function bindActions() {
if (!documentRef) return;
documentRef.addEventListener('submit', function (event) {
var form = event.target.closest('[data-security-form]');
var formType;
if (!form) return;
event.preventDefault();
formType = form.getAttribute('data-security-form');
if (formType === 'password') submitPassword(form);
if (formType === 'phone') submitPhone(form);
if (formType === 'sms-login') submitSmsLogin(form);
if (formType === 'deactivate') submitDeactivate(form);
});
documentRef.addEventListener('click', function (event) {
var button = event.target.closest('[data-security-logout]');
if (!button) return;
event.preventDefault();
logout();
});
}
function init() {
if (!documentRef || !query('[data-security-page]')) return;
bindActions();
}
return {
buildPasswordChangeBody: buildPasswordChangeBody,
buildPhoneChangeBody: buildPhoneChangeBody,
buildSmsLoginBody: buildSmsLoginBody,
buildDeactivateBody: buildDeactivateBody,
isDangerConfirmed: isDangerConfirmed,
init: init
};
});