/** * 好友列表弹窗组件 * 负责显示和管理好友列表的所有功能 */ class FriendListModal { constructor() { this.isVisible = false; this.element = null; this.friends = []; this.currentPage = 1; this.pageSize = 10; this.totalPages = 1; this.isLoading = false; this.searchKeyword = ''; this.init(); } // 初始化组件 init() { this.createStyles(); this.createElement(); this.bindEvents(); } // 创建样式 createStyles() { if (document.getElementById('friend-list-modal-styles')) return; const style = document.createElement('style'); style.id = 'friend-list-modal-styles'; style.textContent = ` .friend-list-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(5px); z-index: 10000; opacity: 0; visibility: hidden; transition: all 0.3s ease; display: flex; justify-content: flex-end; align-items: stretch; } .friend-list-modal.visible { opacity: 1; visibility: visible; } .friend-list-content { background: white; width: 400px; max-width: 90vw; height: 100%; box-shadow: -8px 0 25px rgba(0, 0, 0, 0.15), -2px 0 10px rgba(0, 0, 0, 0.1); transform: translateX(100%); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; display: flex; flex-direction: column; border-radius: 20px 0 0 20px; border-left: 1px solid rgba(255, 255, 255, 0.1); } .friend-list-modal.visible .friend-list-content { transform: translateX(0); } .friend-list-header { padding: 20px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; flex-shrink: 0; border-radius: 20px 0 0 0; flex-direction: column; gap: 10px; } .friend-list-header-top { width: 100%; display: flex; justify-content: space-between; align-items: center; } .friend-list-title { margin: 0; font-size: 18px; font-weight: 600; } .friend-list-user-info { width: 100%; display: flex; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px solid rgba(255, 255, 255, 0.2); min-height: 40px; } .friend-list-user-name { color: white; font-size: 14px; font-weight: 500; line-height: 1; display: flex; align-items: center; height: 32px; } .friend-list-user-badge { flex-shrink: 0; display: flex; align-items: center; height: 32px; } .friend-list-user-badge .rank-badge { vertical-align: middle !important; margin: 0 !important; margin-bottom: 0 !important; display: inline-flex !important; align-items: center !important; justify-content: center !important; } .friend-list-close { background: none; border: none; color: white; font-size: 20px; cursor: pointer; padding: 0; margin: 0; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); line-height: 1; font-family: Arial, sans-serif; font-weight: normal; } .friend-list-close:hover { background: rgba(255, 255, 255, 0.2); transform: scale(1.1); backdrop-filter: blur(10px); } .friend-list-close:active { transform: scale(0.95); } .friend-list-close svg { display: block; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .friend-list-close:hover svg { transform: rotate(90deg); } .friend-list-search { padding: 15px 20px; border-bottom: 1px solid #eee; flex-shrink: 0; } .friend-search-input { width: 100%; padding: 10px 15px; border: 2px solid #e0e0e0; border-radius: 25px; font-size: 14px; outline: none; transition: border-color 0.3s; } .friend-search-input:focus { border-color: #667eea; } .friend-list-body { padding: 20px; flex: 1; overflow-y: auto; } .friend-list-body::-webkit-scrollbar { width: 6px; } .friend-list-body::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 3px; } .friend-list-body::-webkit-scrollbar-thumb { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 3px; } .friend-list-body::-webkit-scrollbar-thumb:hover { background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%); } /* 移动端优化 */ @media (max-width: 768px) { .friend-list-content { border-radius: 15px 0 0 15px; } .friend-list-header { border-radius: 15px 0 0 0; } .friend-list-pagination { border-radius: 0 0 0 15px; } } .friend-item { display: flex; align-items: center; padding: 12px 10px; margin: 2px 0; border-bottom: 1px solid #f5f5f5; border-radius: 8px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; gap: 12px; } .friend-item:hover { background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border-radius: 12px; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); border-bottom: 1px solid transparent; } .friend-item:last-child { border-bottom: none; margin-bottom: 0; } .friend-avatar { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; font-size: 14px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); border: 2px solid rgba(255, 255, 255, 0.9); } .friend-item:hover .friend-avatar { transform: scale(1.05); box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4); } .friend-info { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; } .friend-name { font-weight: 600; font-size: 14px; color: #333; transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex-shrink: 1; } .friend-item:hover .friend-name { color: #667eea; } .friend-rank { display: flex; align-items: center; flex-shrink: 0; } .friend-rank-badge { padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 500; background: #e3f2fd; color: #1976d2; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 0 1px 3px rgba(25, 118, 210, 0.2); white-space: nowrap; } .friend-item:hover .friend-rank-badge { transform: scale(1.02); box-shadow: 0 2px 6px rgba(25, 118, 210, 0.3); } .friend-actions { display: flex; gap: 8px; flex-shrink: 0; } .friend-action-btn { padding: 6px 12px; border: none; border-radius: 20px; font-size: 11px; cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-weight: 500; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); opacity: 0.8; transform: scale(0.95); white-space: nowrap; } .friend-item:hover .friend-action-btn { opacity: 1; transform: scale(1); } .friend-remove-btn { background: linear-gradient(135deg, #ffebee 0%, #fce4ec 100%); color: #d32f2f; border: 1px solid #ffcdd2; } .friend-remove-btn:hover { background: linear-gradient(135deg, #d32f2f 0%, #c62828 100%); color: white; transform: scale(1.05); box-shadow: 0 4px 12px rgba(211, 47, 47, 0.3); } .friend-list-pagination { padding: 15px 20px; border-top: 1px solid #eee; display: flex !important; justify-content: center; align-items: center; gap: 10px; flex-shrink: 0; background: #fafafa; border-radius: 0 0 0 20px; } .pagination-btn { padding: 8px 12px; border: 1px solid #ddd; background: white; color: #333; cursor: pointer; border-radius: 6px; font-size: 12px; font-weight: 500; transition: all 0.3s; opacity: 1; visibility: visible; min-width: 60px; } .pagination-btn:hover:not(:disabled) { background: #667eea; color: white; border-color: #667eea; transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .pagination-btn:disabled { opacity: 0.4; cursor: not-allowed; background: #f5f5f5; color: #999; } /* 强制显示分页按钮 */ .friend-list-pagination .pagination-btn { display: inline-block !important; visibility: visible !important; opacity: 1 !important; } .friend-list-pagination .pagination-btn:disabled { opacity: 0.4 !important; } .pagination-info { font-size: 12px; color: #666; font-weight: 500; margin: 0 10px; white-space: nowrap; } .friend-list-loading { text-align: center; padding: 40px; color: #666; } .friend-list-empty { text-align: center; padding: 40px; color: #999; } .friend-list-error { text-align: center; padding: 40px; color: #d32f2f; } .loading-spinner { display: inline-block; width: 20px; height: 20px; border: 2px solid #f3f3f3; border-top: 2px solid #667eea; border-radius: 50%; animation: spin 1s linear infinite; margin-right: 10px; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .add-friend-section { padding: 15px 20px; border-bottom: 1px solid #eee; background: #f8f9fa; flex-shrink: 0; } .add-friend-tabs { display: flex; margin-bottom: 15px; border-radius: 6px; overflow: hidden; border: 1px solid #ddd; } .add-friend-tab { flex: 1; padding: 8px 12px; background: #fff; border: none; cursor: pointer; font-size: 12px; transition: all 0.3s; color: #666; } .add-friend-tab.active { background: #667eea; color: white; } .add-friend-tab:hover:not(.active) { background: #f0f0f0; } .add-friend-form { display: flex; gap: 8px; align-items: center; flex-wrap: nowrap; } .add-friend-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; outline: none; min-width: 120px; } .add-friend-input:focus { border-color: #667eea; box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1); } .add-friend-btn { padding: 8px 16px; background: #4caf50; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; transition: background 0.3s; } .add-friend-btn:hover { background: #45a049; } .add-friend-btn:disabled { opacity: 0.6; cursor: not-allowed; } `; document.head.appendChild(style); } // 创建DOM元素 createElement() { this.element = document.createElement('div'); this.element.className = 'friend-list-modal'; this.element.innerHTML = `

好友列表

加载中...
`; document.body.appendChild(this.element); } // 绑定事件 bindEvents() { // 关闭弹窗 this.element.querySelector('.friend-list-close').addEventListener('click', () => { this.hide(); }); // 点击背景关闭 this.element.addEventListener('click', (e) => { if (e.target === this.element) { this.hide(); } }); // 搜索功能 const searchInput = this.element.querySelector('.friend-search-input'); let searchTimeout; searchInput.addEventListener('input', (e) => { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { this.searchKeyword = e.target.value.trim(); this.currentPage = 1; this.loadFriends(); }, 300); }); // 分页功能 this.element.querySelector('.friend-list-pagination').addEventListener('click', (e) => { if (e.target.classList.contains('pagination-btn')) { const action = e.target.dataset.action; if (action === 'prev' && this.currentPage > 1) { this.currentPage--; this.loadFriends(); } else if (action === 'next' && this.currentPage < this.totalPages) { this.currentPage++; this.loadFriends(); } } }); // 添加好友选项卡切换 this.element.querySelector('.add-friend-tabs').addEventListener('click', (e) => { if (e.target.classList.contains('add-friend-tab')) { // 移除所有活动状态 this.element.querySelectorAll('.add-friend-tab').forEach(tab => { tab.classList.remove('active'); }); // 设置当前选项卡为活动状态 e.target.classList.add('active'); // 更新输入框 const inputType = e.target.dataset.type; const addFriendInput = this.element.querySelector('.add-friend-input'); addFriendInput.dataset.type = inputType; if (inputType === 'id') { addFriendInput.placeholder = '请输入用户ID(数字)'; addFriendInput.type = 'number'; } else { addFriendInput.placeholder = '请输入用户名'; addFriendInput.type = 'text'; } // 清空输入框 addFriendInput.value = ''; } }); // 添加好友 const addFriendBtn = this.element.querySelector('.add-friend-btn'); const addFriendInput = this.element.querySelector('.add-friend-input'); addFriendBtn.addEventListener('click', () => { this.addFriend(); }); addFriendInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { this.addFriend(); } }); // 事件委托 - 处理好友列表中的按钮点击 this.element.querySelector('.friend-list-body').addEventListener('click', (e) => { if (e.target.classList.contains('friend-remove-btn')) { const userId = parseInt(e.target.dataset.userId); this.removeFriend(userId); } }); } // 显示弹窗 show() { this.isVisible = true; this.element.classList.add('visible'); this.loadUserInfo(); this.loadFriends(); } // 隐藏弹窗 hide() { this.isVisible = false; this.element.classList.remove('visible'); } // 切换显示状态 toggle() { if (this.isVisible) { this.hide(); } else { this.show(); } } // 获取API配置 getApiConfig() { const config = window.CONFIG || {}; const accessToken = localStorage.getItem('access_token') || sessionStorage.getItem('access_token'); return { baseUrl: config.DataServerBaseUrl || '', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' } }; } // 等待徽章生成器加载 async waitForBadgeGenerator() { return new Promise((resolve) => { const checkInterval = setInterval(() => { if (window.RankBadgeGenerator && typeof window.getBadgeOnly === 'function') { clearInterval(checkInterval); resolve(true); } }, 100); // 5秒超时 setTimeout(() => { clearInterval(checkInterval); resolve(false); }, 5000); }); } // 加载用户信息 async loadUserInfo() { try { const apiConfig = this.getApiConfig(); const username = localStorage.getItem('username') || '用户'; // 更新用户名 const userNameElement = this.element.querySelector('.friend-list-user-name'); userNameElement.textContent = username; // 等待徽章生成器加载 await this.waitForBadgeGenerator(); // 获取用户称号信息 const response = await fetch(`${apiConfig.baseUrl}/api/get-user-rank/`, { method: 'POST', headers: apiConfig.headers, body: JSON.stringify({}) }); if (response.ok) { const result = await response.json(); if (result.success && result.data) { const rankLevel = result.data.rank_level || 1; const userBadgeElement = this.element.querySelector('.friend-list-user-badge'); const badge = this.generateUserRankBadge(rankLevel); userBadgeElement.innerHTML = badge; } else { console.warn('获取用户称号信息失败:', result.message); // 使用默认徽章 const userBadgeElement = this.element.querySelector('.friend-list-user-badge'); const badge = this.generateUserRankBadge(1); userBadgeElement.innerHTML = badge; } } } catch (error) { console.error('加载用户信息失败:', error); // 使用默认信息 const userNameElement = this.element.querySelector('.friend-list-user-name'); userNameElement.textContent = localStorage.getItem('username') || '用户'; // 使用默认徽章 const userBadgeElement = this.element.querySelector('.friend-list-user-badge'); const badge = this.generateUserRankBadge(1); userBadgeElement.innerHTML = badge; } } // 加载好友列表 async loadFriends() { if (this.isLoading) return; this.isLoading = true; // 清空当前好友数据,防止累积 this.friends = []; const bodyElement = this.element.querySelector('.friend-list-body'); // 显示加载状态 bodyElement.innerHTML = `
加载中...
`; try { const apiConfig = this.getApiConfig(); const response = await fetch(`${apiConfig.baseUrl}/api/get-friends/`, { method: 'POST', headers: apiConfig.headers, body: JSON.stringify({ page: this.currentPage, page_size: this.pageSize, search: this.searchKeyword }) }); const result = await response.json(); if (result.success) { // 添加调试信息 console.log('接口返回的好友数据:', result.data.friends); console.log('好友数量:', result.data.friends.length); // 数据去重处理(基于user_id) const uniqueFriends = []; const seenIds = new Set(); result.data.friends.forEach(friend => { if (!seenIds.has(friend.user_id)) { seenIds.add(friend.user_id); uniqueFriends.push(friend); } else { console.warn('发现重复的好友数据:', friend); } }); console.log('去重后的好友数据:', uniqueFriends); console.log('去重后的好友数量:', uniqueFriends.length); this.friends = uniqueFriends; this.updatePagination(result.data.pagination); this.renderFriendList(); } else { throw new Error(result.message); } } catch (error) { console.error('加载好友列表失败:', error); const errorMessage = error.message || '未知错误'; bodyElement.innerHTML = `
加载失败: ${errorMessage}

`; } finally { this.isLoading = false; } } // 渲染好友列表 renderFriendList() { const bodyElement = this.element.querySelector('.friend-list-body'); console.log('开始渲染好友列表,数量:', this.friends.length); console.log('要渲染的好友:', this.friends); // 调用调试方法检查重复 this.debugCheckDuplicates(); if (this.friends.length === 0) { bodyElement.innerHTML = `
${this.searchKeyword ? '没有找到匹配的好友' : '还没有好友,快去添加一些吧!'}
`; return; } const friendsHtml = this.friends.map(friend => { const firstChar = friend.full_name ? friend.full_name.charAt(0) : friend.username.charAt(0); const rankBadge = this.generateFriendRankBadge(friend.rank_level); return `
${firstChar}
${friend.full_name || friend.username}
${rankBadge}
`; }).join(''); bodyElement.innerHTML = friendsHtml; console.log('渲染完成,DOM中的好友项数量:', bodyElement.querySelectorAll('.friend-item').length); } // 生成用户自己的段位徽章(原始大小) generateUserRankBadge(rankLevel) { console.log('生成用户徽章,rankLevel:', rankLevel); console.log('window.getBadgeOnly存在:', typeof window.getBadgeOnly === 'function'); console.log('window.rankBadgeGenerator存在:', !!window.rankBadgeGenerator); // 尝试使用全局的便捷方法 if (typeof window.getBadgeOnly === 'function') { const badgeElement = window.getBadgeOnly(rankLevel); console.log('getBadgeOnly返回的元素:', badgeElement); if (badgeElement) { // 确保徽章垂直对齐 badgeElement.style.display = 'inline-flex'; badgeElement.style.alignItems = 'center'; badgeElement.style.justifyContent = 'center'; badgeElement.style.margin = '0'; badgeElement.style.verticalAlign = 'middle'; return badgeElement.outerHTML; } } // 尝试使用实例方法 if (window.rankBadgeGenerator && typeof window.rankBadgeGenerator.getBadgeOnly === 'function') { const badgeElement = window.rankBadgeGenerator.getBadgeOnly(rankLevel); console.log('rankBadgeGenerator.getBadgeOnly返回的元素:', badgeElement); if (badgeElement) { // 确保徽章垂直对齐 badgeElement.style.display = 'inline-flex'; badgeElement.style.alignItems = 'center'; badgeElement.style.justifyContent = 'center'; badgeElement.style.margin = '0'; badgeElement.style.verticalAlign = 'middle'; return badgeElement.outerHTML; } } // 降级方案 console.log('使用降级方案生成用户徽章'); return this.getFallbackBadge(rankLevel, false); } // 生成好友的段位徽章(适合好友列表的小尺寸) generateFriendRankBadge(rankLevel) { console.log('生成好友徽章,rankLevel:', rankLevel); // 尝试使用全局的便捷方法 if (typeof window.getBadgeOnly === 'function') { const badgeElement = window.getBadgeOnly(rankLevel); console.log('getBadgeOnly返回的好友徽章元素:', badgeElement); if (badgeElement) { // 调整样式以适应好友列表 badgeElement.style.width = '128px'; badgeElement.style.height = '32px'; badgeElement.style.fontSize = '9px'; badgeElement.style.marginBottom = '0'; return badgeElement.outerHTML; } } // 尝试使用实例方法 if (window.rankBadgeGenerator && typeof window.rankBadgeGenerator.getBadgeOnly === 'function') { const badgeElement = window.rankBadgeGenerator.getBadgeOnly(rankLevel); console.log('rankBadgeGenerator.getBadgeOnly返回的好友徽章元素:', badgeElement); if (badgeElement) { // 调整样式以适应好友列表 badgeElement.style.width = '128px'; badgeElement.style.height = '32px'; badgeElement.style.fontSize = '9px'; badgeElement.style.marginBottom = '0'; return badgeElement.outerHTML; } } // 降级方案 console.log('使用降级方案生成好友徽章'); return this.getFallbackBadge(rankLevel, true); } // 降级方案的徽章生成 getFallbackBadge(rankLevel, isSmall) { const rankNames = { 1: '坚韧黑铁', 2: '英勇黄铜', 3: '不屈白银', 4: '荣耀黄金', 5: '华贵铂金', 6: '璀璨钻石', 7: '超凡大师', 8: '傲世宗师', 9: '最强王者' }; const rankName = rankNames[rankLevel] || '无段位'; const colors = { 1: '#95a5a6', 2: '#f1c40f', 3: '#f8f9fa', 4: '#fff3cd', 5: '#d5dbdb', 6: '#3498db', 7: '#9b59b6', 8: '#e74c3c', 9: '#f39c12' }; const color = colors[rankLevel] || '#666'; if (isSmall) { return `${rankName}`; } else { return `${rankName}`; } } // 更新分页信息 updatePagination(pagination) { this.currentPage = pagination.current_page; this.totalPages = pagination.total_pages; const paginationElement = this.element.querySelector('.friend-list-pagination'); const prevBtn = paginationElement.querySelector('[data-action="prev"]'); const nextBtn = paginationElement.querySelector('[data-action="next"]'); const infoElement = paginationElement.querySelector('.pagination-info'); // 更新按钮状态 prevBtn.disabled = this.currentPage <= 1; nextBtn.disabled = this.currentPage >= this.totalPages; // 确保按钮可见 prevBtn.style.display = 'inline-block'; nextBtn.style.display = 'inline-block'; prevBtn.style.opacity = '1'; nextBtn.style.opacity = '1'; // 更新分页信息 infoElement.textContent = `第 ${this.currentPage} 页,共 ${this.totalPages} 页`; // 只有多页时才显示分页区域 paginationElement.style.display = this.totalPages > 1 ? 'flex' : 'none'; // 强制显示分页区域用于测试(可以删除这行) // paginationElement.style.display = 'flex'; console.log('分页更新:', { currentPage: this.currentPage, totalPages: this.totalPages, prevDisabled: prevBtn.disabled, nextDisabled: nextBtn.disabled }); } // 添加好友 async addFriend() { const input = this.element.querySelector('.add-friend-input'); const btn = this.element.querySelector('.add-friend-btn'); const inputValue = input.value.trim(); const inputType = input.dataset.type; if (!inputValue) { const typeText = inputType === 'id' ? '用户ID' : '用户名'; alert(`请输入${typeText}`); return; } // 验证输入格式 if (inputType === 'id') { if (!/^\d+$/.test(inputValue)) { alert('用户ID必须是数字'); return; } } else { if (inputValue.length < 2) { alert('用户名至少需要2个字符'); return; } } btn.disabled = true; btn.textContent = '添加中...'; try { const apiConfig = this.getApiConfig(); // 根据选择的类型构建请求数据 const requestData = inputType === 'id' ? { user_to_id: parseInt(inputValue) } : { username: inputValue }; console.log('添加好友请求数据:', requestData); const response = await fetch(`${apiConfig.baseUrl}/api/add-friend/`, { method: 'POST', headers: apiConfig.headers, body: JSON.stringify(requestData) }); const result = await response.json(); if (result.success) { // 显示详细的成功信息 const friendInfo = result.data.user_to; const friendName = friendInfo.full_name || friendInfo.username; alert(`成功添加 ${friendName} (${friendInfo.username}) 为好友!`); input.value = ''; this.currentPage = 1; // 清空当前好友列表,避免重复 this.friends = []; this.loadFriends(); // 重新加载好友列表 } else { alert(`添加失败: ${result.message}`); } } catch (error) { console.error('添加好友失败:', error); alert(`添加失败: ${error.message}`); } finally { btn.disabled = false; btn.textContent = '添加好友'; } } // 删除好友 async removeFriend(userId) { // 找到对应的好友信息用于确认 const friend = this.friends.find(f => f.user_id === userId); const friendName = friend ? (friend.full_name || friend.username) : '该好友'; if (!confirm(`确定要删除好友 "${friendName}" 吗?`)) { return; } // 禁用所有删除按钮,防止重复点击 const removeButtons = this.element.querySelectorAll('.friend-remove-btn'); removeButtons.forEach(btn => { btn.disabled = true; btn.textContent = '删除中...'; }); try { const apiConfig = this.getApiConfig(); const response = await fetch(`${apiConfig.baseUrl}/api/remove-friend/`, { method: 'POST', headers: apiConfig.headers, body: JSON.stringify({ user_to_id: userId }) }); const result = await response.json(); if (result.success) { // 不使用alert,而是直接重新加载列表 // 清空当前好友列表,避免重复 this.friends = []; this.loadFriends(); // 重新加载好友列表 } else { alert(`删除失败: ${result.message}`); // 恢复按钮状态 removeButtons.forEach(btn => { btn.disabled = false; btn.textContent = '删除'; }); } } catch (error) { console.error('删除好友失败:', error); alert(`删除失败: ${error.message}`); // 恢复按钮状态 removeButtons.forEach(btn => { btn.disabled = false; btn.textContent = '删除'; }); } } // 调试方法:检查重复数据 debugCheckDuplicates() { console.group('🔍 重复数据检查'); console.log('当前好友数组:', this.friends); const userIds = this.friends.map(f => f.user_id); const uniqueIds = [...new Set(userIds)]; console.log('用户ID数组:', userIds); console.log('去重后的ID数组:', uniqueIds); console.log('是否有重复:', userIds.length !== uniqueIds.length); if (userIds.length !== uniqueIds.length) { console.warn('❌ 发现重复数据!'); const duplicates = userIds.filter((id, index) => userIds.indexOf(id) !== index); console.log('重复的ID:', [...new Set(duplicates)]); } else { console.log('✅ 没有重复数据'); } console.groupEnd(); } // 销毁组件 destroy() { if (this.element && this.element.parentNode) { this.element.parentNode.removeChild(this.element); } const styles = document.getElementById('friend-list-modal-styles'); if (styles) { styles.parentNode.removeChild(styles); } this.element = null; } } // 暴露给全局使用 if (typeof window !== 'undefined') { window.FriendListModal = FriendListModal; // 暴露调试方法 window.debugFriendList = () => { if (window.friendToggle && window.friendToggle.friendListModal) { window.friendToggle.friendListModal.debugCheckDuplicates(); } else { console.warn('好友组件未初始化'); } }; } // 支持模块导入 if (typeof module !== 'undefined' && module.exports) { module.exports = FriendListModal; } // 支持 ES6 导入 export default FriendListModal;