// 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(...) }, })