/** * 基础资料页 U06(Phase 04 P04-T21) * * 重构要点(遵循 AGENTS.md 不变量): * - 数据:profileService.getProfile + userStore.updateProfile,不再直连 api(第 9 条) * - 性别/出生日期:由身份证自动生成,只读展示(第 8 条:本地不长期保存身份证/完整生日) * - 草稿恢复:onLoad 读 ONBOARDING_DRAFT.basic,保存前写回(验收条件"Draft退出后可恢复") * - 数量限制:本页无数值型限制字段,选项列表遵循 §4.1 配置 * - 下一步:跳 profile-lifestyle */ const { userStore, appStore } = require('../../stores'); const { profileService } = require('../../services'); const { ROUTE, STORAGE_KEYS } = require('../../constants'); const MARITAL_OPTIONS = [ { value: 'never_married', label: '未婚' }, { value: 'divorced', label: '离异' }, { value: 'widowed', label: '丧偶' }, ]; const CHILDREN_OPTIONS = [ { value: 'none', label: '无子女' }, { value: 'has', label: '有子女' }, ]; const EDUCATION_OPTIONS = [ { value: 'high_school', label: '高中/中专' }, { value: 'college', label: '大专' }, { value: 'bachelor', label: '本科' }, { value: 'master', label: '硕士' }, { value: 'phd', label: '博士' }, ]; const OCCUPATION_OPTIONS = [ { value: 'government', label: '机关事业单位' }, { value: 'education', label: '教育' }, { value: 'medical', label: '医疗' }, { value: 'enterprise', label: '企业职员' }, { value: 'technical', label: '技术人员' }, { value: 'self_employed', label: '个体经营' }, { value: 'freelance', label: '自由职业' }, { value: 'service', label: '服务行业' }, { value: 'agriculture', label: '农业' }, { value: 'other', label: '其他' }, ]; const REGION_OPTIONS = ['丹阳', '镇江市区', '镇江其他辖区', '南京']; Page({ data: { statusBarHeight: 20, navBarHeight: 44, loading: false, saving: false, // 身份证自动生成(只读) gender: '', genderLabel: '', ageText: '', // 用户填写 regionName: '', heightCm: '', maritalStatus: '', hasChildren: '', educationCode: '', occupationCode: '', // 选项 maritalOptions: MARITAL_OPTIONS, childrenOptions: CHILDREN_OPTIONS, educationOptions: EDUCATION_OPTIONS, occupationOptions: OCCUPATION_OPTIONS, regionOptions: REGION_OPTIONS, regionIndex: -1, maritalIndex: -1, childrenIndex: -1, educationIndex: -1, occupationIndex: -1, }, 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 draft = this._readDraft(); const regionName = draft.regionName || profile.regionName || ''; const maritalStatus = draft.maritalStatus || profile.maritalStatus || ''; const hasChildren = draft.hasChildren || (profile.hasChildren !== undefined ? (profile.hasChildren ? 'has' : 'none') : ''); const educationCode = draft.educationCode || profile.educationCode || ''; const occupationCode = draft.occupationCode || profile.occupationCode || ''; const heightCm = draft.heightCm || profile.heightCm || ''; this.setData({ gender: profile.gender || draft.gender || '', genderLabel: profile.gender === 'male' ? '男' : (profile.gender === 'female' ? '女' : ''), ageText: profile.age ? `${profile.age}岁` : '', regionName, heightCm, maritalStatus, hasChildren, educationCode, occupationCode, regionIndex: REGION_OPTIONS.indexOf(regionName), maritalIndex: MARITAL_OPTIONS.findIndex((o) => o.value === maritalStatus), childrenIndex: CHILDREN_OPTIONS.findIndex((o) => o.value === hasChildren), educationIndex: EDUCATION_OPTIONS.findIndex((o) => o.value === educationCode), occupationIndex: OCCUPATION_OPTIONS.findIndex((o) => o.value === occupationCode), }); }, // ============ 草稿 ============ _readDraft() { try { const draft = wx.getStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT) || {}; return draft.basic || {}; } catch (e) { return {}; } }, /** 把草稿值填入表单(loadProfile 失败时也能恢复) */ _applyDraft() { const d = this._readDraft(); if (!d || Object.keys(d).length === 0) return; this.setData({ regionName: d.regionName || '', heightCm: d.heightCm || '', maritalStatus: d.maritalStatus || '', hasChildren: d.hasChildren || '', educationCode: d.educationCode || '', occupationCode: d.occupationCode || '', regionIndex: REGION_OPTIONS.indexOf(d.regionName || ''), maritalIndex: MARITAL_OPTIONS.findIndex((o) => o.value === (d.maritalStatus || '')), childrenIndex: CHILDREN_OPTIONS.findIndex((o) => o.value === (d.hasChildren || '')), educationIndex: EDUCATION_OPTIONS.findIndex((o) => o.value === (d.educationCode || '')), occupationIndex: OCCUPATION_OPTIONS.findIndex((o) => o.value === (d.occupationCode || '')), }); }, _writeDraft() { try { const draft = wx.getStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT) || {}; draft.basic = { regionName: this.data.regionName, heightCm: this.data.heightCm, maritalStatus: this.data.maritalStatus, hasChildren: this.data.hasChildren, educationCode: this.data.educationCode, occupationCode: this.data.occupationCode, }; draft.currentStep = 'basic'; wx.setStorageSync(STORAGE_KEYS.ONBOARDING_DRAFT, draft); } catch (e) { /* ignore */ } }, // ============ 表单交互 ============ onRegionChange(e) { const idx = Number(e.detail.value); this.setData({ regionIndex: idx, regionName: REGION_OPTIONS[idx] }); }, onHeightInput(e) { this.setData({ heightCm: e.detail.value }); }, onMaritalChange(e) { const idx = Number(e.detail.value); this.setData({ maritalIndex: idx, maritalStatus: MARITAL_OPTIONS[idx].value }); }, onChildrenChange(e) { const idx = Number(e.detail.value); this.setData({ childrenIndex: idx, hasChildren: CHILDREN_OPTIONS[idx].value }); }, onEducationChange(e) { const idx = Number(e.detail.value); this.setData({ educationIndex: idx, educationCode: EDUCATION_OPTIONS[idx].value }); }, onOccupationChange(e) { const idx = Number(e.detail.value); this.setData({ occupationIndex: idx, occupationCode: OCCUPATION_OPTIONS[idx].value }); }, // ============ 导航 ============ onBack() { this._writeDraft(); wx.navigateBack(); }, /** 下一步:校验必填 → 保存草稿 → 提交服务端 → 跳 profile-lifestyle */ async onNext() { if (this.data.saving) return; const { regionName, heightCm, maritalStatus, hasChildren, educationCode, occupationCode } = this.data; if (!regionName) return appStore.toast('请选择居住区域'); if (!heightCm) return appStore.toast('请填写身高'); if (!maritalStatus) return appStore.toast('请选择婚姻状况'); if (!hasChildren) return appStore.toast('请选择子女情况'); if (!educationCode) return appStore.toast('请选择学历'); if (!occupationCode) return appStore.toast('请选择职业类型'); this.setData({ saving: true }); this._writeDraft(); try { await userStore.updateProfile({ regionName, heightCm: Number(heightCm), maritalStatus, hasChildren: hasChildren === 'has', educationCode, occupationCode, }); this.setData({ saving: false }); wx.navigateTo({ url: ROUTE.ONBOARDING.PROFILE_LIFESTYLE }); } catch (err) { this.setData({ saving: false }); appStore.toastError(err, '保存失败'); } }, });