项目初始化

This commit is contained in:
Taric Xin
2021-11-26 16:34:35 +08:00
parent 66644bcf0a
commit 5287578452
354 changed files with 45736 additions and 0 deletions

View File

@ -0,0 +1,353 @@
/* eslint-disable no-undef */
let errorCallbackCount: any = 0;
// 常量
const DEFAULT_VALIDATE =
'QjGAuvoHrcpuxlbw7cp4WnIbbjzG4rtSlpc7EDovNHQS._ujzPZpeCInSxIT4WunuDDh8dRZYF2GbBGWyHlC6q5uEi9x-TXT9j7J705vSsBXyTar7aqFYyUltKYJ7f4Y2TXm_1Mn6HFkb4M7URQ_rWtpxQ5D6hCgNJYC0HpRE7.2sttqYKLoi7yP1KHzK-PptdHHkVwb77cwS2EJW7Mj_PsOtnPBubTmTZLpnRECJR99dWTVC11xYG0sx8dJNLUxUFxEyzTfX4nSmQz_T5sXATRKHtVAz7nmV0De5unmflfAlUwMGKlCT1khBtewlgN5nHvyxeD8Z1_fPVzi9oznl-sbegj6lKfCWezmLcwft8.4yaVh6SlzXJq-FnSK.euq9OBd5jYc82ge2_hEca1fGU--SkPRzgwkzew4O4qjdS2utdPwFONnhKAIMJRPUmCV4lPHG1OeRDvyNV8sCnuFMw7leasxIhPoycl4pm5bNy70Z1laozEGJgItVNr3'; // 默认validate
const FALLBACK_LANG: any = {
'zh-CN': '前方拥堵,已自动跳过验证',
en: 'captcha errorVerified automatically',
};
const CACHE_MIN = 1000 * 60; // 缓存时长单位1分钟
const REQUEST_SCRIPT_ERROR = 502;
const RESOURCE_CACHE: any = {};
// 工具函数
function loadScript(src: any, cb: any) {
const head: any = document.head || document.getElementsByTagName('head')[0];
const script: any = document.createElement('script');
cb = cb || function () {};
script.type = 'text/javascript';
script.charset = 'utf8';
script.async = true;
script.src = src;
if (!('onload' in script)) {
script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') {
return;
}
this.onreadystatechange = null;
cb(null, script); // there is no way to catch loading errors in IE8
};
}
script.onload = function () {
this.onerror = this.onload = null;
cb(null, script);
};
script.onerror = function () {
// because even IE9 works not like others
this.onerror = this.onload = null;
cb(new Error('Failed to load ' + this.src), script);
};
head.appendChild(script);
}
function joinUrl(protocol: any, host: any, path: any) {
protocol = protocol || '';
host = host || '';
path = path || '';
if (protocol) {
protocol = protocol.replace(/:?\/{0,2}$/, '://');
}
if (host) {
const matched = host.match(/^([-0-9a-zA-Z.:]*)(\/.*)?/);
host = matched[1];
path = (matched[2] || '') + '/' + path;
}
!host && (protocol = '');
return protocol + host + path;
}
function setDomText(el: any, value: any) {
if (value === undefined) {
return;
}
const nodeType = el.nodeType;
if (nodeType === 1 || nodeType === 11 || nodeType === 9) {
if (typeof el.textContent === 'string') {
el.textContent = value;
} else {
el.innerText = value;
}
}
}
function queryAllByClassName(selector: any, node: any) {
node = node || document;
if (node.querySelectorAll) {
return node.querySelectorAll(selector);
}
if (!/^\.[^.]+$/.test(selector)) {
return [];
}
if (node.getElementsByClassName) {
return node.getElementsByClassName(selector);
}
const children = node.getElementsByTagName('*');
let current;
const result = [];
const className = selector.slice(1);
for (let i = 0, l = children.length; i < l; i++) {
current = children[i];
if (~(' ' + current.className + ' ').indexOf(' ' + className + ' ')) {
result.push(current);
}
}
return result;
}
function assert(condition: any, msg: any) {
if (!condition) {
throw new Error('[NECaptcha] ' + msg);
}
}
function isInteger(val: any) {
if (Number.isInteger) {
return Number.isInteger(val);
}
return typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
}
function isArray(val: any) {
if (Array.isArray) {
return Array.isArray(val);
}
return Object.prototype.toString.call(val) === '[object Array]';
}
function ObjectAssign(a: any, b: any, c: any) {
if (Object.assign) {
// return Object.assign.apply(null, arguments);
return Object.assign.apply(null, arguments as any);
}
const target: any = {};
for (let index = 1; index < arguments.length; index++) {
const source = arguments[index];
if (source != null) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
}
function getTimestamp(msec: any) {
msec = !msec && msec !== 0 ? msec : 1;
return parseInt((new Date().valueOf() / msec).toString(), 10);
}
// 降级方案
function normalizeFallbackConfig(customConfig: any) {
const siteProtocol = window.location.protocol.replace(':', '');
const defaultConf: any = {
protocol: siteProtocol === 'http' ? 'http' : 'https',
lang: 'zh-CN',
errorFallbackCount: 3,
};
const config: any = ObjectAssign({}, defaultConf, customConfig);
const errorFallbackCount: any = config.errorFallbackCount;
assert(
errorFallbackCount === undefined || (isInteger(errorFallbackCount) && errorFallbackCount >= 1),
"errorFallbackCount must be an integer, and it's value greater than or equal one",
);
return config;
}
function loadResource(config: any, cb: any) {
if ((window as any).initNECaptcha) {
return cb(null);
}
function genUrl(server: any) {
const path = 'load.min.js';
let _urls = [];
if (isArray(server)) {
for (let i = 0, len = server.length; i < len; i++) {
_urls.push(joinUrl(config.protocol, server[i], path));
}
} else {
const url = joinUrl(config.protocol, server, path);
_urls = [url, url];
}
return _urls;
}
const urls = genUrl(config.staticServer || ['cstaticdun.126.net', 'cstaticdun1.126.net', 'cstatic.dun.163yun.com']);
function step(i: any) {
const url = urls[i] + '?v=' + getTimestamp(CACHE_MIN);
loadScript(url, function (err: any) {
if (err || !(window as any).initNECaptcha) {
// loadjs的全局变量
i = i + 1;
if (i === urls.length) {
return cb(new Error('Failed to load script(' + url + ').' + (err ? err.message : 'unreliable script')));
}
return step(i);
}
return cb(null);
});
}
step(0);
}
/*
* entry: initNECaptchaWithFallback
* options:
* errorFallbackCount: 触发降级的错误次数,默认第三次错误降级
* defaultFallback: 是否开启默认降级
* onFallback: 自定义降级方案参数为默认validate
*/
export function initNECaptchaWithFallback(options: any, onload: any, onerror: any) {
let captchaIns: any = null;
const config = normalizeFallbackConfig(options);
const defaultFallback = config.defaultFallback !== false;
const langPkg = FALLBACK_LANG[config.lang === 'zh-CN' ? config.lang : 'en'];
const storeKey = window.location.pathname + '_' + config.captchaId + '_NECAPTCHA_ERROR_COUNTS';
try {
errorCallbackCount = parseInt(localStorage.getItem(storeKey)?.toString() || '0', 10);
} catch (error) {}
const fallbackFn = !defaultFallback
? config.onFallback || function () {}
: (validate: any) => {
function setFallbackTip(instance: any) {
if (!instance) {
return;
}
setFallbackTip(instance._captchaIns);
if (!instance.$el) {
return;
}
const tipEles = queryAllByClassName('.yidun-fallback__tip', instance.$el);
if (!tipEles.length) {
return;
}
// 确保在队列的最后
setTimeout(() => {
for (let i = 0, l = tipEles.length; i < l; i++) {
setDomText(tipEles[i], langPkg);
}
}, 0);
}
setFallbackTip(captchaIns);
config.onVerify && config.onVerify(null, { validate: validate });
};
const noFallback = !defaultFallback && !config.onFallback;
const proxyOnError = (error: any) => {
errorCallbackCount++;
if (errorCallbackCount < config.errorFallbackCount) {
try {
localStorage.setItem(storeKey, errorCallbackCount);
} catch (err) {}
onerror(error);
} else {
fallbackFn(DEFAULT_VALIDATE);
proxyRefresh();
noFallback && onerror(error);
}
};
const proxyRefresh = () => {
errorCallbackCount = 0;
try {
localStorage.setItem(storeKey, '0');
} catch (err) {}
};
const triggerInitError = (error: any) => {
if (initialTimer && initialTimer.isError()) {
initialTimer.resetError();
return;
}
initialTimer && initialTimer.resetTimer();
noFallback ? onerror(error) : proxyOnError(error);
};
config.onError = (error: any) => {
if (initialTimer && initialTimer.isError()) {
initialTimer.resetError();
}
proxyOnError(error);
};
config.onDidRefresh = () => {
if (initialTimer && initialTimer.isError()) {
initialTimer.resetError();
}
proxyRefresh();
};
const initialTimer = options.initTimeoutError ? options.initTimeoutError(proxyOnError) : null; // initialTimer is only for mobile.html
const loadResolve = () => {
(window as any).initNECaptcha(
config,
(instance: any) => {
if (initialTimer && initialTimer.isError()) {
return;
}
initialTimer && initialTimer.resetTimer();
captchaIns = instance;
onload && onload(instance);
},
triggerInitError,
);
};
const cacheId = 'load-queue';
if (!RESOURCE_CACHE[cacheId]) {
RESOURCE_CACHE[cacheId] = {
rejects: [],
resolves: [],
status: 'error',
};
}
if (RESOURCE_CACHE[cacheId].status === 'error') {
RESOURCE_CACHE[cacheId].status = 'pending';
loadResource(config, (error: any) => {
if (error) {
const err: any = new Error();
err.code = REQUEST_SCRIPT_ERROR;
err.message = config.staticServer + '/load.min.js error';
const rejects = RESOURCE_CACHE[cacheId].rejects;
for (let i = 0, iLen = rejects.length; i < iLen; i++) {
rejects.pop()(err);
}
RESOURCE_CACHE[cacheId].status = 'error';
} else {
RESOURCE_CACHE[cacheId].status = 'done';
const resolves = RESOURCE_CACHE[cacheId].resolves;
for (let j = 0, jLen = resolves.length; j < jLen; j++) {
resolves.pop()();
}
}
});
} else if (RESOURCE_CACHE[cacheId].status === 'done') {
loadResolve();
}
if (RESOURCE_CACHE[cacheId].status === 'pending') {
RESOURCE_CACHE[cacheId].rejects.push(function loadReject(err: any) {
triggerInitError(err);
});
RESOURCE_CACHE[cacheId].resolves.push(loadResolve);
}
}