Files
danyang-match/miniapp/pages/profile-interests/profile-interests.js
T

193 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 兴趣与生活方式页 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, '保存失败');
}
},
});