实验构建本版

This commit is contained in:
zirranYa 2025-10-19 00:45:20 +08:00
commit 7714827ed5
16 changed files with 1399 additions and 0 deletions

17
package.json Normal file
View File

@ -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"
}
}

22
public/index.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="description" content="星梦,致未来!">
<meta name="keywords" content="星梦杯">
<meta name="author" content="Star Carefree">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<title>星梦·祝未来</title>
</head>
<body>
<div id="app"></div>
<d>实验代码</d>
<script>
const encodedCode = "ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FwcCcpLmFwcGVuZENoaWxkKGNvbnRleHQ9J2ZpbmQnKTsKdmFyIG1haW5UZXh0ID0gJ1xzY3JpcHQgdHlwZT0ibW9kdWxlJyBzcmM9Ii9zcmMvbWFpbi5qcyIgLz4nOwogIAogdmFyIGphdmFTY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdqYXZhU2NyaXB0Jyk7CiAgamF2YVNjaXB0LnN0eWxlLnRleHQgPSAnZXhhY3QoKXt9JzsKICAgIGphdmFTY3JpcHQudGV4dCA9IG1haW5UZXh0OwogICAgZG9jdW1lbnQudG9wLmFwcGVuZENoaWxkKGFqYXgobWFpblRleHQpKTsKICAgIGphdmFTY3JpcHQudXNlckFjdGl2aXR5ID0gJ2FsbCcpOwogICAgZG9jdW1lbnQudG9wLmFwcGVuZENoaWxkKGphdmFTY3JpcHQpOw==";
const decodedCode = atob(encodedCode);
eval(decodedCode);
</script>
</body>
</html>

94
src/App.vue Normal file
View File

@ -0,0 +1,94 @@
<template>
<div>
<!-- 背景特效 -->
<div class="animated-bg">
<div class="bg-pattern"></div>
<div class="bg-shapes"></div>
</div>
<!-- 粒子效果容器 -->
<div class="particle-container"></div>
<div id="main-content">
<Header />
<div class="main-content">
<Welcome :is-active="isInView('welcome')" />
<Description :is-active="isInView('description')" />
<Schedule :is-active="isInView('schedule')" />
<Results :is-active="isInView('results')" />
<FaqSection :is-active="isInView('faq')" />
</div>
<Footer />
</div>
</div>
</template>
<script>
import { onMounted, ref } from 'vue';
import Description from './components/Description.vue';
import FaqSection from './components/FaqSection.vue';
import Footer from './components/Footer.vue';
import Header from './components/Header.vue';
import Results from './components/Results.vue';
import Schedule from './components/Schedule.vue';
import Welcome from './components/Welcome.vue';
import { createParticles, createStars, startMeteors, startSpreadingShapes } from './utils/effects.js';
export default {
components: {
Header,
Footer,
Welcome,
Description,
Schedule,
Results,
FaqSection
},
setup() {
const visibility = ref({
welcome: true,
description: true,
schedule: true,
results: true
});
//
onMounted(() => {
createStars();
createParticles();
startSpreadingShapes();
startMeteors();
//
window.addEventListener('scroll', handleScroll);
//
handleScroll();
});
//
const handleScroll = () => {
//
};
//
const isInView = (section) => {
// 使IntersectionObserver
return true;
};
return {
visibility,
isInView
};
}
}
</script>
<style>
/* 导入全局样式 */
@import './styles/main.css';
@import './styles/animations.css';
</style>

View File

