feat(addMember): 添加用户页改造,员工/家庭双tab + 员工编号查询表单

- 顶部胶囊式 tabs(员工/家庭用户)切换
- 员工 tab:员工编号输入 + 确认查询 → 回填用户信息 → 补充身高体重
- 家庭 tab:待实现
- 表单宽度调整为 100% 自适应

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
17792275749
2026-06-11 11:48:11 +08:00
co-authored by Claude Opus 4.7
parent fd93f37d72
commit 57950bd7c2
4 changed files with 340 additions and 183 deletions
+182 -31
View File
@@ -46,16 +46,127 @@
width: 100%;
padding: 0 30rpx;
box-sizing: border-box;
}
/* 表单卡片 */
.form-card {
width: 100%;
padding: 40rpx 30rpx;
border-radius: 16rpx;
box-sizing: border-box;
margin-bottom: 40rpx;
background-color: #FFFFFF;
/* 顶部 tabs - 圆角卡片样式 */
.tabsDom {
width: 100%;
box-sizing: border-box;
padding: 30rpx 30rpx 40rpx;
border-radius: 16rpx 16rpx 0 0;
background-color: #ffffff;
.tabs {
width: 100%;
height: 80rpx;
padding: 4rpx;
display: flex;
flex-wrap: nowrap;
box-sizing: border-box;
border-radius: 16rpx;
background-color: #F3F5F8;
.tab-item {
color: #808080;
flex: 1;
height: 72rpx;
font-size: 32rpx;
text-align: center;
line-height: 72rpx;
box-sizing: border-box;
border-radius: 16rpx;
&.active {
color: #1385FA;
font-weight: bold;
background-color: #FFFFFF;
}
}
}
}
.selectWorkNo {
width: 100%;
margin-bottom: 30rpx;
box-sizing: border-box;
padding: 0 30rpx 40rpx;
border-radius: 0 0 16rpx 16rpx;
background-color: #ffffff;
.selectWorkNoBtn {
color: #FFFFFF;
width: 580rpx;
height: 88rpx;
font-size: 32rpx;
font-weight: bold;
line-height: 88rpx;
border-radius: 44rpx;
text-align: center;
margin: 0 auto;
background-color: #1385FA;
}
}
.workNoDesc {
color: #B6B6B6;
width: 100%;
height: 24rpx;
font-size: 24rpx;
text-align: center;
line-height: 24rpx;
}
.workNoNull {
color: #F24439;
margin: 56rpx auto 0;
width: 640rpx;
height: 88rpx;
font-size: 28rpx;
line-height: 88rpx;
border-radius: 16rpx;
text-align: center;
background: rgba(242,68,57,0.12);
}
.workNoInfo {
width: 100%;
padding-bottom: 100rpx;
.workNoInfo_ {
width: 100%;
margin-bottom: 20rpx;
.workNoInfoTitle {
color: #808080;
width: 100%;
height: 64rpx;
font-size: 24rpx;
line-height: 64rpx;
}
.workNoInfoContent {
width: 100%;
border-radius: 16rpx;
box-sizing: border-box;
padding: 40rpx 30rpx 30rpx;
background-color: #FFFFFF;
> view {
width: 100%;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
.form-row {
width: 300rpx;
}
}
}
}
}
.familyInfo {
}
.form-row {
width: 100%;
@@ -113,10 +224,28 @@
font-size: 26rpx;
}
/* 输入框 + 后缀容器(身高 cm) */
/* 日期选择器 */
.form-picker {
width: 100%;
height: 88rpx;
padding: 0 30rpx;
color: #252535;
font-size: 26rpx;
line-height: 88rpx;
border-radius: 16rpx;
box-sizing: border-box;
background-color: #FFFFFF;
border: 2rpx solid #E6E6EA;
}
.form-picker-placeholder {
color: #B6B6B6;
}
/* 输入框 + 后缀容器(身高 cm / 体重 kg) */
.form-input-wrap {
position: relative;
width: 630rpx;
width: 100%;
.form-input-with-suffix {
padding-right: 80rpx;
@@ -133,9 +262,9 @@
}
}
/* 只读区域(性别 / 年龄) */
/* 只读区域(单位 / 性别 / 年龄 / 出生年月) */
.form-readonly {
width: 630rpx;
width: 100%;
height: 88rpx;
box-sizing: border-box;
padding: 0 24rpx;
@@ -143,16 +272,12 @@
border-radius: 16rpx;
display: flex;
align-items: center;
border: 2rpx solid #E6E6EA;
.readonly-text {
color: #252535;
font-size: 26rpx;
}
.readonly-placeholder {
color: #B6B6B6;
font-size: 26rpx;
}
}
.form-readonly-with-suffix {
@@ -165,22 +290,48 @@
line-height: 88rpx;
}
}
/* 性别切换按钮(家庭用户) */
.gender-toggle {
display: flex;
gap: 24rpx;
.gender-option {
width: 300rpx;
height: 88rpx;
font-size: 28rpx;
text-align: center;
line-height: 88rpx;
border-radius: 16rpx;
box-sizing: border-box;
color: #77849E;
background-color: #FFFFFF;
border: 2rpx solid #E6E6EA;
}
.gender-option-active {
color: #FFFFFF;
font-weight: bold;
background-color: #1385FA;
border-color: #1385FA;
}
}
}
/* 从已有用户中选择(蓝色描边幽灵按钮) */
.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;
// }
}
/* 底部双按钮 */
+29
View File
@@ -42,6 +42,8 @@ interface UserInfoFromServer {
/** 表单数据模型 */
interface MemberForm {
/** 员工编号 */
workNo: string
/** 姓名 */
name: string
/** 身份证号 */
@@ -83,12 +85,15 @@ interface ExistingMember {
*/
Page({
data: {
/** tabs 当前选中:employee | family */
userType: 'employee' as 'employee' | 'family',
/** 编辑模式标记 */
isEdit: false,
/** 编辑时的用户 ID */
userId: '',
form: {
workNo: '',
name: '',
idCard: '',
gender: '',
@@ -122,6 +127,7 @@ Page({
if (!u) return
const parsed = this.parseIdCard(u.idCard ?? '')
this.setData({
'form.workNo': u.workNo ?? '',
'form.name': u.realname ?? '',
'form.idCard': u.idCard ?? '',
'form.gender': parsed.gender,
@@ -135,6 +141,26 @@ Page({
})
},
/** tabs 切换 */
onTabTap(e: WechatMiniprogram.TouchEvent) {
const tab = e.currentTarget.dataset.value as string
this.setData({ userType: tab as 'employee' | 'family' })
},
onWorkNoInput(e: WechatMiniprogram.Input) {
this.setData({ 'form.workNo': e.detail.value })
},
onQueryEmployee() {
const workNo = this.data.form.workNo.trim()
if (!workNo) {
wx.showToast({ title: '请填写员工编号', icon: 'none' })
return
}
// TODO: 调用员工编号查询接口
wx.showToast({ title: '员工编号查询功能待实现', icon: 'none' })
},
onNameInput(e: WechatMiniprogram.Input) {
const name = e.detail.value
this.setData({
@@ -292,6 +318,7 @@ Page({
this.setData({
showSelectDrawer: false,
selectedMember: member,
'form.workNo': member.workNo || '',
'form.name': member.name,
'form.idCard': member.idCard,
'form.gender': parsed.gender,
@@ -316,6 +343,7 @@ Page({
showConfirmModal: false,
readonly: false,
form: {
workNo: '',
name: '',
idCard: '',
gender: '',
@@ -372,6 +400,7 @@ Page({
parentUserId: userInfo?.userId ?? '',
sn: lefuService.deviceInfo?.serialNumber ?? '',
scaleDeviceId: lefuService.deviceInfo?.serialNumber ?? '',
workNo: this.data.form.workNo.trim(),
realname: name.trim(),
idCard,
sex: parsed.sex,
+127 -150
View File
@@ -1,157 +1,134 @@
<view class="add-member">
<!-- 顶部浅蓝提示条 -->
<view class="tips">
<view class="tips-icon">!</view>
<text class="tips-text">最多支持 10 位用户</text>
</view>
<!-- 顶部浅蓝提示条 -->
<view class="tips">
<view class="tips-icon">!</view>
<text class="tips-text">最多支持 10 位用户</text>
</view>
<view class="form">
<scroll-view scroll-y class="scrollView">
<view class="scrollViewContent">
<!-- 白色圆角表单卡片 -->
<view class="form-card">
<view class="form">
<scroll-view scroll-y class="scrollView">
<view class="scrollViewContent">
<view class="tabsDom">
<view class="tabs">
<view class="tab-item active">员工</view>
<view class="tab-item">家庭用户</view>
</view>
</view>
<view class="selectWorkNo">
<view class="form-row">
<view class="form-label">
<text class="label-text">员工编号</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<view class="form-input-wrap">
<input class="form-input" type="number" placeholder="请填写员工编号" placeholder-class="form-placeholder" />
</view>
</view>
</view>
<!-- 姓名 -->
<view class="form-row">
<view class="form-label">
<text class="label-text">姓名</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<input class="form-input"
type="text"
maxlength="20"
placeholder="请填写真实姓名"
placeholder-class="form-placeholder"
value="{{ form.name }}"
disabled="{{ readonly }}"
bind:input="onNameInput"/>
</view>
</view>
<view class="selectWorkNoBtn">确认查询</view>
</view>
<!-- <view class="workNoDesc">输入员工编号后自动查询员工信息</view>
<view class="workNoNull">未查询到员工信息,请确认员工编号是否正确</view> -->
<view class="workNoInfo">
<view class="workNoInfo_">
<view class="workNoInfoTitle">用户信息</view>
<view class="workNoInfoContent">
<view>
<view class="form-row">
<view class="form-label">
<text class="label-text">姓名</text>
</view>
<view class="form-control">
<view class="form-readonly">
<text class="readonly-text">{{ form.name }}</text>
</view>
</view>
</view>
<view class="form-row">
<view class="form-label">
<text class="label-text">单位</text>
</view>
<view class="form-control">
<view class="form-readonly">
<text class="readonly-text">{{ form.name }}</text>
</view>
</view>
</view>
</view>
<view>
<view class="form-row" style="margin-bottom: 0;">
<view class="form-label">
<text class="label-text">性别</text>
</view>
<view class="form-control">
<view class="form-readonly">
<text class="readonly-text">{{ form.name }}</text>
</view>
</view>
</view>
<view class="form-row">
<view class="form-label">
<text class="label-text">年龄</text>
</view>
<view class="form-control">
<view class="form-readonly">
<text class="readonly-text">{{ form.name }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="workNoInfo_">
<view class="workNoInfoTitle">补充信息</view>
<view class="workNoInfoContent">
<view>
<view class="form-row" style="margin-bottom: 0;">
<view class="form-label">
<text class="label-text">身高</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<view class="form-input-wrap">
<input class="form-input form-input-with-suffix" type="digit" maxlength="5" placeholder="请填写身高" placeholder-class="form-placeholder" value="{{ form.height }}" bind:input="onHeightInput" />
<text class="form-suffix form-suffix-inside">cm</text>
</view>
</view>
</view>
<view class="form-row">
<view class="form-label">
<text class="label-text">体重</text>
</view>
<view class="form-control">
<view class="form-input-wrap">
<input class="form-input form-input-with-suffix" type="digit" maxlength="6" placeholder="请填写体重" placeholder-class="form-placeholder" value="{{ form.weight }}" bind:input="onWeightInput" />
<text class="form-suffix form-suffix-inside">kg</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="familyInfo"></view>
</view>
</scroll-view>
</view>
<!-- 身份证号 -->
<view class="form-row">
<view class="form-label">
<text class="label-text">身份证号</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<input class="form-input"
type="idcard"
maxlength="18"
placeholder="请填写身份证号"
placeholder-class="form-placeholder"
value="{{ form.idCard }}"
disabled="{{ readonly }}"
bind:input="onIdCardInput"/>
</view>
</view>
<!-- 底部双按钮:取消 / 保存用户信息 -->
<view class="actions">
<view class="btn-cancel" bind:tap="onCancel">取消</view>
<view class="btn-primary" bind:tap="onSubmit">保存用户信息</view>
</view>
<!-- 性别(由身份证自动生成) -->
<view class="form-row">
<view class="form-label">
<text class="label-text">性别</text>
</view>
<view class="form-control">
<view class="form-readonly">
<block wx:if="{{ form.gender }}">
<text class="readonly-text">{{ form.gender }}</text>
</block>
<block wx:else>
<text class="readonly-placeholder">自动生成,无需填写</text>
</block>
</view>
</view>
</view>
<!-- 选择已有用户抽屉 -->
<select-member-drawer show="{{ showSelectDrawer }}" bind:close="onSelectMemberClose" bind:select="onSelectMember">
</select-member-drawer>
<!-- 年龄(由身份证自动生成) -->
<view class="form-row">
<view class="form-label">
<text class="label-text">年龄</text>
</view>
<view class="form-control">
<view class="form-readonly form-readonly-with-suffix">
<block wx:if="{{ form.age }}">
<text class="readonly-text">{{ form.age }}</text>
</block>
<block wx:else>
<text class="readonly-placeholder">自动生成,无需填写</text>
</block>
<text class="form-suffix">岁</text>
</view>
</view>
</view>
<!-- 身高 -->
<view class="form-row">
<view class="form-label">
<text class="label-text">身高</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<view class="form-input-wrap">
<input class="form-input form-input-with-suffix"
type="digit"
maxlength="5"
placeholder="请填写身高"
placeholder-class="form-placeholder"
value="{{ form.height }}"
disabled="{{ readonly }}"
bind:input="onHeightInput"/>
<text class="form-suffix form-suffix-inside">cm</text>
</view>
</view>
</view>
<!-- 体重 -->
<view class="form-row">
<view class="form-label">
<text class="label-text">体重</text>
<text class="label-star">*</text>
</view>
<view class="form-control">
<view class="form-input-wrap">
<input class="form-input form-input-with-suffix"
type="digit"
maxlength="6"
placeholder="请填写体重"
placeholder-class="form-placeholder"
value="{{ form.weight }}"
disabled="{{ readonly }}"
bind:input="onWeightInput"/>
<text class="form-suffix form-suffix-inside">kg</text>
</view>
</view>
</view>
</view>
<!-- 从已有用户中选择(编辑模式隐藏) -->
<block wx:if="{{ !isEdit }}">
<view class="ghost-btn" bind:tap="onTapSelectExisting">从已有用户中选择</view>
</block>
</view>
</scroll-view>
</view>
<!-- 底部双按钮:取消 / 保存用户信息 -->
<view class="actions">
<view class="btn-cancel" bind:tap="onCancel">取消</view>
<view class="btn-primary" bind:tap="onSubmit">保存用户信息</view>
</view>
<!-- 选择已有用户抽屉 -->
<select-member-drawer
show="{{ showSelectDrawer }}"
bind:close="onSelectMemberClose"
bind:select="onSelectMember">
</select-member-drawer>
<!-- 确认弹框 -->
<user-info-confirm-modal
show="{{ showConfirmModal }}"
userInfo="{{ serverResult }}"
bind:confirm="onConfirmModalConfirm"
bind:cancel="onConfirmModalCancel">
</user-info-confirm-modal>
</view>
<!-- 确认弹框 -->
<user-info-confirm-modal show="{{ showConfirmModal }}" userInfo="{{ serverResult }}" bind:confirm="onConfirmModalConfirm" bind:cancel="onConfirmModalCancel">
</user-info-confirm-modal>
</view>
+2 -2
View File
@@ -134,7 +134,7 @@
/* 输入框 + 后缀容器(身高 cm / 体重 kg) */
.form-input-wrap {
position: relative;
width: 630rpx;
width: 100%;
.form-input-with-suffix {
padding-right: 80rpx;
@@ -153,7 +153,7 @@
/* 只读区域(单位 / 性别 / 年龄 / 出生年月) */
.form-readonly {
width: 630rpx;
width: 100%;
height: 88rpx;
box-sizing: border-box;
padding: 0 24rpx;