commit 7714827ed523a3e50c72f008be673d1a2d9449d4 Author: zirranYa <16774996@qq.com> Date: Sun Oct 19 00:45:20 2025 +0800 实验构建本版 diff --git a/package.json b/package.json new file mode 100644 index 0000000..c1a7acf --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "star-dream", + "version": "1.0.0", + "description": "星梦杯赛事官网", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.3.4" + }, + "devDependencies": { + "vite": "^4.4.5" + } + } \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..8699f53 --- /dev/null +++ b/public/index.html @@ -0,0 +1,22 @@ + + + + + + + + + + + 星梦·祝未来 + + +
+实验代码 + + + \ No newline at end of file diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..faf15e0 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,94 @@ + + + + + \ No newline at end of file diff --git a/src/components/Description.vue b/src/components/Description.vue new file mode 100644 index 0000000..83e26f7 --- /dev/null +++ b/src/components/Description.vue @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/src/components/FaqSection.vue b/src/components/FaqSection.vue new file mode 100644 index 0000000..bcd689b --- /dev/null +++ b/src/components/FaqSection.vue @@ -0,0 +1,102 @@ + + + + + \ No newline at end of file diff --git a/src/components/Footer.vue b/src/components/Footer.vue new file mode 100644 index 0000000..3a66c7a --- /dev/null +++ b/src/components/Footer.vue @@ -0,0 +1,86 @@ + + + + + \ No newline at end of file diff --git a/src/components/Header.vue b/src/components/Header.vue new file mode 100644 index 0000000..27c8adc --- /dev/null +++ b/src/components/Header.vue @@ -0,0 +1,41 @@ + + + + + \ No newline at end of file diff --git a/src/components/Results.vue b/src/components/Results.vue new file mode 100644 index 0000000..7e7ae4c --- /dev/null +++ b/src/components/Results.vue @@ -0,0 +1,117 @@ + + + + + \ No newline at end of file diff --git a/src/components/Schedule.vue b/src/components/Schedule.vue new file mode 100644 index 0000000..64aee15 --- /dev/null +++ b/src/components/Schedule.vue @@ -0,0 +1,80 @@ + + + + + \ No newline at end of file diff --git a/src/components/Welcome.vue b/src/components/Welcome.vue new file mode 100644 index 0000000..ca871b2 --- /dev/null +++ b/src/components/Welcome.vue @@ -0,0 +1,65 @@ + + + + + \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..8995ced --- /dev/null +++ b/src/main.js @@ -0,0 +1,4 @@ +import { createApp } from 'vue'; +import App from './App.vue'; + +createApp(App).mount('#app'); \ No newline at end of file diff --git a/src/styles/animations.css b/src/styles/animations.css new file mode 100644 index 0000000..97e025e --- /dev/null +++ b/src/styles/animations.css @@ -0,0 +1,138 @@ +/* 星星特效 */ +.star { + position: absolute; + background-color: white; + border-radius: 50%; + pointer-events: none; + z-index: 0; + animation: twinkle 2s infinite alternate; +} + +@keyframes twinkle { + 0% { opacity: 0.3; transform: scale(0.8); } + 100% { opacity: 1; transform: scale(1); } +} + +/* 扩散动画的形状 - 蓝色主题 */ +.bg-shape { + position: absolute; + border-radius: 50%; + background: radial-gradient(circle, rgba(22, 93, 255, 0.35) 0%, rgba(22, 93, 255, 0) 70%); + transform: translate(-50%, -50%) scale(0); + opacity: 0; + pointer-events: none; + z-index: 0; +} + +/* 流星特效 */ +.meteor { + position: absolute; + width: 2px; + background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.9), rgba(22, 93, 255, 0.7)); + transform-origin: top left; + pointer-events: none; + z-index: 1; + border-radius: 50% 50% 0 0; + box-shadow: 0 0 20px 3px rgba(22, 93, 255, 0.6); +} + +.meteor::after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 40%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8)); + border-radius: 50%; +} + +@keyframes meteor { + 0% { + transform: rotate(var(--angle)) scaleX(0); + opacity: 0; + } + 10% { + transform: rotate(var(--angle)) scaleX(1); + opacity: 1; + } + 80% { + opacity: 1; + } + 100% { + transform: rotate(var(--angle)) scaleX(1); + opacity: 0; + } +} + +/* 扩散动画 */ +@keyframes spread { + 0% { transform: translate(-50%, -50%) scale(0); opacity: 0.8; } + 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; } +} + +/* 蓝色主背景渐变 */ +@keyframes gradientBG { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} + +/* 粒子浮动动画 */ +.particle { + position: absolute; + background-color: rgba(255, 255, 255, 0.6); + border-radius: 50%; + pointer-events: none; + animation: float 10s infinite ease-in-out; +} + +@keyframes float { + 0%, 100% { transform: translateY(0) rotate(0deg); } + 50% { transform: translateY(-20px) rotate(10deg); } +} + +/* 激光脉冲动画 */ +.laser-circle { + position: absolute; + border-radius: 50%; + background: radial-gradient(circle, rgba(22, 93, 255, 0.35) 0%, rgba(22, 93, 255, 0) 70%); + transform: translate(-50%, -50%) scale(0); + animation: laserPulse 5s ease-out forwards; + pointer-events: none; +} + +@keyframes laserPulse { + 0% { transform: translate(-50%, -50%) scale(0); opacity: 0.8; } + 70% { opacity: 0.4; } + 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; } +} + +/* 元素淡入动画 */ +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +/* 区块发光动画 */ +.block::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 3px; + background: linear-gradient(90deg, transparent, var(--primary-color), transparent); + animation: shine 4s infinite; +} + +@keyframes shine { + 100% { left: 100%; } +} + +/* 底部背景动画 */ +@keyframes bottomGradient { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} \ No newline at end of file diff --git a/src/styles/components/Footer.css b/src/styles/components/Footer.css new file mode 100644 index 0000000..ed8edbd --- /dev/null +++ b/src/styles/components/Footer.css @@ -0,0 +1,229 @@ +.bottom-bar { + position: relative; + background-color: #0A1124; + color: white; + padding: 60px 20px 30px; + z-index: 1; +} + +.footer-bg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient(circle at top, rgba(22, 93, 255, 0.15) 0%, transparent 70%); + z-index: -1; +} + +.footer-inner { + max-width: 1200px; + margin: 0 auto; +} + +.footer-header { + text-align: center; + margin-bottom: 40px; +} + +.footer-logo { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + margin-bottom: 15px; +} + +.footer-logo-img { + width: 40px; + height: 40px; + border-radius: 8px; + object-fit: cover; +} + +.footer-logo-text { + font-size: 1.2rem; + font-weight: 600; + color: white; +} + +.footer-slogan { + color: #A9B3C9; + max-width: 600px; + margin: 0 auto; +} + +.footer-social { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 50px; + padding-bottom: 20px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.footer-social-link { + width: 40px; + height: 40px; + border-radius: 50%; + background-color: rgba(255, 255, 255, 0.1); + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 1.1rem; + text-decoration: none; + transition: var(--transition-normal); +} + +.footer-social-link:hover { + background-color: var(--primary-color); + transform: translateY(-3px); +} + +.footer-content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 30px; + margin-bottom: 50px; +} + +.footer-column-title { + font-size: 1.1rem; + margin-bottom: 20px; + color: white; + position: relative; + padding-bottom: 8px; +} + +.footer-column-title::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 30px; + height: 2px; + background-color: var(--primary-color); +} + +.footer-nav { + list-style: none; +} + +.footer-link { + color: #A9B3C9; + text-decoration: none; + display: block; + margin-bottom: 12px; + transition: var(--transition-normal); +} + +.footer-link:hover { + color: white; + transform: translateX(5px); +} + +.footer-newsletter { + max-width: 600px; + margin: 0 auto 50px; + padding: 30px; + background-color: rgba(255, 255, 255, 0.05); + border-radius: var(--radius); + text-align: center; +} + +.newsletter-title { + font-size: 1.1rem; + margin-bottom: 10px; + color: white; +} + +.newsletter-desc { + color: #A9B3C9; + margin-bottom: 20px; + font-size: 0.95rem; +} + +.newsletter-form { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; +} + +.newsletter-input { + padding: 10px 16px; + border: 1px solid rgba(22, 93, 255, 0.3); + border-radius: var(--radius-sm); + min-width: 200px; + flex: 1; + max-width: 350px; + font-size: 1rem; + background-color: rgba(255, 255, 255, 0.08); + color: white; + transition: var(--transition-normal); +} + +.newsletter-input::placeholder { color: #A9B3C9; } +.newsletter-input:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(22, 93, 255, 0.2); +} + +.newsletter-btn { + padding: 10px 24px; + background-color: var(--primary-color); + color: white; + border: none; + border-radius: var(--radius-sm); + font-weight: 500; + cursor: pointer; + transition: var(--transition-normal); + white-space: nowrap; +} + +.newsletter-btn:hover { + background-color: var(--primary-dark); + transform: translateY(-2px); +} + +.footer-bottom { + text-align: center; + padding-top: 30px; + border-top: 1px solid rgba(255, 255, 255, 0.1); + color: #A9B3C9; + font-size: 0.9rem; +} + +.footer-bottom-links { margin-bottom: 15px; } + +.footer-bottom-link { + color: #A9B3C9; + text-decoration: none; + margin: 0 10px; + transition: var(--transition-normal); +} + +.footer-bottom-link:hover { color: white; } + +.footer-bottom-small { + font-size: 0.8rem; + margin-top: 10px; + opacity: 0.8; +} + +/* 响应式调整 */ +@media (max-width: 767px) { + .footer-content { grid-template-columns: 1fr; text-align: center; } + .footer-column-title::after { left: 50%; transform: translateX(-50%); } + .footer-newsletter { padding: 20px 15px; } + .newsletter-input { min-width: 100%; } + .footer-bottom-links { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 10px 15px; + } + .footer-bottom-link { margin: 0; } +} \ No newline at end of file diff --git a/src/styles/components/Header.css b/src/styles/components/Header.css new file mode 100644 index 0000000..1e562b3 --- /dev/null +++ b/src/styles/components/Header.css @@ -0,0 +1,171 @@ +.top-bar { + position: fixed; + top: 0; + left: 0; + width: 100%; + background-color: white; + box-shadow: var(--shadow-sm); + padding: 0 20px; + z-index: 100; + display: flex; + align-items: center; + justify-content: space-between; + height: 70px; +} + +.laser-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: -1; +} + +.logo-container { + display: flex; + align-items: center; + gap: 12px; + text-decoration: none; + height: 100%; + padding: 10px 0; +} + +.logo { + width: 48px; + height: 48px; + border-radius: 8px; + object-fit: cover; +} + +.logo-text { + font-size: 1.2rem; + font-weight: 600; + color: var(--primary-dark); + white-space: nowrap; +} + +.nav-container { + display: flex; + align-items: center; + gap: 5px; + height: 100%; +} + +.nav-link, .faq-link { + display: flex; + align-items: center; + gap: 6px; + padding: 0 15px; + height: 100%; + text-decoration: none; + color: var(--text-color); + font-weight: 500; + transition: var(--transition-normal); + position: relative; +} + +.nav-link:hover, .faq-link:hover { + color: var(--primary-color); + background-color: var(--primary-light); +} + +.nav-link.active, .faq-link.active { + color: var(--primary-color); +} + +.nav-link.active::after, .faq-link.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + background-color: var(--primary-color); +} + +.social-links { + display: flex; + align-items: center; + margin: 0 10px; +} + +.social-link { + display: flex; + align-items: center; + gap: 6px; + padding: 0 12px; + height: 100%; + text-decoration: none; + color: var(--text-color); + transition: var(--transition-normal); +} + +.social-link:hover { + color: var(--primary-color); + background-color: var(--primary-light); +} + +.menu-toggle { + display: none; + background: none; + border: none; + color: var(--text-color); + font-size: 1.5rem; + cursor: pointer; + padding: 8px; + border-radius: var(--radius-sm); + transition: var(--transition-normal); +} + +.menu-toggle:hover { + color: var(--primary-color); + background-color: var(--primary-light); +} + +/* 移动端样式 */ +@media (max-width: 767px) { + .menu-toggle { display: block; z-index: 101; } + + .nav-container { + position: fixed; + top: 0; + right: -100%; + height: 100vh; + width: 80%; + max-width: 300px; + flex-direction: column; + background-color: white; + box-shadow: -2px 0 10px rgba(0,0,0,0.1); + z-index: 100; + padding: 80px 20px 20px; + transition: right 0.3s ease; + } + + .nav-container.active { right: 0; } + + .social-links { + margin: 15px 0; + width: 100%; + justify-content: center; + border-top: 1px dashed rgba(22, 93, 255, 0.1); + border-bottom: 1px dashed rgba(22, 93, 255, 0.1); + padding: 15px 0; + } + + .nav-link, .faq-link { + width: 100%; + justify-content: center; + padding: 12px 15px; + height: auto; + } + + .nav-link.active::after, .faq-link.active::after { display: none; } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .logo-text { font-size: 1.1rem; } + .nav-link span, .faq-link span, .social-link span { font-size: 0.9rem; } + .nav-link, .faq-link, .social-link { padding: 0 10px; } +} \ No newline at end of file diff --git a/src/styles/main.css b/src/styles/main.css new file mode 100644 index 0000000..b35b696 --- /dev/null +++ b/src/styles/main.css @@ -0,0 +1,56 @@ +:root { + --primary-color: #165DFF; + --primary-dark: #0E42D2; + --primary-light: #E8F3FF; + --light-color: #F0F7FF; + --text-color: #1D2939; + --text-dark: #101828; + --shadow-sm: 0 2px 6px rgba(22, 93, 255, 0.2); + --shadow-md: 0 4px 12px rgba(22, 93, 255, 0.25); + --shadow-lg: 0 8px 24px rgba(22, 93, 255, 0.3); + --transition-normal: all 0.3s ease; + --radius: 12px; + --radius-sm: 8px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + line-height: 1.6; + color: var(--text-color); + background-color: var(--light-color); + padding: 10px; + position: relative; + min-height: 100vh; + overflow-x: hidden; + cursor: default; +} + +#main-content { + max-width: 1200px; + margin: 0 auto; + padding: 0 16px; +} + +.main-content { + width: 100%; +} + +/* 响应式调整 */ +@media (max-width: 767px) { + .footer-content { + flex-direction: column; + align-items: center; + } +} + +@media (max-width: 1023px) and (min-width: 768px) { + .footer-content { + justify-content: space-around; + } +} \ No newline at end of file diff --git a/src/utils/effects.js b/src/utils/effects.js new file mode 100644 index 0000000..0c69d84 --- /dev/null +++ b/src/utils/effects.js @@ -0,0 +1,125 @@ +// 创建星星背景 +export function createStars() { + const shapesContainer = document.querySelector('.bg-shapes'); + if (!shapesContainer) return; + + const starCount = window.innerWidth < 768 ? 50 : 100; + + for (let i = 0; i < starCount; i++) { + const star = document.createElement('div'); + star.classList.add('star'); + + const size = Math.random() * 2 + 1; + const posX = Math.random() * 100; + const posY = Math.random() * 100; + const delay = Math.random() * 5; + + star.style.width = `${size}px`; + star.style.height = `${size}px`; + star.style.left = `${posX}%`; + star.style.top = `${posY}%`; + star.style.animationDelay = `${delay}s`; + + shapesContainer.appendChild(star); + } +} + +// 创建浮动粒子 +export function createParticles() { + const container = document.querySelector('.particle-container'); + if (!container) return; + + const particleCount = window.innerWidth < 768 ? 20 : 40; + + for (let i = 0; i < particleCount; i++) { + const particle = document.createElement('div'); + particle.classList.add('particle'); + + const size = Math.random() * 4 + 1; + const posX = Math.random() * 100; + const posY = Math.random() * 100; + const delay = Math.random() * 10; + const duration = Math.random() * 10 + 10; + + particle.style.width = `${size}px`; + particle.style.height = `${size}px`; + particle.style.left = `${posX}%`; + particle.style.top = `${posY}%`; + particle.style.animationDelay = `${delay}s`; + particle.style.animationDuration = `${duration}s`; + + container.appendChild(particle); + } +} + +// 创建扩散形状 +export function createSpreadingShape() { + const shapesContainer = document.querySelector('.bg-shapes'); + if (!shapesContainer) return; + + const shape = document.createElement('div'); + shape.classList.add('bg-shape'); + + const size = Math.random() * 450 + 200; + const posX = Math.random() * 100; + const posY = Math.random() * 100; + const duration = Math.random() * 6 + 4; + const delay = Math.random() * 1.5; + + shape.style.width = `${size}px`; + shape.style.height = `${size}px`; + shape.style.left = `${posX}%`; + shape.style.top = `${posY}%`; + shape.style.animation = `spread ${duration}s ease-out forwards`; + shape.style.animationDelay = `${delay}s`; + + shapesContainer.appendChild(shape); + + // 动画结束后移除元素 + setTimeout(() => { + shape.remove(); + }, (duration + delay) * 1000); +} + +// 定时创建扩散形状 +export function startSpreadingShapes() { + createSpreadingShape(); + setInterval(createSpreadingShape, 2000); +} + +// 创建流星效果 +export function createMeteor() { + const container = document.querySelector('.bg-shapes'); + if (!container) return; + + const meteor = document.createElement('div'); + meteor.classList.add('meteor'); + + const height = Math.random() * 150 + 100; + const angle = Math.random() * 30 + 45; + const posX = Math.random() * 100; + const posY = Math.random() * 30; + const duration = Math.random() * 2 + 1; + + meteor.style.height = `${height}px`; + meteor.style.left = `${posX}%`; + meteor.style.top = `${posY}%`; + meteor.style.setProperty('--angle', `${angle}deg`); + meteor.style.animation = `meteor ${duration}s linear forwards`; + + container.appendChild(meteor); + + // 动画结束后移除元素 + setTimeout(() => { + meteor.remove(); + }, duration * 1000); +} + +// 定时创建流星 +export function startMeteors() { + setInterval(() => { + if (Math.random() > 0.7) { // 70%概率创建流星 + createMeteor(); + } + }, 5000); +} \ No newline at end of file