;(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 = `
`
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)帮您尽快解决')
}
})
}
})
})();