Files
shencaisuan/utils/AuthPageUtil.js
T
2026-06-08 17:31:30 +08:00

208 lines
7.2 KiB
JavaScript

const AuthPageUtil = {
smsTimers: {},
slideUuid: '',
slideX: 0,
slideToken: '',
isPhone(phone) {
return /^1[3-9]\d{9}$/.test(String(phone || '').trim());
},
isPassword(password) {
const value = String(password || '');
return value.length >= 6 && value.length <= 20;
},
loadVerifyType() {
return ApiClient.get(ApiClient.API.authVerifyConfig, {}, { publicRequest: true })
.then((res) => {
const data = (res && res.data) || res || {};
const yes = (value) =>
value === true || value === 1 || value === '1' || String(value).toLowerCase() === 'true';
if (
yes(data.lottery_slide_captcha) ||
yes(data.lotterySlideCaptcha) ||
yes(data.slideCaptchaEnabled) ||
yes(data.slideEnabled) ||
data.verifyType === 'slide'
) {
return 'slide';
}
return 'captcha';
})
.catch(() => 'captcha');
},
buildSmsParams(options = {}) {
const params = {
phoneNumber: options.phoneNumber,
};
if (options.verifyType === 'slide') {
params.verifyType = 'slide';
params.slideToken = options.slideToken || this.slideToken;
params.slideUuid = options.slideUuid || this.slideUuid;
params.slideX = options.slideX || this.slideX;
}
if (options.verifyType === 'captcha') {
params.verifyType = 'captcha';
params.code = options.code || '';
params.uuid = options.uuid || '';
}
return params;
},
sendSmsCode(options) {
return ApiClient.get(ApiClient.API.authSmsCode, this.buildSmsParams(options), {
publicRequest: true,
});
},
sendForgotPasswordSmsCode(options) {
return ApiClient.get(ApiClient.API.authForgotPasswordSmsCode, this.buildSmsParams(options), {
publicRequest: true,
});
},
getImageCaptcha() {
return ApiClient.get(ApiClient.API.authCode, {}, { publicRequest: true });
},
installSlideCaptchaTenantHeader() {
if (typeof window === 'undefined' || window.__cxzSlideCaptchaTenantPatched) return;
window.__cxzSlideCaptchaTenantPatched = true;
const isSlideCaptchaUrl = (url) => String(url || '').indexOf('/api/web/auth/slide-captcha') >= 0;
const tenantId = () =>
typeof ApiClient !== 'undefined' && ApiClient.tenantId ? ApiClient.tenantId : '000000';
if (typeof window.fetch === 'function') {
const nativeFetch = window.fetch.bind(window);
window.fetch = function (input, init = {}) {
const requestUrl = typeof input === 'string' ? input : input && input.url;
if (!isSlideCaptchaUrl(requestUrl)) return nativeFetch(input, init);
const isRequestInput = typeof Request !== 'undefined' && input instanceof Request;
const headers = new Headers(init.headers || (isRequestInput ? input.headers : undefined));
headers.set('tenantId', tenantId());
if (isRequestInput) {
return nativeFetch(new Request(input, { ...init, headers }));
}
return nativeFetch(input, { ...init, headers });
};
}
if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {
const xhrProto = window.XMLHttpRequest.prototype;
const nativeOpen = xhrProto.open;
const nativeSetRequestHeader = xhrProto.setRequestHeader;
const nativeSend = xhrProto.send;
xhrProto.open = function (method, url, ...args) {
this.__cxzSlideCaptchaRequest = isSlideCaptchaUrl(url);
this.__cxzSlideTenantHeaderSet = false;
return nativeOpen.call(this, method, url, ...args);
};
xhrProto.setRequestHeader = function (name, value) {
if (this.__cxzSlideCaptchaRequest && String(name || '').toLowerCase() === 'tenantid') {
this.__cxzSlideTenantHeaderSet = true;
}
return nativeSetRequestHeader.call(this, name, value);
};
xhrProto.send = function (...args) {
if (this.__cxzSlideCaptchaRequest && !this.__cxzSlideTenantHeaderSet) {
nativeSetRequestHeader.call(this, 'tenantId', tenantId());
this.__cxzSlideTenantHeaderSet = true;
}
return nativeSend.apply(this, args);
};
}
},
startSmsCountdown(buttonSelector, seconds = 60) {
const $button = layui.$(buttonSelector);
let left = seconds;
clearInterval(this.smsTimers[buttonSelector]);
$button.prop('disabled', true).text(`${left}s后重发`);
this.smsTimers[buttonSelector] = setInterval(() => {
left -= 1;
if (left <= 0) {
clearInterval(this.smsTimers[buttonSelector]);
$button.prop('disabled', false).text('获取验证码');
return;
}
$button.text(`${left}s后重发`);
}, 1000);
},
loadSlideCaptchaScript() {
this.installSlideCaptchaTenantHeader();
if (window.SlideCaptcha) return Promise.resolve(window.SlideCaptcha);
if (window.__slideCaptchaLoading) return window.__slideCaptchaLoading;
window.__slideCaptchaLoading = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = `${ApiClient.baseUrl}/static/slide-captcha/slide-captcha.js`;
script.dataset.apiBase = ApiClient.baseUrl || '';
script.dataset.tenantId = ApiClient.tenantId || '000000';
script.onload = () => {
if (window.SlideCaptcha) resolve(window.SlideCaptcha);
else reject(new Error('滑动验证组件加载失败'));
};
script.onerror = () => reject(new Error('滑动验证组件加载失败'));
document.body.appendChild(script);
});
return window.__slideCaptchaLoading;
},
openSlideCaptcha(options = {}) {
this.installSlideCaptchaTenantHeader();
this.loadSlideCaptchaScript()
.then((SlideCaptcha) => {
SlideCaptcha.open({
title: options.title || '安全验证',
subtitle: options.subtitle || '拖动滑块完成验证',
apiBase: ApiClient.baseUrl || '',
tenantId: ApiClient.tenantId || '000000',
headers: ApiClient.publicHeaders(),
onSuccess: (result) => {
const data = result || {};
const nested = data.data || {};
this.slideToken =
data.slideToken || data.token || data.verifyToken ||
nested.slideToken || nested.token || nested.verifyToken || '';
this.slideUuid = data.slideUuid || data.uuid || nested.slideUuid || nested.uuid || '';
this.slideX = Number(data.slideX || data.x || nested.slideX || nested.x || 0) || 0;
if (!this.slideToken && !this.slideUuid) {
if (typeof options.onError === 'function') {
options.onError(new Error('滑动验证未返回凭证,请重试'));
}
return;
}
if (typeof options.onSuccess === 'function') {
options.onSuccess({
slideToken: this.slideToken,
slideUuid: this.slideUuid,
slideX: this.slideX,
});
}
},
onCancel: options.onCancel,
onError: options.onError,
});
})
.catch((error) => {
if (typeof options.onError === 'function') options.onError(error);
});
},
};
if (typeof window !== 'undefined') {
window.AuthPageUtil = AuthPageUtil;
}