miniprogramme/pages/social/friends/friends.js
2025-09-12 16:08:17 +08:00

959 lines
No EOL
24 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 app = getApp();
const apiClient = require('../../../utils/api-client.js');
const friendAPI = require('../../../utils/friend-api.js');
const wsManager = require('../../../utils/websocket-manager-v2.js');
const { modernSystemInfo, initPageSystemInfo } = require('../../../utils/system-info-modern.js');
// 事件处理工具函数
const EventUtils = {
// 安全地阻止事件冒泡
safeStopPropagation(event) {
try {
if (event && typeof event.stopPropagation === 'function') {
event.stopPropagation();
}
} catch (error) {
console.warn('停止事件冒泡失败:', error);
}
},
// 安全地阻止默认行为
safePreventDefault(event) {
try {
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
}
} catch (error) {
console.warn('阻止默认行为失败:', error);
}
},
// 安全地从事件中提取数据
safeGetDataset(event) {
try {
return event?.currentTarget?.dataset || event?.target?.dataset || {};
} catch (error) {
console.warn('获取事件数据失败:', error);
return {};
}
},
// 验证好友数据
validateFriendData(friend) {
return friend &&
friend.customId &&
friend.nickname &&
typeof friend === 'object';
}
};
Page({
data: {
// 好友数据
friends: [],
filteredFriends: [],
// UI状态
loading: true,
refreshing: false,
searchKeyword: '',
// 统计数据
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, // 防止快速连续点击
errorCount: 0,
maxErrors: 5
}
},
onLoad: function (options) {
console.log('好友列表页面加载');
this.initSystemInfo();
this.checkAuthAndLoad();
},
onShow: function () {
console.log('好友列表页面显示');
// 检查是否需要刷新好友请求数量
const app = getApp();
if (app.globalData && app.globalData.needRefreshFriendRequests) {
console.log('🔄 检测到好友请求状态变化,强制刷新');
app.globalData.needRefreshFriendRequests = false;
}
// 刷新数据
this.loadFriends();
this.loadFriendRequestsCount();
},
// 初始化系统信息
// 初始化系统信息 - 使用现代化API
initSystemInfo() {
const pageSystemInfo = initPageSystemInfo();
console.log('系统适配信息:', {
statusBarHeight: pageSystemInfo.statusBarHeight,
menuButtonHeight: pageSystemInfo.menuButtonHeight,
menuButtonTop: pageSystemInfo.menuButtonTop,
navBarHeight: pageSystemInfo.navBarHeight,
windowHeight: pageSystemInfo.windowHeight,
safeAreaBottom: pageSystemInfo.safeAreaBottom,
screenWidth: pageSystemInfo.systemInfo.screenWidth,
screenHeight: pageSystemInfo.systemInfo.screenHeight,
platform: pageSystemInfo.systemInfo.platform
});
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;
}
console.log('好友页面认证检查通过,开始加载数据');
// 获取用户信息 - 确保有完整的用户数据
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) {
console.log('从API获取用户信息...');
const response = await apiClient.getUserInfo();
if (response && response.code === 0) {
userInfo = {
...userInfo,
user: response.data
};
// 更新全局数据
getApp().globalData.userInfo = userInfo;
}
}
this.setData({
userInfo: userInfo
});
console.log('✅ 用户信息已更新:', {
hasUser: !!userInfo?.user,
customId: userInfo?.user?.customId || 'unknown'
});
} catch (error) {
console.error('❌ 获取用户信息失败:', error);
// 不影响主要功能,继续加载好友列表
}
},
// 加载好友列表 - 参考Flutter app的实现
async loadFriends() {
try {
this.setData({ loading: true });
console.log('🔥 开始加载好友列表...');
const response = await friendAPI.getFriendList();
if (response && response.code === 0) {
const friends = response.data || [];
console.log(`✅ 获取到 ${friends.length} 个好友:`, friends);
// 处理好友数据参考Flutter app的数据结构
const processedFriends = this.processFriendsData(friends);
this.setData({
friends: processedFriends,
filteredFriends: processedFriends,
totalFriendsCount: processedFriends.length,
loading: false
});
// 计算在线好友数和其他统计
this.calculateFriendStats(processedFriends);
} else {
throw new Error(response?.message || '获取好友列表失败');
}
} catch (error) {
console.error('❌ 加载好友列表失败:', error);
this.setData({ loading: false });
// 不要频繁弹出错误提示,影响用户体验
if (!error.message?.includes('401')) {
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
});
},
// 获取好友请求数量 - 参考Flutter app的实现
async loadFriendRequestsCount() {
try {
console.log('🔥 获取好友请求数量...');
const response = await friendAPI.getFriendRequestCount();
if (response && response.code === 0) {
const count = response.data?.count || 0;
console.log(`✅ 获取到 ${count} 个好友请求`);
this.setData({
newFriendRequests: count
});
}
} catch (error) {
console.error('❌ 获取好友请求数量失败:', error);
// 不影响主要功能只是数量显示为0
this.setData({
newFriendRequests: 0
});
}
},
// 搜索输入
onSearchInput(e) {
const keyword = e.detail.value;
this.setData({ searchKeyword: keyword });
this.filterFriends(keyword);
},
// 过滤好友
filterFriends(keyword) {
if (!keyword.trim()) {
this.setData({ filteredFriends: this.data.friends });
return;
}
const filtered = this.data.friends.filter(friend => {
const name = friend.remark || friend.nickname;
const signature = friend.personalSignature || '';
const searchText = keyword.toLowerCase();
return name.toLowerCase().includes(searchText) ||
signature.toLowerCase().includes(searchText);
});
this.setData({ filteredFriends: filtered });
},
// 清除搜索
clearSearch() {
this.setData({ searchKeyword: '' });
this.filterFriends('');
},
// 下拉刷新
async onRefresh() {
console.log('下拉刷新好友列表');
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 });
}
},
// 打开聊天 - WXML中引用的方法
// 点击好友时查看个人资料
openChat(e) {
try {
// 安全地获取好友数据
const dataset = EventUtils.safeGetDataset(e);
const friend = dataset.friend;
// 验证好友数据
if (!EventUtils.validateFriendData(friend)) {
console.error('好友数据无效,无法查看个人资料');
wx.showToast({
title: '好友信息错误',
icon: 'none'
});
return;
}
console.log('查看好友个人资料:', friend.nickname);
// 跳转到好友个人资料页面
wx.navigateTo({
url: `/pages/user-profile/user-profile?userId=${friend.customId}&from=friends`
});
} catch (error) {
console.error('查看好友个人资料失败:', error);
wx.showToast({
title: '查看资料失败',
icon: 'none'
});
}
},
// 打开好友资料
openFriendProfile(e) {
const friend = e.currentTarget.dataset.friend;
console.log('打开好友资料:', friend.nickname);
wx.navigateTo({
url: `/pages/social/friend-detail/friend-detail?customId=${friend.customId}`
});
},
// 发送消息 - 参考Flutter app的实现
sendMessage(e) {
try {
// 安全地阻止事件冒泡
EventUtils.safeStopPropagation(e);
// 安全地获取好友数据
const dataset = EventUtils.safeGetDataset(e);
const friend = dataset.friend;
// 验证好友数据
if (!EventUtils.validateFriendData(friend)) {
console.error('好友数据无效或缺失');
wx.showToast({
title: '好友信息错误',
icon: 'none'
});
return;
}
console.log('💬 开始与好友聊天:', friend.nickname);
// 🔥 修复不传递conversationId让聊天页面从API获取正确的会话ID
wx.navigateTo({
url: `/pages/message/chat/chat?targetId=${friend.customId}&name=${encodeURIComponent(friend.nickname)}&chatType=0`
});
} catch (error) {
console.error('发送消息失败:', error);
wx.showToast({
title: '发送消息失败',
icon: 'none'
});
}
},
// 视频通话
startVideoCall(e) {
try {
// 安全地阻止事件冒泡
EventUtils.safeStopPropagation(e);
// 安全地获取好友数据
const dataset = EventUtils.safeGetDataset(e);
const friend = dataset.friend;
// 验证好友数据
if (!EventUtils.validateFriendData(friend)) {
console.error('好友数据无效,无法发起视频通话');
wx.showToast({
title: '好友信息错误',
icon: 'none'
});
return;
}
console.log('📹 发起视频通话:', friend.nickname);
wx.showToast({
title: '视频通话功能开发中',
icon: 'none'
});
} catch (error) {
console.error('视频通话失败:', error);
wx.showToast({
title: '视频通话失败',
icon: 'none'
});
}
},
// 视频通话WXML中使用的方法名
videoCall(e) {
this.startVideoCall(e);
},
// 显示好友菜单
showFriendMenu(e) {
const friend = e.currentTarget.dataset.friend;
console.log('长按好友:', friend.nickname);
wx.showActionSheet({
itemList: ['发送消息', '音视频通话', '查看资料', '设置备注', '删除好友'],
success: (res) => {
switch (res.tapIndex) {
case 0:
this.sendMessage({ currentTarget: { dataset: { friend } } });
break;
case 1:
this.startVideoCall({ currentTarget: { dataset: { friend } } });
break;
case 2:
this.openFriendProfile({ currentTarget: { dataset: { friend } } });
break;
case 3:
this.setFriendRemark(friend);
break;
case 4:
this.deleteFriend(friend);
break;
}
}
});
},
// 设置好友备注
setFriendRemark(friend) {
wx.showModal({
title: '设置备注',
editable: true,
placeholderText: '请输入备注名',
content: friend.remark || '',
success: (res) => {
if (res.confirm) {
console.log('设置备注:', res.content);
// 这里调用API更新备注
}
}
});
},
// 删除好友
deleteFriend(friend) {
wx.showModal({
title: '删除好友',
content: `确定要删除好友"${friend.nickname}"吗?`,
success: (res) => {
if (res.confirm) {
console.log('删除好友:', friend.nickname);
// 这里调用API删除好友
}
}
});
},
// 好友请求 - 修改后的名称
openNewFriends() {
console.log('打开好友请求页面');
wx.navigateTo({
url: '/pages/social/friend-requests/friend-requests'
});
},
// 建群 - 修改后的功能
openGroupChats() {
console.log('打开建群页面');
wx.navigateTo({
url: '/pages/social/create-group/create-group'
});
},
// 标签管理
openTags() {
console.log('打开标签管理');
wx.showToast({
title: '标签功能开发中',
icon: 'none'
});
},
// 添加好友 - 跳转到搜索页面
addFriend() {
console.log('跳转到搜索用户页面');
wx.navigateTo({
url: '/pages/social/search/search'
});
},
// 显示菜单
showMenu() {
wx.showActionSheet({
itemList: ['好友设置', '隐私设置', '黑名单管理', '好友分组', '数据统计'],
success: (res) => {
switch (res.tapIndex) {
case 0:
this.openFriendSettings();
break;
case 1:
this.openPrivacySettings();
break;
case 2:
this.openBlacklist();
break;
case 3:
this.openFriendGroups();
break;
case 4:
this.showFriendStats();
break;
}
}
});
},
// 好友设置
openFriendSettings() {
wx.showToast({
title: '好友设置功能开发中',
icon: 'none'
});
},
// 隐私设置
openPrivacySettings() {
wx.showToast({
title: '隐私设置功能开发中',
icon: 'none'
});
},
// 黑名单管理
openBlacklist() {
wx.showToast({
title: '黑名单管理功能开发中',
icon: 'none'
});
},
// 好友分组
openFriendGroups() {
wx.showToast({
title: '好友分组功能开发中',
icon: 'none'
});
},
// 好友统计
showFriendStats() {
const stats = {
total: this.data.totalFriendsCount,
online: this.data.onlineFriendsCount,
recent: this.data.recentActiveCount,
mutual: this.data.mutualFriendsCount
};
wx.showModal({
title: '好友统计',
content: `总好友数: ${stats.total}\n在线好友: ${stats.online}\n最近活跃: ${stats.recent}\n共同好友: ${stats.mutual}`,
showCancel: false
});
},
// 扫码添加
addByQR() {
this.setData({ showAddTip: false });
wx.scanCode({
success: (res) => {
console.log('扫码结果:', res.result);
// 处理扫码结果
}
});
},
// 搜索添加
addBySearch() {
this.setData({ showAddTip: false });
wx.navigateTo({
url: '/pages/social/search-user/search-user'
});
},
// 手机号添加
addByPhone() {
this.setData({ showAddTip: false });
wx.showToast({
title: '手机号添加功能开发中',
icon: 'none'
});
},
// 附近的人
addByNearby() {
this.setData({ showAddTip: false });
wx.navigateTo({
url: '/pages/map/map'
});
},
// 搜索好友
searchFriends() {
wx.navigateTo({
url: '/pages/social/search/search'
});
},
// 扫描二维码
scanQRCode() {
wx.scanCode({
success: (res) => {
console.log('扫码结果:', res.result);
// 处理扫码结果
}
});
},
// 邀请好友
inviteFriends() {
wx.showActionSheet({
itemList: ['微信邀请', '短信邀请', '复制邀请链接'],
success: (res) => {
switch (res.tapIndex) {
case 0:
wx.showToast({ title: '微信邀请功能开发中', icon: 'none' });
break;
case 1:
wx.showToast({ title: '短信邀请功能开发中', icon: 'none' });
break;
case 2:
wx.setClipboardData({
data: 'https://findme.app/invite',
success: () => {
wx.showToast({ title: '邀请链接已复制', icon: 'success' });
}
});
break;
}
}
});
},
// 🔥 ===== 新增的好友功能方法 =====
// 初始化WebSocket好友功能
initWebSocketFriendFeatures() {
try {
// 注册消息处理器 - 使用V2版本的统一API
wsManager.on('message', (message) => {
console.log('🔥 好友页面收到WebSocket消息:', message);
// 根据消息类型分发处理
switch (message.type) {
case 'friend_request':
this.handleNewFriendRequest(message.data);
break;
case 'friend_accepted':
this.handleFriendAccepted(message.data);
break;
case 'friend_rejected':
this.handleFriendRejected(message.data);
break;
case 'notification':
this.handleFriendNotification(message.data);
break;
default:
console.log('好友页面未处理的消息类型:', message.type);
}
});
} catch (error) {
console.error('初始化WebSocket好友功能失败:', error);
}
},
// 处理新的好友请求
handleNewFriendRequest(data) {
try {
// 更新好友请求数量
const currentCount = this.data.newFriendRequests;
this.setData({
newFriendRequests: currentCount + 1
});
// 显示通知
wx.showToast({
title: `${data.senderName} 请求添加您为好友`,
icon: 'none',
duration: 3000
});
} catch (error) {
console.error('处理新好友请求失败:', error);
}
},
// 处理好友请求被接受
handleFriendAccepted(data) {
try {
// 刷新好友列表
this.loadFriends();
// 显示通知
wx.showToast({
title: `${data.friendName} 接受了您的好友请求`,
icon: 'success',
duration: 2000
});
} catch (error) {
console.error('处理好友请求被接受失败:', error);
}
},
// 处理好友请求被拒绝
handleFriendRejected(data) {
try {
// 显示通知
wx.showToast({
title: '好友请求被拒绝',
icon: 'none',
duration: 2000
});
} catch (error) {
console.error('处理好友请求被拒绝失败:', error);
}
},
// 处理好友相关通知
handleFriendNotification(data) {
try {
switch (data.type) {
case 'new_friend_request':
this.handleNewFriendRequest(data);
break;
case 'friend_accepted':
this.handleFriendAccepted(data);
break;
case 'friend_rejected':
this.handleFriendRejected(data);
break;
default:
console.log('未知好友通知类型:', data.type);
}
} catch (error) {
console.error('处理好友通知失败:', error);
}
},
// 🔥 ===== 好友操作增强 =====
// 删除好友
async deleteFriend(friendId, friendName) {
try {
const result = await new Promise((resolve) => {
wx.showModal({
title: '删除好友',
content: `确定要删除好友 ${friendName} 吗?`,
success: resolve
});
});
if (!result.confirm) return;
await friendAPI.deleteFriend(friendId);
// 从本地数据中移除
const friends = this.data.friends.filter(friend => friend.id !== friendId);
this.setData({
friends: friends,
filteredFriends: friends,
totalFriendsCount: friends.length
});
// 重新计算统计数据
this.calculateFriendStats(friends);
wx.showToast({
title: '已删除好友',
icon: 'success'
});
} catch (error) {
console.error('删除好友失败:', error);
wx.showToast({
title: '删除失败',
icon: 'none'
});
}
},
// 更新好友备注
async updateFriendRemark(friendId, newRemark) {
try {
await friendAPI.updateFriendRelation(friendId, {
remark: newRemark
});
// 更新本地数据
const friends = this.data.friends.map(friend => {
if (friend.id === friendId) {
return { ...friend, remark: newRemark };
}
return friend;
});
this.setData({
friends: friends,
filteredFriends: friends
});
wx.showToast({
title: '备注已更新',
icon: 'success'
});
} catch (error) {
console.error('更新好友备注失败:', error);
wx.showToast({
title: '更新失败',
icon: 'none'
});
}
},
// 设置好友标签
async setFriendLabel(friendId, label) {
try {
await friendAPI.updateFriendRelation(friendId, {
relation: label
});
// 更新本地数据
const friends = this.data.friends.map(friend => {
if (friend.id === friendId) {
return { ...friend, relation: label };
}
return friend;
});
this.setData({
friends: friends,
filteredFriends: friends
});
wx.showToast({
title: '标签已设置',
icon: 'success'
});
} catch (error) {
console.error('设置好友标签失败:', error);
wx.showToast({
title: '设置失败',
icon: 'none'
});
}
}
});