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

248 lines
8.3 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.
/**
* 基础资料页 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, '保存失败');
}
},
});