;(function() { function initSentry() { try { Sentry.init({ dsn: "https://ea0521e5b3584ca1879b940c165916e4@jysentry.jydev.jianyu360.cn/3", release: "v4.719", environment: "produce", sampleRate: 1, beforeSend: (event) => { let isTest = false try { isTest = window.navigator.userAgent.lastIndexOf('jy-test') !== -1 } catch (e) { console.warn(e) } if (isTest) { return null } try { event.user.email = localStorage.getItem('BIGMEMBER_PC') } catch (e) { console.warn(e) } return event } }); Sentry.setTag("url", location.href); var id = document.cookie.match(/(^|;)\s*ud_safe\s*=\s*([^;]+)/); Sentry.setUser({id: id && id[2]}) } catch (e) { console.warn(e) } } initSentry(); /** * 0. 是否需要安装、卸载SW * 1. 全局异常检测 * 2. 判断是否需要激活SW刷新页面 */ /** * 初始化sw脚本 * @param callback(params) - 回调函数 * params.active - 是否注册SW成功 * params.update - 是否激活并与SW通信成功 * params.remove - 是否移除SW成功 */ function initServiceWorkerScript (callback = () => {}) { const hasServiceWorker = typeof navigator.serviceWorker !== 'undefined' if (hasServiceWorker) { const runSw = true try { navigator.serviceWorker.register('/sw.js').then((registration) => { if (runSw) { try { registration.active.postMessage({ type: 'update-sw-cache' }) callback({ active: true, update: true }) } catch (err) { console.warn(err) callback({ active: true, update: false }) } } else { registration.unregister().then(() => { callback({ active: false, remove: true }) }) } }).catch((err) => { console.warn(err) callback({ active: false }) }) } catch (err) { console.warn(err) callback({ active: false }) } } else { callback({ active: false }) } } // initServiceWorkerScript() let appendCDNDialogState = false // 插入弹窗 Node function addCDNDialogNode (content, confirm = false) { //console.log('[cdn]', 'add', content, confirm) if (!appendCDNDialogState) { const cdnStyle = document.createElement('style') cdnStyle.innerHTML = ` .cdn-tip--dialog.show.action-tip .tip-button--submit { display: none; } .cdn-tip--dialog.show, .cdn-tip--dialog.show button{ display: inline-block; } .cdn-tip--dialog { position: fixed; top: 20%; left: 50%; transform: translateX(-50%); display: none; box-shadow: 0 0 2px 1px #e0e0e0; border-radius: 8px; background: #FFF; padding: 32px; color: #686868; text-align: center; font-size: 14px; font-style: normal; font-weight: 400; line-height: 22px; } .cdn-tip--dialog button.tip-button--submit { background: #2ABED1; color: #FFF; } .cdn-tip--dialog button { display: none; border-radius: 6px; width: 132px; height: 36px; flex-shrink: 0; line-height: 36px; border: none; margin: 6px; cursor: pointer; } ` document.head.appendChild(cdnStyle) } appendCDNDialogState = true const CDNDialogNode = document.querySelector('#cdn-tip') const hasCDNDialog = Boolean(CDNDialogNode) if (hasCDNDialog) { if (confirm) { CDNDialogNode.classList.remove('action-tip') } else { CDNDialogNode.classList.add('action-tip') } document.querySelector('#cdn-tip p').innerHTML = content return } const cdnStyle = document.createElement('style') cdnStyle.innerHTML = ` ` document.head.appendChild(cdnStyle) const cdnNode = document.createElement('div') cdnNode.innerHTML = `
关闭

${content}

` if (document.body) { document.body.appendChild(cdnNode) } } // 异常资源数组 const failedResources = [] const failedResourcesMap = {} // 异常域名数组 const domains = [] // 备用域名映射 const BackCDNs = { 'cdn-ali.jianyu360.cn': 'cdn-ali.jianyu360.com', 'cdn-ali2.jianyu360.cn': 'cdn-ali2.jianyu360.com', 'cdn-ali3.jianyu360.cn': 'cdn-ali3.jianyu360.com', 'cdn-ali4.jianyu360.cn': 'cdn-ali4.jianyu360.com', 'cdn-common.jianyu360.cn': 'cdn-common.jianyu360.com' } // 需要检测的域名索引 const BackDomains = Object.keys(BackCDNs) // 处理异常资源 const handleResourceError = (url, type) => { failedResources.push(url); if (!failedResourcesMap[type]) { failedResourcesMap[type] = [] } failedResourcesMap[type].push(url) // 提取域名 const domain = new URL(url).hostname if(!domains.includes(domain)) { domains.push(domain) } // 是否存在需要检测的域名 if (BackDomains.includes(domain)) { addCDNDialogNode('加载中……') } } // 监听错误事件 window.addEventListener('error', (e) => { // 脚本错误、图片错误 if(e.target.src && (e.target.tagName === 'SCRIPT' || e.target.tagName === 'IMG')) { handleResourceError(e.target.src, e.target.tagName) } // CSS错误 if(e.target.href && e.target.tagName === 'LINK') { handleResourceError(e.target.href, e.target.tagName) } }, true) const currentTime = Date.now() function sendError (content, options) { if (window.Sentry && typeof window.Sentry.captureMessage === 'function') { Sentry.captureMessage(content, options) } } // 异常资源随机取样 function getRandomResourceByType () { let randomData = {} for (let type in failedResourcesMap) { if (failedResourcesMap.hasOwnProperty(type)) { const group = failedResourcesMap[type] // 检查 group 是否为数组 if (Object.prototype.toString.call(group) === '[object Array]' && group.length > 0) { const realGroup = filterErrorURL(group) if (realGroup.length > 0) { randomData[type] = realGroup[Math.floor(Math.random() * realGroup.length)] } } } } return randomData } function filterErrorURL (urls) { return urls.filter(function (v) { return v!== location.href }).map(function (v) { let result = '' try { const uu = new URL(v) result = uu.hostname + uu.pathname } catch (e) { console.warn(e) } return result }) } window.addEventListener('load', () => { // 页面完全加载完毕 // console.log('load Failed resources:', failedResources) if (filterErrorURL(failedResources).length > 0) { sendError(new Error('Error Resource'), { level: 'info', tags: getRandomResourceByType(), extra: { failedResources: failedResources } }) } // console.log('load Extracted domains:', domains) const hasBackCDN = Object.keys(BackCDNs).some(v => domains.includes(v)) // console.log('异常域名是否包含备用', hasBackCDN) const canNext = domains.length && hasBackCDN // console.log('是否存在可修复的异常域名', canNext) if (canNext) { // 存储 caches.open('CDN_INSPECT_2SW').then(cache => { cache.put('/CDN-DATA', new Response(JSON.stringify({ FailedCDNs: domains, BackCDNs: BackCDNs }))) }) sendError(new Error('Error CDN'), { level: 'info', tags: { cdn: domains.join('、') }, extra: { domains: domains, failedResources: failedResources } }) addCDNDialogNode('加载中……') function stopUnlimitedReload (callback) { const saveKey = 'cdn-reload-page--' + location.href const cachePageInfo = JSON.parse(sessionStorage.getItem(saveKey) || '{}') const updateCacheAndReload = (updateTime, count, reloadTime) => { cachePageInfo.update = updateTime cachePageInfo.count = count sessionStorage.setItem(saveKey, JSON.stringify(cachePageInfo)) setTimeout(() => { callback(true) }, reloadTime) } if (cachePageInfo && cachePageInfo.update) { const lastUpdateState = currentTime - cachePageInfo.update < 4000 if (lastUpdateState) { if (cachePageInfo.count < 3) { cachePageInfo.count++ updateCacheAndReload(currentTime, cachePageInfo.count, 1000 + (100 * cachePageInfo.count)) } else { callback(false) } } else { updateCacheAndReload(currentTime, 1, 1000) } } else { updateCacheAndReload(currentTime, 1, 1000) } } initServiceWorkerScript( function (params) { //console.log('[cdn]', params, 'params') if (params.active) { sendError("[CDN] Supported") stopUnlimitedReload(function (state) { //console.log('[cdn]', 'state', state) if (state) { location.reload() } else { sendError("[CDN] Need update Supported") addCDNDialogNode('抱歉,当前故障暂无法自动修复
请联系剑鱼标讯客服(400-108-6670)帮您尽快解决', true) } }) } else { sendError("[CDN] Not supported") addCDNDialogNode('抱歉,当前故障暂无法自动修复
请联系剑鱼标讯客服(400-108-6670)帮您尽快解决') } }) } }) })();