class UserInfo extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { this.render(); this.addEventListeners(); this.checkLoginStatus(); } render() { this.shadowRoot.innerHTML = `
用户
用户信息加载中...
用户名 展开
`; } addEventListeners() { const userDropdown = this.shadowRoot.querySelector('.user-dropdown'); const userDropdownToggle = this.shadowRoot.querySelector('.user-dropdown-toggle'); const userIconWrapper = this.shadowRoot.querySelector('.user-icon-wrapper'); // 点击切换下拉菜单 userDropdownToggle.addEventListener('click', (e) => { e.stopPropagation(); userDropdown.classList.toggle('active'); }); // 点击其他地方关闭下拉菜单 document.addEventListener('click', () => { userDropdown.classList.remove('active'); }); // 处理下拉菜单项点击 const dropdownItems = this.shadowRoot.querySelectorAll('.dropdown-item'); dropdownItems.forEach(item => { item.addEventListener('click', (e) => { e.stopPropagation(); const action = item.getAttribute('data-action'); this.handleDropdownAction(action); userDropdown.classList.remove('active'); }); }); // 处理tooltip的定位 userIconWrapper.addEventListener('mouseenter', () => { const tooltip = this.shadowRoot.querySelector('.tooltip'); const rect = userIconWrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); // 检查右边界 if (rect.left + tooltipRect.width > window.innerWidth) { // 计算tooltip应该距离右边界的位置 const rightEdge = window.innerWidth; const tooltipWidth = tooltipRect.width; tooltip.style.position = 'fixed'; tooltip.style.left = 'auto'; tooltip.style.right = '0'; tooltip.style.transform = 'none'; tooltip.style.margin = '0'; tooltip.style.top = `${rect.bottom + 8}px`; } else { tooltip.style.position = 'absolute'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.transform = 'translateX(-50%)'; tooltip.style.margin = '8px 0 0 0'; tooltip.style.top = '100%'; } }); } handleDropdownAction(action) { switch(action) { case 'profile': this.dispatchEvent(new CustomEvent('menu-action', { detail: { action: 'profile' }, bubbles: true, composed: true })); break; case 'users': this.dispatchEvent(new CustomEvent('menu-action', { detail: { action: 'users' }, bubbles: true, composed: true })); break; case 'logout': this.logout(); break; } } async checkLoginStatus() { try { const response = await fetch('/api/check-auth', { credentials: 'include' }); const result = await response.json(); if (result.success) { this.updateUserInfo(result.user); } else { document.getElementById('authContainer').style.display = 'block'; document.getElementById('mainContainer').style.display = 'none'; } } catch (error) { console.error('获取用户信息失败:', error); document.getElementById('authContainer').style.display = 'block'; document.getElementById('mainContainer').style.display = 'none'; } } updateUserInfo(userInfo) { // 设置用户名 this.shadowRoot.getElementById('userName').textContent = userInfo.username; // 设置用户图标和tooltip信息 const userIcon = this.shadowRoot.getElementById('userIcon'); const userTooltip = this.shadowRoot.getElementById('userTooltip'); // 使用用户自定义图标 if (userInfo.icon && userInfo.icon.trim() !== '') { const base64Data = userInfo.icon.trim(); // 检查Base64数据是否有效且看起来像图片数据 if (base64Data.length > 100 && /^[A-Za-z0-9+/]*={0,2}$/.test(base64Data)) { // 根据Base64数据开头判断图片格式 let mimeType = 'image/jpeg'; // 默认 if (base64Data.startsWith('iVBORw0KGgo')) { mimeType = 'image/png'; } else if (base64Data.startsWith('R0lGODlh')) { mimeType = 'image/gif'; } else if (base64Data.startsWith('UklGR')) { mimeType = 'image/webp'; } userIcon.src = `data:${mimeType};base64,${base64Data}`; } else { console.warn('无效的图片Base64数据格式,使用默认头像'); userIcon.src = 'assets/icons/png/user_b.png'; } } else { // 如果没有自定义图标,使用默认用户图标 userIcon.src = 'assets/icons/png/user_b.png'; } userIcon.alt = userInfo.username; // 添加图片加载错误处理 userIcon.onerror = () => { console.warn('用户头像加载失败,使用默认头像'); console.warn('尝试加载的URL:', userIcon.src); userIcon.src = 'assets/icons/png/user_b.png'; }; // 构建HTML内容 const tooltipContent = `
用户名 ${userInfo.username || '未设置'}
真实姓名 ${userInfo.full_name || '未设置'}
权限级别 ${this.getAccessLevelName(userInfo.access_level)}
所属部门 ${userInfo.department || '未设置'}
职位 ${userInfo.position || '未设置'}
电子邮箱 ${userInfo.email || '未设置'}
联系电话 ${userInfo.phone || '未设置'}
`; userTooltip.innerHTML = tooltipContent; // 控制用户管理选项的显示 const userManagementItem = this.shadowRoot.querySelector('.admin-only'); if (userManagementItem) { userManagementItem.style.display = parseInt(userInfo.access_level) >= 3 ? 'flex' : 'none'; } } getAccessLevelName(accessLevel) { const level = parseInt(accessLevel); switch(level) { case 1: return '普通用户'; case 2: return '开发者'; case 3: return '组长'; case 4: return '管理员'; default: return '访客'; } } async logout() { try { const response = await fetch('/api/logout', { method: 'POST', credentials: 'include' }); if (response.ok) { // 获取认证容器和主容器 const authContainer = document.getElementById('authContainer'); const mainContainer = document.getElementById('mainContainer'); // 先隐藏主容器 mainContainer.classList.remove('visible'); // 等待过渡效果完成 setTimeout(() => { location.reload(); mainContainer.style.display = 'none'; // 显示认证容器 authContainer.style.display = 'block'; // 等待一帧以确保display:block生效 requestAnimationFrame(() => { authContainer.classList.add('visible'); // 重置认证组件 const authComponent = document.querySelector('auth-component'); if (authComponent) { authComponent.reset(); } }); }, 300); } else { console.error('登出失败'); } } catch (error) { console.error('登出错误:', error); } } } customElements.define('user-info', UserInfo);