mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-12 04:13:13 +08:00
231 lines
6.1 KiB
JavaScript
231 lines
6.1 KiB
JavaScript
(function createMirrorModal() {
|
|
const SIGN = Symbol.for('antd.mirror-notify');
|
|
const always = window.localStorage.getItem('DEBUG') === 'antd';
|
|
const officialChinaMirror = 'https://ant-design.antgroup.com';
|
|
|
|
const enabledCondition = [
|
|
// Check if the browser language is Chinese
|
|
navigator.languages.includes('zh') || navigator.languages.includes('zh-CN'),
|
|
// Check if the URL path ends with -cn
|
|
/-cn\/?$/.test(window.location.pathname),
|
|
// chinese mirror URL
|
|
!['ant-design.gitee.io', new URL(officialChinaMirror).hostname].includes(
|
|
window.location.hostname,
|
|
),
|
|
// PR review URL
|
|
!window.location.host.includes('surge'),
|
|
// development mode
|
|
!['127.0.0.1', 'localhost'].includes(window.location.hostname),
|
|
];
|
|
|
|
const isEnabled = always || enabledCondition.every(Boolean);
|
|
|
|
if (!isEnabled) return;
|
|
|
|
const prefixCls = 'antd-mirror-notify';
|
|
const primaryColor = '#1677ff';
|
|
|
|
function insertCss() {
|
|
const style = document.createElement('style');
|
|
style.innerHTML = `
|
|
@keyframes slideInRight {
|
|
from {
|
|
transform: translate3d(100%, 0, 0);
|
|
visibility: visible;
|
|
}
|
|
|
|
to {
|
|
transform: translate3d(0, 0, 0);
|
|
}
|
|
}
|
|
|
|
.${prefixCls} {
|
|
position: fixed;
|
|
inset-inline-end: 12px;
|
|
inset-block-start: 12px;
|
|
z-index: 9999;
|
|
width: 360px;
|
|
background-color: #fff;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
animation: slideInRight 0.3s ease-in-out;
|
|
}
|
|
.${prefixCls}-content {
|
|
padding: 16px;
|
|
}
|
|
.${prefixCls}-content a {
|
|
color: ${primaryColor};
|
|
text-decoration: none;
|
|
&:hover {
|
|
text-decoration: underline;
|
|
}
|
|
}
|
|
.${prefixCls}-title {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
margin-block-end: 8px;
|
|
}
|
|
.${prefixCls}-message {
|
|
font-size: 14px;
|
|
color: #555;
|
|
line-height: 1.57;
|
|
}
|
|
.${prefixCls}-footer {
|
|
display: none;
|
|
margin-block-start: 16px;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.${prefixCls}-progress {
|
|
position: relative;
|
|
inset-inline-end: 0;
|
|
width: 100%;
|
|
height: 4px;
|
|
background-color: #f0f0f0;
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.${prefixCls}-progress::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
height: 100%;
|
|
width: var(--progress, 0%);
|
|
background-color: ${primaryColor};
|
|
transition: width 0.05s linear; /* Adjusted for smoother animation matching refreshRate */
|
|
}
|
|
.${prefixCls}-close {
|
|
all: unset;
|
|
position: absolute;
|
|
inset-inline-end: 2px;
|
|
inset-block-start: 2px;
|
|
width: 32px;
|
|
height: 32px;
|
|
font-size: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #999;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.${prefixCls}-close:hover {
|
|
color: #333;
|
|
}
|
|
|
|
.${prefixCls}-action {
|
|
all: unset;
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
background-color: ${primaryColor};
|
|
color: #fff;
|
|
border-radius: 4px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
`;
|
|
|
|
document.head.append(style);
|
|
}
|
|
|
|
function createNotification() {
|
|
insertCss();
|
|
|
|
const notify = document.createElement('div');
|
|
notify.className = `${prefixCls} slideInRight`;
|
|
notify.innerHTML = `
|
|
<div class="${prefixCls}-content">
|
|
<div class="${prefixCls}-title">🇨🇳 访问不畅?试试国内镜像</div>
|
|
<div class="${prefixCls}-message">
|
|
国内镜像站点可以帮助您更快地访问文档和资源。<br>
|
|
请尝试访问 <a href="${officialChinaMirror}">国内镜像站点</a>,以获得更好的体验。
|
|
</div>
|
|
<div class="${prefixCls}-footer">
|
|
<button class="${prefixCls}-action">🚀 立即前往</button>
|
|
</div>
|
|
</div>
|
|
<button class="${prefixCls}-close">X</button>
|
|
<div class="${prefixCls}-progress" style="--progress: 100%;"></div>
|
|
`;
|
|
document.body.appendChild(notify);
|
|
|
|
notify.querySelector(`.${prefixCls}-close`).addEventListener('click', () => {
|
|
removeNotify();
|
|
});
|
|
|
|
notify.querySelector(`.${prefixCls}-action`).addEventListener('click', () => {
|
|
window.location.href = officialChinaMirror;
|
|
removeNotify();
|
|
});
|
|
|
|
const refreshRate = 50; // ms
|
|
const duration = 10; // s
|
|
const step = 100 / ((duration * 1000) / refreshRate);
|
|
let progressInterval = -1;
|
|
|
|
function removeNotify() {
|
|
clearInterval(progressInterval);
|
|
notify.remove();
|
|
}
|
|
|
|
const progressEl = notify.querySelector(`.${prefixCls}-progress`);
|
|
let currentProgressValue = 100;
|
|
|
|
const progress = {
|
|
get value() {
|
|
return currentProgressValue;
|
|
},
|
|
set value(val) {
|
|
currentProgressValue = Math.max(0, Math.min(100, val));
|
|
progressEl.style.setProperty('--progress', `${currentProgressValue}%`);
|
|
},
|
|
};
|
|
|
|
function startProgressTimer() {
|
|
if (progressInterval !== -1) {
|
|
clearInterval(progressInterval);
|
|
}
|
|
progressInterval = setInterval(() => {
|
|
if (progress.value <= 0) {
|
|
removeNotify();
|
|
} else {
|
|
progress.value -= step;
|
|
}
|
|
}, refreshRate);
|
|
}
|
|
|
|
startProgressTimer();
|
|
|
|
notify.addEventListener('mouseenter', () => {
|
|
clearInterval(progressInterval);
|
|
});
|
|
|
|
notify.addEventListener('mouseleave', () => {
|
|
startProgressTimer();
|
|
});
|
|
}
|
|
|
|
// 断定网络不畅阈值(秒)
|
|
const delayDuration = 3;
|
|
|
|
const reactTimeoutId = setTimeout(() => {
|
|
if (typeof window[SIGN]?.YES === 'undefined') {
|
|
console.error(
|
|
`antd.mirror-notify: 页面加载超过 ${delayDuration} 秒,可能是网络不畅。\n请尝试访问国内镜像站点。%c${officialChinaMirror}`,
|
|
`color: ${primaryColor}; font-weight: bold;`,
|
|
);
|
|
createNotification();
|
|
}
|
|
}, delayDuration * 1000);
|
|
|
|
// 交给 React effect 清理
|
|
window[SIGN] = function stopMirrorNotify() {
|
|
window[SIGN].YES = Date.now();
|
|
clearTimeout(reactTimeoutId);
|
|
};
|
|
})();
|