// 好友列表页面 const app = getApp(); const apiClient = require('../../../utils/api-client.js'); const friendAPI = require('../../../utils/friend-api.js'); const notificationManager = require('../../../utils/notification-manager.js'); const wsManager = require('../../../utils/websocket-manager-v2.js'); const nimPresenceManager = require('../../../utils/nim-presence-manager.js'); const { modernSystemInfo, initPageSystemInfo } = require('../../../utils/system-info-modern.js'); Page({ data: { // 好友数据 friends: [], filteredFriends: [], // UI状态 loading: true, refreshing: false, searchKeyword: '', searching: false, searchResultCount: 0, showSearchBar: false, // 统计数据 newFriendRequests: 0, totalFriendsCount: 0, onlineFriendsCount: 0, recentActiveCount: 0, mutualFriendsCount: 0, // 系统适配信息 systemInfo: {}, statusBarHeight: 0, menuButtonHeight: 0, menuButtonTop: 0, navBarHeight: 0, windowHeight: 0, safeAreaBottom: 0, // 添加好友提示 showAddTip: false, userInfo: {}, // 事件处理状态 eventHandlingState: { lastEventTime: 0, eventThrottleMs: 300 } }, onLoad: function (options) { this.initSystemInfo(); this.checkAuthAndLoad(); // 注册在线状态变化监听 this.registerPresenceListener(); }, onShow: function () { // 设置tabBar选中状态为"我的"(索引3) try { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 3 }); } } catch (_) {} // 检查是否需要刷新好友请求数量 const app = getApp(); if (app.globalData && app.globalData.needRefreshFriendRequests) { app.globalData.needRefreshFriendRequests = false; // 立即刷新好友请求数量 this.loadFriendRequestsCount(); } // 刷新数据前先检查认证状态 this.checkAuthAndLoad(); }, // 初始化系统信息 initSystemInfo() { const pageSystemInfo = initPageSystemInfo(); this.setData({ systemInfo: pageSystemInfo.systemInfo, statusBarHeight: pageSystemInfo.statusBarHeight, menuButtonHeight: pageSystemInfo.menuButtonHeight, menuButtonTop: pageSystemInfo.menuButtonTop, navBarHeight: pageSystemInfo.navBarHeight, windowHeight: pageSystemInfo.windowHeight, safeAreaBottom: pageSystemInfo.safeAreaBottom }); }, // 检查认证状态并加载数据 async checkAuthAndLoad() { try { // 确保API客户端能获取到token const currentToken = apiClient.getToken(); if (!currentToken) { console.error('用户未登录,跳转到登录页'); wx.reLaunch({ url: '/pages/login/login' }); return; } // 获取用户信息 - 确保有完整的用户数据 await this.loadUserInfo(); // 🔥 初始化WebSocket好友功能(用于实时接收好友请求通知) this.initWebSocketFriendFeatures(); // 开始加载数据 this.loadFriends(); this.loadFriendRequestsCount(); } catch (error) { console.error('认证检查失败:', error); wx.reLaunch({ url: '/pages/login/login' }); } }, // 加载用户信息 async loadUserInfo() { try { // 先从全局数据获取 let userInfo = getApp().globalData.userInfo; // 如果全局没有完整信息,从API获取 if (!userInfo || !userInfo.user || !userInfo.user.customId) { const response = await apiClient.getUserInfo(); if (response && response.code === 0) { userInfo = { ...userInfo, user: response.data }; // 更新全局数据 getApp().globalData.userInfo = userInfo; } } this.setData({ userInfo: userInfo }); } catch (error) { console.error('❌ 获取用户信息失败:', error); // 不影响主要功能,继续加载好友列表 } }, // 加载好友列表 - 参考Flutter app的实现 async loadFriends() { try { this.setData({ loading: true }); const response = await friendAPI.getFriendList(); if (response && response.code === 0) { const friends = response.data || []; // 处理好友数据,参考Flutter app的数据结构 const processedFriends = this.processFriendsData(friends); this.setData({ friends: processedFriends, filteredFriends: processedFriends, totalFriendsCount: processedFriends.length, loading: false }); // 计算在线好友数和其他统计 this.calculateFriendStats(processedFriends); // 🔥 订阅好友的在线状态(通过NIM实现) this.subscribeFriendsPresence(processedFriends); } else { throw new Error(response?.message || '获取好友列表失败'); } } catch (error) { console.error('❌ 加载好友列表失败:', error); this.setData({ loading: false }); // 未登录用户静默跳转到登录页 const app = getApp(); if (!app.globalData.isLoggedIn) { setTimeout(() => { wx.reLaunch({ url: '/pages/login/login' }); }, 500); return; } // 已登录用户显示错误提示 wx.showToast({ title: '加载好友失败', icon: 'none', duration: 2000 }); } }, // 处理好友数据 - 参考Flutter app的数据结构 processFriendsData(friends) { return friends.map(friend => { // 适配不同的字段名,参考Flutter app的FriendModel const nickname = friend.nickname || friend.username || friend.name || '未知用户'; const customId = friend.customId || friend.customID || friend.id; return { id: customId, customId: customId, name: nickname, nickname: nickname, avatar: friend.avatar || '', // 头像URL personalSignature: friend.signature || friend.bio || friend.personalSignature || '', isOnline: friend.isOnline || false, isVip: friend.isVip || false, gender: friend.gender || null, // male, female, null remark: friend.remark || '', relation: friend.relation || '好友', location: friend.location || '', distance: friend.distance || 0, lastActiveTime: friend.lastActiveTime || '', tags: friend.tags || [], hasMutualFriends: friend.mutualFriends > 0, isBirthdayToday: false, // 可以根据实际情况计算 isNewFriend: friend.isNewFriend || false }; }); }, // 计算好友统计数据 calculateFriendStats(friends) { const onlineCount = friends.filter(f => f.isOnline).length; const recentActiveCount = friends.filter(f => { if (!f.lastActiveTime) return false; const oneHourAgo = Date.now() - (60 * 60 * 1000); return new Date(f.lastActiveTime).getTime() > oneHourAgo; }).length; const mutualCount = friends.filter(f => f.hasMutualFriends).length; this.setData({ onlineFriendsCount: onlineCount, recentActiveCount: recentActiveCount, mutualFriendsCount: mutualCount }); }, // 注册在线状态变化监听 registerPresenceListener() { try { // 移除旧的监听器(如果存在) nimPresenceManager.off('presence_changed', this.handlePresenceChanged); // 注册新的监听器(通过NIM实现在线状态) nimPresenceManager.on('presence_changed', this.handlePresenceChanged.bind(this)); } catch (error) { console.error('注册在线状态监听失败:', error); } }, // 订阅好友的在线状态 async subscribeFriendsPresence(friends) { try { if (!friends || friends.length === 0) { return; } // 提取所有好友的customId const userIds = friends .map(f => f.customId || f.id) .filter(Boolean); if (userIds.length > 0) { // 通过NIM订阅在线状态,immediateSync=true 确保首次订阅时立即返回在线状态 await nimPresenceManager.subscribe(userIds, 7 * 24 * 3600, true); // 订阅后立即从缓存更新在线状态 this.updateFriendsPresenceFromCache(); } } catch (error) { console.error('订阅好友在线状态失败:', error); } }, // 从缓存更新好友的在线状态 updateFriendsPresenceFromCache() { try { let friends = [...this.data.friends]; let hasChanges = false; friends.forEach(friend => { const userId = friend.customId || friend.id; if (!userId) return; const presence = nimPresenceManager.getUserPresence(userId); if (presence) { friend.isOnline = presence.online; hasChanges = true; } }); if (hasChanges) { this.setData({ friends: friends, filteredFriends: this.data.searchKeyword ? this.filterFriendsByKeyword(friends, this.data.searchKeyword) : friends }); // 重新计算统计数据 this.calculateFriendStats(friends); } } catch (error) { console.error('更新好友在线状态失败:', error); } }, // 处理在线状态变化 handlePresenceChanged(data) { try { const { userId, isOnline } = data; let friends = [...this.data.friends]; let hasChanges = false; friends.forEach(friend => { const friendId = friend.customId || friend.id; if (friendId === userId) { friend.isOnline = isOnline; hasChanges = true; } }); if (hasChanges) { this.setData({ friends: friends, filteredFriends: this.data.searchKeyword ? this.filterFriendsByKeyword(friends, this.data.searchKeyword) : friends }); // 重新计算统计数据 this.calculateFriendStats(friends); } } catch (error) { console.error('处理在线状态变化失败:', error); } }, // 辅助方法:根据关键词过滤好友(增强版) filterFriendsByKeyword(friends, keyword) { if (!keyword || !keyword.trim()) { return friends; } const searchText = keyword.toLowerCase().trim(); return friends.filter(friend => { // 1. 匹配备注名(优先级最高) const remark = (friend.remark || '').toLowerCase(); if (remark.includes(searchText)) { return true; } // 2. 匹配昵称 const nickname = (friend.nickname || '').toLowerCase(); if (nickname.includes(searchText)) { return true; } // 3. 匹配自定义ID const customId = (friend.customId || '').toLowerCase(); if (customId.includes(searchText)) { return true; } // 4. 匹配个性签名 const signature = (friend.personalSignature || friend.bio || '').toLowerCase(); if (signature.includes(searchText)) { return true; } // 5. 匹配手机号(如果有) const phone = (friend.phone || '').toLowerCase(); if (phone.includes(searchText)) { return true; } return false; }); }, // 获取好友请求数量 - 参考Flutter app的实现 async loadFriendRequestsCount() { try { const response = await friendAPI.getFriendRequestCount(); if (response && response.code === 0) { const count = response.data?.count || 0; this.setData({ newFriendRequests: count }); // 同步自定义TabBar角标(好友) try { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setFriendsBadge(count); } } catch (_) {} // 同步通知管理器的未读计数 try { notificationManager.setFriendsUnreadCount(count); } catch (_) {} } } catch (error) { console.error('❌ 获取好友请求数量失败:', error); // 不影响主要功能,只是数量显示为0 this.setData({ newFriendRequests: 0 }); } }, // 搜索输入(实时搜索) onSearchInput(e) { const keyword = e.detail.value; this.setData({ searchKeyword: keyword, searching: true }); // 防抖处理 if (this.searchTimer) { clearTimeout(this.searchTimer); } this.searchTimer = setTimeout(() => { this.filterFriends(keyword); }, 300); }, // 过滤好友 filterFriends(keyword) { const filtered = this.filterFriendsByKeyword(this.data.friends, keyword); this.setData({ filteredFriends: filtered, searchResultCount: filtered.length, searching: false }); // 记录搜索历史(非空且有结果) if (keyword && keyword.trim() && filtered.length > 0) { this.saveSearchHistory(keyword.trim()); } }, // 清除搜索 clearSearch() { this.setData({ searchKeyword: '', searchResultCount: 0, searching: false }); this.filterFriends(''); }, // 显示搜索栏 showSearch() { this.setData({ showSearchBar: true }); }, // 隐藏搜索栏 hideSearch() { this.clearSearch(); this.setData({ showSearchBar: false }); }, // 保存搜索历史 saveSearchHistory(keyword) { try { let history = wx.getStorageSync('friendSearchHistory') || []; // 移除重复项 history = history.filter(item => item !== keyword); // 添加到开头 history.unshift(keyword); // 最多保存10条 history = history.slice(0, 10); wx.setStorageSync('friendSearchHistory', history); } catch (error) { console.error('保存搜索历史失败:', error); } }, // 获取搜索历史 getSearchHistory() { try { return wx.getStorageSync('friendSearchHistory') || []; } catch (error) { console.error('获取搜索历史失败:', error); return []; } }, // 清除搜索历史 clearSearchHistory() { try { wx.removeStorageSync('friendSearchHistory'); wx.showToast({ title: '已清除搜索历史', icon: 'success' }); } catch (error) { console.error('清除搜索历史失败:', error); } }, // 下拉刷新 async onRefresh() { this.setData({ refreshing: true }); try { await this.loadFriends(); await this.loadFriendRequestsCount(); wx.showToast({ title: '刷新成功', icon: 'success', duration: 1000 }); } catch (error) { wx.showToast({ title: '刷新失败', icon: 'none' }); } finally { this.setData({ refreshing: false }); } }, // 打开好友资料 openFriendProfile(e) { const friend = e.currentTarget.dataset.friend; wx.navigateTo({ url: `/subpackages/social/friend-detail/friend-detail?customId=${friend.customId}` }); }, // 好友请求 - 修改后的名称 openNewFriends() { // 进入前刷新一次,确保角标与列表同步 try { this.loadFriendRequestsCount(); } catch (_) {} wx.navigateTo({ url: '/subpackages/social/friend-requests/friend-requests' }); }, // 建群 - 修改后的功能 openGroupChats() { wx.navigateTo({ url: '/subpackages/group/create-group/create-group' }); }, // 添加好友 - 跳转到搜索页面 addFriend() { wx.navigateTo({ url: '/subpackages/social/search/search' }); }, // 🔥 初始化WebSocket好友功能(监听好友请求实时通知) initWebSocketFriendFeatures() { try { if (this._wsFriendInited) return; this._wsFriendInited = true; console.log('🔌 初始化WebSocket好友事件监听器'); // 绑定处理函数到 this,方便后续移除 this.handleNotificationMessage = this.handleNotificationMessage.bind(this); // 监听通知消息(包含好友请求) wsManager.on('notification', this.handleNotificationMessage); } catch (error) { console.error('初始化WebSocket好友功能失败:', error); } }, // 处理通知消息 handleNotificationMessage(msg) { try { console.log('🔔 收到通知消息:', msg); const data = msg?.data || msg; // 判断是否为好友通知 if (data?.type === 'friend_notification') { this.handleFriendNotification(data); } else if (data?.type === 'friend_request_notification') { this.handleFriendRequestNotification(data); } } catch (error) { console.error('处理通知消息失败:', error); } }, // 处理好友通知(包含request/accepted/rejected/count_update) handleFriendNotification(data) { try { console.log('🆕 处理好友通知:', data); const subType = data?.subType; const senderName = data?.senderName || '用户'; const pendingCount = data?.pendingCount || 0; switch (subType) { case 'request': // 新好友请求 wx.showToast({ title: `${senderName} 请求添加您为好友`, icon: 'none', duration: 3000 }); this.updateBadge(pendingCount); break; case 'accepted': // 好友请求被接受 wx.showToast({ title: `${senderName} 已接受您的好友申请`, icon: 'success', duration: 2000 }); this.updateBadge(pendingCount); // 刷新好友列表 this.loadFriends(); break; case 'rejected': // 好友请求被拒绝 wx.showToast({ title: `${senderName} 已拒绝您的好友申请`, icon: 'none', duration: 2000 }); this.updateBadge(pendingCount); break; case 'count_update': // 待处理数量更新 this.updateBadge(pendingCount); break; default: console.warn('未知的好友通知子类型:', subType); // 默认刷新数量 this.loadFriendRequestsCount(); } } catch (error) { console.error('处理好友通知失败:', error); } }, // 处理连接时的待处理好友请求通知 handleFriendRequestNotification(data) { try { console.log('📋 处理待处理好友请求通知:', data); const pendingCount = data?.pendingCount || 0; this.updateBadge(pendingCount); } catch (error) { console.error('处理待处理好友请求通知失败:', error); } }, // 更新小红点角标 updateBadge(count) { try { // 更新页面数据 this.setData({ newFriendRequests: count }); // 同步自定义TabBar角标 if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setFriendsBadge(count); } // 同步通知管理器的未读计数 notificationManager.setFriendsUnreadCount(count); console.log('✅ 已更新好友请求角标:', count); } catch (error) { console.error('更新角标失败:', error); } }, // 页面卸载 onUnload() { // 移除在线状态监听器 try { nimPresenceManager.off('presence_changed', this.handlePresenceChanged); } catch (error) { console.error('移除在线状态监听器失败:', error); } // 移除 WebSocket 通知监听器 try { if (this.handleNotificationMessage) { wsManager.off('notification', this.handleNotificationMessage); console.log('✅ 已移除 WebSocket 通知监听器'); } } catch (error) { console.error('移除 WebSocket 通知监听器失败:', error); } } });