过渡界面html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>站点升级中</title>
<meta http-equiv="refresh" content="8">
<style>
:root {
--bg: #faf8f5;
--surface: #ffffff;
--text-primary: #2c2c2c;
--text-secondary: #6b6b6b;
--ring-outer: #c4bfb6;
--ring-mid: #b0a89c;
--ring-inner: #d4a574;
--dot-center: #c7854a;
--btn-bg: #ece8e2;
--btn-active-bg: #d4a574;
--btn-active-text: #fff;
--btn-text: #5c5c5c;
--btn-hover-bg: #e0d9cf;
--shadow-soft: 0 2px 20px rgba(0, 0, 0, 0.05);
--shadow-card: 0 4px 32px rgba(0, 0, 0, 0.07);
--deco-1: rgba(180, 160, 140, 0.10);
--deco-2: rgba(190, 170, 148, 0.08);
--deco-3: rgba(200, 175, 145, 0.06);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1e1d1b;
--surface: #292724;
--text-primary: #e8e4de;
--text-secondary: #b5afa6;
--ring-outer: #5c554c;
--ring-mid: #7a7064;
--ring-inner: #c89464;
--dot-center: #e0a870;
--btn-bg: #35312b;
--btn-active-bg: #c89464;
--btn-active-text: #1e1d1b;
--btn-text: #b5afa6;
--btn-hover-bg: #423c34;
--shadow-soft: 0 2px 20px rgba(0, 0, 0, 0.25);
--shadow-card: 0 4px 32px rgba(0, 0, 0, 0.35);
--deco-1: rgba(180, 160, 140, 0.06);
--deco-2: rgba(190, 170, 148, 0.04);
--deco-3: rgba(200, 175, 145, 0.03);
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans TC', sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: var(--bg);
color: var(--text-primary);
overflow-x: hidden;
position: relative;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* 背景装饰光斑 */
body::before {
content: '';
position: fixed;
top: -18%;
left: -12%;
width: 55vw;
height: 55vw;
max-width: 700px;
max-height: 700px;
border-radius: 50%;
background: radial-gradient(circle, var(--deco-1) 0%, transparent 70%);
pointer-events: none;
z-index: 0;
animation: floatBlob1 28s ease-in-out infinite;
}
body::after {
content: '';
position: fixed;
bottom: -16%;
right: -10%;
width: 48vw;
height: 48vw;
max-width: 600px;
max-height: 600px;
border-radius: 50%;
background: radial-gradient(circle, var(--deco-2) 0%, transparent 70%);
pointer-events: none;
z-index: 0;
animation: floatBlob2 32s ease-in-out infinite;
}
/* 第三个装饰光斑 - 使用额外元素 */
.deco-extra {
position: fixed;
top: 45%;
left: 55%;
width: 35vw;
height: 35vw;
max-width: 450px;
max-height: 450px;
border-radius: 50%;
background: radial-gradient(circle, var(--deco-3) 0%, transparent 70%);
pointer-events: none;
z-index: 0;
animation: floatBlob3 24s ease-in-out infinite;
}
@keyframes floatBlob1 {
0%,
100% {
transform: translate(0, 0) scale(1);
}
25% {
transform: translate(3vw, 2.5vh) scale(1.08);
}
50% {
transform: translate(1.5vw, -1.5vh) scale(0.94);
}
75% {
transform: translate(-2vw, 1vh) scale(1.04);
}
}
@keyframes floatBlob2 {
0%,
100% {
transform: translate(0, 0) scale(1);
}
30% {
transform: translate(-2.5vw, -2vh) scale(1.06);
}
60% {
transform: translate(1vw, 2vh) scale(0.92);
}
85% {
transform: translate(2vw, -1vh) scale(1.03);
}
}
@keyframes floatBlob3 {
0%,
100% {
transform: translate(0, 0) scale(1);
}
20% {
transform: translate(-1.8vw, 2vh) scale(1.05);
}
45% {
transform: translate(2.2vw, -1.8vh) scale(0.93);
}
70% {
transform: translate(-1vw, -1vh) scale(1.07);
}
}
/* 主卡片 */
.main-card {
position: relative;
z-index: 1;
background: var(--surface);
border-radius: 24px;
padding: 48px 40px 40px;
box-shadow: var(--shadow-card);
text-align: center;
max-width: 520px;
width: 90vw;
transition: background 0.4s ease, box-shadow 0.4s ease;
}
/* SVG 动画容器 */
.loader-wrap {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 28px;
}
.loader-wrap svg {
width: clamp(150px, 32vw, 210px);
height: clamp(150px, 32vw, 210px);
display: block;
}
/* SVG 动画关键帧 */
@keyframes spinCW {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes spinCCW {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
@keyframes pulseDot {
0%,
100% {
r: 9;
opacity: 0.75;
}
40% {
r: 13;
opacity: 1;
}
70% {
r: 8;
opacity: 0.6;
}
}
@keyframes pulseRing {
0%,
100% {
opacity: 0.35;
r: 17;
}
50% {
opacity: 0.7;
r: 22;
}
}
@keyframes subtleDashShift {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: 200;
}
}
.ring-outer {
animation: spinCW 9s linear infinite;
transform-origin: 120px 120px;
stroke-dasharray: 32 20;
}
.ring-mid {
animation: spinCCW 6.5s linear infinite;
transform-origin: 120px 120px;
stroke-dasharray: 18 26;
}
.ring-inner {
animation: spinCW 4.2s linear infinite;
transform-origin: 120px 120px;
stroke-dasharray: 10 14;
}
.ring-pulse {
animation: pulseRing 2.6s ease-in-out infinite;
transform-origin: 120px 120px;
}
.dot-center {
animation: pulseDot 2.2s ease-in-out infinite;
}
.dash-flow {
animation: subtleDashShift 7s linear infinite;
}
/* 文字 */
.title {
font-size: clamp(18px, 3.2vw, 22px);
font-weight: 650;
letter-spacing: 0.02em;
margin-bottom: 10px;
color: var(--text-primary);
transition: color 0.4s ease;
line-height: 1.3;
}
.subtitle {
font-size: clamp(13px, 2.2vw, 14.5px);
color: var(--text-secondary);
line-height: 1.6;
transition: color 0.4s ease;
margin-bottom: 26px;
}
/* 语言切换器 */
.lang-switcher {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
user-select: none;
}
.lang-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 38px;
height: 34px;
padding: 0 11px;
border-radius: 17px;
border: 1.5px solid transparent;
background: var(--btn-bg);
color: var(--btn-text);
font-size: 12px;
font-weight: 550;
letter-spacing: 0.03em;
cursor: pointer;
transition: all 0.25s ease;
font-family: inherit;
white-space: nowrap;
-webkit-tap-highlight-color: transparent;
outline: none;
}
.lang-btn:hover {
background: var(--btn-hover-bg);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.lang-btn:active {
transform: scale(0.95);
transition: transform 0.1s ease;
}
.lang-btn.active {
background: var(--btn-active-bg);
color: var(--btn-active-text);
border-color: var(--btn-active-bg);
box-shadow: 0 2px 12px rgba(180, 140, 110, 0.3);
font-weight: 600;
cursor: default;
transform: none;
}
.lang-btn.active:hover {
transform: none;
box-shadow: 0 2px 12px rgba(180, 140, 110, 0.3);
}
/* 响应式 */
@media (max-width: 480px) {
.main-card {
padding: 32px 20px 28px;
border-radius: 18px;
width: 94vw;
}
.lang-switcher {
gap: 6px;
}
.lang-btn {
min-width: 32px;
height: 30px;
padding: 0 9px;
font-size: 11px;
border-radius: 15px;
}
.loader-wrap {
margin-bottom: 20px;
}
.subtitle {
margin-bottom: 20px;
}
}
@media (max-width: 360px) {
.main-card {
padding: 24px 14px 22px;
border-radius: 14px;
width: 96vw;
}
.lang-btn {
min-width: 28px;
height: 28px;
padding: 0 7px;
font-size: 10.5px;
border-radius: 14px;
}
.lang-switcher {
gap: 4px;
}
.loader-wrap svg {
width: clamp(120px, 36vw, 150px);
height: clamp(120px, 36vw, 150px);
}
}
</style>
</head>
<body>
<div class="deco-extra" aria-hidden="true"></div>
<div class="main-card">
<!-- 手绘风格 SVG 加载动画 -->
<div class="loader-wrap" aria-label="加载动画" role="img">
<svg viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg">
<!-- 外环 - 手绘虚线,顺时针慢转 -->
<circle
class="ring-outer"
cx="120" cy="120" r="95"
fill="none"
stroke="var(--ring-outer)"
stroke-width="3.5"
stroke-linecap="round"
stroke-dasharray="32 20"
opacity="0.7"
/>
<!-- 中环 - 不同虚线节奏,逆时针旋转 -->
<circle
class="ring-mid"
cx="120" cy="120" r="68"
fill="none"
stroke="var(--ring-mid)"
stroke-width="3"
stroke-linecap="round"
stroke-dasharray="18 26"
opacity="0.75"
/>
<!-- 内环 - 短促虚线,快速顺时针旋转 -->
<circle
class="ring-inner"
cx="120" cy="120" r="40"
fill="none"
stroke="var(--ring-inner)"
stroke-width="3.2"
stroke-linecap="round"
stroke-dasharray="10 14"
opacity="0.8"
/>
<!-- 脉冲光环 -->
<circle
class="ring-pulse"
cx="120" cy="120" r="17"
fill="none"
stroke="var(--dot-center)"
stroke-width="1.8"
stroke-linecap="round"
opacity="0.45"
/>
<!-- 流动虚线装饰 - 最内圈 -->
<circle
class="dash-flow"
cx="120" cy="120" r="26"
fill="none"
stroke="var(--ring-inner)"
stroke-width="1.6"
stroke-linecap="round"
stroke-dasharray="6 28"
opacity="0.55"
/>
<!-- 中心脉冲点 -->
<circle
class="dot-center"
cx="120" cy="120" r="9"
fill="var(--dot-center)"
opacity="0.8"
/>
<!-- 四个轨道小点 - 手工散布 -->
<circle cx="120" cy="55" r="3.5" fill="var(--ring-mid)" opacity="0.6">
<animateTransform attributeName="transform" type="rotate" from="0 120 120" to="360 120 120" dur="5s" repeatCount="indefinite" />
</circle>
<circle cx="120" cy="185" r="3" fill="var(--ring-outer)" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" from="120 120 120" to="480 120 120" dur="5.8s" repeatCount="indefinite" />
</circle>
<circle cx="175" cy="100" r="2.8" fill="var(--ring-inner)" opacity="0.55">
<animateTransform attributeName="transform" type="rotate" from="240 120 120" to="600 120 120" dur="5.3s" repeatCount="indefinite" />
</circle>
<circle cx="68" cy="145" r="3.2" fill="var(--ring-mid)" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" from="60 120 120" to="420 120 120" dur="6.1s" repeatCount="indefinite" />
</circle>
<!-- 额外散布微点 -->
<circle cx="155" cy="75" r="2" fill="var(--ring-outer)" opacity="0.4">
<animateTransform attributeName="transform" type="rotate" from="180 120 120" to="540 120 120" dur="7.2s" repeatCount="indefinite" />
</circle>
<circle cx="80" cy="170" r="2.2" fill="var(--ring-inner)" opacity="0.4">
<animateTransform attributeName="transform" type="rotate" from="300 120 120" to="660 120 120" dur="6.6s" repeatCount="indefinite" />
</circle>
</svg>
</div>
<!-- 文字内容 -->
<h1 class="title" id="mainTitle">站点正在更新中</h1>
<p class="subtitle" id="mainSubtitle">预计1分钟内恢复,页面将自动刷新</p>
<!-- 语言切换 -->
<nav class="lang-switcher" aria-label="语言选择">
<button class="lang-btn" data-lang="zh-CN" aria-pressed="false">简</button>
<button class="lang-btn" data-lang="zh-TW" aria-pressed="false">繁</button>
<button class="lang-btn" data-lang="en" aria-pressed="false">EN</button>
<button class="lang-btn" data-lang="fr" aria-pressed="false">FR</button>
<button class="lang-btn" data-lang="de" aria-pressed="false">DE</button>
<button class="lang-btn" data-lang="it" aria-pressed="false">IT</button>
</nav>
</div>
<script>
(function() {
// 多语言文本
const i18n = {
'zh-CN': {
title: '站点正在更新中',
subtitle: '预计1分钟内恢复,页面将自动刷新',
htmlLang: 'zh-CN'
},
'zh-TW': {
title: '站點正在更新中',
subtitle: '預計1分鐘內恢復,頁面將自動刷新',
htmlLang: 'zh-TW'
},
'en': {
title: 'Site is being updated',
subtitle: 'Expected to be back within 1 minute, page will refresh automatically',
htmlLang: 'en'
},
'fr': {
title: 'Site en cours de mise à jour',
subtitle: 'Retour prévu dans 1 minute, la page s\'actualisera automatiquement',
htmlLang: 'fr'
},
'de': {
title: 'Website wird aktualisiert',
subtitle: 'Voraussichtlich in 1 Minute zurück, Seite wird automatisch aktualisiert',
htmlLang: 'de'
},
'it': {
title: 'Sito in aggiornamento',
subtitle: 'Tornerà entro 1 minuto, la pagina si aggiornerà automaticamente',
htmlLang: 'it'
}
};
const titleEl = document.getElementById('mainTitle');
const subtitleEl = document.getElementById('mainSubtitle');
const langBtns = document.querySelectorAll('.lang-btn');
const htmlEl = document.documentElement;
const STORAGE_KEY = 'site-upgrade-lang';
// 检测浏览器语言,匹配最佳语言
function detectBestLang() {
const browserLang = (navigator.language || navigator.userLanguage || 'en').toLowerCase();
// 精确匹配
if (i18n[browserLang]) return browserLang;
if (browserLang === 'zh-hk' || browserLang === 'zh-mo') return 'zh-TW';
if (browserLang === 'zh-sg' || browserLang === 'zh') return 'zh-CN';
if (browserLang.startsWith('zh')) return 'zh-CN';
if (browserLang.startsWith('fr')) return 'fr';
if (browserLang.startsWith('de')) return 'de';
if (browserLang.startsWith('it')) return 'it';
if (browserLang.startsWith('en')) return 'en';
// 默认英语
return 'en';
}
// 获取初始语言:优先localStorage,其次浏览器检测
function getInitialLang() {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored && i18n[stored]) return stored;
} catch (e) { /* localStorage不可用 */ }
return detectBestLang();
}
// 应用语言
function applyLang(langCode) {
const texts = i18n[langCode];
if (!texts) return;
titleEl.textContent = texts.title;
subtitleEl.textContent = texts.subtitle;
htmlEl.lang = texts.htmlLang;
document.title = texts.title;
// 更新按钮状态
langBtns.forEach(btn => {
const isActive = btn.getAttribute('data-lang') === langCode;
btn.classList.toggle('active', isActive);
btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
});
// 存储偏好
try {
localStorage.setItem(STORAGE_KEY, langCode);
} catch (e) { /* 忽略 */ }
}
// 绑定点击事件
langBtns.forEach(btn => {
btn.addEventListener('click', function() {
const langCode = this.getAttribute('data-lang');
if (langCode && i18n[langCode]) {
applyLang(langCode);
}
});
});
// 初始化
const initialLang = getInitialLang();
applyLang(initialLang);
// 页面恢复时(从bfcache),重新应用语言
window.addEventListener('pageshow', function() {
const currentLang = htmlEl.lang || getInitialLang();
if (i18n[currentLang]) {
applyLang(currentLang);
}
});
})();
</script>
</body>
</html>