/** 表单数据模型 */ interface MemberForm { /** 姓名 */ name: string /** 身份证号 */ idCard: string /** 性别(由身份证解析,只读) */ gender: string /** 年龄(由身份证解析,只读) */ age: string /** 身高(cm) */ height: string } /** 身份证解析结果 */ interface IdCardParsed { /** 性别,空字符串表示解析失败 */ gender: string /** 年龄,空字符串表示解析失败 */ age: string } /** * 添加成员页 * 收集姓名、身份证号、身高,并根据身份证自动解析性别与年龄 * 保存后返回设备成员列表页 */ Page({ data: { // 表单数据 form: { name: '', // 姓名 idCard: '', // 身份证号 gender: '', // 性别(由身份证解析,只读) age: '', // 年龄(由身份证解析,只读) height: '' // 身高(cm) } as MemberForm }, /** * 姓名输入 */ onNameInput(e: WechatMiniprogram.Input) { this.setData({ 'form.name': e.detail.value }) }, /** * 身份证号输入 * 长度满 18 位时自动解析性别与年龄,否则清空 */ onIdCardInput(e: WechatMiniprogram.Input) { const idCard = (e.detail.value || '').trim().toUpperCase() const parsed = this.parseIdCard(idCard) this.setData({ 'form.idCard': idCard, 'form.gender': parsed.gender, 'form.age': parsed.age }) }, /** * 身高输入 */ onHeightInput(e: WechatMiniprogram.Input) { this.setData({ 'form.height': e.detail.value }) }, /** * 解析身份证号,返回性别与年龄 * @param idCard 18 位身份证号 */ parseIdCard(idCard: string): IdCardParsed { // 简单校验:18 位且前 17 位为数字 const reg = /^\d{17}[\dX]$/ if (!reg.test(idCard)) { return { gender: '', age: '' } } // 性别:第 17 位奇数为男,偶数为女 const genderCode = parseInt(idCard.charAt(16), 10) const gender = genderCode % 2 === 1 ? '男' : '女' // 出生日期:第 7-14 位 const year = parseInt(idCard.substr(6, 4), 10) const month = parseInt(idCard.substr(10, 2), 10) const day = parseInt(idCard.substr(12, 2), 10) // 基本合法性校验 if ( !year || !month || !day || month < 1 || month > 12 || day < 1 || day > 31 ) { return { gender: '', age: '' } } // 计算周岁(看是否过了今年生日) const now = new Date() let age = now.getFullYear() - year const nowMonth = now.getMonth() + 1 const nowDay = now.getDate() if (nowMonth < month || (nowMonth === month && nowDay < day)) { age -= 1 } if (age < 0 || age > 150) { return { gender: '', age: '' } } return { gender, age: String(age) } }, /** * 从已有成员中选择(暂留空,后续接入选择浮层) */ onTapSelectExisting() { // TODO: 接入"从已有成员中选择"浮层/选择页 }, /** * 取消:直接返回上一页 */ onCancel() { wx.navigateBack() }, /** * 保存成员信息 * 必填:姓名、身份证号(18 位且解析成功)、身高 * 未通过时 toast 提示,通过后返回上一页 */ onSubmit() { const { name, idCard, gender, age, height } = this.data.form const heightNum = parseFloat(height) if (!name.trim()) { wx.showToast({ title: '请填写姓名', icon: 'none' }) return } if (idCard.length !== 18) { wx.showToast({ title: '请填写正确的身份证号', icon: 'none' }) return } if (!gender || !age) { wx.showToast({ title: '身份证号有误,请检查', icon: 'none' }) return } if (!height || isNaN(heightNum) || heightNum <= 0) { wx.showToast({ title: '请填写身高', icon: 'none' }) return } // TODO: 此处后续接入成员保存接口 wx.navigateBack() } })