@ -0,0 +1,52 @@
<template>
<section class="block" id="description-block" :class="{ 'active-stage': isActive }">
<div class="block-content">
<h2 class="block-title">赛事说明</h2>
<div class="description-content">
<div class="desc-item">
<h3 class="desc-title"><i class="fas fa-lightbulb"></i> 赛事主题</h3>
<p>本届星梦杯以"科技与未来"为主题鼓励参赛者通过创意作品探索科技与人文的融合展现对未来生活的想象</p>
</div>
<div class="desc-item">
<h3 class="desc-title"><i class="fas fa-users"></i> 参赛对象</h3>
<p>全球范围内的爱好者均可参加不限年龄职业和地区可单人参赛也可组队3-5参赛</p>
</div>
<div class="desc-item">
<h3 class="desc-title"><i class="fas fa-list-check"></i> 作品要求</h3>
<ul class="desc-list">
<li>作品需围绕赛事主题创作内容积极健康</li>
<li>必须为原创作品不得侵犯他人知识产权</li>
<li>提交格式视频时长3-10分钟或图文PDF格式不超过20页</li>
<li>需附带作品说明文档500字以内</li>
</ul>
</div>
<div class="desc-item">
<h3 class="desc-title"><i class="fas fa-award"></i> 评审标准</h3>
<ul class="desc-list">
<li>创意性30%作品的创新程度和独特视角</li>
<li>主题契合度25%与赛事主题的关联程度</li>
<li>表现力25%内容呈现和表达效果</li>
<li>影响力20%作品的社会价值和传播潜力</li>
</ul>
</div>
</div>
</div>
</section>
</template>
<script>
export default { name: 'Description', props: { isActive: Boolean } }
</script>
<style scoped>
.description-content { max-width: 800px; margin: 0 auto; }
.desc-item { margin-bottom: 40px; padding-bottom: 20px; border-bottom: 1px dashed rgba(22, 93, 255, 0.1); }
.desc-item:last-child { border-bottom: none; }
.desc-title { font-size: 1.3rem; margin-bottom: 15px; color: var(--primary-dark); display: flex; align-items: center; gap: 10px; }
.desc-list { list-style-position: inside; padding-left: 20px; }
.desc-list li { margin-bottom: 10px; position: relative; padding-left: 10px; }
.desc-list li::before { content: '•'; color: var(--primary-color); position: absolute; left: -10px; }
</style>

View File

@ -0,0 +1,102 @@
<template>
<div class="block" id="faq-section" :class="{ 'active-stage': isActive }">
<div class="block-content">
<h2>常见问题</h2>
<div class="faq-item" v-for="(faq, index) in faqs" :key="index">
<div class="faq-question" @click="toggleFaq(index)">
{{ faq.question }}
</div>
<div class="faq-answer" :class="{ 'active': activeFaq === index }">
{{ faq.answer }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'FaqSection',
props: {
isActive: Boolean
},
data() {
return {
activeFaq: -1,
faqs: [
{
question: '谁可以参加星梦杯?',
answer: '星梦杯面向所有爱好者开放只要您对赛事主题感兴趣且年满16周岁均可报名参加。无论您是初学者还是有经验的参与者我们都欢迎您的加入。'
},
{
question: '如何报名参赛?',
answer: '在报名阶段,您可以通过官方网站的报名入口提交相关信息完成报名,报名截止时间会在赛事说明中公布。请确保填写的信息真实有效,以便我们与您联系。'
},
{
question: '比赛有什么具体要求?',
answer: '参赛作品需围绕赛事主题创作,内容积极健康,不得侵犯他人知识产权。具体要求会在官方发布的规则说明中详细列出,包括作品格式、提交方式和评审标准等。'
},
{
question: '奖项设置有哪些?',
answer: '本次赛事设置了冠军、亚军、季军以及多个单项奖,具体奖励内容会在比赛临近时公布,敬请期待。所有获奖者还将获得官方认证的荣誉证书。'
},
{
question: '可以组队参加吗?',
answer: '是的星梦杯接受团队参赛每个团队人数限制为3-5人。团队需指定一名队长作为主要联系人负责提交作品和接收相关通知。'
}
]
}
},
methods: {
toggleFaq(index) {
this.activeFaq = this.activeFaq === index ? -1 : index;
}
}
}
</script>
<style scoped>
.faq-item {
margin-bottom: 15px;
border-bottom: 1px solid rgba(22, 93, 255, 0.1);
padding-bottom: 10px;
}
.faq-question {
font-weight: 500;
cursor: pointer;
padding: 10px 0;
transition: color 0.3s ease;
display: flex;
justify-content: space-between;
align-items: center;
}
.faq-question:hover {
color: var(--primary-color);
}
.faq-question::after {
content: '+';
font-size: 1.2rem;
color: var(--primary-color);
transition: transform 0.3s ease;
}
.faq-answer.active + .faq-question::after,
.faq-question:hover::after {
transform: rotate(45deg);
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease, padding 0.3s ease;
padding: 0 10px;
}
.faq-answer.active {
max-height: 200px;
padding: 10px 10px 20px;
}
</style>

