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