ERP/frontend/js/app.js

261 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(() => {
// 应用保存的主题
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);
let currentUser = null;
// 更新用户显示
function updateUserDisplay(user) {
const userNameDisplay = document.getElementById('user-name-display');
const userCard = document.getElementById('user-card');
const username = (user && user.username) ? user.username : '未登录';
if (userNameDisplay) userNameDisplay.textContent = username;
if (userCard) userCard.textContent = username;
// 加载用户头像(如果有设置)
const avatarImg = document.getElementById('user-avatar-img');
if (avatarImg && user && user.avatar) {
avatarImg.src = user.avatar;
} else if (avatarImg) {
avatarImg.src = './assets/user-avatar.svg';
}
// 更新水印
if (user && user.username) {
createWatermark(user.username);
} else {
removeWatermark();
}
}
// 根据用户角色控制菜单显示
function updateMenuVisibility(user) {
// 超级管理员专属菜单
const superadminMenus = document.querySelectorAll('.superadmin-only');
superadminMenus.forEach(menu => {
if (user && user.role === 'superadmin') {
menu.style.display = '';
} else {
menu.style.display = 'none';
}
});
// 计划管理菜单(顶部导航)
const planMenu = document.querySelector('[data-menu="plan"]');
if (planMenu) {
if (user && user.role === 'superadmin') {
planMenu.style.display = '';
} else {
planMenu.style.display = 'none';
}
}
}
// 高亮当前活动的导航项
function updateActiveNav(path) {
// 移除所有活动状态
document.querySelectorAll('.topnav-item').forEach(item => item.classList.remove('active'));
document.querySelectorAll('.dropdown-item').forEach(item => item.classList.remove('active'));
// 查找匹配的导航项
const route = path.replace('#', '').replace('/', '');
const activeItem = document.querySelector(`.topnav-item[data-route="${route}"]`) ||
document.querySelector(`.dropdown-item[data-route="${route}"]`);
if (activeItem) {
activeItem.classList.add('active');
// 如果是下拉菜单项,也高亮父菜单
const parentDropdown = activeItem.closest('.topnav-item.has-dropdown');
if (parentDropdown) {
parentDropdown.classList.add('active');
}
}
}
// 创建水印
function createWatermark(username) {
// 检查水印是否启用
const watermarkEnabled = localStorage.getItem('watermarkEnabled');
if (watermarkEnabled === 'false') {
return;
}
removeWatermark();
const watermarkDiv = document.createElement('div');
watermarkDiv.id = 'watermark-container';
watermarkDiv.className = 'watermark';
const now = new Date();
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
const watermarkText = `${username} ${dateStr}`;
// 计算水印平铺
const spacing = 300;
const rows = Math.ceil(window.innerHeight / spacing) + 2;
const cols = Math.ceil(window.innerWidth / spacing) + 2;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
const span = document.createElement('span');
span.className = 'watermark-text';
span.textContent = watermarkText;
span.style.left = `${j * spacing - 100}px`;
span.style.top = `${i * spacing - 100}px`;
watermarkDiv.appendChild(span);
}
}
document.body.appendChild(watermarkDiv);
}
// 移除水印
function removeWatermark() {
const existing = document.getElementById('watermark-container');
if (existing) {
existing.remove();
}
}
Router.onBeforeEach(async (path) => {
document.getElementById('overlay').classList.remove('hidden');
try {
currentUser = await API.me().catch(() => null);
if (!currentUser || !currentUser.username) {
// 未登录,重定向到独立登录页面
window.location.href = './login.html';
return;
}
} catch(e) {}
});
Router.onAfterEach(async (path) => {
document.getElementById('overlay').classList.add('hidden');
updateUserDisplay(currentUser);
// 根据用户角色控制菜单显示
updateMenuVisibility(currentUser);
// 高亮当前导航项
updateActiveNav(path);
// 初始化通知系统(超级管理员和管理员)
if (currentUser && (currentUser.role === 'superadmin' || currentUser.role === 'admin') && window.NotificationSystem) {
window.NotificationSystem.init();
}
});
Router.init();
API.me().then(user => {
currentUser = user;
updateUserDisplay(user);
updateMenuVisibility(user);
// 初始化通知系统(超级管理员和管理员)
if (user && (user.role === 'superadmin' || user.role === 'admin') && window.NotificationSystem) {
window.NotificationSystem.init();
}
}).catch(() => {
// 未登录,重定向到独立登录页面
window.location.href = './login.html';
});
// 用户头像按钮点击事件 - 显示/隐藏下拉菜单
const userAvatarBtn = document.getElementById('user-avatar-btn');
const userDropdown = document.getElementById('user-dropdown');
userAvatarBtn?.addEventListener('click', (e) => {
e.stopPropagation();
const isVisible = userDropdown.style.display !== 'none';
userDropdown.style.display = isVisible ? 'none' : 'block';
});
// 点击页面其他地方关闭下拉菜单
document.addEventListener('click', (e) => {
if (userDropdown && !userDropdown.contains(e.target) && e.target !== userAvatarBtn) {
userDropdown.style.display = 'none';
}
});
// 退出登录
const logoutBtn = document.getElementById('user-dropdown-logout');
logoutBtn?.addEventListener('click', () => {
// 清理通知系统
if (window.NotificationSystem) {
window.NotificationSystem.cleanup();
}
API.logout()
.then(() => {
currentUser = null;
removeWatermark();
updateUserDisplay(null);
userDropdown.style.display = 'none';
// 重定向到独立登录页面
window.location.href = './login.html';
})
.catch(() => {});
});
// 顶部导航下拉菜单点击切换(移动端或点击常显示)
document.querySelectorAll('.topnav-item.has-dropdown').forEach(item => {
item.addEventListener('click', (e) => {
// 如果点击的是下拉菜单内的链接,不处理
if (e.target.closest('.topnav-dropdown')) return;
// 切换open状态
const isOpen = item.classList.contains('open');
// 关闭其他打开的菜单
document.querySelectorAll('.topnav-item.has-dropdown.open').forEach(other => {
if (other !== item) other.classList.remove('open');
});
item.classList.toggle('open', !isOpen);
});
});
// 点击页面其他地方关闭下拉菜单
document.addEventListener('click', (e) => {
if (!e.target.closest('.topnav-item.has-dropdown')) {
document.querySelectorAll('.topnav-item.has-dropdown.open').forEach(item => {
item.classList.remove('open');
});
}
});
// 主题切换
const themeToggleCheckbox = document.getElementById('theme-toggle-checkbox');
// 初始化 checkbox 状态dark = checked
if (themeToggleCheckbox) {
themeToggleCheckbox.checked = savedTheme === 'dark';
}
// 主题切换事件
themeToggleCheckbox?.addEventListener('change', () => {
const newTheme = themeToggleCheckbox.checked ? 'dark' : 'light';
localStorage.setItem('theme', newTheme);
document.documentElement.setAttribute('data-theme', newTheme);
API.toast(`已切换到${newTheme === 'dark' ? '深色' : '浅色'}主题`);
// 触发自定义事件,通知其他组件主题已更改
window.dispatchEvent(new CustomEvent('themeChanged', { detail: { theme: newTheme } }));
});
// 暴露更新用户显示的函数,供设置页面使用
window.updateUserDisplay = updateUserDisplay;
// 暴露水印控制函数
window.toggleWatermark = function(enabled) {
localStorage.setItem('watermarkEnabled', enabled ? 'true' : 'false');
if (enabled && currentUser && currentUser.username) {
createWatermark(currentUser.username);
} else {
removeWatermark();
}
};
})();