437 lines
12 KiB
JavaScript
437 lines
12 KiB
JavaScript
|
|
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'
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|