将前端文件从html目录迁移到views目录,按功能模块组织 重构认证中间件和路由处理,简化页面权限控制 更新静态资源引用路径,统一使用/public前缀 添加学生仪表板页面,优化移动端显示 移除旧版html和js文件,更新样式和脚本
214 lines
7.1 KiB
JavaScript
214 lines
7.1 KiB
JavaScript
// 首页通用JavaScript功能
|
||
// 主è¦<C3A8>处ç<E2809E>†å¯¼èˆªæ <C3A6>交互ã€<C3A3>页é<C2B5>¢æ»šåŠ¨æ•ˆæžœç‰é€šç”¨åŠŸèƒ½
|
||
|
||
class MainPage {
|
||
constructor() {
|
||
this.init();
|
||
}
|
||
|
||
init() {
|
||
// åˆ<C3A5>始化所有功èƒ? this.initNavbar();
|
||
this.initScrollEffects();
|
||
this.initSmoothScroll();
|
||
this.initBackToTop();
|
||
this.initMobileMenu();
|
||
this.initAuthButtons();
|
||
}
|
||
|
||
// åˆ<C3A5>始化导航æ <C3A6>交互
|
||
initNavbar() {
|
||
const navbar = document.querySelector('.navbar');
|
||
if (!navbar) return;
|
||
|
||
// 滚动时改å<C2B9>˜å¯¼èˆªæ <C3A6>æ ·å¼<C3A5>
|
||
window.addEventListener('scroll', () => {
|
||
if (window.scrollY > 50) {
|
||
navbar.classList.add('navbar-scrolled');
|
||
} else {
|
||
navbar.classList.remove('navbar-scrolled');
|
||
}
|
||
});
|
||
|
||
// åˆ<C3A5>始化当å‰<C3A5>页é<C2B5>¢é«˜äº? this.highlightCurrentPage();
|
||
}
|
||
|
||
// 高亮当å‰<C3A5>页é<C2B5>¢å¯¼èˆªé“¾æŽ¥
|
||
highlightCurrentPage() {
|
||
const currentPath = window.location.pathname;
|
||
const navLinks = document.querySelectorAll('.nav-link');
|
||
|
||
navLinks.forEach(link => {
|
||
const href = link.getAttribute('href');
|
||
if (href && currentPath.includes(href.replace('.html', ''))) {
|
||
link.classList.add('active');
|
||
}
|
||
});
|
||
}
|
||
|
||
// åˆ<C3A5>始化滚动效æž? initScrollEffects() {
|
||
// 滚动时显ç¤?éš<C3A9>è—<C3A8>å…ƒç´
|
||
const observerOptions = {
|
||
root: null,
|
||
rootMargin: '0px',
|
||
threshold: 0.1
|
||
};
|
||
|
||
const observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(entry => {
|
||
if (entry.isIntersecting) {
|
||
entry.target.classList.add('animate-in');
|
||
}
|
||
});
|
||
}, observerOptions);
|
||
|
||
// 观察需è¦<C3A8>动画的元ç´
|
||
document.querySelectorAll('.feature-card, .hero-content').forEach(el => {
|
||
observer.observe(el);
|
||
});
|
||
}
|
||
|
||
// åˆ<C3A5>始化平滑滚åŠ? initSmoothScroll() {
|
||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||
anchor.addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
const targetId = anchor.getAttribute('href');
|
||
if (targetId === '#') return;
|
||
|
||
const targetElement = document.querySelector(targetId);
|
||
if (targetElement) {
|
||
targetElement.scrollIntoView({
|
||
behavior: 'smooth',
|
||
block: 'start'
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// åˆ<C3A5>始化返回顶部按é’? initBackToTop() {
|
||
const backToTopBtn = document.createElement('button');
|
||
backToTopBtn.id = 'backToTop';
|
||
backToTopBtn.innerHTML = '<i class="fas fa-chevron-up"></i>';
|
||
backToTopBtn.title = '返回顶部';
|
||
document.body.appendChild(backToTopBtn);
|
||
|
||
// 滚动时显ç¤?éš<C3A9>è—<C3A8>按钮
|
||
window.addEventListener('scroll', () => {
|
||
if (window.scrollY > 300) {
|
||
backToTopBtn.classList.add('show');
|
||
} else {
|
||
backToTopBtn.classList.remove('show');
|
||
}
|
||
});
|
||
|
||
// 点击返回顶部
|
||
backToTopBtn.addEventListener('click', () => {
|
||
window.scrollTo({
|
||
top: 0,
|
||
behavior: 'smooth'
|
||
});
|
||
});
|
||
}
|
||
|
||
// åˆ<C3A5>始化移动端è<C2AF>œå<C593>•
|
||
initMobileMenu() {
|
||
const navbarToggler = document.querySelector('.navbar-toggler');
|
||
const navbarCollapse = document.querySelector('.navbar-collapse');
|
||
|
||
if (!navbarToggler || !navbarCollapse) return;
|
||
|
||
navbarToggler.addEventListener('click', () => {
|
||
navbarCollapse.classList.toggle('show');
|
||
});
|
||
|
||
// 点击è<C2BB>œå<C593>•项å<C2B9>Žè‡ªåЍ关é—移动è<C2A8>œå<C593>•
|
||
document.querySelectorAll('.navbar-nav .nav-link').forEach(link => {
|
||
link.addEventListener('click', () => {
|
||
if (navbarCollapse.classList.contains('show')) {
|
||
navbarCollapse.classList.remove('show');
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// åˆ<C3A5>始化认è¯<C3A8>按钮状æ€? initAuthButtons() {
|
||
// 检查用户是å<C2AF>¦å·²ç™»å½•
|
||
this.checkLoginStatus().then(user => {
|
||
const loginBtn = document.getElementById('loginBtn');
|
||
const registerBtn = document.getElementById('registerBtn');
|
||
const heroLoginBtn = document.getElementById('heroLoginBtn');
|
||
|
||
if (user) {
|
||
// 用户已登录,显示仪表æ<C2A8>¿æŒ‰é’? // æ ¹æ<C2B9>®ç”¨æˆ·è§’色设置æ£ç¡®çš„仪表æ<C2A8>¿è·¯å¾„
|
||
let dashboardUrl = '/dashboard';
|
||
if (user.role === 'student') {
|
||
dashboardUrl = '/student/dashboard';
|
||
} else if (user.role === 'teacher') {
|
||
dashboardUrl = '/teacher/dashboard';
|
||
} else if (user.role === 'admin') {
|
||
dashboardUrl = '/admin/dashboard';
|
||
}
|
||
|
||
if (loginBtn) {
|
||
loginBtn.textContent = '进入仪表æ<C2A8>?;
|
||
loginBtn.href = dashboardUrl;
|
||
}
|
||
if (heroLoginBtn) {
|
||
heroLoginBtn.textContent = '进入仪表æ<EFBFBD>?;
|
||
heroLoginBtn.href = dashboardUrl;
|
||
}
|
||
if (registerBtn) {
|
||
registerBtn.style.display = 'none';
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 检查登录状� async checkLoginStatus() {
|
||
try {
|
||
const apiBase = window.location.protocol === 'file:' ? 'http://localhost:3000/api' : '/api';
|
||
const response = await fetch(`${apiBase}/auth/me`);
|
||
const data = await response.json();
|
||
return data.success && data.user;
|
||
} catch (error) {
|
||
console.log('用户未登�);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 显示通知
|
||
showNotification(message, type = 'info') {
|
||
// 创建通知元ç´
|
||
const notification = document.createElement('div');
|
||
notification.className = `notification notification-${type}`;
|
||
notification.innerHTML = `
|
||
<div class="notification-content">
|
||
<i class="fas ${type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : 'fa-info-circle'}"></i>
|
||
<span>${message}</span>
|
||
</div>
|
||
`;
|
||
|
||
// æ·»åŠ åˆ°é¡µé<C2B5>? document.body.appendChild(notification);
|
||
|
||
// 显示通知
|
||
setTimeout(() => {
|
||
notification.classList.add('show');
|
||
}, 10);
|
||
|
||
// 自动éš<C3A9>è—<C3A8>
|
||
setTimeout(() => {
|
||
notification.classList.remove('show');
|
||
setTimeout(() => {
|
||
if (notification.parentNode) {
|
||
notification.parentNode.removeChild(notification);
|
||
}
|
||
}, 300);
|
||
}, 3000);
|
||
}
|
||
}
|
||
|
||
// 页é<C2B5>¢åŠ è½½å®Œæˆ<C3A6>å<EFBFBD>Žåˆ<C3A5>始化
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
new MainPage();
|
||
});
|