refactor: 移除过时的前端资源和优化配置
详细说明: - 删除不再使用的HTML、CSS和JavaScript文件,包括index.html、animations.css、styles.css等。 - 更新settings.local.json,添加新的Bash命令以优化文件处理。 - 清理无用的脚本和样式,提升项目结构的整洁性和可维护性。 影响模块: 前端资源管理和项目结构优化 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -109,7 +109,11 @@
|
|||||||
"Bash(else)",
|
"Bash(else)",
|
||||||
"Bash(xxd:*)",
|
"Bash(xxd:*)",
|
||||||
"Bash(open \"http://localhost:4155/order-classes/civil/\")",
|
"Bash(open \"http://localhost:4155/order-classes/civil/\")",
|
||||||
"Bash(file:*)"
|
"Bash(file:*)",
|
||||||
|
"Bash(do sed -i '' 's|\"\"\\.\\./js/|\"\"js/|g' \"$file\")",
|
||||||
|
"Bash(do sed -i '' 's|\"\"\\.\\./css/|\"\"css/|g' \"$file\")",
|
||||||
|
"Bash(do sed -i '' 's|\"\"\\.\\./data/|\"\"data/|g' \"$file\")",
|
||||||
|
"Bash(do sed -i '' \"s|url(''\\.\\./data/|url(''data/|g\" \"$file\")"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": [],
|
"ask": [],
|
||||||
|
|||||||
BIN
.playwright-mcp/wenlu-nav-issue.png
Normal file
BIN
.playwright-mcp/wenlu-nav-issue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 MiB |
@@ -1,919 +0,0 @@
|
|||||||
/* 2024长三角国际新能源汽车与智能交通产业博览会 - 高级动画样式 */
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
字体图标引入
|
|
||||||
============================================ */
|
|
||||||
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css');
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
自定义字体
|
|
||||||
============================================ */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'TechFont';
|
|
||||||
src: url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
核心动画变量
|
|
||||||
============================================ */
|
|
||||||
:root {
|
|
||||||
/* 动画时长 */
|
|
||||||
--anim-fast: 0.2s;
|
|
||||||
--anim-normal: 0.3s;
|
|
||||||
--anim-slow: 0.5s;
|
|
||||||
--anim-slower: 0.8s;
|
|
||||||
--anim-slowest: 1.2s;
|
|
||||||
|
|
||||||
/* 缓动函数 */
|
|
||||||
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
--ease-elastic: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
--ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
--ease-sharp: cubic-bezier(0.4, 0, 0.6, 1);
|
|
||||||
|
|
||||||
/* 渐变色 */
|
|
||||||
--gradient-electric: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
--gradient-ocean: linear-gradient(135deg, #667eea 0%, #42e695 100%);
|
|
||||||
--gradient-sunset: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
|
||||||
--gradient-aurora: linear-gradient(135deg, #42e695 0%, #3bb2b8 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
基础动画类
|
|
||||||
============================================ */
|
|
||||||
/* 淡入向上动画 */
|
|
||||||
.animate-fadeInUp {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(30px);
|
|
||||||
animation: fadeInUp 0.8s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInUp {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 淡入向左动画 */
|
|
||||||
.animate-fadeInLeft {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-30px);
|
|
||||||
animation: fadeInLeft 0.8s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInLeft {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 淡入向右动画 */
|
|
||||||
.animate-fadeInRight {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(30px);
|
|
||||||
animation: fadeInRight 0.8s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInRight {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 动画延迟类 */
|
|
||||||
.animation-delay-100 { animation-delay: 0.1s; }
|
|
||||||
.animation-delay-200 { animation-delay: 0.2s; }
|
|
||||||
.animation-delay-300 { animation-delay: 0.3s; }
|
|
||||||
.animation-delay-400 { animation-delay: 0.4s; }
|
|
||||||
.animation-delay-500 { animation-delay: 0.5s; }
|
|
||||||
.animation-delay-600 { animation-delay: 0.6s; }
|
|
||||||
.animation-delay-700 { animation-delay: 0.7s; }
|
|
||||||
.animation-delay-800 { animation-delay: 0.8s; }
|
|
||||||
.animation-delay-900 { animation-delay: 0.9s; }
|
|
||||||
.animation-delay-1000 { animation-delay: 1s; }
|
|
||||||
.animation-delay-1100 { animation-delay: 1.1s; }
|
|
||||||
.animation-delay-2000 { animation-delay: 2s; }
|
|
||||||
.animation-delay-4000 { animation-delay: 4s; }
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
页面加载动画
|
|
||||||
============================================ */
|
|
||||||
.page-loader {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
z-index: 9999;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
animation: fadeOut 0.5s ease-out 1s forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-content {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-logo {
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
margin: 0 auto 20px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
animation: pulse 1s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-text {
|
|
||||||
color: white;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
animation: fadeInUp 0.5s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-progress {
|
|
||||||
width: 200px;
|
|
||||||
height: 4px;
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 2px;
|
|
||||||
margin: 20px auto;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-progress-bar {
|
|
||||||
width: 0%;
|
|
||||||
height: 100%;
|
|
||||||
background: white;
|
|
||||||
animation: loading 1s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loading {
|
|
||||||
to { width: 100%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
入场动画
|
|
||||||
============================================ */
|
|
||||||
.fade-in {
|
|
||||||
opacity: 0;
|
|
||||||
animation: fadeIn var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-up {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(30px);
|
|
||||||
animation: fadeInUp var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInUp {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-down {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-30px);
|
|
||||||
animation: fadeInDown var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInDown {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-left {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-30px);
|
|
||||||
animation: fadeInLeft var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInLeft {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-right {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(30px);
|
|
||||||
animation: fadeInRight var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInRight {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
缩放动画
|
|
||||||
============================================ */
|
|
||||||
.zoom-in {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.8);
|
|
||||||
animation: zoomIn var(--anim-slow) var(--ease-bounce) forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes zoomIn {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-out {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(1.2);
|
|
||||||
animation: zoomOut var(--anim-slow) var(--ease-bounce) forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes zoomOut {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
旋转动画
|
|
||||||
============================================ */
|
|
||||||
.rotate-in {
|
|
||||||
opacity: 0;
|
|
||||||
transform: rotate(-180deg) scale(0.8);
|
|
||||||
animation: rotateIn var(--anim-slow) var(--ease-bounce) forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotateIn {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: rotate(0) scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flip-in-x {
|
|
||||||
opacity: 0;
|
|
||||||
transform: rotateX(-90deg);
|
|
||||||
animation: flipInX var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes flipInX {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: rotateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flip-in-y {
|
|
||||||
opacity: 0;
|
|
||||||
transform: rotateY(-90deg);
|
|
||||||
animation: flipInY var(--anim-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes flipInY {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: rotateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
弹跳动画
|
|
||||||
============================================ */
|
|
||||||
.bounce-in {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.3);
|
|
||||||
animation: bounceIn var(--anim-slower) var(--ease-bounce) forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bounceIn {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.3);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
70% {
|
|
||||||
transform: scale(0.9);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
悬停效果
|
|
||||||
============================================ */
|
|
||||||
.hover-grow {
|
|
||||||
transition: transform var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-grow:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-shrink {
|
|
||||||
transition: transform var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-shrink:hover {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-rotate {
|
|
||||||
transition: transform var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-rotate:hover {
|
|
||||||
transform: rotate(5deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-lift {
|
|
||||||
transition: all var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-lift:hover {
|
|
||||||
transform: translateY(-8px);
|
|
||||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-sink {
|
|
||||||
transition: all var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-sink:hover {
|
|
||||||
transform: translateY(3px);
|
|
||||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
按钮悬停效果
|
|
||||||
============================================ */
|
|
||||||
.btn-hover-fill {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: color var(--anim-normal);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-hover-fill::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: var(--gradient-electric);
|
|
||||||
transition: left var(--anim-normal) var(--ease-smooth);
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-hover-fill:hover::before {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-hover-fill:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮波纹效果 */
|
|
||||||
.btn-ripple {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-ripple::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
transition: width 0.6s, height 0.6s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-ripple:active::after {
|
|
||||||
width: 300px;
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮发光效果 */
|
|
||||||
.btn-glow {
|
|
||||||
transition: all var(--anim-normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-glow:hover {
|
|
||||||
box-shadow: 0 0 20px rgba(102, 126, 234, 0.6),
|
|
||||||
0 0 40px rgba(102, 126, 234, 0.4),
|
|
||||||
0 0 60px rgba(102, 126, 234, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
图片悬停效果
|
|
||||||
============================================ */
|
|
||||||
.img-hover-zoom {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-zoom img {
|
|
||||||
transition: transform var(--anim-slow) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-zoom:hover img {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-rotate {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-rotate img {
|
|
||||||
transition: transform var(--anim-slow) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-rotate:hover img {
|
|
||||||
transform: scale(1.1) rotate(3deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-blur {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-blur img {
|
|
||||||
transition: all var(--anim-slow) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-hover-blur:hover img {
|
|
||||||
filter: blur(3px);
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 图片叠加效果 */
|
|
||||||
.img-overlay {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-overlay::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.8), rgba(118, 75, 162, 0.8));
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity var(--anim-normal);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-overlay:hover::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-overlay-content {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity var(--anim-normal);
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-overlay:hover .img-overlay-content {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
文字动画
|
|
||||||
============================================ */
|
|
||||||
.text-glow {
|
|
||||||
animation: textGlow 2s ease-in-out infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes textGlow {
|
|
||||||
from {
|
|
||||||
text-shadow: 0 0 10px rgba(102, 126, 234, 0.5),
|
|
||||||
0 0 20px rgba(102, 126, 234, 0.3);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
text-shadow: 0 0 20px rgba(102, 126, 234, 0.8),
|
|
||||||
0 0 30px rgba(102, 126, 234, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-typing {
|
|
||||||
overflow: hidden;
|
|
||||||
border-right: 2px solid;
|
|
||||||
white-space: nowrap;
|
|
||||||
animation: typing 3.5s steps(40, end),
|
|
||||||
blink-caret 0.75s step-end infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes typing {
|
|
||||||
from { width: 0; }
|
|
||||||
to { width: 100%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes blink-caret {
|
|
||||||
from, to { border-color: transparent; }
|
|
||||||
50% { border-color: currentColor; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-gradient-animate {
|
|
||||||
background: linear-gradient(90deg, #667eea, #764ba2, #42e695, #667eea);
|
|
||||||
background-size: 300% 100%;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-clip: text;
|
|
||||||
animation: gradientMove 5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes gradientMove {
|
|
||||||
0% { background-position: 0% 50%; }
|
|
||||||
50% { background-position: 100% 50%; }
|
|
||||||
100% { background-position: 0% 50%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
卡片动画
|
|
||||||
============================================ */
|
|
||||||
.card-3d {
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
transition: transform var(--anim-slow) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-3d:hover {
|
|
||||||
transform: rotateY(10deg) rotateX(10deg) translateZ(20px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-flip {
|
|
||||||
position: relative;
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
transition: transform var(--anim-slow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-flip:hover {
|
|
||||||
transform: rotateY(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-flip-front,
|
|
||||||
.card-flip-back {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-flip-back {
|
|
||||||
transform: rotateY(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
滚动动画
|
|
||||||
============================================ */
|
|
||||||
.scroll-reveal {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(50px);
|
|
||||||
transition: all var(--anim-slower) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal.revealed {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-left {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-50px);
|
|
||||||
transition: all var(--anim-slower) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-left.revealed {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-right {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(50px);
|
|
||||||
transition: all var(--anim-slower) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-right.revealed {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-scale {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.8);
|
|
||||||
transition: all var(--anim-slower) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-reveal-scale.revealed {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
视差效果
|
|
||||||
============================================ */
|
|
||||||
.parallax {
|
|
||||||
position: relative;
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parallax-layer {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parallax-layer-back {
|
|
||||||
transform: translateZ(-1px) scale(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.parallax-layer-base {
|
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.parallax-layer-front {
|
|
||||||
transform: translateZ(1px) scale(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
加载动画
|
|
||||||
============================================ */
|
|
||||||
.skeleton {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeleton::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
|
|
||||||
animation: skeleton-loading 1.5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes skeleton-loading {
|
|
||||||
to {
|
|
||||||
left: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
脉冲动画
|
|
||||||
============================================ */
|
|
||||||
.pulse {
|
|
||||||
animation: pulse 2s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: scale(1.05);
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pulse-slow {
|
|
||||||
animation: pulse 3s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pulse-fast {
|
|
||||||
animation: pulse 1s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
抖动动画
|
|
||||||
============================================ */
|
|
||||||
.shake {
|
|
||||||
animation: shake 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shake {
|
|
||||||
0%, 100% { transform: translateX(0); }
|
|
||||||
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
|
|
||||||
20%, 40%, 60%, 80% { transform: translateX(10px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.shake-horizontal {
|
|
||||||
animation: shakeHorizontal 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shakeHorizontal {
|
|
||||||
0%, 100% { transform: translateX(0); }
|
|
||||||
25% { transform: translateX(-5px); }
|
|
||||||
75% { transform: translateX(5px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
浮动动画
|
|
||||||
============================================ */
|
|
||||||
.float {
|
|
||||||
animation: float 3s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float {
|
|
||||||
0%, 100% { transform: translateY(0); }
|
|
||||||
50% { transform: translateY(-20px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.float-slow {
|
|
||||||
animation: float 5s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.float-fast {
|
|
||||||
animation: float 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
闪烁动画
|
|
||||||
============================================ */
|
|
||||||
.blink {
|
|
||||||
animation: blink 1s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes blink {
|
|
||||||
0%, 100% { opacity: 1; }
|
|
||||||
50% { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.flash {
|
|
||||||
animation: flash 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes flash {
|
|
||||||
0%, 50%, 100% { opacity: 1; }
|
|
||||||
25%, 75% { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
渐变背景动画
|
|
||||||
============================================ */
|
|
||||||
.bg-gradient-animate {
|
|
||||||
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
|
|
||||||
background-size: 400% 400%;
|
|
||||||
animation: gradientShift 15s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes gradientShift {
|
|
||||||
0% { background-position: 0% 50%; }
|
|
||||||
50% { background-position: 100% 50%; }
|
|
||||||
100% { background-position: 0% 50%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
光标跟随效果
|
|
||||||
============================================ */
|
|
||||||
.cursor-follow {
|
|
||||||
position: fixed;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border: 2px solid #667eea;
|
|
||||||
border-radius: 50%;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: all 0.1s ease;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cursor-follow.active {
|
|
||||||
transform: scale(2);
|
|
||||||
background: rgba(102, 126, 234, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
工具提示
|
|
||||||
============================================ */
|
|
||||||
.tooltip {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip::after {
|
|
||||||
content: attr(data-tooltip);
|
|
||||||
position: absolute;
|
|
||||||
bottom: 125%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%) scale(0);
|
|
||||||
background: #333;
|
|
||||||
color: white;
|
|
||||||
padding: 8px 12px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 14px;
|
|
||||||
white-space: nowrap;
|
|
||||||
opacity: 0;
|
|
||||||
transition: all var(--anim-normal) var(--ease-smooth);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 115%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%) scale(0);
|
|
||||||
border: 6px solid transparent;
|
|
||||||
border-top-color: #333;
|
|
||||||
opacity: 0;
|
|
||||||
transition: all var(--anim-normal) var(--ease-smooth);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip:hover::after,
|
|
||||||
.tooltip:hover::before {
|
|
||||||
transform: translateX(-50%) scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
交错动画
|
|
||||||
============================================ */
|
|
||||||
.stagger-children > * {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(20px);
|
|
||||||
animation: staggerIn var(--anim-slow) var(--ease-smooth) forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stagger-children > *:nth-child(1) { animation-delay: 0.1s; }
|
|
||||||
.stagger-children > *:nth-child(2) { animation-delay: 0.2s; }
|
|
||||||
.stagger-children > *:nth-child(3) { animation-delay: 0.3s; }
|
|
||||||
.stagger-children > *:nth-child(4) { animation-delay: 0.4s; }
|
|
||||||
.stagger-children > *:nth-child(5) { animation-delay: 0.5s; }
|
|
||||||
.stagger-children > *:nth-child(6) { animation-delay: 0.6s; }
|
|
||||||
.stagger-children > *:nth-child(7) { animation-delay: 0.7s; }
|
|
||||||
.stagger-children > *:nth-child(8) { animation-delay: 0.8s; }
|
|
||||||
|
|
||||||
@keyframes staggerIn {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
模糊背景
|
|
||||||
============================================ */
|
|
||||||
.blur-background {
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glass-morphism {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
||||||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================
|
|
||||||
响应式动画
|
|
||||||
============================================ */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
animation-duration: 0.01ms !important;
|
|
||||||
animation-iteration-count: 1 !important;
|
|
||||||
transition-duration: 0.01ms !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,454 +0,0 @@
|
|||||||
/* 2024长三角国际新能源汽车与智能交通产业博览会 - 全局样式 */
|
|
||||||
|
|
||||||
/* 根变量定义 */
|
|
||||||
:root {
|
|
||||||
/* 主题色彩系统 */
|
|
||||||
--primary-gradient-start: #10b981;
|
|
||||||
--primary-gradient-end: #3b82f6;
|
|
||||||
--secondary-gradient-start: #8b5cf6;
|
|
||||||
--secondary-gradient-end: #ec4899;
|
|
||||||
--accent-gradient-start: #f59e0b;
|
|
||||||
--accent-gradient-end: #ef4444;
|
|
||||||
|
|
||||||
/* 中性色 */
|
|
||||||
--gray-50: #f9fafb;
|
|
||||||
--gray-100: #f3f4f6;
|
|
||||||
--gray-200: #e5e7eb;
|
|
||||||
--gray-300: #d1d5db;
|
|
||||||
--gray-400: #9ca3af;
|
|
||||||
--gray-500: #6b7280;
|
|
||||||
--gray-600: #4b5563;
|
|
||||||
--gray-700: #374151;
|
|
||||||
--gray-800: #1f2937;
|
|
||||||
--gray-900: #111827;
|
|
||||||
|
|
||||||
/* 间距系统 */
|
|
||||||
--spacing-xs: 0.5rem;
|
|
||||||
--spacing-sm: 1rem;
|
|
||||||
--spacing-md: 1.5rem;
|
|
||||||
--spacing-lg: 2rem;
|
|
||||||
--spacing-xl: 3rem;
|
|
||||||
--spacing-2xl: 4rem;
|
|
||||||
|
|
||||||
/* 动画时长 */
|
|
||||||
--transition-fast: 150ms;
|
|
||||||
--transition-base: 300ms;
|
|
||||||
--transition-slow: 500ms;
|
|
||||||
--transition-slower: 700ms;
|
|
||||||
|
|
||||||
/* 阴影 */
|
|
||||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
||||||
--shadow-base: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
||||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
||||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
/* 圆角 */
|
|
||||||
--radius-sm: 0.375rem;
|
|
||||||
--radius-base: 0.5rem;
|
|
||||||
--radius-lg: 0.75rem;
|
|
||||||
--radius-xl: 1rem;
|
|
||||||
--radius-full: 9999px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 全局重置和基础样式 */
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', 'Microsoft YaHei', sans-serif;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: var(--gray-800);
|
|
||||||
background-color: var(--gray-50);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 渐变背景动画 */
|
|
||||||
@keyframes gradientShift {
|
|
||||||
0% { background-position: 0% 50%; }
|
|
||||||
50% { background-position: 100% 50%; }
|
|
||||||
100% { background-position: 0% 50%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.gradient-bg {
|
|
||||||
background: linear-gradient(-45deg,
|
|
||||||
var(--primary-gradient-start),
|
|
||||||
var(--primary-gradient-end),
|
|
||||||
var(--secondary-gradient-start),
|
|
||||||
var(--secondary-gradient-end));
|
|
||||||
background-size: 400% 400%;
|
|
||||||
animation: gradientShift 15s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gradient-primary {
|
|
||||||
background: linear-gradient(135deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
}
|
|
||||||
|
|
||||||
.gradient-secondary {
|
|
||||||
background: linear-gradient(135deg, var(--secondary-gradient-start), var(--secondary-gradient-end));
|
|
||||||
}
|
|
||||||
|
|
||||||
.gradient-accent {
|
|
||||||
background: linear-gradient(135deg, var(--accent-gradient-start), var(--accent-gradient-end));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导航栏样式 */
|
|
||||||
.navbar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
background: rgba(255, 255, 255, 0.95);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
box-shadow: var(--shadow-base);
|
|
||||||
transition: all var(--transition-base) ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar.scrolled {
|
|
||||||
background: rgba(255, 255, 255, 0.98);
|
|
||||||
box-shadow: var(--shadow-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
position: relative;
|
|
||||||
padding: var(--spacing-xs) var(--spacing-sm);
|
|
||||||
color: var(--gray-700);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color var(--transition-fast) ease;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 50%;
|
|
||||||
width: 0;
|
|
||||||
height: 2px;
|
|
||||||
background: linear-gradient(90deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
transform: translateX(-50%);
|
|
||||||
transition: width var(--transition-base) ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link:hover::after,
|
|
||||||
.nav-link.active::after {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 卡片动画效果 */
|
|
||||||
@keyframes cardFloat {
|
|
||||||
0%, 100% { transform: translateY(0); }
|
|
||||||
50% { transform: translateY(-10px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background: white;
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
padding: var(--spacing-lg);
|
|
||||||
box-shadow: var(--shadow-base);
|
|
||||||
transition: all var(--transition-base) ease;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 4px;
|
|
||||||
background: linear-gradient(90deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
transform: scaleX(0);
|
|
||||||
transform-origin: left;
|
|
||||||
transition: transform var(--transition-base) ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card:hover {
|
|
||||||
transform: translateY(-5px);
|
|
||||||
box-shadow: var(--shadow-xl);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card:hover::before {
|
|
||||||
transform: scaleX(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮样式 */
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: var(--spacing-sm) var(--spacing-lg);
|
|
||||||
border-radius: var(--radius-full);
|
|
||||||
font-weight: 600;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all var(--transition-base) ease;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background: linear-gradient(135deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
color: white;
|
|
||||||
box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary {
|
|
||||||
background: white;
|
|
||||||
color: var(--gray-700);
|
|
||||||
border: 2px solid var(--gray-200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
background: var(--gray-50);
|
|
||||||
border-color: var(--primary-gradient-start);
|
|
||||||
color: var(--primary-gradient-start);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 波纹效果 */
|
|
||||||
@keyframes ripple {
|
|
||||||
0% {
|
|
||||||
transform: scale(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(4);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ripple {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
animation: ripple 0.6s ease-out;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 加载动画 */
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
display: inline-block;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border: 4px solid var(--gray-200);
|
|
||||||
border-top-color: var(--primary-gradient-start);
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 数字滚动动画 */
|
|
||||||
@keyframes countUp {
|
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
|
||||||
to { opacity: 1; transform: translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-up {
|
|
||||||
animation: countUp var(--transition-slow) ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 淡入动画 */
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
|
||||||
to { opacity: 1; transform: translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in {
|
|
||||||
animation: fadeIn var(--transition-slower) ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滑入动画 */
|
|
||||||
@keyframes slideInLeft {
|
|
||||||
from { opacity: 0; transform: translateX(-50px); }
|
|
||||||
to { opacity: 1; transform: translateX(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideInRight {
|
|
||||||
from { opacity: 0; transform: translateX(50px); }
|
|
||||||
to { opacity: 1; transform: translateX(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.slide-in-left {
|
|
||||||
animation: slideInLeft var(--transition-slow) ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slide-in-right {
|
|
||||||
animation: slideInRight var(--transition-slow) ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 脉冲动画 */
|
|
||||||
@keyframes pulse {
|
|
||||||
0%, 100% { transform: scale(1); opacity: 1; }
|
|
||||||
50% { transform: scale(1.05); opacity: 0.9; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.pulse {
|
|
||||||
animation: pulse 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 光晕效果 */
|
|
||||||
@keyframes glow {
|
|
||||||
0%, 100% { box-shadow: 0 0 20px rgba(16, 185, 129, 0.5); }
|
|
||||||
50% { box-shadow: 0 0 40px rgba(16, 185, 129, 0.8); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.glow {
|
|
||||||
animation: glow 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 时间线样式 */
|
|
||||||
.timeline {
|
|
||||||
position: relative;
|
|
||||||
padding-left: var(--spacing-xl);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: 15px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 2px;
|
|
||||||
background: linear-gradient(180deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-item {
|
|
||||||
position: relative;
|
|
||||||
padding-bottom: var(--spacing-xl);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-item::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: -25px;
|
|
||||||
top: 5px;
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: var(--primary-gradient-start);
|
|
||||||
border: 3px solid white;
|
|
||||||
box-shadow: var(--shadow-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 网格布局动画 */
|
|
||||||
.grid-item {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.9);
|
|
||||||
animation: gridFadeIn var(--transition-slow) ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes gridFadeIn {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-item:nth-child(1) { animation-delay: 0.1s; }
|
|
||||||
.grid-item:nth-child(2) { animation-delay: 0.2s; }
|
|
||||||
.grid-item:nth-child(3) { animation-delay: 0.3s; }
|
|
||||||
.grid-item:nth-child(4) { animation-delay: 0.4s; }
|
|
||||||
.grid-item:nth-child(5) { animation-delay: 0.5s; }
|
|
||||||
.grid-item:nth-child(6) { animation-delay: 0.6s; }
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
:root {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: var(--spacing-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline {
|
|
||||||
padding-left: var(--spacing-lg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
animation-duration: 0.01ms !important;
|
|
||||||
animation-iteration-count: 1 !important;
|
|
||||||
transition-duration: 0.01ms !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 打印样式 */
|
|
||||||
@media print {
|
|
||||||
.navbar,
|
|
||||||
.btn,
|
|
||||||
.no-print {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-size: 12pt;
|
|
||||||
color: black;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
box-shadow: none;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
page-break-inside: avoid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 辅助类 */
|
|
||||||
.text-gradient {
|
|
||||||
background: linear-gradient(135deg, var(--primary-gradient-start), var(--primary-gradient-end));
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-clip: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-scale {
|
|
||||||
transition: transform var(--transition-base) ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-scale:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-lift {
|
|
||||||
transition: transform var(--transition-base) ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-lift:hover {
|
|
||||||
transform: translateY(-5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.7));
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 var(--spacing-md);
|
|
||||||
}
|
|
||||||
@@ -1,569 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes, viewport-fit=cover">
|
|
||||||
<title>2024长三角国际新能源汽车与智能交通产业博览会</title>
|
|
||||||
|
|
||||||
<!-- 预加载关键资源 -->
|
|
||||||
<link rel="preload" href="css/styles.css" as="style">
|
|
||||||
<link rel="preload" href="css/animations.css" as="style">
|
|
||||||
|
|
||||||
<!-- 样式表 -->
|
|
||||||
<link rel="stylesheet" href="css/styles.css">
|
|
||||||
<link rel="stylesheet" href="css/animations.css">
|
|
||||||
|
|
||||||
<!-- Tailwind CSS -->
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
|
|
||||||
<!-- 字体 -->
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Noto+Sans+SC:wght@300;400;500;700;900&family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- 错误处理(需要最早加载) -->
|
|
||||||
<script src="js/error-handler.js"></script>
|
|
||||||
|
|
||||||
<!-- 订单班处理器(需要早加载) -->
|
|
||||||
<script src="js/order-class-handler.js"></script>
|
|
||||||
|
|
||||||
<!-- 页面加载动画(需要尽早加载) -->
|
|
||||||
<script src="js/page-loader.js"></script>
|
|
||||||
|
|
||||||
<!-- 移动端优化 -->
|
|
||||||
<script src="js/mobile-optimize.js"></script>
|
|
||||||
|
|
||||||
<!-- 性能优化 -->
|
|
||||||
<script src="js/performance-optimizer.js"></script>
|
|
||||||
|
|
||||||
<!-- Font Awesome 图标 -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
font-family: 'Inter', 'Noto Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-gradient {
|
|
||||||
background: linear-gradient(135deg,
|
|
||||||
rgba(16, 185, 129, 0.1) 0%,
|
|
||||||
rgba(59, 130, 246, 0.1) 50%,
|
|
||||||
rgba(139, 92, 246, 0.1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-shine {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-shine::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: -50%;
|
|
||||||
left: -50%;
|
|
||||||
width: 200%;
|
|
||||||
height: 200%;
|
|
||||||
background: linear-gradient(
|
|
||||||
45deg,
|
|
||||||
transparent 30%,
|
|
||||||
rgba(255, 255, 255, 0.3) 50%,
|
|
||||||
transparent 70%
|
|
||||||
);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
transition: all 0.6s;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-shine:hover::before {
|
|
||||||
animation: shine 0.6s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shine {
|
|
||||||
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); opacity: 0; }
|
|
||||||
50% { opacity: 1; }
|
|
||||||
100% { transform: translateX(100%) translateY(100%) rotate(45deg); opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating {
|
|
||||||
animation: floating 3s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes floating {
|
|
||||||
0%, 100% { transform: translateY(0px); }
|
|
||||||
50% { transform: translateY(-20px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 确保页面加载时body不能滚动 */
|
|
||||||
body.loading {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 图片加载优化 */
|
|
||||||
img {
|
|
||||||
background-color: #f3f4f6;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.image-loaded {
|
|
||||||
opacity: 1;
|
|
||||||
animation: fadeIn 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.image-error {
|
|
||||||
opacity: 0.5;
|
|
||||||
filter: grayscale(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="bg-gray-50 loading">
|
|
||||||
<!-- 页面加载器将由page-loader.js动态创建 -->
|
|
||||||
|
|
||||||
<!-- Navigation -->
|
|
||||||
<nav class="fixed top-0 w-full glass-morphism shadow-md z-50 transition-all duration-300" id="navbar">
|
|
||||||
<!-- Content will be dynamically generated by nav-component.js -->
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Hero Section -->
|
|
||||||
<section class="relative min-h-screen flex items-center justify-center overflow-hidden hero-gradient py-32">
|
|
||||||
<!-- 背景图片 -->
|
|
||||||
<div class="absolute inset-0 z-0">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-100 via-blue-50 to-emerald-50"></div>
|
|
||||||
<div class="absolute inset-0 opacity-10" style="background-image: url('../data/订单班文档资料/文旅/notion文稿/image/博览会.jpg'); background-size: cover; background-position: center;"></div>
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-white/60 to-white/90"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 浮动装饰元素 -->
|
|
||||||
<div class="absolute top-20 left-10 w-20 h-20 bg-emerald-400 rounded-full opacity-20 floating"></div>
|
|
||||||
<div class="absolute bottom-20 right-10 w-32 h-32 bg-blue-400 rounded-full opacity-20 floating" style="animation-delay: 1s;"></div>
|
|
||||||
<div class="absolute top-1/2 left-20 w-16 h-16 bg-purple-400 rounded-full opacity-20 floating" style="animation-delay: 2s;"></div>
|
|
||||||
|
|
||||||
<div class="relative z-10 container mx-auto px-6 text-center py-12">
|
|
||||||
<div class="fade-in-up">
|
|
||||||
<!-- 标签 -->
|
|
||||||
<div class="inline-flex items-center px-4 py-2 bg-white/80 backdrop-blur-sm rounded-full mb-6 shadow-lg">
|
|
||||||
<span class="animate-pulse w-2 h-2 bg-emerald-500 rounded-full mr-2"></span>
|
|
||||||
<span class="text-sm font-semibold text-gray-700">2024年6月15-17日 · 苏州国际博览中心</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 class="text-5xl md:text-7xl font-black mb-6">
|
|
||||||
<span class="block text-gradient-animate" data-order-title>2024长三角国际新能源汽车与智能交通产业博览会</span>
|
|
||||||
<span class="block text-4xl md:text-5xl text-gray-600 mt-2" data-order-subtitle>新能源汽车产业博览会</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p class="text-xl md:text-2xl text-gray-600 mb-8 max-w-3xl mx-auto">
|
|
||||||
<i class="fas fa-quote-left text-emerald-500 mr-2"></i>
|
|
||||||
引领绿色出行新时代 · 共创智能交通新未来
|
|
||||||
<i class="fas fa-quote-right text-emerald-500 ml-2"></i>
|
|
||||||
</p>
|
|
||||||
<!-- 核心信息展示 -->
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12 max-w-5xl mx-auto">
|
|
||||||
<div class="bg-white/95 backdrop-blur-md rounded-2xl p-6 border-2 border-purple-200 hover:border-purple-400 transition-all duration-300 transform hover:scale-105 animate-fadeInUp animation-delay-200 shadow-2xl">
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-full flex items-center justify-center mb-3 shadow-lg">
|
|
||||||
<i class="fas fa-calendar-alt text-3xl text-white"></i>
|
|
||||||
</div>
|
|
||||||
<p class="text-gray-600 text-sm font-medium mb-2">展会时间</p>
|
|
||||||
<p class="text-gray-900 font-bold text-2xl text-center">2024年9月</p>
|
|
||||||
<p class="text-gray-800 font-bold text-xl">12-15日</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white/95 backdrop-blur-md rounded-2xl p-6 border-2 border-blue-200 hover:border-blue-400 transition-all duration-300 transform hover:scale-105 animate-fadeInUp animation-delay-400 shadow-2xl">
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-full flex items-center justify-center mb-3 shadow-lg">
|
|
||||||
<i class="fas fa-map-marked-alt text-3xl text-white"></i>
|
|
||||||
</div>
|
|
||||||
<p class="text-gray-600 text-sm font-medium mb-2">展会地点</p>
|
|
||||||
<p class="text-gray-900 font-bold text-2xl text-center">国家会展中心</p>
|
|
||||||
<p class="text-gray-800 font-bold text-xl">上海</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white/95 backdrop-blur-md rounded-2xl p-6 border-2 border-green-200 hover:border-green-400 transition-all duration-300 transform hover:scale-105 animate-fadeInUp animation-delay-600 shadow-2xl">
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-full flex items-center justify-center mb-3 shadow-lg">
|
|
||||||
<i class="fas fa-expand-arrows-alt text-3xl text-white"></i>
|
|
||||||
</div>
|
|
||||||
<p class="text-gray-600 text-sm font-medium mb-2">展览规模</p>
|
|
||||||
<p class="text-gray-900 font-bold text-3xl">50,000</p>
|
|
||||||
<p class="text-gray-800 font-bold text-lg">平方米</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- CTA按钮组 -->
|
|
||||||
<div class="flex flex-col md:flex-row gap-6 justify-center items-center animate-fadeInUp animation-delay-800">
|
|
||||||
<a href="pages/overview.html" class="group relative overflow-hidden bg-white text-purple-700 px-12 py-5 rounded-full font-bold text-xl shadow-2xl hover:shadow-white/30 transition-all duration-300 transform hover:scale-110">
|
|
||||||
<span class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
|
|
||||||
<span class="relative z-10 flex items-center group-hover:text-white">
|
|
||||||
<i class="fas fa-sparkles mr-3 text-2xl animate-pulse"></i>
|
|
||||||
了解详情
|
|
||||||
<i class="fas fa-arrow-right ml-3 group-hover:translate-x-2 transition-transform"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a href="#highlights" class="group relative overflow-hidden bg-gradient-to-r from-purple-600 to-pink-600 text-white px-12 py-5 rounded-full font-bold text-xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-110 shadow-2xl">
|
|
||||||
<span class="relative z-10 flex items-center">
|
|
||||||
<i class="fas fa-star mr-3 text-2xl text-yellow-300"></i>
|
|
||||||
展会亮点
|
|
||||||
<i class="fas fa-chevron-down ml-3 animate-bounce"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Key Stats Section -->
|
|
||||||
<section class="py-20 -mt-20 relative z-20 bg-gradient-to-br from-white via-gray-50 to-white">
|
|
||||||
<!-- 背景装饰 -->
|
|
||||||
<div class="absolute inset-0 opacity-5" style="background-image: url('../data/订单班文档资料/文旅/notion文稿/image/Whisk_9e8c1f44ac.jpg'); background-size: cover; background-position: center;"></div>
|
|
||||||
|
|
||||||
<div class="container mx-auto px-6 relative z-10" title="核心数据展示区">
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12">
|
|
||||||
<div class="text-center group animate-fadeInUp animation-delay-200 transform hover:scale-105 transition-all duration-300">
|
|
||||||
<div class="w-24 h-24 mx-auto mb-4 bg-white rounded-2xl flex items-center justify-center shadow-lg group-hover:shadow-xl border-2 border-purple-200 group-hover:border-purple-400 group-hover:rotate-3 transition-all">
|
|
||||||
<i class="fas fa-building text-4xl text-purple-600"></i>
|
|
||||||
</div>
|
|
||||||
<div class="text-5xl font-bold text-gray-800 mb-2">
|
|
||||||
<span class="counter" data-target="350">0</span>+
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-700 font-semibold text-lg">参展企业</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center group animate-fadeInUp animation-delay-400 transform hover:scale-105 transition-all duration-300">
|
|
||||||
<div class="w-24 h-24 mx-auto mb-4 bg-white rounded-2xl flex items-center justify-center shadow-lg group-hover:shadow-xl border-2 border-blue-200 group-hover:border-blue-400 group-hover:-rotate-3 transition-all">
|
|
||||||
<i class="fas fa-users text-4xl text-blue-600"></i>
|
|
||||||
</div>
|
|
||||||
<div class="text-5xl font-bold text-gray-800 mb-2">
|
|
||||||
<span class="counter" data-target="50000">0</span>+
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-700 font-semibold text-lg">预计观众</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center group animate-fadeInUp animation-delay-600 transform hover:scale-105 transition-all duration-300">
|
|
||||||
<div class="w-24 h-24 mx-auto mb-4 bg-white rounded-2xl flex items-center justify-center shadow-lg group-hover:shadow-xl border-2 border-green-200 group-hover:border-green-400 group-hover:rotate-3 transition-all">
|
|
||||||
<i class="fas fa-hand-holding-usd text-4xl text-green-600"></i>
|
|
||||||
</div>
|
|
||||||
<div class="text-5xl font-bold text-gray-800 mb-2">
|
|
||||||
<span class="counter" data-target="10">0</span>亿+
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-700 font-semibold text-lg">预计成交额</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center group animate-fadeInUp animation-delay-800 transform hover:scale-105 transition-all duration-300">
|
|
||||||
<div class="w-24 h-24 mx-auto mb-4 bg-white rounded-2xl flex items-center justify-center shadow-lg group-hover:shadow-xl border-2 border-orange-200 group-hover:border-orange-400 group-hover:-rotate-3 transition-all">
|
|
||||||
<i class="fas fa-microphone-alt text-4xl text-orange-600"></i>
|
|
||||||
</div>
|
|
||||||
<div class="text-5xl font-bold text-gray-800 mb-2">
|
|
||||||
<span class="counter" data-target="20">0</span>+
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-700 font-semibold text-lg">专业论坛</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Highlights Section -->
|
|
||||||
<section id="highlights" class="py-20 relative overflow-hidden">
|
|
||||||
<!-- 背景图片层 - 降低透明度 -->
|
|
||||||
<div class="absolute inset-0 opacity-20" style="background-image: url('../data/订单班文档资料/文旅/notion文稿/image/Whisk_27184afa6e.jpg'); background-size: cover; background-position: center; background-attachment: fixed;"></div>
|
|
||||||
|
|
||||||
<!-- 强化遮罩层 - 确保主体内容清晰 -->
|
|
||||||
<div class="absolute inset-0 bg-white/85"></div>
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-gray-50/95 to-purple-50/95"></div>
|
|
||||||
<div class="absolute inset-0 opacity-10">
|
|
||||||
<div class="absolute top-20 left-20 w-72 h-72 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl animate-blob"></div>
|
|
||||||
<div class="absolute top-40 right-20 w-72 h-72 bg-yellow-300 rounded-full mix-blend-multiply filter blur-xl animate-blob animation-delay-2000"></div>
|
|
||||||
<div class="absolute -bottom-8 left-40 w-72 h-72 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl animate-blob animation-delay-4000"></div>
|
|
||||||
</div>
|
|
||||||
<div class="container mx-auto px-6 relative z-10" title="展会亮点展示区">
|
|
||||||
<h2 class="text-3xl md:text-4xl font-bold text-center text-gray-800 mb-12 animate-fadeInUp">展会亮点</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
||||||
<!-- Card 1 -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden transform transition-all duration-300 hover:scale-105 hover:shadow-2xl animate-fadeInUp animation-delay-200">
|
|
||||||
<div class="h-48 relative overflow-hidden">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/3.小米汽车.jpg" alt="小米汽车" class="w-full h-full object-cover">
|
|
||||||
<div class="absolute top-4 left-4">
|
|
||||||
<div class="bg-blue-500 text-white px-3 py-1 rounded-full text-xs font-semibold">热门展区</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
<h3 class="text-xl font-bold mb-3 text-gray-800">全产业链展示</h3>
|
|
||||||
<p class="text-gray-600 mb-4">
|
|
||||||
涵盖整车制造、核心零部件、充电设施、智能网联等全产业链环节,打造一站式采购平台。
|
|
||||||
</p>
|
|
||||||
<a href="pages/exhibition.html" class="text-purple-600 font-semibold hover:text-purple-800 flex items-center group">
|
|
||||||
了解更多 <i class="fas fa-arrow-right ml-2 transform transition-transform group-hover:translate-x-2"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 2 -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden transform transition-all duration-300 hover:scale-105 hover:shadow-2xl animate-fadeInUp animation-delay-400">
|
|
||||||
<div class="h-48 relative overflow-hidden">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/2.试驾小景.jpg" alt="试驾体验" class="w-full h-full object-cover">
|
|
||||||
<div class="absolute top-4 left-4">
|
|
||||||
<div class="bg-emerald-500 text-white px-3 py-1 rounded-full text-xs font-semibold">互动体验</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
<h3 class="text-xl font-bold mb-3 text-gray-800">创新技术体验</h3>
|
|
||||||
<p class="text-gray-600 mb-4">
|
|
||||||
设置自动驾驶体验区、智能交通演示区,让观众亲身体验最新科技成果。
|
|
||||||
</p>
|
|
||||||
<a href="pages/operation.html" class="text-emerald-600 font-semibold hover:text-emerald-800 flex items-center group">
|
|
||||||
了解更多 <i class="fas fa-arrow-right ml-2 transform transition-transform group-hover:translate-x-2"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 3 -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden transform transition-all duration-300 hover:scale-105 hover:shadow-2xl animate-fadeInUp animation-delay-600">
|
|
||||||
<div class="h-48 relative overflow-hidden">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/展会内部参观.jpg" alt="论坛峰会" class="w-full h-full object-cover">
|
|
||||||
<div class="absolute top-4 left-4">
|
|
||||||
<div class="bg-purple-500 text-white px-3 py-1 rounded-full text-xs font-semibold">主题论坛</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
<h3 class="text-xl font-bold mb-3 text-gray-800">高端论坛峰会</h3>
|
|
||||||
<p class="text-gray-600 mb-4">
|
|
||||||
汇聚行业领袖、专家学者,探讨产业发展趋势,发布权威研究报告。
|
|
||||||
</p>
|
|
||||||
<a href="pages/marketing.html" class="text-purple-600 font-semibold hover:text-purple-800 flex items-center group">
|
|
||||||
了解更多 <i class="fas fa-arrow-right ml-2 transform transition-transform group-hover:translate-x-2"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Exhibition Areas -->
|
|
||||||
<section class="py-20 bg-gradient-to-br from-white via-indigo-50 to-purple-50">
|
|
||||||
<div class="container mx-auto px-6">
|
|
||||||
<h2 class="text-3xl md:text-4xl font-bold text-center text-gray-800 mb-4 animate-fadeInUp">展区规划</h2>
|
|
||||||
<p class="text-center text-gray-600 mb-12 animate-fadeInUp animation-delay-200">50,000平方米超大展览空间,打造沉浸式体验</p>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
||||||
<div class="group text-center p-6 bg-white/80 backdrop-blur border-2 border-purple-200 rounded-2xl hover:border-purple-500 hover:shadow-2xl transform transition-all duration-300 hover:-translate-y-2 animate-fadeInUp animation-delay-300">
|
|
||||||
<div class="w-20 h-20 bg-gradient-to-br from-blue-400 to-purple-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:rotate-6 transition-transform duration-300">
|
|
||||||
<i class="fas fa-car text-white text-2xl"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-bold mb-2 text-gray-800">整车展示区</h3>
|
|
||||||
<p class="text-purple-600 font-bold text-xl mb-1">20,000m²</p>
|
|
||||||
<p class="text-gray-500 text-sm">100+品牌车型</p>
|
|
||||||
<div class="mt-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
|
||||||
<span class="inline-block bg-purple-100 text-purple-700 px-3 py-1 rounded-full text-xs">核心展区</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="group text-center p-6 bg-white/80 backdrop-blur border-2 border-emerald-200 rounded-2xl hover:border-emerald-500 hover:shadow-2xl transform transition-all duration-300 hover:-translate-y-2 animate-fadeInUp animation-delay-400">
|
|
||||||
<div class="w-20 h-20 bg-gradient-to-br from-emerald-400 to-teal-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:rotate-6 transition-transform duration-300">
|
|
||||||
<i class="fas fa-microchip text-white text-2xl"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-bold mb-2 text-gray-800">核心零部件区</h3>
|
|
||||||
<p class="text-emerald-600 font-bold text-xl mb-1">15,000m²</p>
|
|
||||||
<p class="text-gray-500 text-sm">500+供应商</p>
|
|
||||||
<div class="mt-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
|
||||||
<span class="inline-block bg-emerald-100 text-emerald-700 px-3 py-1 rounded-full text-xs">技术展示</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="group text-center p-6 bg-white/80 backdrop-blur border-2 border-indigo-200 rounded-2xl hover:border-indigo-500 hover:shadow-2xl transform transition-all duration-300 hover:-translate-y-2 animate-fadeInUp animation-delay-500">
|
|
||||||
<div class="w-20 h-20 bg-gradient-to-br from-indigo-400 to-blue-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:rotate-6 transition-transform duration-300">
|
|
||||||
<i class="fas fa-network-wired text-white text-2xl"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-bold mb-2 text-gray-800">智能交通区</h3>
|
|
||||||
<p class="text-indigo-600 font-bold text-xl mb-1">10,000m²</p>
|
|
||||||
<p class="text-gray-500 text-sm">50+解决方案</p>
|
|
||||||
<div class="mt-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
|
||||||
<span class="inline-block bg-indigo-100 text-indigo-700 px-3 py-1 rounded-full text-xs">创新科技</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="group text-center p-6 bg-white/80 backdrop-blur border-2 border-pink-200 rounded-2xl hover:border-pink-500 hover:shadow-2xl transform transition-all duration-300 hover:-translate-y-2 animate-fadeInUp animation-delay-600">
|
|
||||||
<div class="w-20 h-20 bg-gradient-to-br from-pink-400 to-rose-600 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:rotate-6 transition-transform duration-300">
|
|
||||||
<i class="fas fa-gamepad text-white text-2xl"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-bold mb-2 text-gray-800">体验互动区</h3>
|
|
||||||
<p class="text-pink-600 font-bold text-xl mb-1">5,000m²</p>
|
|
||||||
<p class="text-gray-500 text-sm">20+互动项目</p>
|
|
||||||
<div class="mt-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
|
||||||
<span class="inline-block bg-pink-100 text-pink-700 px-3 py-1 rounded-full text-xs">沉浸体验</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 展馆布置图 -->
|
|
||||||
<div class="mt-12 animate-fadeInUp animation-delay-700">
|
|
||||||
<div class="bg-white/90 backdrop-blur rounded-2xl shadow-xl overflow-hidden">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/展馆布置图.jpeg" alt="展馆布置图" class="w-full h-auto hover:scale-105 transition-transform duration-700">
|
|
||||||
<div class="p-4 bg-gradient-to-r from-purple-600 to-indigo-600 text-white">
|
|
||||||
<p class="text-center font-semibold"><i class="fas fa-map-marked-alt mr-2"></i>展馆3D全景布置图 - 点击查看详情</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Gallery Section -->
|
|
||||||
<section class="py-20 bg-gradient-to-br from-gray-900 to-purple-900 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 opacity-10">
|
|
||||||
<div class="absolute top-0 left-0 w-full h-full bg-[url('../data/订单班文档资料/文旅/notion文稿/image/展会内部参观.jpg')] bg-cover bg-center bg-fixed"></div>
|
|
||||||
</div>
|
|
||||||
<div class="container mx-auto px-6 relative z-10" title="精彩瞬间展示区">
|
|
||||||
<h2 class="text-3xl md:text-4xl font-bold text-center text-white mb-12 animate-fadeInUp">精彩瞬间</h2>
|
|
||||||
<div class="grid md:grid-cols-3 gap-6 mb-8">
|
|
||||||
<div class="group relative overflow-hidden rounded-2xl shadow-2xl animate-fadeInUp animation-delay-200">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/展会内部参观.jpg" alt="展会内部" class="w-full h-64 object-cover transform transition-transform duration-700 group-hover:scale-110">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-6 text-white transform translate-y-20 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h3 class="text-xl font-bold mb-2">展馆内部参观</h3>
|
|
||||||
<p class="text-sm">宽敞明亮的展示空间,科技感十足</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="group relative overflow-hidden rounded-2xl shadow-2xl animate-fadeInUp animation-delay-400">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/签到.jpg" alt="签到处" class="w-full h-64 object-cover transform transition-transform duration-700 group-hover:scale-110">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-6 text-white transform translate-y-20 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h3 class="text-xl font-bold mb-2">智能签到系统</h3>
|
|
||||||
<p class="text-sm">快速便捷的入场体验</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="group relative overflow-hidden rounded-2xl shadow-2xl animate-fadeInUp animation-delay-600">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/3.小米汽车.jpg" alt="展品展示" class="w-full h-64 object-cover transform transition-transform duration-700 group-hover:scale-110">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-6 text-white transform translate-y-20 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h3 class="text-xl font-bold mb-2">明星展品</h3>
|
|
||||||
<p class="text-sm">最新款新能源汽车亮相</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 更多图片展示 -->
|
|
||||||
<div class="grid md:grid-cols-4 gap-4">
|
|
||||||
<div class="group relative overflow-hidden rounded-xl shadow-xl animate-fadeInUp animation-delay-800">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/Whisk_03282ab7e5.jpg" alt="展品1" class="w-full h-48 object-cover transform transition-all duration-500 group-hover:scale-110 group-hover:rotate-1">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-purple-600/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-4 text-white transform translate-y-10 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h4 class="text-sm font-bold">智能驾驶展示</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="group relative overflow-hidden rounded-xl shadow-xl animate-fadeInUp animation-delay-900">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/Whisk_15f65339bb.jpg" alt="展品2" class="w-full h-48 object-cover transform transition-all duration-500 group-hover:scale-110 group-hover:rotate-1">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-indigo-600/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-4 text-white transform translate-y-10 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h4 class="text-sm font-bold">充电技术革新</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="group relative overflow-hidden rounded-xl shadow-xl animate-fadeInUp animation-delay-1000">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/Whisk_192cdc54bc.jpg" alt="展品3" class="w-full h-48 object-cover transform transition-all duration-500 group-hover:scale-110 group-hover:rotate-1">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-blue-600/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-4 text-white transform translate-y-10 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h4 class="text-sm font-bold">电池技术展览</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="group relative overflow-hidden rounded-xl shadow-xl animate-fadeInUp animation-delay-1100">
|
|
||||||
<img src="../data/订单班文档资料/文旅/notion文稿/image/Whisk_1c05424f7f.jpg" alt="展品4" class="w-full h-48 object-cover transform transition-all duration-500 group-hover:scale-110 group-hover:rotate-1">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-cyan-600/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
|
|
||||||
<div class="p-4 text-white transform translate-y-10 group-hover:translate-y-0 transition-transform duration-300">
|
|
||||||
<h4 class="text-sm font-bold">智慧交通系统</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="bg-gradient-to-b from-gray-900 to-black text-white py-16 relative overflow-hidden">
|
|
||||||
<!-- 背景装饰 -->
|
|
||||||
<div class="absolute inset-0 opacity-10">
|
|
||||||
<div class="absolute bottom-0 left-0 w-96 h-96 bg-purple-500 rounded-full filter blur-3xl"></div>
|
|
||||||
<div class="absolute top-0 right-0 w-96 h-96 bg-blue-500 rounded-full filter blur-3xl"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mx-auto px-6 relative z-10" title="页脚信息区">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
|
|
||||||
<div class="animate-fadeInUp">
|
|
||||||
<div class="flex items-center mb-4">
|
|
||||||
<i class="fas fa-car-side text-2xl text-purple-400 mr-2"></i>
|
|
||||||
<h3 class="text-lg font-semibold">关于展会</h3>
|
|
||||||
</div>
|
|
||||||
<p class="text-gray-400 text-sm leading-relaxed">
|
|
||||||
长三角地区最具影响力的新能源汽车与智能交通产业盛会,汇聚全球顶尖企业与技术
|
|
||||||
</p>
|
|
||||||
<div class="mt-4 flex space-x-3">
|
|
||||||
<a href="#" class="w-8 h-8 bg-gray-800 rounded-full flex items-center justify-center hover:bg-purple-600 transition">
|
|
||||||
<i class="fab fa-weixin text-sm"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="w-8 h-8 bg-gray-800 rounded-full flex items-center justify-center hover:bg-blue-600 transition">
|
|
||||||
<i class="fab fa-weibo text-sm"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="w-8 h-8 bg-gray-800 rounded-full flex items-center justify-center hover:bg-red-600 transition">
|
|
||||||
<i class="fab fa-linkedin text-sm"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="animate-fadeInUp animation-delay-200">
|
|
||||||
<h3 class="text-lg font-semibold mb-4">
|
|
||||||
<i class="fas fa-link text-purple-400 mr-2"></i>快速链接
|
|
||||||
</h3>
|
|
||||||
<ul class="space-y-2 text-sm text-gray-400">
|
|
||||||
<li><a href="pages/overview.html" class="hover:text-purple-400 transition">
|
|
||||||
<i class="fas fa-chevron-right text-xs mr-1"></i>策划概述
|
|
||||||
</a></li>
|
|
||||||
<li><a href="pages/exhibition.html" class="hover:text-purple-400 transition">
|
|
||||||
<i class="fas fa-chevron-right text-xs mr-1"></i>展会介绍
|
|
||||||
</a></li>
|
|
||||||
<li><a href="pages/marketing.html" class="hover:text-purple-400 transition">
|
|
||||||
<i class="fas fa-chevron-right text-xs mr-1"></i>营销方案
|
|
||||||
</a></li>
|
|
||||||
<li><a href="pages/operation.html" class="hover:text-purple-400 transition">
|
|
||||||
<i class="fas fa-chevron-right text-xs mr-1"></i>现场运营
|
|
||||||
</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="animate-fadeInUp animation-delay-400">
|
|
||||||
<h3 class="text-lg font-semibold mb-4">
|
|
||||||
<i class="fas fa-phone-alt text-purple-400 mr-2"></i>联系方式
|
|
||||||
</h3>
|
|
||||||
<ul class="space-y-2 text-sm text-gray-400">
|
|
||||||
<li><i class="fas fa-map-marker-alt text-purple-400 mr-2"></i>上海市青浦区崧泽大道333号</li>
|
|
||||||
<li><i class="fas fa-phone text-purple-400 mr-2"></i>021-12345678</li>
|
|
||||||
<li><i class="fas fa-envelope text-purple-400 mr-2"></i>info@greenmobility2024.com</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="animate-fadeInUp animation-delay-600">
|
|
||||||
<h3 class="text-lg font-semibold mb-4">
|
|
||||||
<i class="fas fa-qrcode text-purple-400 mr-2"></i>关注我们
|
|
||||||
</h3>
|
|
||||||
<div class="flex space-x-4">
|
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700">
|
|
||||||
<span>微信</span>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="w-10 h-10 bg-gray-800 rounded-full flex items-center justify-center hover:bg-gray-700">
|
|
||||||
<span>微博</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="border-t border-gray-800 mt-8 pt-8 text-center text-sm text-gray-400">
|
|
||||||
<p>© 2024 长三角国际新能源汽车与智能交通产业博览会. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="js/nav-component.js"></script>
|
|
||||||
<script src="js/back-to-top.js"></script>
|
|
||||||
<script src="js/main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
// 返回顶部按钮组件
|
|
||||||
(function() {
|
|
||||||
// 创建返回顶部按钮HTML
|
|
||||||
function createBackToTopButton() {
|
|
||||||
const button = document.createElement('div');
|
|
||||||
button.id = 'back-to-top';
|
|
||||||
button.className = 'fixed bottom-8 right-8 z-40 opacity-0 pointer-events-none transition-all duration-300';
|
|
||||||
button.innerHTML = `
|
|
||||||
<button class="back-to-top-btn group relative w-12 h-12 bg-gradient-to-br from-emerald-400 to-blue-500 rounded-full shadow-lg hover:shadow-xl transform hover:scale-110 transition-all duration-300">
|
|
||||||
<span class="absolute inset-0 rounded-full bg-white opacity-0 group-hover:opacity-10 transition-opacity duration-300"></span>
|
|
||||||
<svg class="w-6 h-6 text-white absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
|
||||||
fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"></path>
|
|
||||||
</svg>
|
|
||||||
<span class="absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-300 whitespace-nowrap">
|
|
||||||
返回顶部
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
`;
|
|
||||||
document.body.appendChild(button);
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
function addStyles() {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
#back-to-top.show {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: auto;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#back-to-top:not(.show) {
|
|
||||||
transform: translateY(100px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
|
||||||
transition: left 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn:hover::before {
|
|
||||||
left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn svg {
|
|
||||||
animation: float 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float {
|
|
||||||
0%, 100% {
|
|
||||||
transform: translateX(-50%) translateY(-50%);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: translateX(-50%) translateY(calc(-50% - 3px));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端适配 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
#back-to-top {
|
|
||||||
bottom: 1.5rem;
|
|
||||||
right: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn {
|
|
||||||
width: 2.5rem;
|
|
||||||
height: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-top-btn svg {
|
|
||||||
width: 1.25rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 平滑滚动行为 */
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 防止按钮与其他元素冲突 */
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
#back-to-top {
|
|
||||||
bottom: 5rem; /* 避免与移动端菜单按钮重叠 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动到顶部功能
|
|
||||||
function scrollToTop() {
|
|
||||||
// 使用 smooth 滚动
|
|
||||||
window.scrollTo({
|
|
||||||
top: 0,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 可选:添加动画反馈
|
|
||||||
const button = document.querySelector('.back-to-top-btn');
|
|
||||||
if (button) {
|
|
||||||
button.style.transform = 'scale(0.9)';
|
|
||||||
setTimeout(() => {
|
|
||||||
button.style.transform = '';
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 控制按钮显示/隐藏
|
|
||||||
function handleScroll() {
|
|
||||||
const button = document.getElementById('back-to-top');
|
|
||||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
const windowHeight = window.innerHeight;
|
|
||||||
|
|
||||||
// 当滚动超过一屏高度时显示按钮
|
|
||||||
if (scrollTop > windowHeight * 0.5) {
|
|
||||||
button.classList.add('show');
|
|
||||||
} else {
|
|
||||||
button.classList.remove('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 可选:根据滚动位置调整按钮透明度
|
|
||||||
if (scrollTop > windowHeight) {
|
|
||||||
const maxScroll = document.documentElement.scrollHeight - windowHeight;
|
|
||||||
const scrollProgress = Math.min(scrollTop / maxScroll, 1);
|
|
||||||
const opacity = 0.5 + scrollProgress * 0.5; // 从50%到100%透明度
|
|
||||||
button.style.opacity = button.classList.contains('show') ? opacity : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
function init() {
|
|
||||||
// 添加样式
|
|
||||||
addStyles();
|
|
||||||
|
|
||||||
// 创建按钮
|
|
||||||
const button = createBackToTopButton();
|
|
||||||
|
|
||||||
// 添加点击事件
|
|
||||||
button.addEventListener('click', scrollToTop);
|
|
||||||
|
|
||||||
// 添加滚动监听(使用节流)
|
|
||||||
let scrollTimer;
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (scrollTimer) {
|
|
||||||
clearTimeout(scrollTimer);
|
|
||||||
}
|
|
||||||
scrollTimer = setTimeout(handleScroll, 50);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始检查
|
|
||||||
handleScroll();
|
|
||||||
|
|
||||||
// 键盘快捷键支持(按 'T' 键返回顶部)
|
|
||||||
document.addEventListener('keydown', (e) => {
|
|
||||||
// 排除输入框等元素
|
|
||||||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按 T 键或 Home 键返回顶部
|
|
||||||
if (e.key === 't' || e.key === 'T' || e.key === 'Home') {
|
|
||||||
e.preventDefault();
|
|
||||||
scrollToTop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM加载完成后初始化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
|
||||||
} else {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
// 错误处理和兼容性脚本
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// 全局错误处理
|
|
||||||
window.addEventListener('error', function(event) {
|
|
||||||
console.error('Global error:', {
|
|
||||||
message: event.message,
|
|
||||||
filename: event.filename,
|
|
||||||
lineno: event.lineno,
|
|
||||||
colno: event.colno,
|
|
||||||
error: event.error
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送错误到控制台(便于调试)
|
|
||||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|
||||||
console.group('Error Details:');
|
|
||||||
console.log('Message:', event.message);
|
|
||||||
console.log('File:', event.filename);
|
|
||||||
console.log('Line:', event.lineno + ':' + event.colno);
|
|
||||||
if (event.error && event.error.stack) {
|
|
||||||
console.log('Stack:', event.error.stack);
|
|
||||||
}
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true; // 阻止默认错误处理
|
|
||||||
});
|
|
||||||
|
|
||||||
// Promise 错误处理
|
|
||||||
window.addEventListener('unhandledrejection', function(event) {
|
|
||||||
console.error('Unhandled promise rejection:', event.reason);
|
|
||||||
|
|
||||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|
||||||
console.group('Promise Rejection:');
|
|
||||||
console.log('Reason:', event.reason);
|
|
||||||
if (event.reason && event.reason.stack) {
|
|
||||||
console.log('Stack:', event.reason.stack);
|
|
||||||
}
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault(); // 阻止默认处理
|
|
||||||
});
|
|
||||||
|
|
||||||
// DOM 查询安全包装
|
|
||||||
function safeQuerySelector(selector) {
|
|
||||||
try {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Invalid selector:', selector, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function safeQuerySelectorAll(selector) {
|
|
||||||
try {
|
|
||||||
return document.querySelectorAll(selector);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Invalid selector:', selector, e);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安全的getElementById
|
|
||||||
function safeGetElementById(id) {
|
|
||||||
try {
|
|
||||||
return document.getElementById(id);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Invalid element ID:', id, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复常见的兼容性问题
|
|
||||||
function fixCompatibilityIssues() {
|
|
||||||
// 修复classList不支持的情况(简化版本以避免Illegal invocation)
|
|
||||||
try {
|
|
||||||
// 安全检测classList支持
|
|
||||||
var testElement = document.createElement('div');
|
|
||||||
if (!testElement.classList) {
|
|
||||||
// 简单的classList polyfill
|
|
||||||
window.ClassListPolyfill = {
|
|
||||||
addClass: function(element, className) {
|
|
||||||
if (element && className) {
|
|
||||||
var classes = element.className ? element.className.split(' ') : [];
|
|
||||||
if (classes.indexOf(className) === -1) {
|
|
||||||
classes.push(className);
|
|
||||||
element.className = classes.join(' ').trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeClass: function(element, className) {
|
|
||||||
if (element && className) {
|
|
||||||
var classes = element.className ? element.className.split(' ') : [];
|
|
||||||
var index = classes.indexOf(className);
|
|
||||||
if (index !== -1) {
|
|
||||||
classes.splice(index, 1);
|
|
||||||
element.className = classes.join(' ').trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasClass: function(element, className) {
|
|
||||||
if (!element || !className) return false;
|
|
||||||
var classes = element.className ? element.className.split(' ') : [];
|
|
||||||
return classes.indexOf(className) !== -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// 如果检测失败,忽略错误
|
|
||||||
console.warn('classList detection failed:', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复addEventListener不支持的情况
|
|
||||||
if (!Element.prototype.addEventListener && Element.prototype.attachEvent) {
|
|
||||||
Element.prototype.addEventListener = function(event, listener) {
|
|
||||||
this.attachEvent('on' + event, listener);
|
|
||||||
};
|
|
||||||
Element.prototype.removeEventListener = function(event, listener) {
|
|
||||||
this.detachEvent('on' + event, listener);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复Array.from不支持的情况
|
|
||||||
if (!Array.from) {
|
|
||||||
Array.from = function(arrayLike) {
|
|
||||||
var result = [];
|
|
||||||
for (var i = 0; i < arrayLike.length; i++) {
|
|
||||||
result.push(arrayLike[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复forEach不支持的情况
|
|
||||||
if (!NodeList.prototype.forEach) {
|
|
||||||
NodeList.prototype.forEach = function(callback, thisArg) {
|
|
||||||
for (var i = 0; i < this.length; i++) {
|
|
||||||
callback.call(thisArg, this[i], i, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测浏览器支持情况
|
|
||||||
function detectBrowserSupport() {
|
|
||||||
const features = {
|
|
||||||
es6: {
|
|
||||||
arrow: false,
|
|
||||||
const: false,
|
|
||||||
let: false,
|
|
||||||
template: false,
|
|
||||||
destructuring: false
|
|
||||||
},
|
|
||||||
dom: {
|
|
||||||
classList: (function() {
|
|
||||||
try {
|
|
||||||
var testElement = document.createElement('div');
|
|
||||||
return !!testElement.classList;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})(),
|
|
||||||
querySelector: !!document.querySelector,
|
|
||||||
addEventListener: !!window.addEventListener
|
|
||||||
},
|
|
||||||
css: {
|
|
||||||
grid: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'grid'),
|
|
||||||
flexbox: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'flex'),
|
|
||||||
transform: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('transform', 'translateX(0)')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 测试ES6功能
|
|
||||||
try {
|
|
||||||
eval('const x = 1');
|
|
||||||
features.es6.const = true;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
eval('let x = 1');
|
|
||||||
features.es6.let = true;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
eval('`template`');
|
|
||||||
features.es6.template = true;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
eval('() => {}');
|
|
||||||
features.es6.arrow = true;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|
||||||
console.group('Browser Support:');
|
|
||||||
console.table(features);
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
return features;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复具体的错误
|
|
||||||
function fixSpecificErrors() {
|
|
||||||
// 确保所有必要的元素存在
|
|
||||||
const requiredElements = [
|
|
||||||
'navbar',
|
|
||||||
'mobile-menu-button',
|
|
||||||
'mobile-menu',
|
|
||||||
'mobile-menu-overlay',
|
|
||||||
'close-menu'
|
|
||||||
];
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
requiredElements.forEach(function(id) {
|
|
||||||
const element = document.getElementById(id);
|
|
||||||
if (!element) {
|
|
||||||
console.warn('Missing required element:', id);
|
|
||||||
|
|
||||||
// 尝试创建缺失的元素(某些情况下)
|
|
||||||
if (id === 'mobile-menu-overlay' && !document.getElementById(id)) {
|
|
||||||
const overlay = document.createElement('div');
|
|
||||||
overlay.id = id;
|
|
||||||
overlay.className = 'mobile-menu-overlay hidden';
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
console.log('Created missing overlay element');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安全的脚本加载
|
|
||||||
function safeLoadScript(src, callback) {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.src = src;
|
|
||||||
script.onload = function() {
|
|
||||||
if (callback) callback();
|
|
||||||
};
|
|
||||||
script.onerror = function() {
|
|
||||||
console.error('Failed to load script:', src);
|
|
||||||
};
|
|
||||||
document.head.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化错误处理
|
|
||||||
function init() {
|
|
||||||
// 修复兼容性问题
|
|
||||||
fixCompatibilityIssues();
|
|
||||||
|
|
||||||
// 检测浏览器支持
|
|
||||||
detectBrowserSupport();
|
|
||||||
|
|
||||||
// 修复具体错误
|
|
||||||
fixSpecificErrors();
|
|
||||||
|
|
||||||
// 为调试添加全局工具
|
|
||||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|
||||||
window.debugTools = {
|
|
||||||
safeQuerySelector: safeQuerySelector,
|
|
||||||
safeQuerySelectorAll: safeQuerySelectorAll,
|
|
||||||
safeGetElementById: safeGetElementById,
|
|
||||||
fixCompatibilityIssues: fixCompatibilityIssues,
|
|
||||||
detectBrowserSupport: detectBrowserSupport
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Error handler initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 在DOM加载后初始化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
|
||||||
} else {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,713 +0,0 @@
|
|||||||
// 2024长三角国际新能源汽车与智能交通产业博览会 - 交互脚本
|
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// 隐藏页面加载器
|
|
||||||
hidePageLoader();
|
|
||||||
|
|
||||||
initNavbar();
|
|
||||||
initAnimations();
|
|
||||||
initCounters();
|
|
||||||
initScrollEffects();
|
|
||||||
initRippleEffect();
|
|
||||||
initLazyLoading();
|
|
||||||
initFormValidation();
|
|
||||||
initCharts();
|
|
||||||
initTimeline();
|
|
||||||
initInteractiveElements();
|
|
||||||
handleImageErrors();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 隐藏页面加载器(兼容新的加载器)
|
|
||||||
function hidePageLoader() {
|
|
||||||
const loader = document.getElementById('pageLoader') || document.getElementById('page-loader');
|
|
||||||
if (loader) {
|
|
||||||
// 如果是新的加载器,使用其自带的隐藏方法
|
|
||||||
if (loader.id === 'page-loader' && window.PageLoader) {
|
|
||||||
window.PageLoader.hideLoader();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 旧的加载器逻辑
|
|
||||||
loader.style.opacity = '0';
|
|
||||||
loader.style.transition = 'opacity 0.5s ease-out';
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
loader.style.display = 'none';
|
|
||||||
document.body.style.overflow = 'auto';
|
|
||||||
document.body.classList.remove('loading');
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
// 如果没有找到加载器,也要确保恢复滚动
|
|
||||||
document.body.style.overflow = 'auto';
|
|
||||||
document.body.classList.remove('loading');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果页面加载超过3秒,强制隐藏加载器
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
setTimeout(() => {
|
|
||||||
hidePageLoader();
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 导航栏交互
|
|
||||||
function initNavbar() {
|
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
const navLinks = document.querySelectorAll('.nav-link');
|
|
||||||
const mobileMenuBtn = document.querySelector('.mobile-menu-btn');
|
|
||||||
const mobileMenu = document.querySelector('.mobile-menu');
|
|
||||||
|
|
||||||
// 滚动时改变导航栏样式
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (window.scrollY > 100) {
|
|
||||||
navbar?.classList.add('scrolled');
|
|
||||||
} else {
|
|
||||||
navbar?.classList.remove('scrolled');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 高亮当前页面链接
|
|
||||||
const currentPath = window.location.pathname;
|
|
||||||
navLinks.forEach(link => {
|
|
||||||
if (link.getAttribute('href') === currentPath) {
|
|
||||||
link.classList.add('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 移动端菜单切换
|
|
||||||
mobileMenuBtn?.addEventListener('click', () => {
|
|
||||||
mobileMenu?.classList.toggle('open');
|
|
||||||
mobileMenuBtn.classList.toggle('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 平滑滚动到锚点
|
|
||||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
||||||
anchor.addEventListener('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const target = document.querySelector(this.getAttribute('href'));
|
|
||||||
if (target) {
|
|
||||||
target.scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'start'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动画初始化
|
|
||||||
function initAnimations() {
|
|
||||||
// Intersection Observer for fade-in animations
|
|
||||||
const observerOptions = {
|
|
||||||
threshold: 0.1,
|
|
||||||
rootMargin: '0px 0px -50px 0px'
|
|
||||||
};
|
|
||||||
|
|
||||||
const observer = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
entry.target.classList.add('animate-in');
|
|
||||||
observer.unobserve(entry.target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, observerOptions);
|
|
||||||
|
|
||||||
// 观察所有需要动画的元素
|
|
||||||
document.querySelectorAll('.fade-in, .slide-in-left, .slide-in-right, .grid-item').forEach(el => {
|
|
||||||
observer.observe(el);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字计数器动画
|
|
||||||
function initCounters() {
|
|
||||||
const counters = document.querySelectorAll('.counter');
|
|
||||||
const speed = 200; // 动画速度
|
|
||||||
|
|
||||||
const countUp = (counter) => {
|
|
||||||
const target = +counter.getAttribute('data-target');
|
|
||||||
const increment = target / speed;
|
|
||||||
|
|
||||||
const updateCount = () => {
|
|
||||||
const count = +counter.innerText.replace(/[^0-9]/g, '');
|
|
||||||
|
|
||||||
if (count < target) {
|
|
||||||
counter.innerText = Math.ceil(count + increment).toLocaleString();
|
|
||||||
setTimeout(updateCount, 1);
|
|
||||||
} else {
|
|
||||||
counter.innerText = target.toLocaleString();
|
|
||||||
|
|
||||||
// 添加单位
|
|
||||||
const unit = counter.getAttribute('data-unit');
|
|
||||||
if (unit) {
|
|
||||||
counter.innerText += unit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateCount();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 使用 Intersection Observer 触发计数
|
|
||||||
const counterObserver = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
countUp(entry.target);
|
|
||||||
counterObserver.unobserve(entry.target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, { threshold: 0.5 });
|
|
||||||
|
|
||||||
counters.forEach(counter => {
|
|
||||||
counter.innerText = '0';
|
|
||||||
counterObserver.observe(counter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动效果
|
|
||||||
function initScrollEffects() {
|
|
||||||
let lastScrollTop = 0;
|
|
||||||
const header = document.querySelector('header');
|
|
||||||
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
// 隐藏/显示导航栏
|
|
||||||
if (scrollTop > lastScrollTop && scrollTop > 300) {
|
|
||||||
header?.classList.add('hide');
|
|
||||||
} else {
|
|
||||||
header?.classList.remove('hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
|
|
||||||
|
|
||||||
// 视差效果
|
|
||||||
const parallaxElements = document.querySelectorAll('.parallax');
|
|
||||||
parallaxElements.forEach(el => {
|
|
||||||
const speed = el.getAttribute('data-speed') || 0.5;
|
|
||||||
const yPos = -(scrollTop * speed);
|
|
||||||
el.style.transform = `translateY(${yPos}px)`;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 进度条
|
|
||||||
const progressBar = document.querySelector('.progress-bar');
|
|
||||||
if (progressBar) {
|
|
||||||
const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
|
|
||||||
const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
|
|
||||||
const scrolled = (winScroll / height) * 100;
|
|
||||||
progressBar.style.width = scrolled + '%';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 波纹效果
|
|
||||||
function initRippleEffect() {
|
|
||||||
document.querySelectorAll('.btn, .card').forEach(element => {
|
|
||||||
element.addEventListener('click', function(e) {
|
|
||||||
const ripple = document.createElement('span');
|
|
||||||
ripple.classList.add('ripple');
|
|
||||||
|
|
||||||
const rect = this.getBoundingClientRect();
|
|
||||||
const size = Math.max(rect.width, rect.height);
|
|
||||||
const x = e.clientX - rect.left - size / 2;
|
|
||||||
const y = e.clientY - rect.top - size / 2;
|
|
||||||
|
|
||||||
ripple.style.width = ripple.style.height = size + 'px';
|
|
||||||
ripple.style.left = x + 'px';
|
|
||||||
ripple.style.top = y + 'px';
|
|
||||||
|
|
||||||
this.appendChild(ripple);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
ripple.remove();
|
|
||||||
}, 600);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 懒加载
|
|
||||||
function initLazyLoading() {
|
|
||||||
const images = document.querySelectorAll('img[data-src]');
|
|
||||||
|
|
||||||
const imageObserver = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
const img = entry.target;
|
|
||||||
img.src = img.dataset.src;
|
|
||||||
img.removeAttribute('data-src');
|
|
||||||
imageObserver.unobserve(img);
|
|
||||||
|
|
||||||
// 添加加载完成动画
|
|
||||||
img.addEventListener('load', () => {
|
|
||||||
img.classList.add('loaded');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, {
|
|
||||||
rootMargin: '50px 0px'
|
|
||||||
});
|
|
||||||
|
|
||||||
images.forEach(img => imageObserver.observe(img));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表单验证
|
|
||||||
function initFormValidation() {
|
|
||||||
const forms = document.querySelectorAll('form');
|
|
||||||
|
|
||||||
forms.forEach(form => {
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
let isValid = true;
|
|
||||||
const inputs = form.querySelectorAll('input[required], textarea[required]');
|
|
||||||
|
|
||||||
inputs.forEach(input => {
|
|
||||||
if (!input.value.trim()) {
|
|
||||||
isValid = false;
|
|
||||||
input.classList.add('error');
|
|
||||||
showError(input, '此字段为必填项');
|
|
||||||
} else {
|
|
||||||
input.classList.remove('error');
|
|
||||||
clearError(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 邮箱验证
|
|
||||||
if (input.type === 'email' && input.value) {
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(input.value)) {
|
|
||||||
isValid = false;
|
|
||||||
input.classList.add('error');
|
|
||||||
showError(input, '请输入有效的邮箱地址');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 电话验证
|
|
||||||
if (input.type === 'tel' && input.value) {
|
|
||||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
|
||||||
if (!phoneRegex.test(input.value)) {
|
|
||||||
isValid = false;
|
|
||||||
input.classList.add('error');
|
|
||||||
showError(input, '请输入有效的手机号码');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isValid) {
|
|
||||||
// 显示成功消息
|
|
||||||
showSuccess('表单提交成功!');
|
|
||||||
form.reset();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 实时验证
|
|
||||||
form.querySelectorAll('input, textarea').forEach(input => {
|
|
||||||
input.addEventListener('blur', function() {
|
|
||||||
validateInput(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addEventListener('input', function() {
|
|
||||||
if (this.classList.contains('error')) {
|
|
||||||
validateInput(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示错误信息
|
|
||||||
function showError(input, message) {
|
|
||||||
const errorEl = input.nextElementSibling;
|
|
||||||
if (errorEl && errorEl.classList.contains('error-message')) {
|
|
||||||
errorEl.textContent = message;
|
|
||||||
} else {
|
|
||||||
const error = document.createElement('span');
|
|
||||||
error.classList.add('error-message');
|
|
||||||
error.textContent = message;
|
|
||||||
input.parentNode.insertBefore(error, input.nextSibling);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除错误信息
|
|
||||||
function clearError(input) {
|
|
||||||
const errorEl = input.nextElementSibling;
|
|
||||||
if (errorEl && errorEl.classList.contains('error-message')) {
|
|
||||||
errorEl.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证输入
|
|
||||||
function validateInput(input) {
|
|
||||||
if (input.hasAttribute('required') && !input.value.trim()) {
|
|
||||||
input.classList.add('error');
|
|
||||||
showError(input, '此字段为必填项');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.classList.remove('error');
|
|
||||||
clearError(input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示成功消息
|
|
||||||
function showSuccess(message) {
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.classList.add('toast', 'success');
|
|
||||||
toast.textContent = message;
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.classList.add('show');
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.classList.remove('show');
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.remove();
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化图表
|
|
||||||
function initCharts() {
|
|
||||||
// 预算分配饼图
|
|
||||||
const budgetChart = document.getElementById('budgetChart');
|
|
||||||
if (budgetChart) {
|
|
||||||
const data = [
|
|
||||||
{ label: '场地租赁', value: 35, color: '#10b981' },
|
|
||||||
{ label: '营销推广', value: 25, color: '#3b82f6' },
|
|
||||||
{ label: '运营服务', value: 20, color: '#8b5cf6' },
|
|
||||||
{ label: '人员成本', value: 15, color: '#f59e0b' },
|
|
||||||
{ label: '其他费用', value: 5, color: '#ef4444' }
|
|
||||||
];
|
|
||||||
|
|
||||||
drawPieChart(budgetChart, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参展商类别分布
|
|
||||||
const exhibitorChart = document.getElementById('exhibitorChart');
|
|
||||||
if (exhibitorChart) {
|
|
||||||
const data = [
|
|
||||||
{ label: '整车制造', value: 40 },
|
|
||||||
{ label: '零部件', value: 30 },
|
|
||||||
{ label: '充电设施', value: 15 },
|
|
||||||
{ label: '智能驾驶', value: 10 },
|
|
||||||
{ label: '其他', value: 5 }
|
|
||||||
];
|
|
||||||
|
|
||||||
drawBarChart(exhibitorChart, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制饼图
|
|
||||||
function drawPieChart(canvas, data) {
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const centerX = canvas.width / 2;
|
|
||||||
const centerY = canvas.height / 2;
|
|
||||||
const radius = Math.min(centerX, centerY) - 20;
|
|
||||||
|
|
||||||
let currentAngle = -Math.PI / 2;
|
|
||||||
const total = data.reduce((sum, item) => sum + item.value, 0);
|
|
||||||
|
|
||||||
data.forEach(item => {
|
|
||||||
const sliceAngle = (item.value / total) * 2 * Math.PI;
|
|
||||||
|
|
||||||
// 绘制扇形
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
|
|
||||||
ctx.lineTo(centerX, centerY);
|
|
||||||
ctx.fillStyle = item.color;
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
// 绘制标签
|
|
||||||
const labelX = centerX + Math.cos(currentAngle + sliceAngle / 2) * (radius * 0.7);
|
|
||||||
const labelY = centerY + Math.sin(currentAngle + sliceAngle / 2) * (radius * 0.7);
|
|
||||||
|
|
||||||
ctx.fillStyle = '#fff';
|
|
||||||
ctx.font = '14px sans-serif';
|
|
||||||
ctx.textAlign = 'center';
|
|
||||||
ctx.fillText(item.value + '%', labelX, labelY);
|
|
||||||
|
|
||||||
currentAngle += sliceAngle;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制柱状图
|
|
||||||
function drawBarChart(canvas, data) {
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const barWidth = canvas.width / (data.length * 2);
|
|
||||||
const maxValue = Math.max(...data.map(item => item.value));
|
|
||||||
const chartHeight = canvas.height - 40;
|
|
||||||
|
|
||||||
data.forEach((item, index) => {
|
|
||||||
const barHeight = (item.value / maxValue) * chartHeight;
|
|
||||||
const x = (index * 2 + 0.5) * barWidth;
|
|
||||||
const y = canvas.height - barHeight - 20;
|
|
||||||
|
|
||||||
// 绘制柱子
|
|
||||||
const gradient = ctx.createLinearGradient(x, y, x, y + barHeight);
|
|
||||||
gradient.addColorStop(0, '#10b981');
|
|
||||||
gradient.addColorStop(1, '#3b82f6');
|
|
||||||
|
|
||||||
ctx.fillStyle = gradient;
|
|
||||||
ctx.fillRect(x, y, barWidth, barHeight);
|
|
||||||
|
|
||||||
// 绘制数值
|
|
||||||
ctx.fillStyle = '#333';
|
|
||||||
ctx.font = '12px sans-serif';
|
|
||||||
ctx.textAlign = 'center';
|
|
||||||
ctx.fillText(item.value + '%', x + barWidth / 2, y - 5);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化时间线
|
|
||||||
function initTimeline() {
|
|
||||||
const timelineItems = document.querySelectorAll('.timeline-item');
|
|
||||||
|
|
||||||
const timelineObserver = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
entry.target.classList.add('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, { threshold: 0.5 });
|
|
||||||
|
|
||||||
timelineItems.forEach(item => {
|
|
||||||
timelineObserver.observe(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 交互元素初始化
|
|
||||||
function initInteractiveElements() {
|
|
||||||
// 标签页切换
|
|
||||||
const tabs = document.querySelectorAll('.tab');
|
|
||||||
const tabContents = document.querySelectorAll('.tab-content');
|
|
||||||
|
|
||||||
tabs.forEach(tab => {
|
|
||||||
tab.addEventListener('click', () => {
|
|
||||||
const target = tab.dataset.tab;
|
|
||||||
|
|
||||||
// 切换标签状态
|
|
||||||
tabs.forEach(t => t.classList.remove('active'));
|
|
||||||
tab.classList.add('active');
|
|
||||||
|
|
||||||
// 切换内容显示
|
|
||||||
tabContents.forEach(content => {
|
|
||||||
if (content.id === target) {
|
|
||||||
content.classList.add('active');
|
|
||||||
content.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
content.classList.remove('active');
|
|
||||||
content.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 手风琴效果
|
|
||||||
const accordionHeaders = document.querySelectorAll('.accordion-header');
|
|
||||||
|
|
||||||
accordionHeaders.forEach(header => {
|
|
||||||
header.addEventListener('click', () => {
|
|
||||||
const content = header.nextElementSibling;
|
|
||||||
const isOpen = header.classList.contains('active');
|
|
||||||
|
|
||||||
// 关闭其他项
|
|
||||||
accordionHeaders.forEach(h => {
|
|
||||||
h.classList.remove('active');
|
|
||||||
h.nextElementSibling.style.maxHeight = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 切换当前项
|
|
||||||
if (!isOpen) {
|
|
||||||
header.classList.add('active');
|
|
||||||
content.style.maxHeight = content.scrollHeight + 'px';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 模态框
|
|
||||||
const modalTriggers = document.querySelectorAll('[data-modal]');
|
|
||||||
const modals = document.querySelectorAll('.modal');
|
|
||||||
const modalCloses = document.querySelectorAll('.modal-close');
|
|
||||||
|
|
||||||
modalTriggers.forEach(trigger => {
|
|
||||||
trigger.addEventListener('click', () => {
|
|
||||||
const modalId = trigger.dataset.modal;
|
|
||||||
const modal = document.getElementById(modalId);
|
|
||||||
if (modal) {
|
|
||||||
modal.classList.add('open');
|
|
||||||
document.body.style.overflow = 'hidden';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modalCloses.forEach(close => {
|
|
||||||
close.addEventListener('click', () => {
|
|
||||||
const modal = close.closest('.modal');
|
|
||||||
modal.classList.remove('open');
|
|
||||||
document.body.style.overflow = '';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 点击背景关闭模态框
|
|
||||||
modals.forEach(modal => {
|
|
||||||
modal.addEventListener('click', (e) => {
|
|
||||||
if (e.target === modal) {
|
|
||||||
modal.classList.remove('open');
|
|
||||||
document.body.style.overflow = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 工具提示
|
|
||||||
const tooltips = document.querySelectorAll('[data-tooltip]');
|
|
||||||
|
|
||||||
tooltips.forEach(element => {
|
|
||||||
const tooltip = document.createElement('div');
|
|
||||||
tooltip.classList.add('tooltip');
|
|
||||||
tooltip.textContent = element.dataset.tooltip;
|
|
||||||
|
|
||||||
element.addEventListener('mouseenter', () => {
|
|
||||||
document.body.appendChild(tooltip);
|
|
||||||
const rect = element.getBoundingClientRect();
|
|
||||||
tooltip.style.left = rect.left + rect.width / 2 - tooltip.offsetWidth / 2 + 'px';
|
|
||||||
tooltip.style.top = rect.top - tooltip.offsetHeight - 10 + 'px';
|
|
||||||
tooltip.classList.add('show');
|
|
||||||
});
|
|
||||||
|
|
||||||
element.addEventListener('mouseleave', () => {
|
|
||||||
tooltip.classList.remove('show');
|
|
||||||
setTimeout(() => {
|
|
||||||
tooltip.remove();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 复制到剪贴板
|
|
||||||
function copyToClipboard(text) {
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
textarea.value = text;
|
|
||||||
document.body.appendChild(textarea);
|
|
||||||
textarea.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(textarea);
|
|
||||||
showSuccess('已复制到剪贴板');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分享功能
|
|
||||||
function shareContent(platform) {
|
|
||||||
const url = encodeURIComponent(window.location.href);
|
|
||||||
const title = encodeURIComponent(document.title);
|
|
||||||
let shareUrl = '';
|
|
||||||
|
|
||||||
switch(platform) {
|
|
||||||
case 'wechat':
|
|
||||||
// 生成微信分享二维码
|
|
||||||
generateQRCode(window.location.href);
|
|
||||||
break;
|
|
||||||
case 'weibo':
|
|
||||||
shareUrl = `https://service.weibo.com/share/share.php?url=${url}&title=${title}`;
|
|
||||||
break;
|
|
||||||
case 'linkedin':
|
|
||||||
shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;
|
|
||||||
break;
|
|
||||||
case 'twitter':
|
|
||||||
shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shareUrl) {
|
|
||||||
window.open(shareUrl, '_blank', 'width=600,height=400');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成二维码
|
|
||||||
function generateQRCode(text) {
|
|
||||||
const modal = document.createElement('div');
|
|
||||||
modal.classList.add('qr-modal');
|
|
||||||
modal.innerHTML = `
|
|
||||||
<div class="qr-content">
|
|
||||||
<h3>微信扫码分享</h3>
|
|
||||||
<div id="qrcode"></div>
|
|
||||||
<button class="btn btn-secondary" onclick="this.parentElement.parentElement.remove()">关闭</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
document.body.appendChild(modal);
|
|
||||||
|
|
||||||
// 这里可以集成实际的二维码生成库
|
|
||||||
document.getElementById('qrcode').innerHTML = '二维码生成区域';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主题切换
|
|
||||||
function initThemeToggle() {
|
|
||||||
const themeToggle = document.getElementById('themeToggle');
|
|
||||||
const currentTheme = localStorage.getItem('theme') || 'light';
|
|
||||||
|
|
||||||
document.documentElement.setAttribute('data-theme', currentTheme);
|
|
||||||
|
|
||||||
themeToggle?.addEventListener('click', () => {
|
|
||||||
const theme = document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light';
|
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
|
||||||
localStorage.setItem('theme', theme);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出为 PDF
|
|
||||||
function exportToPDF() {
|
|
||||||
window.print();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 性能监控
|
|
||||||
function initPerformanceMonitoring() {
|
|
||||||
// 页面加载时间
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
|
|
||||||
console.log(`页面加载时间: ${loadTime}ms`);
|
|
||||||
|
|
||||||
// 发送到分析服务
|
|
||||||
if (window.gtag) {
|
|
||||||
gtag('event', 'page_load_time', {
|
|
||||||
value: loadTime,
|
|
||||||
page_path: window.location.pathname
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监控长任务
|
|
||||||
if ('PerformanceObserver' in window) {
|
|
||||||
const observer = new PerformanceObserver((list) => {
|
|
||||||
for (const entry of list.getEntries()) {
|
|
||||||
console.log('Long Task detected:', entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe({ entryTypes: ['longtask'] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理图片加载错误
|
|
||||||
function handleImageErrors() {
|
|
||||||
const images = document.querySelectorAll('img');
|
|
||||||
const defaultImage = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZTJlOGYwIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzk0YTNiOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuWbvueJh+WKoOi9veS4rTwvdGV4dD48L3N2Zz4=';
|
|
||||||
|
|
||||||
images.forEach(img => {
|
|
||||||
// 添加错误处理
|
|
||||||
img.addEventListener('error', function() {
|
|
||||||
console.warn('图片加载失败:', this.src);
|
|
||||||
// 设置默认占位图
|
|
||||||
this.src = defaultImage;
|
|
||||||
this.alt = '图片加载失败';
|
|
||||||
this.classList.add('image-error');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加加载成功处理
|
|
||||||
img.addEventListener('load', function() {
|
|
||||||
this.classList.add('image-loaded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化性能监控
|
|
||||||
initPerformanceMonitoring();
|
|
||||||
initThemeToggle();
|
|
||||||
@@ -1,516 +0,0 @@
|
|||||||
// 移动端优化组件
|
|
||||||
(function() {
|
|
||||||
let isMobile = false;
|
|
||||||
let isTablet = false;
|
|
||||||
let currentOrientation = 'portrait';
|
|
||||||
|
|
||||||
// 检测设备类型
|
|
||||||
function detectDevice() {
|
|
||||||
const userAgent = navigator.userAgent.toLowerCase();
|
|
||||||
const screenWidth = window.innerWidth;
|
|
||||||
const screenHeight = window.innerHeight;
|
|
||||||
|
|
||||||
// 检测是否为移动设备
|
|
||||||
isMobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent) || screenWidth <= 768;
|
|
||||||
isTablet = /ipad|android(?!.*mobile)|tablet/i.test(userAgent) || (screenWidth > 768 && screenWidth <= 1024);
|
|
||||||
|
|
||||||
// 检测屏幕方向
|
|
||||||
currentOrientation = screenWidth > screenHeight ? 'landscape' : 'portrait';
|
|
||||||
|
|
||||||
// 添加设备类到body(确保body存在)
|
|
||||||
if (document.body) {
|
|
||||||
document.body.classList.remove('mobile', 'tablet', 'desktop', 'portrait', 'landscape');
|
|
||||||
document.body.classList.add(
|
|
||||||
isMobile ? 'mobile' : isTablet ? 'tablet' : 'desktop',
|
|
||||||
currentOrientation
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { isMobile, isTablet, currentOrientation };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加移动端优化样式
|
|
||||||
function addMobileStyles() {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
/* 移动端基础优化 */
|
|
||||||
* {
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 允许文本选择 */
|
|
||||||
p, h1, h2, h3, h4, h5, h6, span, div, article, section {
|
|
||||||
-webkit-user-select: text;
|
|
||||||
-moz-user-select: text;
|
|
||||||
-ms-user-select: text;
|
|
||||||
user-select: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端滚动优化 */
|
|
||||||
html {
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端字体优化 */
|
|
||||||
body.mobile {
|
|
||||||
font-size: 16px; /* 防止iOS缩放 */
|
|
||||||
line-height: 1.6;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
-moz-text-size-adjust: 100%;
|
|
||||||
-ms-text-size-adjust: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端容器优化 */
|
|
||||||
.container {
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile .container {
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.tablet .container {
|
|
||||||
padding-left: 2rem;
|
|
||||||
padding-right: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端导航优化 */
|
|
||||||
body.mobile #navbar {
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile .nav-container {
|
|
||||||
padding: 0.75rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端按钮优化 */
|
|
||||||
body.mobile button,
|
|
||||||
body.mobile .btn {
|
|
||||||
min-height: 44px; /* iOS推荐的最小触摸目标 */
|
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端表单优化 */
|
|
||||||
body.mobile input,
|
|
||||||
body.mobile textarea,
|
|
||||||
body.mobile select {
|
|
||||||
min-height: 44px;
|
|
||||||
padding: 0.75rem;
|
|
||||||
font-size: 16px; /* 防止iOS缩放 */
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端卡片优化 */
|
|
||||||
body.mobile .card,
|
|
||||||
body.mobile .glass-card {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端文字优化 */
|
|
||||||
body.mobile h1 {
|
|
||||||
font-size: 2rem;
|
|
||||||
line-height: 1.2;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile h2 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
line-height: 1.3;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile h3 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: 1.4;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile p {
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端网格优化 */
|
|
||||||
body.mobile .grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile .grid-cols-2,
|
|
||||||
body.mobile .grid-cols-3,
|
|
||||||
body.mobile .grid-cols-4,
|
|
||||||
body.mobile .md\\:grid-cols-2,
|
|
||||||
body.mobile .md\\:grid-cols-3,
|
|
||||||
body.mobile .lg\\:grid-cols-3 {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 平板端网格优化 */
|
|
||||||
body.tablet .grid-cols-3,
|
|
||||||
body.tablet .lg\\:grid-cols-3 {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端间距优化 */
|
|
||||||
body.mobile .py-16 { padding-top: 3rem; padding-bottom: 3rem; }
|
|
||||||
body.mobile .py-12 { padding-top: 2rem; padding-bottom: 2rem; }
|
|
||||||
body.mobile .py-8 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
|
||||||
body.mobile .mb-12 { margin-bottom: 2rem; }
|
|
||||||
body.mobile .mb-8 { margin-bottom: 1.5rem; }
|
|
||||||
|
|
||||||
/* 移动端图片优化 */
|
|
||||||
body.mobile img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 横屏优化 */
|
|
||||||
body.mobile.landscape {
|
|
||||||
/* 横屏时减少垂直间距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile.landscape .py-16 {
|
|
||||||
padding-top: 2rem;
|
|
||||||
padding-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile.landscape h1 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端返回顶部按钮优化 */
|
|
||||||
body.mobile #back-to-top {
|
|
||||||
bottom: 1.5rem;
|
|
||||||
right: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile .back-to-top-btn {
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端页面加载器优化 */
|
|
||||||
body.mobile #page-loader .w-20 {
|
|
||||||
width: 4rem;
|
|
||||||
height: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile #page-loader h1 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile #page-loader .w-64 {
|
|
||||||
width: 16rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 防止页面缩放 */
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
html {
|
|
||||||
zoom: 1;
|
|
||||||
-ms-zoom: 1;
|
|
||||||
-webkit-zoom: 1;
|
|
||||||
-moz-zoom: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 触摸设备特定优化 */
|
|
||||||
@media (hover: none) and (pointer: coarse) {
|
|
||||||
/* 移除hover效果,使用active效果 */
|
|
||||||
.hover\\:scale-110:hover {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\\:scale-110:active {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\\:shadow-xl:hover {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\\:shadow-xl:active {
|
|
||||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 安全区域适配(iPhone X等带刘海屏的设备) */
|
|
||||||
@supports (padding: max(0px)) {
|
|
||||||
body.mobile {
|
|
||||||
padding-left: max(1rem, env(safe-area-inset-left));
|
|
||||||
padding-right: max(1rem, env(safe-area-inset-right));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile #navbar {
|
|
||||||
padding-left: max(1rem, env(safe-area-inset-left));
|
|
||||||
padding-right: max(1rem, env(safe-area-inset-right));
|
|
||||||
padding-top: max(0.75rem, env(safe-area-inset-top));
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile #back-to-top {
|
|
||||||
right: max(1.5rem, env(safe-area-inset-right));
|
|
||||||
bottom: max(1.5rem, env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优化图片加载
|
|
||||||
function optimizeImages() {
|
|
||||||
const images = document.querySelectorAll('img');
|
|
||||||
|
|
||||||
images.forEach(img => {
|
|
||||||
// 添加懒加载
|
|
||||||
if (!img.loading) {
|
|
||||||
img.loading = 'lazy';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加错误处理
|
|
||||||
img.addEventListener('error', function() {
|
|
||||||
this.style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
// 移动端图片优化
|
|
||||||
if (isMobile) {
|
|
||||||
// 移动端使用较小的图片
|
|
||||||
const src = img.src;
|
|
||||||
if (src && !src.includes('placeholder')) {
|
|
||||||
// 这里可以添加图片压缩逻辑
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优化触摸事件
|
|
||||||
function optimizeTouch() {
|
|
||||||
// 添加触摸反馈
|
|
||||||
document.addEventListener('touchstart', function(e) {
|
|
||||||
const target = e.target;
|
|
||||||
if (target.tagName === 'BUTTON' || target.classList.contains('btn') || target.tagName === 'A') {
|
|
||||||
target.style.opacity = '0.7';
|
|
||||||
}
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
document.addEventListener('touchend', function(e) {
|
|
||||||
const target = e.target;
|
|
||||||
if (target.tagName === 'BUTTON' || target.classList.contains('btn') || target.tagName === 'A') {
|
|
||||||
setTimeout(() => {
|
|
||||||
target.style.opacity = '';
|
|
||||||
}, 150);
|
|
||||||
}
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
// 防止双击缩放
|
|
||||||
let lastTouchEnd = 0;
|
|
||||||
document.addEventListener('touchend', function(event) {
|
|
||||||
const now = (new Date()).getTime();
|
|
||||||
if (now - lastTouchEnd <= 300) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
lastTouchEnd = now;
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理屏幕方向变化
|
|
||||||
function handleOrientationChange() {
|
|
||||||
// 延迟执行以确保尺寸更新
|
|
||||||
setTimeout(() => {
|
|
||||||
detectDevice();
|
|
||||||
|
|
||||||
// 重新计算布局
|
|
||||||
const event = new Event('resize');
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
|
|
||||||
// 滚动到顶部(防止方向变化后位置错乱)
|
|
||||||
if (window.scrollY > 100) {
|
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优化键盘弹出时的布局
|
|
||||||
function handleKeyboard() {
|
|
||||||
if (!isMobile) return;
|
|
||||||
|
|
||||||
const originalHeight = window.innerHeight;
|
|
||||||
let keyboardOpen = false;
|
|
||||||
|
|
||||||
window.addEventListener('resize', function() {
|
|
||||||
const currentHeight = window.innerHeight;
|
|
||||||
const heightDifference = originalHeight - currentHeight;
|
|
||||||
|
|
||||||
// 键盘弹出(高度减少超过150px)
|
|
||||||
if (heightDifference > 150 && !keyboardOpen) {
|
|
||||||
keyboardOpen = true;
|
|
||||||
document.body.classList.add('keyboard-open');
|
|
||||||
|
|
||||||
// 隐藏导航栏(为输入框腾出空间)
|
|
||||||
const navbar = document.getElementById('navbar');
|
|
||||||
if (navbar) {
|
|
||||||
navbar.style.transform = 'translateY(-100%)';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 隐藏返回顶部按钮
|
|
||||||
const backToTop = document.getElementById('back-to-top');
|
|
||||||
if (backToTop) {
|
|
||||||
backToTop.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 键盘收起
|
|
||||||
else if (heightDifference <= 150 && keyboardOpen) {
|
|
||||||
keyboardOpen = false;
|
|
||||||
document.body.classList.remove('keyboard-open');
|
|
||||||
|
|
||||||
// 恢复导航栏
|
|
||||||
const navbar = document.getElementById('navbar');
|
|
||||||
if (navbar) {
|
|
||||||
navbar.style.transform = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 恢复返回顶部按钮
|
|
||||||
const backToTop = document.getElementById('back-to-top');
|
|
||||||
if (backToTop) {
|
|
||||||
backToTop.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 性能优化
|
|
||||||
function optimizePerformance() {
|
|
||||||
// 使用 Intersection Observer 优化动画
|
|
||||||
if ('IntersectionObserver' in window) {
|
|
||||||
const observer = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
entry.target.classList.add('animate-visible');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, {
|
|
||||||
threshold: 0.1,
|
|
||||||
rootMargin: '50px'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 观察所有动画元素
|
|
||||||
document.querySelectorAll('[class*="animate-"]').forEach(el => {
|
|
||||||
if (!el.classList.contains('animate-visible')) {
|
|
||||||
observer.observe(el);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动端减少动画
|
|
||||||
if (isMobile) {
|
|
||||||
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
||||||
if (mediaQuery.matches) {
|
|
||||||
document.body.classList.add('reduce-motion');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加调试信息(开发环境)
|
|
||||||
function addDebugInfo() {
|
|
||||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|
||||||
const debugInfo = document.createElement('div');
|
|
||||||
debugInfo.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
top: 70px;
|
|
||||||
right: 10px;
|
|
||||||
background: rgba(0,0,0,0.8);
|
|
||||||
color: white;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
z-index: 10000;
|
|
||||||
font-family: monospace;
|
|
||||||
`;
|
|
||||||
|
|
||||||
function updateDebugInfo() {
|
|
||||||
const { isMobile, isTablet, currentOrientation } = detectDevice();
|
|
||||||
debugInfo.innerHTML = `
|
|
||||||
${window.innerWidth}×${window.innerHeight}<br>
|
|
||||||
${isMobile ? 'Mobile' : isTablet ? 'Tablet' : 'Desktop'}<br>
|
|
||||||
${currentOrientation}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDebugInfo();
|
|
||||||
document.body.appendChild(debugInfo);
|
|
||||||
|
|
||||||
window.addEventListener('resize', updateDebugInfo);
|
|
||||||
window.addEventListener('orientationchange', updateDebugInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化移动端优化
|
|
||||||
function init() {
|
|
||||||
// 检测设备类型
|
|
||||||
detectDevice();
|
|
||||||
|
|
||||||
// 添加移动端样式
|
|
||||||
addMobileStyles();
|
|
||||||
|
|
||||||
// 优化触摸体验
|
|
||||||
optimizeTouch();
|
|
||||||
|
|
||||||
// 处理屏幕方向变化
|
|
||||||
window.addEventListener('orientationchange', handleOrientationChange);
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
setTimeout(detectDevice, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 页面加载完成后的优化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
optimizeImages();
|
|
||||||
handleKeyboard();
|
|
||||||
optimizePerformance();
|
|
||||||
addDebugInfo();
|
|
||||||
}, 500);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
optimizeImages();
|
|
||||||
handleKeyboard();
|
|
||||||
optimizePerformance();
|
|
||||||
addDebugInfo();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听页面加载完成事件
|
|
||||||
document.addEventListener('pageLoaded', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
optimizeImages();
|
|
||||||
optimizePerformance();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提供外部接口
|
|
||||||
window.MobileOptimize = {
|
|
||||||
detectDevice,
|
|
||||||
isMobile: () => isMobile,
|
|
||||||
isTablet: () => isTablet,
|
|
||||||
getCurrentOrientation: () => currentOrientation,
|
|
||||||
optimizeImages,
|
|
||||||
optimizePerformance
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
init();
|
|
||||||
})();
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
// 导航组件 - 统一管理所有页面的导航栏
|
|
||||||
(function() {
|
|
||||||
// 检测当前页面路径,自动调整链接
|
|
||||||
const currentPath = window.location.pathname;
|
|
||||||
const isInPagesFolder = currentPath.includes('/pages/');
|
|
||||||
const currentPage = currentPath.split('/').pop() || 'index.html';
|
|
||||||
|
|
||||||
// 导航项配置
|
|
||||||
const navItems = [
|
|
||||||
{ href: 'index.html', icon: 'fa-home', text: '首页', id: 'index' },
|
|
||||||
{ href: 'overview.html', icon: 'fa-info-circle', text: '展会概览', id: 'overview' },
|
|
||||||
{ href: 'exhibition.html', icon: 'fa-th-large', text: '展览内容', id: 'exhibition' },
|
|
||||||
{ href: 'operation.html', icon: 'fa-drafting-compass', text: '布局设计', id: 'operation' },
|
|
||||||
{ href: 'marketing.html', icon: 'fa-bullhorn', text: '营销推广', id: 'marketing' },
|
|
||||||
{ href: 'budget.html', icon: 'fa-chart-pie', text: '预算分析', id: 'budget' },
|
|
||||||
{ href: 'risk.html', icon: 'fa-shield-alt', text: '风险评估', id: 'risk' }
|
|
||||||
];
|
|
||||||
|
|
||||||
// 根据当前页面位置调整路径
|
|
||||||
function getCorrectPath(href) {
|
|
||||||
// 移除可能存在的 pages/ 前缀
|
|
||||||
if (href.startsWith('pages/')) {
|
|
||||||
return href.substring(6); // 移除 'pages/' 前缀
|
|
||||||
}
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否为当前激活页面
|
|
||||||
function isActive(href) {
|
|
||||||
return currentPage === href ||
|
|
||||||
(currentPage === '' && href === 'index.html');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成导航HTML
|
|
||||||
function generateNavHTML() {
|
|
||||||
return `
|
|
||||||
<div class="nav-container container mx-auto px-6 py-4">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div class="flex items-center nav-logo">
|
|
||||||
<div class="logo-icon w-10 h-10 bg-gradient-to-br from-emerald-400 to-blue-500 rounded-lg flex items-center justify-center mr-3 transition-transform hover:scale-110">
|
|
||||||
<i class="fas fa-charging-station text-white"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 class="text-lg font-bold text-gray-800">NEVIT 2024</h1>
|
|
||||||
<p class="text-xs text-gray-500">新能源汽车产业博览会</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hidden md:flex space-x-6 lg:space-x-8">
|
|
||||||
${navItems.map(item => `
|
|
||||||
<a href="${getCorrectPath(item.href)}"
|
|
||||||
class="nav-link ${isActive(item.href) ? 'active text-emerald-500' : 'text-gray-700'} hover:text-emerald-500 transition-all duration-300 relative group"
|
|
||||||
data-nav="${item.id}">
|
|
||||||
<i class="fas ${item.icon} mr-2"></i>${item.text}
|
|
||||||
${isActive(item.href) ? '<span class="absolute bottom-0 left-0 w-full h-0.5 bg-emerald-500"></span>' : '<span class="absolute bottom-0 left-0 w-0 h-0.5 bg-emerald-500 transition-all duration-300 group-hover:w-full"></span>'}
|
|
||||||
</a>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
<button class="md:hidden menu-toggle" id="mobile-menu-button">
|
|
||||||
<span class="menu-icon">
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile Menu -->
|
|
||||||
<div class="mobile-menu-overlay hidden" id="mobile-menu-overlay"></div>
|
|
||||||
<div class="mobile-menu transform translate-x-full transition-transform duration-300 fixed top-0 right-0 h-full w-80 bg-white shadow-2xl z-50" id="mobile-menu">
|
|
||||||
<div class="p-6">
|
|
||||||
<button class="absolute top-6 right-6 text-gray-500 hover:text-gray-700" id="close-menu">
|
|
||||||
<i class="fas fa-times text-2xl"></i>
|
|
||||||
</button>
|
|
||||||
<div class="mb-8">
|
|
||||||
<h2 class="text-2xl font-bold text-gray-800">NEVIT 2024</h2>
|
|
||||||
<p class="text-sm text-gray-500">新能源汽车产业博览会</p>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-4">
|
|
||||||
${navItems.map(item => `
|
|
||||||
<a href="${getCorrectPath(item.href)}"
|
|
||||||
class="block py-3 px-4 rounded-lg ${isActive(item.href) ? 'bg-emerald-50 text-emerald-500' : 'text-gray-700 hover:bg-gray-50'} transition-all duration-300"
|
|
||||||
data-nav="${item.id}">
|
|
||||||
<i class="fas ${item.icon} mr-3 w-5"></i>${item.text}
|
|
||||||
</a>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
<div class="mt-8 pt-8 border-t border-gray-200">
|
|
||||||
<p class="text-sm text-gray-500">2024年9月12-15日</p>
|
|
||||||
<p class="text-sm text-gray-500">国家会展中心(上海)</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
function addStyles() {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
.nav-container {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
.navbar-scrolled {
|
|
||||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
|
||||||
.navbar-scrolled .nav-container {
|
|
||||||
padding-top: 0.75rem;
|
|
||||||
padding-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
.nav-logo {
|
|
||||||
animation: fadeInLeft 0.6s ease-out;
|
|
||||||
}
|
|
||||||
.nav-link {
|
|
||||||
position: relative;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.menu-icon {
|
|
||||||
width: 24px;
|
|
||||||
height: 20px;
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.menu-icon span {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 2px;
|
|
||||||
background-color: #374151;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
.menu-icon span:nth-child(1) {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.menu-icon span:nth-child(2) {
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
.menu-icon span:nth-child(3) {
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
.menu-open .menu-icon span:nth-child(1) {
|
|
||||||
transform: rotate(45deg) translate(6px, 6px);
|
|
||||||
}
|
|
||||||
.menu-open .menu-icon span:nth-child(2) {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.menu-open .menu-icon span:nth-child(3) {
|
|
||||||
transform: rotate(-45deg) translate(6px, -6px);
|
|
||||||
}
|
|
||||||
.mobile-menu-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
z-index: 40;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
.mobile-menu-overlay.show {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.mobile-menu.show {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
@keyframes fadeInLeft {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-20px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.nav-container {
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化导航
|
|
||||||
function initNav() {
|
|
||||||
const navElement = document.querySelector('nav') || document.getElementById('navbar');
|
|
||||||
if (navElement) {
|
|
||||||
// 统一设置导航栏样式
|
|
||||||
navElement.className = 'fixed top-0 w-full bg-white z-50 transition-all duration-300';
|
|
||||||
navElement.id = 'navbar';
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
addStyles();
|
|
||||||
|
|
||||||
// 更新导航内容
|
|
||||||
navElement.innerHTML = generateNavHTML();
|
|
||||||
|
|
||||||
// 添加滚动效果
|
|
||||||
let lastScrollTop = 0;
|
|
||||||
window.addEventListener('scroll', function() {
|
|
||||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
// 添加滚动阴影
|
|
||||||
if (scrollTop > 50) {
|
|
||||||
navElement.classList.add('navbar-scrolled');
|
|
||||||
} else {
|
|
||||||
navElement.classList.remove('navbar-scrolled');
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScrollTop = scrollTop;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 移动端菜单交互
|
|
||||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
|
||||||
const mobileMenu = document.getElementById('mobile-menu');
|
|
||||||
const mobileMenuOverlay = document.getElementById('mobile-menu-overlay');
|
|
||||||
const closeMenuButton = document.getElementById('close-menu');
|
|
||||||
|
|
||||||
if (mobileMenuButton && mobileMenu) {
|
|
||||||
// 打开菜单
|
|
||||||
mobileMenuButton.addEventListener('click', function() {
|
|
||||||
mobileMenu.classList.add('show');
|
|
||||||
if (mobileMenuOverlay) {
|
|
||||||
mobileMenuOverlay.classList.remove('hidden');
|
|
||||||
setTimeout(function() {
|
|
||||||
mobileMenuOverlay.classList.add('show');
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
mobileMenuButton.classList.add('menu-open');
|
|
||||||
document.body.style.overflow = 'hidden';
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭菜单功能
|
|
||||||
const closeMenu = function() {
|
|
||||||
mobileMenu.classList.remove('show');
|
|
||||||
if (mobileMenuOverlay) {
|
|
||||||
mobileMenuOverlay.classList.remove('show');
|
|
||||||
setTimeout(function() {
|
|
||||||
mobileMenuOverlay.classList.add('hidden');
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
mobileMenuButton.classList.remove('menu-open');
|
|
||||||
document.body.style.overflow = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击关闭按钮
|
|
||||||
closeMenuButton.addEventListener('click', closeMenu);
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
mobileMenuOverlay.addEventListener('click', closeMenu);
|
|
||||||
|
|
||||||
// 点击菜单项后关闭
|
|
||||||
mobileMenu.querySelectorAll('a').forEach(function(link) {
|
|
||||||
link.addEventListener('click', closeMenu);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM加载完成后初始化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initNav);
|
|
||||||
} else {
|
|
||||||
initNav();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
// 处理订单班参数和动态内容加载
|
|
||||||
(function() {
|
|
||||||
// 订单班配置
|
|
||||||
const orderClassConfig = {
|
|
||||||
'tourism': {
|
|
||||||
name: '文旅',
|
|
||||||
title: '2024长三角国际新能源汽车与智能交通产业博览会',
|
|
||||||
subtitle: '新能源汽车产业博览会',
|
|
||||||
icon: 'fa-charging-station',
|
|
||||||
color: 'emerald'
|
|
||||||
},
|
|
||||||
'food': {
|
|
||||||
name: '食品',
|
|
||||||
title: '2024国际健康食品与轻食产业博览会',
|
|
||||||
subtitle: '健康食品轻食博览会',
|
|
||||||
icon: 'fa-utensils',
|
|
||||||
color: 'orange'
|
|
||||||
},
|
|
||||||
'finance': {
|
|
||||||
name: '财经商贸',
|
|
||||||
title: '2024国际美妆产业与电商创新博览会',
|
|
||||||
subtitle: '美妆电商博览会',
|
|
||||||
icon: 'fa-chart-line',
|
|
||||||
color: 'blue'
|
|
||||||
},
|
|
||||||
'dev': {
|
|
||||||
name: '智能开发',
|
|
||||||
title: '2024国际教育科技与智慧学习博览会',
|
|
||||||
subtitle: '教育科技博览会',
|
|
||||||
icon: 'fa-code',
|
|
||||||
color: 'purple'
|
|
||||||
},
|
|
||||||
'manufacturing': {
|
|
||||||
name: '智能制造',
|
|
||||||
title: '2024国际智能制造与工业自动化博览会',
|
|
||||||
subtitle: '智能制造博览会',
|
|
||||||
icon: 'fa-industry',
|
|
||||||
color: 'gray'
|
|
||||||
},
|
|
||||||
'design': {
|
|
||||||
name: '视觉设计',
|
|
||||||
title: '2024国际文创设计与视觉艺术博览会',
|
|
||||||
subtitle: '文创设计博览会',
|
|
||||||
icon: 'fa-palette',
|
|
||||||
color: 'pink'
|
|
||||||
},
|
|
||||||
'logistics': {
|
|
||||||
name: '交通物流',
|
|
||||||
title: '2024国际智慧物流与供应链博览会',
|
|
||||||
subtitle: '智慧物流博览会',
|
|
||||||
icon: 'fa-truck',
|
|
||||||
color: 'indigo'
|
|
||||||
},
|
|
||||||
'civil': {
|
|
||||||
name: '土木',
|
|
||||||
title: '2024国际建筑科技与绿色建造博览会',
|
|
||||||
subtitle: '绿色建筑博览会',
|
|
||||||
icon: 'fa-building',
|
|
||||||
color: 'yellow'
|
|
||||||
},
|
|
||||||
'health': {
|
|
||||||
name: '大健康',
|
|
||||||
title: '2024国际大健康产业与医疗创新博览会',
|
|
||||||
subtitle: '大健康博览会',
|
|
||||||
icon: 'fa-heartbeat',
|
|
||||||
color: 'red'
|
|
||||||
},
|
|
||||||
'energy': {
|
|
||||||
name: '能源',
|
|
||||||
title: '2024国际新能源与光伏产业博览会',
|
|
||||||
subtitle: '新能源博览会',
|
|
||||||
icon: 'fa-solar-panel',
|
|
||||||
color: 'green'
|
|
||||||
},
|
|
||||||
'chemical': {
|
|
||||||
name: '化工',
|
|
||||||
title: '2024国际新材料与精细化工博览会',
|
|
||||||
subtitle: '新材料博览会',
|
|
||||||
icon: 'fa-flask',
|
|
||||||
color: 'teal'
|
|
||||||
},
|
|
||||||
'environment': {
|
|
||||||
name: '环保',
|
|
||||||
title: '2024国际环保科技与生态治理博览会',
|
|
||||||
subtitle: '环保科技博览会',
|
|
||||||
icon: 'fa-leaf',
|
|
||||||
color: 'lime'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取URL参数
|
|
||||||
function getUrlParam(name) {
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
return params.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前订单班
|
|
||||||
function getCurrentOrderClass() {
|
|
||||||
const orderClass = getUrlParam('orderClass');
|
|
||||||
return orderClass && orderClassConfig[orderClass] ? orderClass : 'tourism';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新页面标题
|
|
||||||
function updatePageTitle(config) {
|
|
||||||
const titleElement = document.querySelector('title');
|
|
||||||
if (titleElement) {
|
|
||||||
titleElement.textContent = config.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新页面中的标题
|
|
||||||
const pageTitleElements = document.querySelectorAll('[data-order-title]');
|
|
||||||
pageTitleElements.forEach(el => {
|
|
||||||
el.textContent = config.title;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 更新副标题
|
|
||||||
const subtitleElements = document.querySelectorAll('[data-order-subtitle]');
|
|
||||||
subtitleElements.forEach(el => {
|
|
||||||
el.textContent = config.subtitle;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新导航栏
|
|
||||||
function updateNavigation(config) {
|
|
||||||
const navbar = document.getElementById('navbar');
|
|
||||||
if (!navbar) return;
|
|
||||||
|
|
||||||
// 更新导航栏logo和标题
|
|
||||||
const logoIcon = navbar.querySelector('.logo-icon i');
|
|
||||||
const logoTitle = navbar.querySelector('.nav-logo h1');
|
|
||||||
const logoSubtitle = navbar.querySelector('.nav-logo p');
|
|
||||||
|
|
||||||
if (logoIcon) {
|
|
||||||
logoIcon.className = `fas ${config.icon} text-white`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logoTitle) {
|
|
||||||
logoTitle.textContent = config.name + ' 2024';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logoSubtitle) {
|
|
||||||
logoSubtitle.textContent = config.subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新颜色主题
|
|
||||||
updateColorTheme(config.color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新颜色主题
|
|
||||||
function updateColorTheme(color) {
|
|
||||||
// 移除所有可能的颜色类
|
|
||||||
const colors = ['emerald', 'orange', 'blue', 'purple', 'gray', 'pink', 'indigo', 'yellow', 'red', 'green', 'teal', 'lime'];
|
|
||||||
colors.forEach(c => {
|
|
||||||
document.documentElement.classList.remove(`theme-${c}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加新的颜色类
|
|
||||||
document.documentElement.classList.add(`theme-${color}`);
|
|
||||||
|
|
||||||
// 动态创建CSS变量
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.id = 'theme-colors';
|
|
||||||
|
|
||||||
// 移除旧的样式
|
|
||||||
const oldStyle = document.getElementById('theme-colors');
|
|
||||||
if (oldStyle) {
|
|
||||||
oldStyle.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定义颜色映射
|
|
||||||
const colorMap = {
|
|
||||||
emerald: { primary: '#10b981', secondary: '#34d399', accent: '#6ee7b7' },
|
|
||||||
orange: { primary: '#f97316', secondary: '#fb923c', accent: '#fdba74' },
|
|
||||||
blue: { primary: '#3b82f6', secondary: '#60a5fa', accent: '#93bbfc' },
|
|
||||||
purple: { primary: '#8b5cf6', secondary: '#a78bfa', accent: '#c4b5fd' },
|
|
||||||
gray: { primary: '#6b7280', secondary: '#9ca3af', accent: '#d1d5db' },
|
|
||||||
pink: { primary: '#ec4899', secondary: '#f472b6', accent: '#f9a8d4' },
|
|
||||||
indigo: { primary: '#6366f1', secondary: '#818cf8', accent: '#a5b4fc' },
|
|
||||||
yellow: { primary: '#eab308', secondary: '#facc15', accent: '#fde047' },
|
|
||||||
red: { primary: '#ef4444', secondary: '#f87171', accent: '#fca5a5' },
|
|
||||||
green: { primary: '#22c55e', secondary: '#4ade80', accent: '#86efac' },
|
|
||||||
teal: { primary: '#14b8a6', secondary: '#2dd4bf', accent: '#5eead4' },
|
|
||||||
lime: { primary: '#84cc16', secondary: '#a3e635', accent: '#bef264' }
|
|
||||||
};
|
|
||||||
|
|
||||||
const colors = colorMap[color] || colorMap.emerald;
|
|
||||||
|
|
||||||
style.textContent = `
|
|
||||||
:root {
|
|
||||||
--color-primary: ${colors.primary};
|
|
||||||
--color-secondary: ${colors.secondary};
|
|
||||||
--color-accent: ${colors.accent};
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-gradient-primary {
|
|
||||||
background: linear-gradient(135deg, ${colors.primary} 0%, ${colors.secondary} 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-primary { color: ${colors.primary}; }
|
|
||||||
.bg-primary { background-color: ${colors.primary}; }
|
|
||||||
.border-primary { border-color: ${colors.primary}; }
|
|
||||||
|
|
||||||
.nav-link.active { color: ${colors.primary}; }
|
|
||||||
.nav-link.active span { background-color: ${colors.primary}; }
|
|
||||||
.nav-link:hover { color: ${colors.primary}; }
|
|
||||||
.nav-link span { background-color: ${colors.primary}; }
|
|
||||||
|
|
||||||
.logo-icon {
|
|
||||||
background: linear-gradient(to bottom right, ${colors.secondary}, ${colors.primary});
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载订单班特定内容
|
|
||||||
function loadOrderClassContent(orderClass) {
|
|
||||||
// 这里可以根据订单班加载不同的内容
|
|
||||||
// 例如,加载不同的图片、文本等
|
|
||||||
console.log(`Loading content for order class: ${orderClass}`);
|
|
||||||
|
|
||||||
// 触发自定义事件,让其他组件知道订单班已改变
|
|
||||||
window.dispatchEvent(new CustomEvent('orderClassChanged', {
|
|
||||||
detail: { orderClass, config: orderClassConfig[orderClass] }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
function init() {
|
|
||||||
const orderClass = getCurrentOrderClass();
|
|
||||||
const config = orderClassConfig[orderClass];
|
|
||||||
|
|
||||||
if (config) {
|
|
||||||
updatePageTitle(config);
|
|
||||||
updateNavigation(config);
|
|
||||||
loadOrderClassContent(orderClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM加载完成后初始化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
|
||||||
} else {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 暴露全局函数供其他模块使用
|
|
||||||
window.OrderClassHandler = {
|
|
||||||
getCurrentOrderClass,
|
|
||||||
getConfig: () => orderClassConfig[getCurrentOrderClass()],
|
|
||||||
getAllConfigs: () => orderClassConfig
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
@@ -1,387 +0,0 @@
|
|||||||
// 页面加载动画组件
|
|
||||||
(function() {
|
|
||||||
// 创建加载器HTML结构
|
|
||||||
function createLoader() {
|
|
||||||
const loaderHTML = `
|
|
||||||
<div id="page-loader" class="fixed inset-0 bg-white z-[9999] flex items-center justify-center">
|
|
||||||
<!-- 背景动画 -->
|
|
||||||
<div class="absolute inset-0 overflow-hidden">
|
|
||||||
<!-- 渐变背景 -->
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-emerald-50"></div>
|
|
||||||
|
|
||||||
<!-- 浮动粒子 -->
|
|
||||||
<div class="floating-particles">
|
|
||||||
${Array.from({length: 12}).map((_, i) => `
|
|
||||||
<div class="particle particle-${i + 1}"></div>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 几何图形 -->
|
|
||||||
<div class="geometric-shapes">
|
|
||||||
<div class="shape shape-1"></div>
|
|
||||||
<div class="shape shape-2"></div>
|
|
||||||
<div class="shape shape-3"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 主加载内容 -->
|
|
||||||
<div class="relative z-10 text-center">
|
|
||||||
<!-- Logo区域 -->
|
|
||||||
<div class="mb-8">
|
|
||||||
<div class="w-20 h-20 mx-auto mb-4 relative">
|
|
||||||
<!-- 旋转的环 -->
|
|
||||||
<div class="absolute inset-0 border-4 border-transparent border-t-emerald-500 border-r-blue-500 rounded-full animate-spin"></div>
|
|
||||||
<div class="absolute inset-2 border-4 border-transparent border-b-purple-500 border-l-pink-500 rounded-full animate-spin-reverse"></div>
|
|
||||||
|
|
||||||
<!-- 中心图标 -->
|
|
||||||
<div class="absolute inset-0 flex items-center justify-center">
|
|
||||||
<div class="w-8 h-8 bg-gradient-to-br from-emerald-400 to-blue-500 rounded-lg flex items-center justify-center text-white font-bold text-sm animate-pulse">
|
|
||||||
新
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 品牌名称 -->
|
|
||||||
<h1 class="text-2xl font-bold text-gray-800 mb-2 animate-fade-in">
|
|
||||||
长三角国际新能源汽车博览会
|
|
||||||
</h1>
|
|
||||||
<p class="text-gray-600 animate-fade-in-delay">
|
|
||||||
智行未来,绿动长三角
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 进度条 -->
|
|
||||||
<div class="w-64 mx-auto mb-6">
|
|
||||||
<div class="bg-gray-200 rounded-full h-2 overflow-hidden">
|
|
||||||
<div id="loading-progress" class="h-full bg-gradient-to-r from-emerald-400 to-blue-500 rounded-full transition-all duration-300 ease-out" style="width: 0%"></div>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between text-xs text-gray-500 mt-2">
|
|
||||||
<span>加载中</span>
|
|
||||||
<span id="loading-percentage">0%</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 加载状态文字 -->
|
|
||||||
<div class="text-sm text-gray-500">
|
|
||||||
<span id="loading-text">正在准备展会信息</span>
|
|
||||||
<span class="loading-dots">
|
|
||||||
<span class="dot">.</span>
|
|
||||||
<span class="dot">.</span>
|
|
||||||
<span class="dot">.</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 将加载器插入到 body 的最前面,确保body存在
|
|
||||||
if (document.body) {
|
|
||||||
document.body.insertAdjacentHTML('afterbegin', loaderHTML);
|
|
||||||
} else {
|
|
||||||
// 如果body不存在,等待DOM加载完成
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
if (document.body && !document.getElementById('page-loader')) {
|
|
||||||
document.body.insertAdjacentHTML('afterbegin', loaderHTML);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
function addStyles() {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
/* 基础动画定义 */
|
|
||||||
@keyframes spin-reverse {
|
|
||||||
from { transform: rotate(0deg); }
|
|
||||||
to { transform: rotate(-360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-in {
|
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
|
||||||
to { opacity: 1; transform: translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-in-delay {
|
|
||||||
from { opacity: 0; transform: translateY(15px); }
|
|
||||||
to { opacity: 1; transform: translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
25% { transform: translateY(-10px) rotate(90deg); }
|
|
||||||
50% { transform: translateY(-5px) rotate(180deg); }
|
|
||||||
75% { transform: translateY(-15px) rotate(270deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dot-blink {
|
|
||||||
0%, 20% { opacity: 0; }
|
|
||||||
50% { opacity: 1; }
|
|
||||||
100% { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shape-float {
|
|
||||||
0%, 100% { transform: translateY(0px) translateX(0px) rotate(0deg); }
|
|
||||||
33% { transform: translateY(-20px) translateX(10px) rotate(120deg); }
|
|
||||||
66% { transform: translateY(10px) translateX(-10px) rotate(240deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes particle-drift {
|
|
||||||
0% { transform: translateY(100vh) translateX(0px) rotate(0deg); opacity: 0; }
|
|
||||||
10% { opacity: 1; }
|
|
||||||
90% { opacity: 1; }
|
|
||||||
100% { transform: translateY(-100px) translateX(50px) rotate(360deg); opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 应用动画类 */
|
|
||||||
.animate-spin-reverse {
|
|
||||||
animation: spin-reverse 2s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-fade-in {
|
|
||||||
animation: fade-in 1s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-fade-in-delay {
|
|
||||||
animation: fade-in-delay 1s ease-out 0.3s forwards;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 加载点动画 */
|
|
||||||
.loading-dots {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dots .dot {
|
|
||||||
animation: dot-blink 1.4s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dots .dot:nth-child(2) {
|
|
||||||
animation-delay: 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dots .dot:nth-child(3) {
|
|
||||||
animation-delay: 0.4s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 浮动粒子 */
|
|
||||||
.floating-particles {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.particle {
|
|
||||||
position: absolute;
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: particle-drift 8s infinite linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.particle-1 { background: rgba(16, 185, 129, 0.6); left: 10%; animation-delay: 0s; animation-duration: 8s; }
|
|
||||||
.particle-2 { background: rgba(59, 130, 246, 0.6); left: 20%; animation-delay: 1s; animation-duration: 10s; }
|
|
||||||
.particle-3 { background: rgba(168, 85, 247, 0.6); left: 30%; animation-delay: 2s; animation-duration: 9s; }
|
|
||||||
.particle-4 { background: rgba(236, 72, 153, 0.6); left: 40%; animation-delay: 3s; animation-duration: 11s; }
|
|
||||||
.particle-5 { background: rgba(245, 158, 11, 0.6); left: 50%; animation-delay: 4s; animation-duration: 7s; }
|
|
||||||
.particle-6 { background: rgba(239, 68, 68, 0.6); left: 60%; animation-delay: 5s; animation-duration: 9s; }
|
|
||||||
.particle-7 { background: rgba(16, 185, 129, 0.6); left: 70%; animation-delay: 6s; animation-duration: 8s; }
|
|
||||||
.particle-8 { background: rgba(59, 130, 246, 0.6); left: 80%; animation-delay: 7s; animation-duration: 10s; }
|
|
||||||
.particle-9 { background: rgba(168, 85, 247, 0.6); left: 90%; animation-delay: 1.5s; animation-duration: 9s; }
|
|
||||||
.particle-10 { background: rgba(236, 72, 153, 0.6); left: 15%; animation-delay: 2.5s; animation-duration: 11s; }
|
|
||||||
.particle-11 { background: rgba(245, 158, 11, 0.6); left: 25%; animation-delay: 3.5s; animation-duration: 7s; }
|
|
||||||
.particle-12 { background: rgba(239, 68, 68, 0.6); left: 85%; animation-delay: 4.5s; animation-duration: 8s; }
|
|
||||||
|
|
||||||
/* 几何图形 */
|
|
||||||
.geometric-shapes {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shape {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 12px;
|
|
||||||
animation: shape-float 6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shape-1 {
|
|
||||||
top: 20%;
|
|
||||||
left: 10%;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: linear-gradient(45deg, rgba(16, 185, 129, 0.1), rgba(59, 130, 246, 0.1));
|
|
||||||
animation-delay: 0s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shape-2 {
|
|
||||||
top: 60%;
|
|
||||||
right: 15%;
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(236, 72, 153, 0.1));
|
|
||||||
border-radius: 50%;
|
|
||||||
animation-delay: 2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shape-3 {
|
|
||||||
bottom: 30%;
|
|
||||||
left: 20%;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background: linear-gradient(225deg, rgba(245, 158, 11, 0.1), rgba(239, 68, 68, 0.1));
|
|
||||||
animation-delay: 4s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 加载器隐藏动画 */
|
|
||||||
#page-loader.fade-out {
|
|
||||||
animation: fadeOutLoader 0.8s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOutLoader {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 防止页面滚动 */
|
|
||||||
body.loading {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新加载进度
|
|
||||||
function updateProgress(percentage, text) {
|
|
||||||
const progressBar = document.getElementById('loading-progress');
|
|
||||||
const percentageText = document.getElementById('loading-percentage');
|
|
||||||
const loadingText = document.getElementById('loading-text');
|
|
||||||
|
|
||||||
if (progressBar) {
|
|
||||||
progressBar.style.width = percentage + '%';
|
|
||||||
}
|
|
||||||
if (percentageText) {
|
|
||||||
percentageText.textContent = percentage + '%';
|
|
||||||
}
|
|
||||||
if (loadingText && text) {
|
|
||||||
loadingText.textContent = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟加载过程
|
|
||||||
function simulateLoading() {
|
|
||||||
const loadingSteps = [
|
|
||||||
{ progress: 0, text: '正在准备展会信息', delay: 100 },
|
|
||||||
{ progress: 15, text: '加载导航组件', delay: 200 },
|
|
||||||
{ progress: 30, text: '获取展会数据', delay: 300 },
|
|
||||||
{ progress: 45, text: '渲染页面布局', delay: 250 },
|
|
||||||
{ progress: 60, text: '加载图片资源', delay: 400 },
|
|
||||||
{ progress: 75, text: '初始化交互功能', delay: 200 },
|
|
||||||
{ progress: 85, text: '优化页面性能', delay: 150 },
|
|
||||||
{ progress: 95, text: '准备完成', delay: 200 },
|
|
||||||
{ progress: 100, text: '加载完成', delay: 300 }
|
|
||||||
];
|
|
||||||
|
|
||||||
let currentStep = 0;
|
|
||||||
|
|
||||||
function nextStep() {
|
|
||||||
if (currentStep < loadingSteps.length) {
|
|
||||||
const step = loadingSteps[currentStep];
|
|
||||||
updateProgress(step.progress, step.text);
|
|
||||||
currentStep++;
|
|
||||||
setTimeout(nextStep, step.delay);
|
|
||||||
} else {
|
|
||||||
// 加载完成,延迟一点时间后隐藏加载器
|
|
||||||
setTimeout(hideLoader, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始加载过程
|
|
||||||
setTimeout(nextStep, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 隐藏加载器
|
|
||||||
function hideLoader() {
|
|
||||||
const loader = document.getElementById('page-loader');
|
|
||||||
if (loader) {
|
|
||||||
loader.classList.add('fade-out');
|
|
||||||
|
|
||||||
// 动画结束后移除元素并恢复页面滚动
|
|
||||||
setTimeout(() => {
|
|
||||||
loader.remove();
|
|
||||||
document.body.classList.remove('loading');
|
|
||||||
|
|
||||||
// 触发页面加载完成事件
|
|
||||||
document.dispatchEvent(new CustomEvent('pageLoaded'));
|
|
||||||
}, 800);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化加载器
|
|
||||||
function init() {
|
|
||||||
// 确保DOM已加载
|
|
||||||
if (!document.body) {
|
|
||||||
// 如果body还不存在,等待DOM加载完成
|
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
addStyles();
|
|
||||||
|
|
||||||
// 创建加载器
|
|
||||||
createLoader();
|
|
||||||
|
|
||||||
// 禁用页面滚动
|
|
||||||
if (document.body) {
|
|
||||||
document.body.classList.add('loading');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 等待页面资源加载完成
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
setTimeout(simulateLoading, 200);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setTimeout(simulateLoading, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听 window load 事件(所有资源包括图片都加载完成)
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
// 如果加载器仍然存在,加速完成过程
|
|
||||||
if (document.getElementById('page-loader')) {
|
|
||||||
updateProgress(100, '加载完成');
|
|
||||||
setTimeout(hideLoader, 300);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听页面可见性变化(用户切换标签页时暂停动画)
|
|
||||||
document.addEventListener('visibilitychange', function() {
|
|
||||||
const loader = document.getElementById('page-loader');
|
|
||||||
if (loader) {
|
|
||||||
if (document.hidden) {
|
|
||||||
loader.style.animationPlayState = 'paused';
|
|
||||||
} else {
|
|
||||||
loader.style.animationPlayState = 'running';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提供外部接口
|
|
||||||
window.PageLoader = {
|
|
||||||
updateProgress,
|
|
||||||
hideLoader
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
init();
|
|
||||||
})();
|
|
||||||
@@ -1,461 +0,0 @@
|
|||||||
// 页面性能优化组件
|
|
||||||
(function() {
|
|
||||||
let performanceData = {};
|
|
||||||
let isOptimizing = false;
|
|
||||||
|
|
||||||
// 性能监测
|
|
||||||
function measurePerformance() {
|
|
||||||
if ('performance' in window) {
|
|
||||||
const navigation = performance.getEntriesByType('navigation')[0];
|
|
||||||
const paint = performance.getEntriesByType('paint');
|
|
||||||
|
|
||||||
performanceData = {
|
|
||||||
// 页面加载时间
|
|
||||||
domLoading: navigation.domContentLoadedEventEnd - navigation.navigationStart,
|
|
||||||
pageLoading: navigation.loadEventEnd - navigation.navigationStart,
|
|
||||||
|
|
||||||
// 渲染时间
|
|
||||||
firstPaint: paint.find(p => p.name === 'first-paint')?.startTime || 0,
|
|
||||||
firstContentfulPaint: paint.find(p => p.name === 'first-contentful-paint')?.startTime || 0,
|
|
||||||
|
|
||||||
// 网络时间
|
|
||||||
dnsTime: navigation.domainLookupEnd - navigation.domainLookupStart,
|
|
||||||
connectTime: navigation.connectEnd - navigation.connectStart,
|
|
||||||
requestTime: navigation.responseStart - navigation.requestStart,
|
|
||||||
downloadTime: navigation.responseEnd - navigation.responseStart,
|
|
||||||
|
|
||||||
// 内存使用(如果支持)
|
|
||||||
memory: performance.memory ? {
|
|
||||||
used: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024),
|
|
||||||
total: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024),
|
|
||||||
limit: Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024)
|
|
||||||
} : null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return performanceData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 资源预加载优化
|
|
||||||
function optimizeResourceLoading() {
|
|
||||||
// 根据当前页面位置调整路径
|
|
||||||
const isInPagesFolder = window.location.pathname.includes('/pages/');
|
|
||||||
const basePath = isInPagesFolder ? '../' : '';
|
|
||||||
|
|
||||||
// 预加载关键资源
|
|
||||||
const criticalResources = [
|
|
||||||
{ href: basePath + 'css/styles.css', as: 'style' },
|
|
||||||
{ href: basePath + 'css/animations.css', as: 'style' },
|
|
||||||
{ href: basePath + 'js/nav-component.js', as: 'script' }
|
|
||||||
];
|
|
||||||
|
|
||||||
criticalResources.forEach(resource => {
|
|
||||||
if (!document.querySelector(`link[href*="${resource.href.split('/').pop()}"]`)) {
|
|
||||||
const link = document.createElement('link');
|
|
||||||
link.rel = 'preload';
|
|
||||||
link.href = resource.href;
|
|
||||||
link.as = resource.as;
|
|
||||||
document.head.appendChild(link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图片懒加载和优化
|
|
||||||
function optimizeImages() {
|
|
||||||
// 创建 Intersection Observer 用于懒加载
|
|
||||||
if ('IntersectionObserver' in window) {
|
|
||||||
const imageObserver = new IntersectionObserver((entries, observer) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
const img = entry.target;
|
|
||||||
|
|
||||||
// 懒加载图片
|
|
||||||
if (img.dataset.src) {
|
|
||||||
img.src = img.dataset.src;
|
|
||||||
img.removeAttribute('data-src');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加加载状态
|
|
||||||
img.classList.add('loading');
|
|
||||||
|
|
||||||
img.addEventListener('load', () => {
|
|
||||||
img.classList.remove('loading');
|
|
||||||
img.classList.add('loaded');
|
|
||||||
});
|
|
||||||
|
|
||||||
img.addEventListener('error', () => {
|
|
||||||
img.classList.add('error');
|
|
||||||
img.style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.unobserve(img);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, {
|
|
||||||
rootMargin: '50px',
|
|
||||||
threshold: 0.01
|
|
||||||
});
|
|
||||||
|
|
||||||
// 观察所有图片
|
|
||||||
document.querySelectorAll('img[data-src], img:not([src])').forEach(img => {
|
|
||||||
imageObserver.observe(img);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为现有图片添加优化
|
|
||||||
document.querySelectorAll('img').forEach(img => {
|
|
||||||
// 添加 loading="lazy" 属性
|
|
||||||
if (!img.loading) {
|
|
||||||
img.loading = 'lazy';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加 decode="async" 属性
|
|
||||||
if (!img.decode) {
|
|
||||||
img.decode = 'async';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图片错误处理
|
|
||||||
img.addEventListener('error', function() {
|
|
||||||
this.style.opacity = '0';
|
|
||||||
this.style.transition = 'opacity 0.3s';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// CSS 优化
|
|
||||||
function optimizeCSS() {
|
|
||||||
// 内联关键 CSS
|
|
||||||
const criticalCSS = `
|
|
||||||
/* 关键渲染路径 CSS */
|
|
||||||
body { font-family: 'Inter', sans-serif; margin: 0; padding: 0; }
|
|
||||||
#navbar { position: fixed; top: 0; width: 100%; z-index: 50; background: white; }
|
|
||||||
.container { max-width: 1200px; margin: 0 auto; padding: 0 1rem; }
|
|
||||||
|
|
||||||
/* 页面加载器样式 */
|
|
||||||
#page-loader { position: fixed; inset: 0; z-index: 9999; background: white; display: flex; align-items: center; justify-content: center; }
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 添加关键 CSS 到 head
|
|
||||||
if (!document.getElementById('critical-css')) {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.id = 'critical-css';
|
|
||||||
style.textContent = criticalCSS;
|
|
||||||
document.head.insertBefore(style, document.head.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 异步加载非关键 CSS
|
|
||||||
const nonCriticalCSS = document.querySelectorAll('link[rel="stylesheet"]:not([data-critical])');
|
|
||||||
nonCriticalCSS.forEach(link => {
|
|
||||||
if (link.href.includes('tailwind') || link.href.includes('font-awesome')) {
|
|
||||||
link.media = 'print';
|
|
||||||
link.addEventListener('load', function() {
|
|
||||||
this.media = 'all';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// JavaScript 优化
|
|
||||||
function optimizeJavaScript() {
|
|
||||||
// 延迟加载非关键脚本
|
|
||||||
const deferScripts = [
|
|
||||||
'js/back-to-top.js',
|
|
||||||
'js/mobile-optimize.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
deferScripts.forEach(src => {
|
|
||||||
const script = document.querySelector(`script[src*="${src}"]`);
|
|
||||||
if (script && !script.defer && !script.async) {
|
|
||||||
script.defer = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 移除未使用的事件监听器(防止内存泄漏)
|
|
||||||
const cleanupEvents = () => {
|
|
||||||
// 移除已销毁元素的事件监听器
|
|
||||||
document.querySelectorAll('[data-cleanup]').forEach(el => {
|
|
||||||
el.removeEventListener('click', null);
|
|
||||||
el.removeEventListener('scroll', null);
|
|
||||||
el.removeEventListener('resize', null);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 页面卸载时清理
|
|
||||||
window.addEventListener('beforeunload', cleanupEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 网络优化
|
|
||||||
function optimizeNetwork() {
|
|
||||||
// DNS 预解析
|
|
||||||
const domains = [
|
|
||||||
'fonts.googleapis.com',
|
|
||||||
'cdnjs.cloudflare.com',
|
|
||||||
'cdn.jsdelivr.net'
|
|
||||||
];
|
|
||||||
|
|
||||||
domains.forEach(domain => {
|
|
||||||
if (!document.querySelector(`link[rel="dns-prefetch"][href*="${domain}"]`)) {
|
|
||||||
const link = document.createElement('link');
|
|
||||||
link.rel = 'dns-prefetch';
|
|
||||||
link.href = `https://${domain}`;
|
|
||||||
document.head.appendChild(link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 预连接到关键域名
|
|
||||||
const preconnectDomains = ['fonts.gstatic.com'];
|
|
||||||
preconnectDomains.forEach(domain => {
|
|
||||||
if (!document.querySelector(`link[rel="preconnect"][href*="${domain}"]`)) {
|
|
||||||
const link = document.createElement('link');
|
|
||||||
link.rel = 'preconnect';
|
|
||||||
link.href = `https://${domain}`;
|
|
||||||
link.crossOrigin = '';
|
|
||||||
document.head.appendChild(link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存优化
|
|
||||||
function optimizeCache() {
|
|
||||||
// Service Worker 注册(如果支持)
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
navigator.serviceWorker.register('./sw.js')
|
|
||||||
.then(registration => {
|
|
||||||
console.log('SW registered: ', registration);
|
|
||||||
})
|
|
||||||
.catch(registrationError => {
|
|
||||||
console.log('SW registration failed: ', registrationError);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 本地存储优化
|
|
||||||
try {
|
|
||||||
// 缓存静态数据
|
|
||||||
if (localStorage) {
|
|
||||||
const cacheKey = 'page-cache-' + window.location.pathname;
|
|
||||||
const cacheTime = 30 * 60 * 1000; // 30分钟
|
|
||||||
|
|
||||||
const cachedData = localStorage.getItem(cacheKey);
|
|
||||||
if (cachedData) {
|
|
||||||
const { timestamp, data } = JSON.parse(cachedData);
|
|
||||||
if (Date.now() - timestamp < cacheTime) {
|
|
||||||
// 使用缓存数据
|
|
||||||
console.log('Using cached data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('LocalStorage not available');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动画性能优化
|
|
||||||
function optimizeAnimations() {
|
|
||||||
// 检测是否需要减少动画
|
|
||||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
||||||
|
|
||||||
if (prefersReducedMotion) {
|
|
||||||
document.body.classList.add('reduce-motion');
|
|
||||||
|
|
||||||
// 添加减少动画的 CSS
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
.reduce-motion *,
|
|
||||||
.reduce-motion *::before,
|
|
||||||
.reduce-motion *::after {
|
|
||||||
animation-duration: 0.01ms !important;
|
|
||||||
animation-iteration-count: 1 !important;
|
|
||||||
transition-duration: 0.01ms !important;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 transform 和 opacity 进行动画(硬件加速)
|
|
||||||
document.querySelectorAll('[class*="animate-"]').forEach(el => {
|
|
||||||
el.style.willChange = 'transform, opacity';
|
|
||||||
|
|
||||||
// 动画完成后移除 will-change
|
|
||||||
el.addEventListener('animationend', function() {
|
|
||||||
this.style.willChange = 'auto';
|
|
||||||
}, { once: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 内存优化
|
|
||||||
function optimizeMemory() {
|
|
||||||
// 定期清理无用的 DOM 元素
|
|
||||||
const cleanup = () => {
|
|
||||||
// 移除隐藏的元素(如果不再需要)
|
|
||||||
document.querySelectorAll('.hidden, [style*="display: none"]').forEach(el => {
|
|
||||||
if (el.dataset.keepHidden !== 'true') {
|
|
||||||
// 这里可以添加更智能的清理逻辑
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 每5分钟执行一次清理
|
|
||||||
setInterval(cleanup, 5 * 60 * 1000);
|
|
||||||
|
|
||||||
// 监听内存压力(如果支持)
|
|
||||||
if ('memory' in performance) {
|
|
||||||
const checkMemory = () => {
|
|
||||||
const used = performance.memory.usedJSHeapSize;
|
|
||||||
const limit = performance.memory.jsHeapSizeLimit;
|
|
||||||
const usage = used / limit;
|
|
||||||
|
|
||||||
if (usage > 0.8) {
|
|
||||||
console.warn('High memory usage detected:', Math.round(usage * 100) + '%');
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setInterval(checkMemory, 30000); // 每30秒检查一次
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 性能监控和报告
|
|
||||||
function monitorPerformance() {
|
|
||||||
// 使用 Performance Observer 监控
|
|
||||||
if ('PerformanceObserver' in window) {
|
|
||||||
// 监控 Long Tasks
|
|
||||||
const longTaskObserver = new PerformanceObserver(list => {
|
|
||||||
list.getEntries().forEach(entry => {
|
|
||||||
if (entry.duration > 50) {
|
|
||||||
console.warn('Long task detected:', entry.duration + 'ms');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
longTaskObserver.observe({ entryTypes: ['longtask'] });
|
|
||||||
} catch (e) {
|
|
||||||
// longtask 不被支持
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监控 Layout Shift
|
|
||||||
const clsObserver = new PerformanceObserver(list => {
|
|
||||||
list.getEntries().forEach(entry => {
|
|
||||||
if (entry.value > 0.1) {
|
|
||||||
console.warn('Layout shift detected:', entry.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
clsObserver.observe({ entryTypes: ['layout-shift'] });
|
|
||||||
} catch (e) {
|
|
||||||
// layout-shift 不被支持
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加性能优化样式
|
|
||||||
function addPerformanceStyles() {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = `
|
|
||||||
/* 硬件加速 */
|
|
||||||
.gpu-accelerated {
|
|
||||||
transform: translateZ(0);
|
|
||||||
will-change: transform, opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 图片加载状态 */
|
|
||||||
img.loading {
|
|
||||||
opacity: 0.3;
|
|
||||||
filter: blur(5px);
|
|
||||||
transition: opacity 0.3s, filter 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.loaded {
|
|
||||||
opacity: 1;
|
|
||||||
filter: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.error {
|
|
||||||
opacity: 0;
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 字体加载优化 */
|
|
||||||
.font-loading {
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 减少重绘 */
|
|
||||||
.contain-layout {
|
|
||||||
contain: layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contain-paint {
|
|
||||||
contain: paint;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滚动优化 */
|
|
||||||
.scroll-smooth {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化性能优化
|
|
||||||
function init() {
|
|
||||||
if (isOptimizing) return;
|
|
||||||
isOptimizing = true;
|
|
||||||
|
|
||||||
// 立即执行的优化
|
|
||||||
optimizeResourceLoading();
|
|
||||||
optimizeCSS();
|
|
||||||
optimizeNetwork();
|
|
||||||
addPerformanceStyles();
|
|
||||||
|
|
||||||
// DOM 加载完成后执行
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
optimizeImages();
|
|
||||||
optimizeJavaScript();
|
|
||||||
optimizeAnimations();
|
|
||||||
monitorPerformance();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
optimizeImages();
|
|
||||||
optimizeJavaScript();
|
|
||||||
optimizeAnimations();
|
|
||||||
monitorPerformance();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页面完全加载后执行
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
optimizeCache();
|
|
||||||
optimizeMemory();
|
|
||||||
|
|
||||||
// 测量性能
|
|
||||||
setTimeout(() => {
|
|
||||||
const perf = measurePerformance();
|
|
||||||
console.log('Performance metrics:', perf);
|
|
||||||
|
|
||||||
// 发送性能数据到分析系统(如果需要)
|
|
||||||
if (window.gtag) {
|
|
||||||
gtag('event', 'performance', {
|
|
||||||
'page_load_time': Math.round(perf.pageLoading),
|
|
||||||
'dom_load_time': Math.round(perf.domLoading)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提供外部接口
|
|
||||||
window.PerformanceOptimizer = {
|
|
||||||
measurePerformance,
|
|
||||||
optimizeImages,
|
|
||||||
getPerformanceData: () => performanceData
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
init();
|
|
||||||
})();
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
// 路由系统 - 支持多订单班结果展示
|
|
||||||
class OrderClassRouter {
|
|
||||||
constructor() {
|
|
||||||
this.routes = {
|
|
||||||
'wenlu': {
|
|
||||||
name: '文旅订单班',
|
|
||||||
path: '/result/wenlu',
|
|
||||||
template: 'wenlu-result.html',
|
|
||||||
title: '2024长三角国际新能源汽车与智能交通产业博览会',
|
|
||||||
agents: ['项目策划专家', '展会设计师', '市场营销专家', '运营管理专家', '财务分析师', '风险控制专家']
|
|
||||||
},
|
|
||||||
'food': {
|
|
||||||
name: '食品订单班',
|
|
||||||
path: '/result/food',
|
|
||||||
template: 'food-result.html',
|
|
||||||
title: '中高端个性化轻食店铺经营方案',
|
|
||||||
agents: ['轻食店经营管理专家', '餐饮市场调研专家', '餐饮品牌设计专家', '菜品研发专家', '餐厅选址装修专家', '餐饮团队人员管理专家', '财务预算专家']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.currentRoute = null;
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
// 监听URL变化
|
|
||||||
window.addEventListener('popstate', () => this.handleRoute());
|
|
||||||
|
|
||||||
// 处理初始路由
|
|
||||||
this.handleRoute();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleRoute() {
|
|
||||||
const path = window.location.pathname;
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const orderClass = urlParams.get('class') || this.getClassFromPath(path);
|
|
||||||
|
|
||||||
if (orderClass && this.routes[orderClass]) {
|
|
||||||
this.loadRoute(orderClass);
|
|
||||||
} else {
|
|
||||||
// 默认加载文旅订单班
|
|
||||||
this.loadRoute('wenlu');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getClassFromPath(path) {
|
|
||||||
// 从路径中提取订单班类型
|
|
||||||
const match = path.match(/\/result\/(\w+)/);
|
|
||||||
return match ? match[1] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadRoute(orderClass) {
|
|
||||||
const route = this.routes[orderClass];
|
|
||||||
if (!route) return;
|
|
||||||
|
|
||||||
this.currentRoute = orderClass;
|
|
||||||
|
|
||||||
// 更新页面标题
|
|
||||||
document.title = route.title;
|
|
||||||
|
|
||||||
// 更新URL(不刷新页面)
|
|
||||||
const newUrl = `${window.location.origin}${route.path}`;
|
|
||||||
if (window.location.href !== newUrl) {
|
|
||||||
window.history.pushState({ orderClass }, '', newUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载对应的内容
|
|
||||||
this.loadContent(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadContent(route) {
|
|
||||||
// 检查是否有特定的内容容器
|
|
||||||
const contentContainer = document.getElementById('order-class-content');
|
|
||||||
if (!contentContainer) {
|
|
||||||
console.warn('未找到内容容器 #order-class-content');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据订单班类型加载不同的内容
|
|
||||||
if (route.template) {
|
|
||||||
this.loadTemplate(route.template, contentContainer);
|
|
||||||
} else {
|
|
||||||
// 动态生成内容
|
|
||||||
this.generateContent(route, contentContainer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadTemplate(templatePath, container) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/pages/${templatePath}`);
|
|
||||||
if (response.ok) {
|
|
||||||
const html = await response.text();
|
|
||||||
container.innerHTML = html;
|
|
||||||
this.initializePageScripts();
|
|
||||||
} else {
|
|
||||||
this.generateContent(this.routes[this.currentRoute], container);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载模板失败:', error);
|
|
||||||
this.generateContent(this.routes[this.currentRoute], container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generateContent(route, container) {
|
|
||||||
// 动态生成页面内容
|
|
||||||
const html = `
|
|
||||||
<div class="order-class-result">
|
|
||||||
<header class="result-header">
|
|
||||||
<h1>${route.title}</h1>
|
|
||||||
<p class="subtitle">基于AI Agent多角色协作生成的完整方案</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="agents-section">
|
|
||||||
<h2>参与的AI专家团队</h2>
|
|
||||||
<div class="agents-grid">
|
|
||||||
${route.agents.map(agent => `
|
|
||||||
<div class="agent-card">
|
|
||||||
<div class="agent-avatar">
|
|
||||||
<img src="/data/订单班文档资料/${this.currentRoute === 'food' ? '食品' : '文旅'}/agent头像/${agent}.png"
|
|
||||||
alt="${agent}"
|
|
||||||
onerror="this.src='/data/订单班文档资料/文旅/agent头像/default.png'">
|
|
||||||
</div>
|
|
||||||
<h3>${agent}</h3>
|
|
||||||
</div>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="content-section">
|
|
||||||
<div id="dynamic-content">
|
|
||||||
<!-- 动态加载具体内容 -->
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
container.innerHTML = html;
|
|
||||||
|
|
||||||
// 加载具体内容
|
|
||||||
this.loadOrderClassContent(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadOrderClassContent(route) {
|
|
||||||
const contentDiv = document.getElementById('dynamic-content');
|
|
||||||
if (!contentDiv) return;
|
|
||||||
|
|
||||||
// 根据不同订单班加载不同内容
|
|
||||||
if (this.currentRoute === 'food') {
|
|
||||||
await this.loadFoodContent(contentDiv);
|
|
||||||
} else if (this.currentRoute === 'wenlu') {
|
|
||||||
await this.loadWenluContent(contentDiv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadFoodContent(container) {
|
|
||||||
// 加载食品订单班的具体内容
|
|
||||||
container.innerHTML = `
|
|
||||||
<div class="food-content">
|
|
||||||
<nav class="content-nav">
|
|
||||||
<a href="#market-research">市场调研</a>
|
|
||||||
<a href="#brand-design">品牌设计</a>
|
|
||||||
<a href="#menu-development">菜品研发</a>
|
|
||||||
<a href="#location-design">选址装修</a>
|
|
||||||
<a href="#team-management">团队管理</a>
|
|
||||||
<a href="#financial-budget">财务预算</a>
|
|
||||||
<a href="#operation-management">经营管理</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="content-sections">
|
|
||||||
<section id="market-research">
|
|
||||||
<h3>市场调研分析</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="brand-design">
|
|
||||||
<h3>品牌设计方案</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="menu-development">
|
|
||||||
<h3>菜品研发计划</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="location-design">
|
|
||||||
<h3>选址与装修设计</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="team-management">
|
|
||||||
<h3>团队人员管理</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="financial-budget">
|
|
||||||
<h3>财务预算规划</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="operation-management">
|
|
||||||
<h3>经营管理策略</h3>
|
|
||||||
<div class="section-content"></div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 加载各部分内容
|
|
||||||
await this.loadFoodSectionContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadWenluContent(container) {
|
|
||||||
// 加载文旅订单班的内容(使用现有的页面)
|
|
||||||
container.innerHTML = `
|
|
||||||
<div class="wenlu-content">
|
|
||||||
<nav class="content-nav">
|
|
||||||
<a href="/pages/overview.html">项目概览</a>
|
|
||||||
<a href="/pages/exhibition.html">展会设计</a>
|
|
||||||
<a href="/pages/marketing.html">市场营销</a>
|
|
||||||
<a href="/pages/operation.html">运营管理</a>
|
|
||||||
<a href="/pages/budget.html">财务预算</a>
|
|
||||||
<a href="/pages/risk.html">风险控制</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="content-frame">
|
|
||||||
<iframe src="/pages/overview.html" frameborder="0"></iframe>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadFoodSectionContent() {
|
|
||||||
// 从markdown文件加载内容
|
|
||||||
try {
|
|
||||||
const response = await fetch('/data/订单班文档资料/食品/notion文稿/中高端个性化轻食店铺经营方案 278d463fce51805081f7cfdc7280f4a4.md');
|
|
||||||
if (response.ok) {
|
|
||||||
const markdown = await response.text();
|
|
||||||
// 这里可以使用markdown解析器将内容转换为HTML
|
|
||||||
this.parseFoodMarkdown(markdown);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载食品内容失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parseFoodMarkdown(markdown) {
|
|
||||||
// 简单的markdown解析(实际项目中建议使用专门的markdown解析库)
|
|
||||||
const sections = markdown.split(/^#{1,3}\s+/m);
|
|
||||||
// 分配内容到各个部分
|
|
||||||
// 这里需要根据实际的markdown结构进行解析
|
|
||||||
}
|
|
||||||
|
|
||||||
initializePageScripts() {
|
|
||||||
// 初始化页面特定的脚本
|
|
||||||
if (window.initOrderClassPage) {
|
|
||||||
window.initOrderClassPage(this.currentRoute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导航到指定订单班
|
|
||||||
navigateTo(orderClass) {
|
|
||||||
if (this.routes[orderClass]) {
|
|
||||||
this.loadRoute(orderClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化路由器
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
window.orderClassRouter = new OrderClassRouter();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 导出给其他模块使用
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
module.exports = OrderClassRouter;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user