/** * 兴趣与生活方式页 U09(Phase 04 P04-T24) * * 重构要点(遵循 AGENTS.md 不变量): * - 数据:profileService.getProfile + userStore.updateProfile(第 9 条) * - 数量限制:BUSINESS_LIMITS.MAX_INTEREST_TAGS(第 12 条,不硬编码) * - 草稿恢复:onLoad 读 ONBOARDING_DRAFT.interests,保存前写回 * - 下一步:跳 profile-intent */ const { userStore, appStore } = require('../../stores'); const { profileService } = require('../../services'); const { ROUTE, STORAGE_KEYS, BUSINESS_LIMITS } = require('../../constants'); const INTEREST_OPTIONS = [ { code: 'travel', name: '旅行' }, { code: 'reading', name: '阅读' }, { code: 'sports', name: '运动' }, { code: 'fitness', name: '健身' }, { code: 'photography', name: '摄影' }, { code: 'movie', name: '电影' }, { code: 'music', name: '音乐' }, { code: 'food', name: '美食' }, { code: 'cooking', name: '烹饪' }, { code: 'outdoor', name: '户外' }, { code: 'pets', name: '宠物' }, { code: 'games', name: '游戏' }, { code: 'culture', name: '传统文化' }, { code: 'charity', name: '公益活动' }, { code: 'other', name: '其他' }, ]; const LIFESTYLE_OPTIONS = [ { code: 'quiet', name: '喜欢安静' }, { code: 'social', name: '喜欢社交' }, { code: 'outdoor', name: '喜欢户外' }, { code: 'homebody', name: '居家型' }, { code: 'regular_work', name: '工作规律' }, { code: 'frequent_travel', name: '经常出差' }, { code: 'family_oriented', name: '注重家庭' }, { code: 'other', name: '其他' }, ]; Page({ data: { statusBarHeight: 20, navBarHeight: 44, loading: false, saving: false, interests: INTEREST_OPTIONS.map((o) => ({ ...o, selected: false })), lifestyles: LIFESTYLE_OPTIONS.map((o) => ({ ...o, selected: false })), maxTags: BUSINESS_LIMITS.MAX_INTEREST_TAGS, selectedInterestsCount: 0, }, onLoad() { this._initSystemInfo(); this._applyDraft(); this.loadProfile(); }, _initSystemInfo() { try { const sysInfo = wx.getSystemInfoSync(); this.setData({ statusBarHeight: sysInfo.statusBarHeight || 20, navBarHeight: 44, }); } catch (e) { /* 使用默认值 */ } }, async loadProfile() { this.setData({ loading: true }); try { const profile = await profileService.getProfile(); this._mergeProfile(profile); } catch (err) { /* 首次填写 */ } finally { this.setData({ loading: false }); } }, _mergeProfile(profile) { if (!profile) return; const d = this._readDraft(); const savedInterests = d.interests || profile.interests || []; const savedLifestyles = d.lifestyles || profile.lifestyles || []; const interests = this.data.interests.map((o) => ({ ...o, selected: savedInterests.includes(o.code), })); const lifestyles = this.data.lifestyles.map((o) => ({ ...o, selected: savedLifestyles.includes(o.code), })); this.setData({ interests, lifestyles, selectedInterestsCount: interests.filter((o) => o.selected).length, }); }, // ============ 草稿 ============ _readDraft() { try { const draft = wx.getStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT) || {}; return draft.interests || {}; } catch (e) { return {}; } }, _applyDraft() { const d = this._readDraft(); if (!d || Object.keys(d).length === 0) return; const savedInterests = d.interests || []; const savedLifestyles = d.lifestyles || []; const interests = this.data.interests.map((o) => ({ ...o, selected: savedInterests.includes(o.code), })); const lifestyles = this.data.lifestyles.map((o) => ({ ...o, selected: savedLifestyles.includes(o.code), })); this.setData({ interests, lifestyles, selectedInterestsCount: interests.filter((o) => o.selected).length, }); }, _writeDraft() { try { const draft = wx.getStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT) || {}; draft.interests = { interests: this.data.interests.filter((o) => o.selected).map((o) => o.code), lifestyles: this.data.lifestyles.filter((o) => o.selected).map((o) => o.code), }; draft.currentStep = 'interests'; wx.setStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT, draft); } catch (e) { /* ignore */ } }, // ============ 交互 ============ onInterestTap(e) { const code = e.currentTarget.dataset.code; const interests = this.data.interests.map((o) => { if (o.code !== code) return o; // 取消选中直接切换;选中需检查上限 if (!o.selected && this.data.selectedInterestsCount >= this.data.maxTags) { appStore.toast(`最多选择 ${this.data.maxTags} 个兴趣`); return o; } return { ...o, selected: !o.selected }; }); this.setData({ interests, selectedInterestsCount: interests.filter((o) => o.selected).length, }); }, onLifestyleTap(e) { const code = e.currentTarget.dataset.code; const lifestyles = this.data.lifestyles.map((o) => { if (o.code !== code) return o; return { ...o, selected: !o.selected }; }); this.setData({ lifestyles }); }, // ============ 导航 ============ onBack() { this._writeDraft(); wx.navigateBack(); }, async onNext() { if (this.data.saving) return; this.setData({ saving: true }); this._writeDraft(); try { await userStore.updateProfile({ interests: this.data.interests.filter((o) => o.selected).map((o) => o.code), lifestyles: this.data.lifestyles.filter((o) => o.selected).map((o) => o.code), }); this.setData({ saving: false }); wx.navigateTo({ url: ROUTE.ONBOARDING.PROFILE_INTENT }); } catch (err) { this.setData({ saving: false }); appStore.toastError(err, '保存失败'); } }, });