From 4e4afd695801af4ea25122270ad9759fb043fd9c Mon Sep 17 00:00:00 2001 From: 17792275749 <812100002@qq.com> Date: Thu, 11 Jun 2026 13:32:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(addMember):=20=E5=91=98=E5=B7=A5/=E5=AE=B6?= =?UTF-8?q?=E5=BA=AD=E5=8F=8Ctab=E5=AE=8C=E6=95=B4=E6=94=B9=E9=80=A0?= =?UTF-8?q?=EF=BC=8C=E7=8A=B6=E6=80=81=E6=9C=BA=E6=8E=A7=E5=88=B6=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 员工tab:编号输入+查询→三种状态(未查询/查不到/查到展示) - 家庭tab:familyInfo_卡片包裹,昵称/身份证/性别切换/出生年月/身高体重同行 - 切换tab或改编号即时清空查询结果 - 提交区分员工/家庭双模式校验,dataType写入payload Co-Authored-By: Claude Opus 4.7 --- miniprogram/pages/addMember/addMember.less | 59 +++++-- miniprogram/pages/addMember/addMember.ts | 187 ++++++++++++++------ miniprogram/pages/addMember/addMember.wxml | 193 ++++++++++++++------- 3 files changed, 305 insertions(+), 134 deletions(-) diff --git a/miniprogram/pages/addMember/addMember.less b/miniprogram/pages/addMember/addMember.less index a311686..77f6407 100644 --- a/miniprogram/pages/addMember/addMember.less +++ b/miniprogram/pages/addMember/addMember.less @@ -74,7 +74,7 @@ line-height: 72rpx; box-sizing: border-box; border-radius: 16rpx; - + &.active { color: #1385FA; font-weight: bold; @@ -129,7 +129,7 @@ .workNoInfo { width: 100%; - padding-bottom: 100rpx; + padding-bottom: 10rpx; .workNoInfo_ { width: 100%; @@ -165,7 +165,34 @@ } .familyInfo { + width: 100%; + padding-bottom: 10rpx; + .familyInfo_ { + width: 100%; + border-radius: 16rpx; + box-sizing: border-box; + padding: 0 30rpx 10rpx; + margin-bottom: 40rpx; + background-color: #FFFFFF; + } + + .form-row { + width: 100%; + margin-bottom: 40rpx; + } + + /* 身高体重同行 */ + .form-row-inline { + width: 100%; + display: flex; + gap: 24rpx; + margin-bottom: 40rpx; + + .form-row-half { + flex: 1; + } + } } .form-row { @@ -262,7 +289,7 @@ } } - /* 只读区域(单位 / 性别 / 年龄 / 出生年月) */ + /* 只读区域 */ .form-readonly { width: 100%; height: 88rpx; @@ -319,19 +346,19 @@ } /* 从已有用户中选择(蓝色描边幽灵按钮) */ - // .ghost-btn { - // color: #1385FA; - // width: 580rpx; - // height: 88rpx; - // font-size: 32rpx; - // font-weight: bold; - // text-align: center; - // line-height: 84rpx; - // border-radius: 44rpx; - // box-sizing: border-box; - // border: 2rpx solid #1385FA; - // margin: 0 auto; - // } + .ghost-btn { + color: #1385FA; + width: 580rpx; + height: 88rpx; + font-size: 32rpx; + font-weight: bold; + text-align: center; + line-height: 84rpx; + border-radius: 44rpx; + box-sizing: border-box; + border: 2rpx solid #1385FA; + margin: 0 auto; + } } /* 底部双按钮 */ diff --git a/miniprogram/pages/addMember/addMember.ts b/miniprogram/pages/addMember/addMember.ts index 13302b0..cb5b27b 100644 --- a/miniprogram/pages/addMember/addMember.ts +++ b/miniprogram/pages/addMember/addMember.ts @@ -44,18 +44,20 @@ interface UserInfoFromServer { interface MemberForm { /** 员工编号 */ workNo: string - /** 姓名 */ + /** 姓名 / 昵称 */ name: string /** 身份证号 */ idCard: string - /** 性别(由身份证解析,只读) */ + /** 性别 */ gender: string - /** 年龄(由身份证解析,只读) */ + /** 年龄 */ age: string /** 身高(cm) */ height: string /** 体重(kg) */ weight: string + /** 1=男 2=女 */ + sex: number } /** 身份证解析结果 */ @@ -80,8 +82,9 @@ interface ExistingMember { } /** - * 添加/编辑用户页 - * URL 参数含 userId 时为编辑模式,隐藏「从已有用户中选择」按钮并预填表单 + * 添加用户页 + * 员工 tab:员工编号查询 → 回填信息 → 补充身高体重 + * 家庭 tab:昵称/身份证/性别/出生年月/身高体重 */ Page({ data: { @@ -99,22 +102,31 @@ Page({ gender: '', age: '', height: '', - weight: '' + weight: '', + sex: 0, } as MemberForm, + /** 出生年月(家庭用户 date picker) */ + birthday: '', + /** 从抽屉选中的完整用户数据,提交时作为 base spread */ selectedMember: null as ExistingMember | null, showSelectDrawer: false, /** 正在请求身份证查询接口 */ querying: false, - /** 是否已完成一次身份证查询(成功 200 即视为完成,无论 result 是否为 null) */ + /** 是否已完成一次身份证查询 */ hasQueried: false, - /** 接口返回的用户信息,姓名 + 身份证联动校正性别年龄 */ + /** 接口返回的用户信息 */ serverResult: null as UserInfoFromServer | null, /** 表单只读状态(code=101 时置为 true) */ readonly: false, /** 是否显示确认弹框 */ showConfirmModal: false, + + /** 员工编号是否已查询 */ + employeeQueried: false, + /** 员工编号查询是否未找到 */ + employeeNotFound: false, }, onLoad(options: Record) { @@ -141,24 +153,52 @@ Page({ }) }, - /** tabs 切换 */ + /** tabs 切换:清空查询结果、重置表单只读状态 */ onTabTap(e: WechatMiniprogram.TouchEvent) { const tab = e.currentTarget.dataset.value as string - this.setData({ userType: tab as 'employee' | 'family' }) + this.setData({ + userType: tab as 'employee' | 'family', + employeeQueried: false, + employeeNotFound: false, + readonly: false, + hasQueried: false, + serverResult: null, + 'form.workNo': '', + 'form.name': '', + 'form.idCard': '', + 'form.gender': '', + 'form.age': '', + 'form.height': '', + 'form.weight': '', + 'form.sex': 0, + birthday: '', + selectedMember: null, + }) }, + /** 员工编号变更即清空查询状态 */ onWorkNoInput(e: WechatMiniprogram.Input) { - this.setData({ 'form.workNo': e.detail.value }) + this.setData({ + 'form.workNo': e.detail.value, + employeeQueried: false, + employeeNotFound: false, + 'form.name': '', + 'form.gender': '', + 'form.age': '', + 'form.height': '', + 'form.weight': '', + }) }, + /** 员工编号查询(API 预留) */ onQueryEmployee() { const workNo = this.data.form.workNo.trim() if (!workNo) { wx.showToast({ title: '请填写员工编号', icon: 'none' }) return } - // TODO: 调用员工编号查询接口 - wx.showToast({ title: '员工编号查询功能待实现', icon: 'none' }) + // TODO: 接入员工编号查询接口 + wx.showToast({ title: '查询功能暂未开放', icon: 'none' }) }, onNameInput(e: WechatMiniprogram.Input) { @@ -191,6 +231,21 @@ Page({ } }, + /** 家庭用户性别切换 */ + onGenderTap(e: WechatMiniprogram.TouchEvent) { + const value = e.currentTarget.dataset.value as string + const sex = value === '男' ? 1 : 2 + this.setData({ + 'form.gender': value, + 'form.sex': sex, + }) + }, + + /** 出生年月变更 */ + onBirthdayChange(e: WechatMiniprogram.PickerChange) { + this.setData({ birthday: e.detail.value as string }) + }, + onHeightInput(e: WechatMiniprogram.Input) { this.setData({ 'form.height': e.detail.value }) }, @@ -199,6 +254,20 @@ Page({ this.setData({ 'form.weight': e.detail.value }) }, + /** 从生日字符串计算周岁 */ + calcAge(birthday: string): number { + if (!birthday) return 0 + const parts = birthday.split('-').map(Number) + const [year, month, day] = parts + if (!year || !month || !day) return 0 + 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 + return Math.max(0, age) + }, + /** * 校验身份证格式:18 位,前 17 位数字,末位数字或 X */ @@ -233,10 +302,7 @@ Page({ }, /** - * 调用服务端接口校验身份证与姓名,成功后用接口返回的身份证重新计算性别年龄 - * result 为 null 视为「查无此人」,标记 hasQueried 允许新增提交 - * result.code 101 视为「信息已存在」,弹框提示并锁定表单 - * result.code 102 视为正常,走原有逻辑 + * 调用服务端接口校验身份证与姓名 */ fetchUserInfoByIdCard(name: string, idCard: string) { if (this.data.querying) return @@ -250,9 +316,8 @@ Page({ .then(res => { const serverResult = res.result if (!serverResult) { - // 查无此人:用本地身份证解析补偿性别年龄 - wx.showToast({ - title: res.message || '未查询到用户信息', + wx.showToast({ + title: res.message || '未查询到用户信息', icon: 'none' }) const parsed = this.parseIdCard(idCard) @@ -297,7 +362,7 @@ Page({ } }) .catch(() => { - // 查询失败保留本地解析结果,hasQueried 维持 false 以便用户重试时再次触发 + // 查询失败保留本地解析结果,hasQueried 维持 false }) .finally(() => { this.setData({ querying: false }) @@ -349,7 +414,8 @@ Page({ gender: '', age: '', height: '', - weight: '' + weight: '', + sex: 0, } }) }, @@ -359,68 +425,75 @@ Page({ }, onSubmit() { - const { name, idCard, gender, age, height, weight } = this.data.form + const { name, idCard, gender, height, weight, sex } = this.data.form + const { isEdit, userType } = this.data const heightNum = parseFloat(height) const weightNum = parseFloat(weight) - 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 - } - if (!weight || isNaN(weightNum) || weightNum <= 0) { - wx.showToast({ title: '请填写体重', icon: 'none' }) - return - } - if (!this.data.hasQueried) { - wx.showToast({ title: this.data.querying ? '身份信息验证中,请稍候' : '请检查姓名与身份证号', icon: 'none' }) - return + if (userType === 'employee') { + // 员工:必须查询成功 + if (!this.data.employeeQueried || this.data.employeeNotFound) { + wx.showToast({ title: '请先查询员工信息', icon: 'none' }) + return + } + if (!height || isNaN(heightNum) || heightNum <= 0) { + wx.showToast({ title: '请填写身高', icon: 'none' }) + return + } + } else { + // 家庭用户 + if (!name.trim()) { + wx.showToast({ title: '请填写昵称', icon: 'none' }) + return + } + if (!gender) { + wx.showToast({ title: '请选择性别', icon: 'none' }) + return + } + if (!this.data.birthday.trim()) { + wx.showToast({ title: '请填写出生年月', icon: 'none' }) + return + } + if (!height || isNaN(heightNum) || heightNum <= 0) { + wx.showToast({ title: '请填写身高', icon: 'none' }) + return + } } - const parsed = this.parseIdCard(idCard) const userInfo = wx.getStorageSync('userInfo') const connectDeviceInfoRaw = wx.getStorageSync('connectDeviceInfo') const serverResult = this.data.serverResult - // selectedMember(抽屉选中) → serverResult(接口校验,可能为 null) → 表单/本地解析(用户输入) 依次覆盖 + const baseSpread = userType === 'family' ? (this.data.selectedMember ?? {}) : {} + const birthday = userType === 'family' ? this.data.birthday : '' + const finalSex = userType === 'family' ? sex : this.data.form.sex + const payload: Record = { - ...(this.data.selectedMember ?? {}), + ...(baseSpread), ...(serverResult ?? {}), + dataType: userType === 'family' ? 1 : 0, parentUserId: userInfo?.userId ?? '', sn: lefuService.deviceInfo?.serialNumber ?? '', scaleDeviceId: lefuService.deviceInfo?.serialNumber ?? '', - workNo: this.data.form.workNo.trim(), realname: name.trim(), idCard, - sex: parsed.sex, - birthday: parsed.birthday, + sex: finalSex, + birthday, height: heightNum, - weight: weightNum, + weight: isNaN(weightNum) ? 0 : weightNum, connectDeviceInfo: connectDeviceInfoRaw ? JSON.stringify(connectDeviceInfoRaw) : '', } - if (this.data.isEdit) { + if (isEdit) { payload.id = this.data.userId } - const successMsg = this.data.isEdit ? '保存成功' : '添加成功' - const failMsg = this.data.isEdit ? '保存失败,请重试' : '添加失败,请重试' + const successMsg = isEdit ? '保存成功' : '添加成功' + const failMsg = isEdit ? '保存失败,请重试' : '添加失败,请重试' put('weighingScale/v3/edit/user', payload) .then(() => { wx.showToast({ title: successMsg, icon: 'success' }) setTimeout(() => { - // 通知上一页(equipmentMember)刷新用户列表 const pages = getCurrentPages() const prevPage = pages[pages.length - 2] as any if (prevPage && prevPage.data?.sn) { diff --git a/miniprogram/pages/addMember/addMember.wxml b/miniprogram/pages/addMember/addMember.wxml index 751719b..f9791bf 100644 --- a/miniprogram/pages/addMember/addMember.wxml +++ b/miniprogram/pages/addMember/addMember.wxml @@ -9,84 +9,155 @@ + - 员工 - 家庭用户 + 员工 + 家庭用户 - - - - 员工编号 - * - - - - + + + + + + + + 员工编号 + * + + + + 确认查询 - 确认查询 - - - - - 用户信息 - - - - - 姓名 + + 输入员工编号后自动查询员工信息 + + + 未查询到员工信息,请确认员工编号是否正确 + + + + + 用户信息 + + + + 姓名 + + {{ form.name }} + - - - {{ form.name }} + + 单位 + + {{ form.workNo }} - - - 单位 + + + 性别 + + {{ form.gender }} + - - - {{ form.name }} + + 年龄 + + {{ form.age }} - - - - 性别 - - - - {{ form.name }} + + + 补充信息 + + + + + 身高 + * + + + + + cm + - - - - 年龄 - - - - {{ form.name }} + + 体重 + + + + kg + - - 补充信息 - - - + + + + + + + + + + 昵称 + * + + + + + + + + + 身份证号 + + + + + + + + + 性别 + * + + + + + + + + + + + + + 出生年月 + * + + + + {{ birthday || '请选择出生年月' }} + + + + + + + 身高 * @@ -98,10 +169,8 @@ - - - 体重 - + + 体重 @@ -111,14 +180,16 @@ + + + 从已有用户中选择 - - + - + 取消 保存用户信息 @@ -131,4 +202,4 @@ - \ No newline at end of file +