const app = getApp(); const svc = require('../../services/exercise'); const planSvc = require('../../services/plan'); const favSvc = require('../../services/favorite'); const { iconName } = require('../../utils/icon-name'); function greeting() { const h = new Date().getHours(); if (h < 6) return '夜深了,'; if (h < 11) return '早上好,'; if (h < 13) return '中午好,'; if (h < 18) return '下午好,'; if (h < 22) return '晚上好,'; return '夜深了,'; } function isLogin() { return !!wx.getStorageSync('access_token'); } Page({ data: { statusBarHeight: 20, stats: null, bodyParts: [], equipment: [], featured: [], collections: [], loading: true, quickEntries: [ { key: 'recommend', label: '智能推荐', icon: 'sparkles', url: '/pages/recommend/recommend' }, { key: 'bodyPart', label: '按部位', icon: 'accessibility', url: '/pages/category/category?dimension=bodyPart' }, { key: 'equipment', label: '按器械', icon: 'dumbbell', url: '/pages/category/category?dimension=equipment' }, { key: 'official', label: '官方计划', icon: 'clipboard-list', url: '/pages/collection/collection' }, { key: 'myPlans', label: '我的计划', icon: 'folder-open', url: '/pages/my-plans/my-plans' }, { key: 'mine', label: '我的', icon: 'user', url: '/pages/profile/profile' } ], // —— 轻量个性化(登录后)—— isLogin: false, greeting: '', myPlans: [], myFavorites: [], todayRecommend: [] }, onLoad() { this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20 }); this.loadData(); }, onShow() { // tab 切回:已登录则静默刷新个性化(优先缓存) if (isLogin()) this.loadPersonal(true); }, loadData() { this.setData({ loading: true }); Promise.all([ svc.getStats().catch(() => null), svc.listExercises({ pageSize: 8 }).catch(() => ({ items: [] })), svc.listCollections().catch(() => []) ]).then(([stats, list, collections]) => { const cols = (collections || []).map((c) => ({ ...c, icon: iconName(c.emoji) })); this.setData({ stats, bodyParts: (stats && stats.bodyParts) || [], equipment: (stats && stats.equipment) || [], featured: (list && list.items) || [], collections: cols, loading: false }); if (isLogin()) this.loadPersonal(false); }).catch(() => { this.setData({ loading: false }); }); }, // 轻量个性化:复用现有 API,纯前端聚合;silent=切 tab 静默刷新 loadPersonal(silent) { if (!isLogin()) return; this.setData({ isLogin: true, greeting: greeting() }); if (!silent) this.setData({ personalLoading: true }); const CACHE_KEY = 'fc_personal_cache'; const cached = wx.getStorageSync(CACHE_KEY); const now = Date.now(); if (cached && now - (cached.ts || 0) < 5 * 60 * 1000 && !silent) { this.applyPersonal(cached.data); return; } Promise.all([ planSvc.listMine().catch(() => []), favSvc.listExercises().catch(() => []) ]).then(([plans, favs]) => { const planArr = Array.isArray(plans) ? plans : (plans && plans.items) || []; const favArr = Array.isArray(favs) ? favs : (favs && favs.items) || []; const data = { myPlans: planArr.slice(0, 3).map((p) => ({ id: p.id, name: p.name, count: p.exerciseCount || 0 })), myFavorites: favArr.slice(0, 6), todayRecommend: (this.data.featured || []).slice(0, 3).map((e) => ({ id: e.id, name: e.displayName || e.name, reason: '为你精选 · 高效入门' })) }; wx.setStorageSync(CACHE_KEY, { ts: now, data }); this.applyPersonal(data); }).catch(() => { this.setData({ personalLoading: false }); }); }, applyPersonal(data) { this.setData({ myPlans: data.myPlans, myFavorites: data.myFavorites, todayRecommend: data.todayRecommend, personalLoading: false }); }, goRecommend() { wx.navigateTo({ url: '/pages/recommend/recommend' }); }, onQuick(e) { wx.navigateTo({ url: e.currentTarget.dataset.url }); }, onSearch() { wx.navigateTo({ url: '/pages/search/search' }); }, onPlanTap(e) { const id = e.currentTarget.dataset.id; if (id) wx.navigateTo({ url: '/pages/plan-detail/plan-detail?id=' + encodeURIComponent(id) }); }, onExercise(e) { const id = (e.detail && e.detail.id) || (e.currentTarget && e.currentTarget.dataset.id); if (!id) return; wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(id) }); }, onScanBodyPart(e) { const { value, label } = e.currentTarget.dataset; wx.navigateTo({ url: '/pages/category/category?dimension=bodyPart&value=' + encodeURIComponent(value) + '&title=' + encodeURIComponent(label) }); }, onScanEquipment(e) { const { value, label } = e.currentTarget.dataset; wx.navigateTo({ url: '/pages/category/category?dimension=equipment&value=' + encodeURIComponent(value) + '&title=' + encodeURIComponent(label) }); }, onCollection(e) { wx.navigateTo({ url: '/pages/collection-detail/collection-detail?slug=' + encodeURIComponent(e.currentTarget.dataset.slug) }); } });