findme-miniprogram-frontend/pages/user-profile/user-profile.js
2025-12-27 17:16:03 +08:00

436 lines
12 KiB
JavaScript
Raw Permalink 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 config = require('../../config/config.js');
const apiClient = require('../../utils/api-client.js');
const imageCacheManager = require('../../utils/image-cache-manager.js');
Page({
data: {
// 用户基本信息
userInfo: null,
// 动态列表
feedList: [],
// 统计数据
stats: {
friendsCount: 0,
postsCount: 0,
likesCount: 0
},
// 加载状态
loading: true,
error: '',
// 页面相关
currentPage: 1,
pageSize: 5,
hasMoreData: true,
loadingMore: false,
// 当前年份
currentYear: new Date().getFullYear(),
// 是否是当前用户的资料页
isCurrentUser: false,
// 关注状态
isFollowing: false,
// 好友状态
isFriend: false,
// 系统适配信息
systemInfo: {},
statusBarHeight: 0,
navBarHeight: 0,
windowHeight: 0,
safeAreaBottom: 0
},
onLoad: function(options) {
if (!options.customId) {
wx.showToast({
title: '用户信息错误',
icon: 'none'
});
wx.navigateBack();
return;
}
// 保存用户ID
this.setData({
customId: options.customId
});
// 初始化系统信息
this.initSystemInfo();
// 加载用户资料
this.loadUserProfile();
},
// 初始化系统信息
initSystemInfo: function() {
try {
const systemInfo = wx.getSystemInfoSync();
const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
this.setData({
systemInfo: systemInfo,
statusBarHeight: systemInfo.statusBarHeight,
navBarHeight: menuButtonInfo.top + menuButtonInfo.height,
windowHeight: systemInfo.windowHeight,
safeAreaBottom: systemInfo.safeArea?.bottom || systemInfo.windowHeight
});
} catch (error) {
console.error('获取系统信息失败:', error);
}
},
// 加载用户资料
loadUserProfile: function() {
const { customId } = this.data;
this.setData({ loading: true, error: '' });
wx.request({
url: `${config.api.baseUrl}/api/v1/users/${customId}`,
method: 'GET',
success: (res) => {
// 🔥 统一处理401 - 使用apiClient的统一处理
const apiClient = require('../../utils/api-client.js');
if (apiClient.is401Error && apiClient.is401Error(res)) {
const app = getApp();
const isLoggedIn = app?.globalData?.isLoggedIn || false;
apiClient.handle401Error(isLoggedIn);
return;
}
if (res.data.code !== 200) {
this.setData({
loading: false,
error: res.data.message || '加载用户资料失败'
});
return;
}
const userData = res.data.data.user || {};
// 处理头像URL
let avatar = userData.avatar || '/images/findme-logo.png';
if (avatar && !avatar.startsWith('http')) {
try {
const baseDomain = config.api.baseUrl.replace(/\/api\/v1$/, '');
avatar = `${baseDomain}${avatar}`;
} catch (e) {
console.error('头像路径处理失败:', e);
}
}
// 缓存头像
imageCacheManager.cacheImage(avatar, 'user_avatar')
.then(cachedAvatar => {
// 更新用户数据
const processedUserInfo = {
...userData,
avatar: cachedAvatar,
nickname: userData.nickname || userData.customId || '未知用户',
// 格式化用户信息
formattedGender: userData.gender === 1 ? '男' : (userData.gender === 2 ? '女' : '未设置'),
formattedLocation: userData.location || '未设置'
};
// 检查是否是当前用户
const currentUser = app.globalData.userInfo || {};
const isCurrentUser = currentUser.user && currentUser.user.customId === customId;
this.setData({
userInfo: processedUserInfo,
stats: res.data.data.stats || this.data.stats,
isCurrentUser: isCurrentUser,
isFollowing: res.data.data.isFollowing || false,
isFriend: res.data.data.isFriend || false,
loading: false
});
// 加载用户动态
this.loadUserFeeds();
})
.catch(error => {
console.error('头像缓存失败:', error);
// 继续处理使用原始头像URL
this.setData({
userInfo: userData,
loading: false
});
this.loadUserFeeds();
});
},
fail: (err) => {
console.error('加载用户资料失败:', err);
this.setData({
loading: false,
error: '网络请求失败,请检查网络连接'
});
}
});
},
// 加载用户动态
loadUserFeeds: function() {
const { customId, currentPage, pageSize, feedList } = this.data;
// 防止重复加载
if (this.data.loadingMore || !this.data.hasMoreData) {
return;
}
this.setData({ loadingMore: true });
wx.request({
url: `${config.api.baseUrl}/api/v1/feeds/user/${customId}`,
method: 'GET',
data: {
page: currentPage,
pageSize: pageSize
},
header: {
'Authorization': `Bearer ${apiClient.getToken() || ''}`
},
success: (res) => {
if (res.data.code === 200) {
const newFeeds = res.data.data.feeds || [];
// 格式化动态数据
const processedFeeds = newFeeds.map(feed => {
// 格式化时间
let formattedTime = '未知时间';
try {
formattedTime = this.formatTime(feed.createdAt || '');
} catch (error) {
console.error('时间格式化失败:', error);
}
// 处理媒体URL
let processedMedia = [];
if (feed.media && Array.isArray(feed.media)) {
processedMedia = feed.media.map(mediaItem => {
let url = mediaItem.url || '';
if (url && !url.startsWith('http') && url.startsWith('/')) {
try {
const baseDomain = config.api.baseUrl.replace(/\/api\/v1$/, '');
url = `${baseDomain}${url}`;
} catch (e) {}
}
return {
...mediaItem,
url: url
};
});
}
const imageMedia = processedMedia.filter(item => item.type === 'image');
const imageRowCount = imageMedia.length > 0 ? Math.ceil(imageMedia.length / 3) : 0;
return {
...feed,
formattedTime: formattedTime,
media: processedMedia,
imageMedia,
imageRowCount
};
});
// 合并动态列表
const updatedFeeds = currentPage === 1 ? processedFeeds : [...feedList, ...processedFeeds];
this.setData({
feedList: updatedFeeds,
currentPage: currentPage + 1,
hasMoreData: res.data.data.hasMore || false,
loadingMore: false
});
} else {
console.error('加载用户动态失败:', res.data.message);
this.setData({ loadingMore: false });
}
},
fail: (err) => {
console.error('加载用户动态网络失败:', err);
this.setData({ loadingMore: false });
}
});
},
// 格式化时间
formatTime: function(timeStr) {
if (!timeStr) return '未知时间';
const createTime = new Date(timeStr);
if (isNaN(createTime.getTime())) return '未知时间';
const now = new Date();
const diffMinutes = Math.floor((now - createTime) / (1000 * 60));
// 5分钟内刚刚
if (diffMinutes < 5) return '刚刚';
// 1小时内xx分钟前
if (diffMinutes < 60) return `${diffMinutes}分钟前`;
// 24小时内xx小时前
const diffHours = Math.floor(diffMinutes / 60);
if (diffHours < 24) return `${diffHours}小时前`;
// 7天内xx天前
const diffDays = Math.floor(diffHours / 24);
if (diffDays < 7) return `${diffDays}天前`;
// 格式化日期时间
const year = createTime.getFullYear();
const month = String(createTime.getMonth() + 1).padStart(2, '0');
const day = String(createTime.getDate()).padStart(2, '0');
// 跨年份显示完整日期,同年份省略年份
return year === this.data.currentYear
? `${month}${day}`
: `${year}${month}${day}`;
},
// 点击返回按钮
onBack: function() {
wx.navigateBack();
},
// 点击关注/取消关注
onFollowToggle: function() {
const { customId, isFollowing } = this.data;
wx.request({
url: `${config.api.baseUrl}/api/v1/users/${customId}/follow`,
method: isFollowing ? 'DELETE' : 'POST',
header: {
'Authorization': `Bearer ${apiClient.getToken() || ''}`
},
success: (res) => {
if (res.data.code === 200) {
this.setData({
isFollowing: !isFollowing
});
wx.showToast({
title: isFollowing ? '已取消关注' : '关注成功',
icon: 'success'
});
} else {
wx.showToast({
title: res.data.message || '操作失败',
icon: 'none'
});
}
},
fail: (err) => {
console.error('关注操作失败:', err);
wx.showToast({
title: '网络请求失败',
icon: 'none'
});
}
});
},
// 点击发送消息
onSendMessage: function() {
const { customId, userInfo } = this.data;
wx.navigateTo({
url: `/pages/message/chat/chat?userId=${customId}&userName=${userInfo.nickname || '未知用户'}`
});
},
// 点击添加好友
onAddFriend: function() {
const { customId, userInfo } = this.data;
wx.request({
url: `${config.api.baseUrl}/api/v1/friends/request`,
method: 'POST',
data: {
targetUserId: customId,
message: '我想加你为好友'
},
header: {
'Authorization': `Bearer ${apiClient.getToken() || ''}`
},
success: (res) => {
if (res.data.code === 200) {
wx.showToast({
title: '好友请求已发送',
icon: 'success'
});
} else {
wx.showToast({
title: res.data.message || '发送请求失败',
icon: 'none'
});
}
},
fail: (err) => {
console.error('发送好友请求失败:', err);
wx.showToast({
title: '网络请求失败',
icon: 'none'
});
}
});
},
// 点击动态图片
onImageTap: function(e) {
const { index, feedIndex } = e.currentTarget.dataset;
const feed = this.data.feedList[feedIndex];
if (!feed || !feed.imageMedia) return;
const urls = feed.imageMedia.map(item => item.url);
if (urls.length === 0) return;
wx.previewImage({
current: urls[index],
urls: urls
});
},
// 点击动态项
onFeedTap: function(e) {
const { feedIndex } = e.currentTarget.dataset;
const feed = this.data.feedList[feedIndex];
if (!feed) return;
// 可以跳转到动态详情页,如果有的话
wx.showToast({
title: '查看动态详情',
icon: 'none'
});
},
// 下拉刷新
onPullDownRefresh: function() {
this.setData({
currentPage: 1,
hasMoreData: true,
feedList: []
}, () => {
this.loadUserProfile();
wx.stopPullDownRefresh();
});
},
// 上拉加载更多
onReachBottom: function() {
this.loadUserFeeds();
},
// 分享功能
onShareAppMessage: function() {
const { userInfo } = this.data;
return {
title: `${userInfo.nickname}的个人主页`,
path: `/pages/user-profile/user-profile?customId=${this.data.customId}`,
imageUrl: userInfo.avatar || '/images/findme-logo.png'
};
}
});