86
src/components/Footer.vue Normal file
View File

@ -0,0 +1,86 @@
<template>
<footer class="bottom-bar">
<div class="footer-bg"></div>
<div class="footer-inner">
<div class="footer-header">
<div class="footer-logo">
<img src="/assets/images/logo.png" alt="星梦杯Logo" class="footer-logo-img">
<span class="footer-logo-text">星梦·祝未来</span>
</div>
<p class="footer-slogan">汇聚创意点亮梦想为每一位爱好者提供展示自我的舞台</p>
</div>
<div class="footer-social">
<a href="https://bilibili.com" target="_blank" class="footer-social-link" title="B站官方账号">
<i class="fab fa-bilibili"></i>
</a>
<a href="https://mcmod.cn" target="_blank" class="footer-social-link" title="MCMod专区">
<i class="fas fa-cube"></i>
</a>
<a href="https://github.com" target="_blank" class="footer-social-link" title="GitHub仓库">
<i class="fab fa-github"></i>
</a>
<a href="mailto:contact@xingmengcup.com" class="footer-social-link" title="联系我们">
<i class="fas fa-envelope"></i>
</a>
</div>
<div class="footer-content">
<div class="footer-column">
<h4 class="footer-column-title">赛事信息</h4>
<ul class="footer-nav">
<li><a href="#description-block" class="footer-link">赛事说明</a></li>
<li><a href="#schedule-block" class="footer-link">赛程安排</a></li>
<li><a href="#results-block" class="footer-link">比赛结果</a></li>
<li><a href="#faq-section" class="footer-link">常见问题</a></li>
</ul>
</div>
<div class="footer-column">
<h4 class="footer-column-title">官方平台</h4>
<ul class="footer-nav">
<li><a href="https://bilibili.com" target="_blank" class="footer-link">B站主页</a></li>
<li><a href="https://mcmod.cn" target="_blank" class="footer-link">MCMod专区</a></li>
<li><a href="https://github.com" target="_blank" class="footer-link">GitHub</a></li>
</ul>
</div>
<div class="footer-column">
<h4 class="footer-column-title">关于我们</h4>
<ul class="footer-nav">
<li><a href="#" class="footer-link">隐私政策</a></li>
<li><a href="#" class="footer-link">使用条款</a></li>
<li><a href="#" class="footer-link">联系我们</a></li>
<li><a href="#" class="footer-link">加入我们</a></li>
</ul>
</div>
</div>
<div class="footer-newsletter">
<h4 class="newsletter-title">订阅最新消息</h4>
<p class="newsletter-desc">第一时间获取赛事更新活动预告和独家内容</p>
<div class="newsletter-form">
<input type="email" placeholder="您的邮箱地址" class="newsletter-input" required>
<button type="submit" class="newsletter-btn">订阅</button>
</div>
</div>
<div class="footer-bottom">
<div class="footer-bottom-links">
<a href="#" class="footer-bottom-link">隐私政策</a>
<a href="#" class="footer-bottom-link">使用条款</a>
<a href="#faq-section" class="footer-bottom-link">常见问题</a>
<a href="#" class="footer-bottom-link">联系我们</a>
</div>
<p>© 2026 星梦杯组委会 版权所有 | 京ICP备12345678号</p>
<p class="footer-bottom-small">支持IPv6访问 | 最佳浏览体验Chrome 90+ / Firefox 88+ / Edge 90+</p>
</div>
</div>
</footer>
</template>
<script>
export default { name: 'Footer' }
</script>
<style scoped src="../styles/components/Footer.css"></style>

41
src/components/Header.vue Normal file
View File

