M23环节1公告轮播+卡片交互+状态动态化完成
This commit is contained in:
parent
ebeee8c424
commit
e00171e073
123
homepage/app.js
123
homepage/app.js
|
|
@ -1,8 +1,33 @@
|
||||||
/**
|
/**
|
||||||
* app.js - 光湖首页导航中心
|
* app.js - 光湖首页导航中心
|
||||||
* M23 环节0 · 模块卡片渲染 + 状态指示
|
* M23 环节1 · 公告轮播 + 卡片交互 + 状态动态化
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// 公告轮播数据(Mock数据,未来对接M22真实API)
|
||||||
|
const announcements = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "光湖实验室v1.0开发中",
|
||||||
|
content: "全团队并行推进,多模块同步建设",
|
||||||
|
date: "2026-03-13",
|
||||||
|
type: "update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "模块进度总览",
|
||||||
|
content: "4个模块在线 · 2个建设中",
|
||||||
|
date: "2026-03-13",
|
||||||
|
type: "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "欢迎新开发者",
|
||||||
|
content: "零点原核频道持续壮大",
|
||||||
|
date: "2026-03-13",
|
||||||
|
type: "welcome"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
// 模块卡片数据
|
// 模块卡片数据
|
||||||
const moduleCards = [
|
const moduleCards = [
|
||||||
{
|
{
|
||||||
|
|
@ -51,10 +76,16 @@ const moduleCards = [
|
||||||
|
|
||||||
// 首页应用对象
|
// 首页应用对象
|
||||||
window.HomepageApp = {
|
window.HomepageApp = {
|
||||||
|
currentAnnouncementIndex: 0,
|
||||||
|
carouselInterval: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.renderCards();
|
this.renderCards();
|
||||||
|
this.renderCarousel();
|
||||||
|
this.startCarousel();
|
||||||
|
this.bindEvents();
|
||||||
this.updateStatusBar();
|
this.updateStatusBar();
|
||||||
console.log('✅ 首页初始化完成');
|
console.log('✅ 首页初始化完成 · 15连胜版');
|
||||||
},
|
},
|
||||||
|
|
||||||
// 渲染卡片
|
// 渲染卡片
|
||||||
|
|
@ -63,20 +94,102 @@ window.HomepageApp = {
|
||||||
if (!grid) return;
|
if (!grid) return;
|
||||||
|
|
||||||
const cardsHTML = moduleCards.map(card => `
|
const cardsHTML = moduleCards.map(card => `
|
||||||
<div class="card">
|
<div class="card" data-module-id="${card.id}" data-module-path="${card.path}">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-icon">${card.icon}</div>
|
<div class="card-icon">${card.icon}</div>
|
||||||
<span class="card-name">${card.name}</span>
|
<span class="card-name">${card.name}</span>
|
||||||
<span class="card-status ${card.status}">${card.status === 'online' ? '在线' : '建设中'}</span>
|
<span class="card-status ${card.status}">${card.status === 'online' ? '在线' : '建设中'}</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="${card.path}" class="card-link">进入模块 →</a>
|
<span class="card-link">进入模块 →</span>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
grid.innerHTML = cardsHTML;
|
grid.innerHTML = cardsHTML;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 更新状态栏(后续可对接真实API)
|
// 渲染轮播
|
||||||
|
renderCarousel() {
|
||||||
|
const carousel = document.getElementById('announcementCarousel');
|
||||||
|
if (!carousel) return;
|
||||||
|
|
||||||
|
const announcement = announcements[this.currentAnnouncementIndex];
|
||||||
|
carousel.innerHTML = `
|
||||||
|
<div class="carousel-item">
|
||||||
|
<div class="carousel-title">📢 ${announcement.title}</div>
|
||||||
|
<div class="carousel-content">${announcement.content}</div>
|
||||||
|
<div class="carousel-date">${announcement.date}</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 启动轮播(自动4秒切换)
|
||||||
|
startCarousel() {
|
||||||
|
if (this.carouselInterval) clearInterval(this.carouselInterval);
|
||||||
|
this.carouselInterval = setInterval(() => {
|
||||||
|
this.nextAnnouncement();
|
||||||
|
}, 4000);
|
||||||
|
console.log('🔄 轮播已启动,4秒自动切换');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下一条公告
|
||||||
|
nextAnnouncement() {
|
||||||
|
this.currentAnnouncementIndex = (this.currentAnnouncementIndex + 1) % announcements.length;
|
||||||
|
this.renderCarousel();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上一条公告
|
||||||
|
prevAnnouncement() {
|
||||||
|
this.currentAnnouncementIndex = (this.currentAnnouncementIndex - 1 + announcements.length) % announcements.length;
|
||||||
|
this.renderCarousel();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 模块跳转
|
||||||
|
navigateTo(moduleId) {
|
||||||
|
const module = moduleCards.find(m => m.id === moduleId);
|
||||||
|
if (module) {
|
||||||
|
console.log(`🧭 跳转到模块: ${module.name} | 路径: ${module.path}`);
|
||||||
|
} else {
|
||||||
|
console.log(`⚠️ 未找到模块: ${moduleId}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 绑定事件
|
||||||
|
bindEvents() {
|
||||||
|
// 卡片点击事件
|
||||||
|
document.querySelectorAll('.card').forEach(card => {
|
||||||
|
card.addEventListener('click', (e) => {
|
||||||
|
const moduleId = card.dataset.moduleId;
|
||||||
|
const modulePath = card.dataset.modulePath;
|
||||||
|
console.log(`🖱️ 点击卡片: ${moduleId} | 路径: ${modulePath}`);
|
||||||
|
this.navigateTo(moduleId);
|
||||||
|
// 未来这里会实现实际跳转:window.location.href = modulePath;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 轮播箭头点击
|
||||||
|
document.getElementById('carouselPrev')?.addEventListener('click', () => {
|
||||||
|
console.log('◀️ 点击左箭头');
|
||||||
|
this.prevAnnouncement();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('carouselNext')?.addEventListener('click', () => {
|
||||||
|
console.log('▶️ 点击右箭头');
|
||||||
|
this.nextAnnouncement();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 键盘事件
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'ArrowLeft') {
|
||||||
|
console.log('⌨️ 键盘左箭头');
|
||||||
|
this.prevAnnouncement();
|
||||||
|
} else if (e.key === 'ArrowRight') {
|
||||||
|
console.log('⌨️ 键盘右箭头');
|
||||||
|
this.nextAnnouncement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新状态栏
|
||||||
updateStatusBar() {
|
updateStatusBar() {
|
||||||
const onlineCount = moduleCards.filter(c => c.status === 'online').length;
|
const onlineCount = moduleCards.filter(c => c.status === 'online').length;
|
||||||
const totalCount = moduleCards.length;
|
const totalCount = moduleCards.length;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,14 @@
|
||||||
<p class="hero-description">探索未来之域 · 零点原核频道</p>
|
<p class="hero-description">探索未来之域 · 零点原核频道</p>
|
||||||
<a href="#" class="hero-btn">进入系统</a>
|
<a href="#" class="hero-btn">进入系统</a>
|
||||||
</header>
|
</header>
|
||||||
|
<!-- 公告轮播区(新增) -->
|
||||||
|
<div class="carousel-container">
|
||||||
|
<div class="carousel" id="announcementCarousel">
|
||||||
|
<!-- 轮播内容由 JS 动态生成 -->
|
||||||
|
</div>
|
||||||
|
<button class="carousel-arrow left" id="carouselPrev">←</button>
|
||||||
|
<button class="carousel-arrow right" id="carouselNext">→</button>
|
||||||
|
</div>
|
||||||
<!-- 模块导航网格 -->
|
<!-- 模块导航网格 -->
|
||||||
<section class="modules">
|
<section class="modules">
|
||||||
<h2 class="section-title">核心模块</h2>
|
<h2 class="section-title">核心模块</h2>
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ body {
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
animation: cardFadeIn 0.5s ease forwards;
|
animation: cardFadeIn 0.5s ease forwards;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover {
|
.card:hover {
|
||||||
|
|
@ -260,4 +261,177 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 公告轮播区样式 ===== */
|
||||||
|
.carousel-container {
|
||||||
|
position: relative;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 2rem;
|
||||||
|
padding: 2rem;
|
||||||
|
margin: 2rem 0 3rem;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
animation: fadeIn 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel {
|
||||||
|
min-height: 100px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-title {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: var(--accent);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-content {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-date {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow:hover {
|
||||||
|
background: var(--accent);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow.left {
|
||||||
|
left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow.right {
|
||||||
|
right: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 卡片悬停效果增强 ===== */
|
||||||
|
.card {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-8px) scale(1.02);
|
||||||
|
border-color: var(--accent);
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 状态标签动态化 ===== */
|
||||||
|
.card-status.online {
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-status.building {
|
||||||
|
animation: flicker 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
box-shadow: 0 0 0 10px rgba(16, 185, 129, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flicker {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.6;
|
||||||
|
box-shadow: 0 0 10px rgba(245, 158, 11, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 响应式调整 ===== */
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.carousel-container {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow.left {
|
||||||
|
left: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-arrow.right {
|
||||||
|
right: -10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 暴力增强版(确保生效)===== */
|
||||||
|
.card {
|
||||||
|
cursor: pointer !important;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-10px) scale(1.05) !important;
|
||||||
|
border-color: var(--accent) !important;
|
||||||
|
box-shadow: 0 30px 50px rgba(59, 130, 246, 0.5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-status.online {
|
||||||
|
animation: pulse 1.5s infinite !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-status.building {
|
||||||
|
animation: flicker 1s infinite !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 20px 10px rgba(16, 185, 129, 0.3);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flicker {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
text-shadow: 0 0 5px rgba(245, 158, 11, 0.5);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
text-shadow: 0 0 15px rgba(245, 158, 11, 0.8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue