Files
sundynix-plant-mp/pages/profile/index.js
T
2026-02-10 17:22:53 +08:00

361 lines
11 KiB
JavaScript

// pages/profile/index.js
import request from '../../utils/request';
const app = getApp();
Page({
data: {
view: 'profile', // profile, favorites, posts, about
// User Info
userName: '植物爱好者',
userAvatar: '',
userLevel: '', // Reserved for future level system
userLevelTag: '', // e.g. 'Lv.4 资深植人'
// Stats
plantCount: 0,
taskDoneCount: 0,
postCount: 0,
// Favorites
favTab: 'all',
favorites: [],
filteredFavorites: [],
// Posts
postsTab: 'published',
myPublishedPosts: [],
myDrafts: [],
// App version
appVersion: '1.0.0'
},
onLoad() {
this.loadUserInfo();
},
onShow() {
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({ selected: 4 });
}
},
// ======== User Info ========
loadUserInfo() {
// Try to get from globalData or storage
const userInfo = app.globalData.userInfo || wx.getStorageSync('userInfo');
if (userInfo && userInfo.name) {
this.setData({
userName: userInfo.name || '植物爱好者',
userAvatar: userInfo.avatarUrl || userInfo.avatar || ''
});
return; // Use cached data, no API call
}
// Only fetch from backend if no cached info
request.get('/user/info').then(user => {
if (!user) return;
const avatarUrl = user.avatar ? user.avatar.url : '';
this.setData({
userName: user.name || '植物爱好者',
userAvatar: avatarUrl
});
const info = {
id: user.id,
name: user.name,
avatarUrl: avatarUrl,
account: user.account,
phone: user.phone,
avatarId: user.avatarId
};
app.globalData.userInfo = info;
wx.setStorageSync('userInfo', info);
}).catch(() => { });
},
// ======== Stats ========
loadStats() {
// Fetch plant count
request.post('/plant/page', { current: 1, pageSize: 1 }).then(res => {
this.setData({ plantCount: res.total || 0 });
}).catch(() => { });
// Fetch post count - user's own posts
request.post('/post/page', { current: 1, pageSize: 1, onlyMine: true }).then(res => {
this.setData({ postCount: res.total || 0 });
}).catch(() => { });
// Fetch completed tasks count
request.get('/plant/taskCount').then(res => {
this.setData({ taskDoneCount: res || 0 });
}).catch(() => { });
},
// ======== Navigation ========
setView(e) {
const view = e.currentTarget.dataset.view;
this.setData({ view });
if (view === 'favorites') {
this.loadFavorites();
} else if (view === 'posts') {
this.loadMyPosts();
this.loadDrafts();
}
},
goBack() {
this.setData({ view: 'profile' });
},
// ======== Favorites ========
loadFavorites() {
// TODO: Call favorites API when available
// request.get('/user/favorites').then(...)
this.filterFavorites();
},
onFavTabChange(e) {
this.setData({ favTab: e.detail.value }, () => {
this.filterFavorites();
});
},
filterFavorites() {
const { favorites, favTab } = this.data;
const filtered = favorites.filter(item => {
if (favTab === 'all') return true;
return item.type === favTab;
});
this.setData({ filteredFavorites: filtered });
},
// ======== Posts ========
loadMyPosts() {
request.post('/post/page', { current: 1, pageSize: 50, onlyMine: true }).then(res => {
const records = res.records || res.list || [];
const posts = records.map(item => {
const publisher = item.publisher || {};
const imgList = item.imgList || [];
return {
id: item.id,
content: item.content || '',
time: this._formatTime(item.createdAt || item.createTime),
images: imgList.map(img => img.url),
likes: item.likeList || [],
comments: item.commentList || []
};
});
this.setData({ myPublishedPosts: posts });
}).catch(() => {
this.setData({ myPublishedPosts: [] });
});
},
loadDrafts() {
try {
const draft = wx.getStorageSync('post_draft');
if (draft && (draft.content || (draft.images && draft.images.length > 0))) {
this.setData({
myDrafts: [{
id: 'draft_1',
content: draft.content || '',
images: draft.images || [],
selectedTopics: draft.selectedTopics || []
}]
});
} else {
this.setData({ myDrafts: [] });
}
} catch (e) {
this.setData({ myDrafts: [] });
}
},
onPostsTabChange(e) {
this.setData({ postsTab: e.detail.value });
},
deletePost(e) {
const postId = e.currentTarget.dataset.id;
wx.showModal({
title: '删除动态',
content: '确定要删除这条动态吗?',
confirmColor: '#EF5350',
success: (res) => {
if (!res.confirm) return;
wx.showLoading({ title: '删除中...' });
request.get('/post/delete', { id: postId }).then(() => {
wx.hideLoading();
this.loadMyPosts();
wx.showToast({ title: '已删除', icon: 'success' });
}).catch(() => {
wx.hideLoading();
wx.showToast({ title: '删除失败', icon: 'none' });
});
}
});
},
editDraft() {
wx.navigateTo({ url: '/pages/community/create/index' });
},
deleteDraft() {
wx.showModal({
title: '删除草稿',
content: '确定要删除这份草稿吗?',
confirmColor: '#EF5350',
success: (res) => {
if (!res.confirm) return;
try { wx.removeStorageSync('post_draft'); } catch (e) { }
this.setData({ myDrafts: [] });
wx.showToast({ title: '已删除', icon: 'success' });
}
});
},
// ======== Menu Actions ========
goToIdentifyHistory() {
wx.navigateTo({ url: '/pages/profile/identify-history/index' });
},
goToNotificationSettings() {
// Open WeChat notification settings
wx.openSetting({
success: (res) => {
console.log('Settings opened', res);
}
});
},
goToAbout() {
this.setData({ view: 'about' });
},
goToAgreement() {
// TODO: Navigate to agreement page or show inline
wx.showToast({ title: '功能开发中', icon: 'none' });
},
goToPrivacy() {
// TODO: Navigate to privacy page or show inline
wx.showToast({ title: '功能开发中', icon: 'none' });
},
// ======== Profile Editor Popup ========
openProfileEditor() {
this.setData({
showProfileEditor: true,
tempAvatar: '',
tempNickname: this.data.userName === '植物爱好者' ? '' : this.data.userName
});
},
closeProfileEditor() {
this.setData({ showProfileEditor: false });
},
onProfilePopupChange(e) {
if (!e.detail.visible) {
this.setData({ showProfileEditor: false });
}
},
// WeChat native chooseAvatar callback
onChooseAvatar(e) {
const avatarUrl = e.detail.avatarUrl;
if (avatarUrl) {
this.setData({ tempAvatar: avatarUrl });
}
},
onNicknameInput(e) {
this.setData({ tempNickname: e.detail.value });
},
onNicknameBlur(e) {
// WeChat nickname type may return value on blur
if (e.detail.value) {
this.setData({ tempNickname: e.detail.value });
}
},
async saveProfile() {
const { tempAvatar, tempNickname } = this.data;
if (!tempAvatar && !tempNickname) {
wx.showToast({ title: '请选择头像或输入昵称', icon: 'none' });
return;
}
wx.showLoading({ title: '保存中...', mask: true });
try {
const updatePayload = {};
// 1. Upload avatar if changed
if (tempAvatar) {
const data = await request.upload(tempAvatar);
const fileData = data?.file || {};
if (fileData.id) {
updatePayload.avatar_id = fileData.id;
// Update local display
this.setData({ userAvatar: fileData.url || tempAvatar });
}
}
// 2. Set name if provided
if (tempNickname) {
updatePayload.name = tempNickname;
this.setData({ userName: tempNickname });
}
// 3. Call update API
if (Object.keys(updatePayload).length > 0) {
await request.post('/user/update', updatePayload);
}
wx.hideLoading();
this.setData({ showProfileEditor: false });
wx.showToast({ title: '资料已更新', icon: 'success' });
// Update globalData
const userInfo = app.globalData.userInfo || {};
if (updatePayload.name) userInfo.name = updatePayload.name;
if (updatePayload.avatar_id) userInfo.avatarId = updatePayload.avatar_id;
app.globalData.userInfo = userInfo;
} catch (err) {
wx.hideLoading();
console.error('Save profile failed', err);
wx.showToast({ title: '保存失败', icon: 'none' });
}
},
// ======== Utilities ========
_formatTime(dateStr) {
if (!dateStr) return '';
const d = new Date(dateStr);
const now = new Date();
const diffMs = now - d;
const diffMin = Math.floor(diffMs / 60000);
if (diffMin < 1) return '刚刚';
if (diffMin < 60) return diffMin + '分钟前';
const diffHour = Math.floor(diffMin / 60);
if (diffHour < 24) return diffHour + '小时前';
const diffDay = Math.floor(diffHour / 24);
if (diffDay < 7) return diffDay + '天前';
const month = (d.getMonth() + 1).toString().padStart(2, '0');
const day = d.getDate().toString().padStart(2, '0');
return `${month}-${day}`;
},
// ======== Reserved: Future Level/Badge System ========
// These methods will be implemented when the backend supports level/badge APIs
// loadLevelInfo() { request.get('/user/level').then(...) },
// loadBadges() { request.get('/user/badges').then(...) },
})