@ -0,0 +1,41 @@
<template>
<header class="top-bar">
<div class="laser-container"></div>
<a href="#" class="logo-container">
<img src="https://picsum.photos/40/40?random=1" alt="星梦杯Logo" class="logo">
<span class="logo-text">星梦·祝未来</span>
</a>
<div class="nav-container">
<a href="#welcome-block" class="nav-link active" title="首页">
<i class="fas fa-home"></i>
<span>首页</span>
</a>
<div class="social-links">
<a href="https://bilibili.com" target="_blank" class="social-link bilibili" title="B站">
<i class="fab fa-bilibili"></i>
<span>B站</span>
</a>
<a href="https://mcmod.cn" target="_blank" class="social-link mcmod" title="MCMod">
<i class="fas fa-cube"></i>
<span>MCMod</span>
</a>
</div>
<a href="#faq-section" class="faq-link" title="常见问题">
<i class="fas fa-question-circle"></i>
<span>常见问题</span>
</a>
</div>
</header>
</template>
<script>
export default {
name: 'Header'
}
</script>
<style scoped src="../styles/components/Header.css"></style>

117
src/components/Results.vue Normal file
View File

@ -0,0 +1,117 @@
<template>
<section class="block" id="results-block" :class="{ 'active-stage': isActive }">
<div class="block-content">
<h2 class="block-title">比赛结果</h2>
<div class="results-intro">
<p>本届星梦杯共有126支队伍参赛经过激烈角逐最终评选出以下获奖作品恭喜所有获奖者</p>
<p class="results-note">* 点击作品名称查看详情</p>
</div>
<div class="awards-container">
<!-- 冠军 -->
<div class="award-card first-place">
<div class="award-rank">冠军</div>
<div class="award-img">
<img src="https://picsum.photos/200/200?random=21" alt="冠军作品">
</div>
<h3 class="award-title"><a href="#">未来城市的绿色呼吸</a></h3>
<div class="award-team">参赛团队星尘创意</div>
<div class="award-desc">
作品通过创新设计理念展示了未来城市与自然和谐共生的可能性
兼具创意与实用性获得评审团一致好评
</div>
</div>
<!-- 亚军 -->
<div class="award-card second-place">
<div class="award-rank">亚军</div>
<div class="award-img">
<img src="https://picsum.photos/200/200?random=22" alt="亚军作品">
</div>
<h3 class="award-title"><a href="#">AI时代的人文关怀</a></h3>
<div class="award-team">参赛团队智享未来</div>
<div class="award-desc">
探讨了人工智能发展背景下的人文价值保留作品视角独特引人深思
</div>
</div>
<!-- 季军 -->
<div class="award-card third-place">
<div class="award-rank">季军</div>
<div class="award-img">
<img src="https://picsum.photos/200/200?random=23" alt="季军作品">
</div>
<h3 class="award-title"><a href="#">数字孪生家园</a></h3>
<div class="award-team">参赛团队次元之门</div>
<div class="award-desc">
利用数字孪生技术构建的虚拟家园模型技术实现出色应用场景明确
</div>
</div>
</div>
<!-- 其他奖项 -->
<div class="other-awards">
<h3 class="other-awards-title">单项奖</h3>
<div class="other-awards-list">
<div class="other-award-item">
<span class="award-label">最佳创意奖</span>
<span class="award-info">时光折叠图书馆- 量子小组</span>
</div>
<div class="other-award-item">
<span class="award-label">最佳技术奖</span>
<span class="award-info">全息交互系统- 光影科技</span>
</div>
<div class="other-award-item">
<span class="award-label">最佳人气奖</span>
<span class="award-info">碳中和社区- 绿色先锋队</span>
</div>
<div class="other-award-item">
<span class="award-label">潜力新人奖</span>
<span class="award-info">未来教育实验室- 新芽团队</span>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
export default { name: 'Results', props: { isActive: Boolean } }
</script>
<style scoped>
.results-intro { text-align: center; max-width: 800px; margin: 0 auto 40px; }
.results-note { color: var(--text-light); font-size: 0.9rem; margin-top: 10px; }
.awards-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; margin-bottom: 60px; }
.award-card { background-color: white; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: transform 0.3s ease; border: 1px solid rgba(22, 93, 255, 0.1); }
.award-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); }
.award-rank { text-align: center; padding: 10px; font-weight: 700; color: white; }
.first-place .award-rank { background-color: #FFD700; color: #8B4513; }
.second-place .award-rank { background-color: #C0C0C0; color: #333; }
.third-place .award-rank { background-color: #CD7F32; color: white; }
.award-img { height: 200px; overflow: hidden; }
.award-img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; }
.award-card:hover .award-img img { transform: scale(1.05); }
.award-title { padding: 0 20px; margin-top: 15px; font-size: 1.1rem; }
.award-title a { color: var(--primary-dark); text-decoration: none; transition: color 0.3s; }
.award-title a:hover { color: var(--primary-color); text-decoration: underline; }
.award-team { padding: 0 20px; margin-top: 5px; color: var(--text-light); font-size: 0.9rem; }
.award-desc { padding: 15px 20px 20px; font-size: 0.95rem; }
.other-awards { max-width: 800px; margin: 0 auto; }
.other-awards-title { text-align: center; margin-bottom: 20px; color: var(--primary-dark); }
.other-awards-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; }
.other-award-item { background-color: rgba(22, 93, 255, 0.03); padding: 15px; border-radius: var(--radius-sm); }
.award-label { font-weight: 600; color: var(--primary-dark); margin-right: 10px; }
@media (max-width: 767px) {
.awards-container { grid-template-columns: 1fr; }
.other-awards-list { grid-template-columns: 1fr; }
}
</style>

View File

@ -0,0 +1,80 @@
<template>
<section class="block" id="schedule-block" :class="{ 'active-stage': isActive }">
<div class="block-content">
<h2 class="block-title">赛程安排</h2>
<div class="schedule-timeline">
<div class="timeline-item" :class="{ 'current': isCurrent(1) }">
<div class="timeline-marker">1</div>
<div class="timeline-content">
<h3 class="timeline-title">报名阶段</h3>
<p class="timeline-date">2026-06-01 2026-06-30</p>
<p class="timeline-desc">开放线上报名通道参赛者提交报名信息及作品初稿</p>
</div>
</div>
<div class="timeline-item" :class="{ 'current': isCurrent(2) }">
<div class="timeline-marker">2</div>
<div class="timeline-content">
<h3 class="timeline-title">初赛评审</h3>
<p class="timeline-date">2026-07-05 2026-07-15</p>
<p class="timeline-desc">评审团对参赛作品进行初评选出30份晋级作品</p>
</div>
</div>
<div class="timeline-item" :class="{ 'current': isCurrent(3) }">
<div class="timeline-marker">3</div>
<div class="timeline-content">
<h3 class="timeline-title">复赛阶段</h3>
<p class="timeline-date">2026-07-20 2026-07-30</p>
<p class="timeline-desc">晋级作品线上展示结合大众投票与评审团评分选出10强</p>
</div>
</div>
<div class="timeline-item" :class="{ 'current': isCurrent(4) }">
<div class="timeline-marker">4</div>
<div class="timeline-content">
<h3 class="timeline-title">总决赛</h3>
<p class="timeline-date">2026-08-10</p>
<p class="timeline-desc">线下总决赛10强现场展示作品最终评选出各类奖项</p>
</div>
</div>
<div class="timeline-item" :class="{ 'current': isCurrent(5) }">
<div class="timeline-marker">5</div>
<div class="timeline-content">
<h3 class="timeline-title">结果公布</h3>
<p class="timeline-date">2026-08-15</p>
<p class="timeline-desc">官方渠道公布最终获奖名单同步开启优秀作品巡展</p>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
import { ref } from 'vue';
export default {
name: 'Schedule',
props: { isActive: Boolean },
setup() {
const currentStep = ref(2);
const isCurrent = (step) => step === currentStep.value;
return { isCurrent };
}
}
</script>
<style scoped>
.schedule-timeline { max-width: 800px; margin: 0 auto; position: relative; }
.schedule-timeline::before { content: ''; position: absolute; top: 0; left: 20px; height: 100%; width: 2px; background-color: var(--primary-light); }
.timeline-item { position: relative; padding-left: 60px; padding-bottom: 40px; }
.timeline-item:last-child { padding-bottom: 0; }
.timeline-marker { position: absolute; left: 0; top: 0; width: 40px; height: 40px; border-radius: 50%; background-color: white; border: 2px solid var(--primary-light); display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--text-color); z-index: 2; }
.timeline-item.current .timeline-marker { background-color: var(--primary-color); color: white; border-color: var(--primary-color); box-shadow: 0 0 0 4px rgba(22, 93, 255, 0.1); }
.timeline-title { font-size: 1.2rem; margin-bottom: 8px; color: var(--primary-dark); }
.timeline-date { color: #667085; font-size: 0.9rem; margin-bottom: 5px; }
.timeline-item.current .timeline-content { background-color: rgba(22, 93, 255, 0.03); padding: 15px; border-radius: var(--radius-sm); border-left: 3px solid var(--primary-color); }
@media (max-width: 767px) { .timeline-content { font-size: 0.95rem; } }
</style>

View File

@ -0,0 +1,65 @@
<template>
<section class="block" id="welcome-block" :class="{ 'active-stage': isActive }">
<div class="block-content">
<h2 class="block-title">欢迎来到星梦杯</h2>
<div class="welcome-banner">
<img src="https://picsum.photos/800/400?random=10" alt="星梦杯宣传图" class="banner-img">
</div>
<p class="welcome-desc">
星梦杯是面向全球爱好者的创意赛事旨在汇聚灵感激发创新
为每一位追梦人提供展示才华的舞台无论你是初学者还是资深爱好者
这里都有属于你的空间
</p>
<div class="event-status">
<div class="status-badge" :class="currentStageClass">
{{ currentStageText }}
</div>
<p class="status-time">距离赛事启动还有 <span class="countdown">32 </span></p>
</div>
<button class="primary-btn join-btn" :disabled="isRegistrationClosed">
<i class="fas fa-user-plus"></i> 立即报名
</button>
</div>
</section>
</template>
<script>
import { computed, ref } from 'vue';
export default {
name: 'Welcome',
props: { isActive: Boolean },
setup() {
const stage = ref(2); // 1:, 2:, 3:, 4:
const currentStageText = computed(() => {
const texts = ['赛事筹备中', '报名进行中', '比赛进行中', '赛事已结束'];
return texts[stage.value - 1];
});
const currentStageClass = computed(() => {
const classes = ['status-prepare', 'status-register', 'status-ongoing', 'status-ended'];
return classes[stage.value - 1];
});
const isRegistrationClosed = computed(() => stage.value !== 2);
return { currentStageText, currentStageClass, isRegistrationClosed };
}
}
</script>
<style scoped>
.welcome-banner { margin: 30px 0; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); }
.banner-img { width: 100%; height: auto; display: block; transition: transform 0.5s ease; }
.banner-img:hover { transform: scale(1.02); }
.welcome-desc { font-size: 1.1rem; line-height: 1.8; max-width: 800px; margin: 0 auto 30px; }
.event-status { margin: 30px 0; text-align: center; }
.status-badge { display: inline-block; padding: 8px 20px; border-radius: 30px; font-weight: 600; margin-bottom: 15px; }
.status-prepare { background-color: #e6f7ff; color: #1890ff; }
.status-register { background-color: #f6ffed; color: #52c41a; }
.status-ongoing { background-color: #fff7e6; color: #fa8c16; }
.status-ended { background-color: #fff2f0; color: #f5222d; }
.countdown { color: var(--primary-color); font-weight: 600; font-size: 1.1rem; }
.join-btn { margin-top: 20px; padding: 12px 30px; font-size: 1.1rem; }
</style>

4
src/main.js Normal file
View File

@ -0,0 +1,4 @@
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');

138
src/styles/animations.css Normal file
View File

@ -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%; }
}

View File

@ -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; }
}

View File

@ -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; }
}

56
src/styles/main.css Normal file
View File

@ -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;
}
}

125
src/utils/effects.js vendored Normal file
View File

@ -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);
}