feat(addUser): 添加用户模块接入员工查询与身份证复用
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a80a5cd939
commit
4b61c882a1
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"usingComponents": {},
|
"usingComponents": {
|
||||||
|
"user-info-confirm-modal": "/components/userInfoConfirmModal/userInfoConfirmModal"
|
||||||
|
},
|
||||||
"navigationBarTitleText": "添加用户",
|
"navigationBarTitleText": "添加用户",
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "black",
|
||||||
"navigationBarBackgroundColor": "#FFFFFF"
|
"navigationBarBackgroundColor": "#FFFFFF"
|
||||||
|
|||||||
@@ -1,16 +1,55 @@
|
|||||||
// pages/addUser/addUser.ts
|
import { get, put } from '../../utils/request/index'
|
||||||
|
import { getUserInfoByIdCard, type UserInfo } from '../../api/index'
|
||||||
|
import { parseIdCard, isIdCardValid } from '../../utils/idCard/index'
|
||||||
|
|
||||||
|
/** 表单数据模型 */
|
||||||
|
interface MemberForm {
|
||||||
|
workNo: string
|
||||||
|
name: string
|
||||||
|
idCard: string
|
||||||
|
gender: string
|
||||||
|
age: string
|
||||||
|
height: string
|
||||||
|
weight: string
|
||||||
|
sex: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 员工编号查询接口(页面私有) */
|
||||||
|
const getEmployeeByWorkNo = (sn: string, workNo: string) =>
|
||||||
|
get<any>('weighingScale/v5/getUserInfoByWkno', { sn, workNo })
|
||||||
|
|
||||||
|
/** 添加/编辑用户接口(页面私有) */
|
||||||
|
const addUser = (data: Record<string, any>) =>
|
||||||
|
put('weighingScale/v5/edit/user', data)
|
||||||
|
|
||||||
|
/** 目标设备 SN(由 userManagement 跳转传入) */
|
||||||
|
let targetSn = ''
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
data: {
|
data: {
|
||||||
userType: 'employee',
|
userType: 'employee' as 'employee' | 'family',
|
||||||
employeeId: '9527',
|
form: {
|
||||||
employeeInfo: {
|
workNo: '',
|
||||||
name: '王旭',
|
name: '',
|
||||||
company: '技术部·研发组',
|
idCard: '',
|
||||||
gender: '男',
|
gender: '',
|
||||||
age: '32岁'
|
age: '',
|
||||||
},
|
|
||||||
height: '',
|
height: '',
|
||||||
weight: ''
|
weight: '',
|
||||||
|
sex: 0,
|
||||||
|
} as MemberForm,
|
||||||
|
birthday: '',
|
||||||
|
readonly: false,
|
||||||
|
showConfirmModal: false,
|
||||||
|
serverResult: null as UserInfo | null,
|
||||||
|
employeeQueried: false,
|
||||||
|
employeeNotFound: false,
|
||||||
|
unitDisplay: '',
|
||||||
|
employeeQueryResult: null as Record<string, any> | null,
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(options: Record<string, string>) {
|
||||||
|
targetSn = decodeURIComponent(options.sn || '')
|
||||||
},
|
},
|
||||||
|
|
||||||
/** tabs 切换:清空查询结果、重置表单 */
|
/** tabs 切换:清空查询结果、重置表单 */
|
||||||
@@ -18,21 +57,268 @@ Page({
|
|||||||
const tab = e.currentTarget.dataset.value as string
|
const tab = e.currentTarget.dataset.value as string
|
||||||
this.setData({
|
this.setData({
|
||||||
userType: tab as 'employee' | 'family',
|
userType: tab as 'employee' | 'family',
|
||||||
|
employeeQueried: false,
|
||||||
|
employeeNotFound: false,
|
||||||
|
unitDisplay: '',
|
||||||
|
employeeQueryResult: null,
|
||||||
|
readonly: false,
|
||||||
|
serverResult: null,
|
||||||
|
form: { workNo: '', name: '', idCard: '', gender: '', age: '', height: '', weight: '', sex: 0 },
|
||||||
|
birthday: '',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
onTapType(e: WechatMiniprogram.TouchEvent) {
|
/** 员工编号变更:清空查询状态与表单 */
|
||||||
const type = e.currentTarget.dataset.type as string
|
onWorkNoInput(e: WechatMiniprogram.Input) {
|
||||||
this.setData({ userType: type })
|
this.setData({
|
||||||
|
'form.workNo': e.detail.value,
|
||||||
|
employeeQueried: false,
|
||||||
|
employeeNotFound: false,
|
||||||
|
unitDisplay: '',
|
||||||
|
employeeQueryResult: null,
|
||||||
|
'form.name': '',
|
||||||
|
'form.gender': '',
|
||||||
|
'form.age': '',
|
||||||
|
'form.height': '',
|
||||||
|
'form.weight': '',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 员工编号查询 */
|
||||||
|
onQueryEmployee() {
|
||||||
|
const workNo = this.data.form.workNo.trim()
|
||||||
|
if (!workNo) {
|
||||||
|
wx.showToast({ title: '请填写员工编号', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.setData({ employeeQueried: false, employeeNotFound: false })
|
||||||
|
getEmployeeByWorkNo(targetSn, workNo)
|
||||||
|
.then((res) => {
|
||||||
|
const result = res.result
|
||||||
|
if (!result) {
|
||||||
|
this.setData({
|
||||||
|
employeeQueried: true,
|
||||||
|
employeeNotFound: true,
|
||||||
|
unitDisplay: '',
|
||||||
|
employeeQueryResult: null,
|
||||||
|
'form.name': '',
|
||||||
|
'form.gender': '',
|
||||||
|
'form.age': '',
|
||||||
|
'form.height': '',
|
||||||
|
'form.weight': '',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const idCard = result.idCard || ''
|
||||||
|
const parsed = parseIdCard(idCard)
|
||||||
|
const sex = result.sex || parsed.sex
|
||||||
|
this.setData({
|
||||||
|
employeeQueried: true,
|
||||||
|
employeeNotFound: false,
|
||||||
|
employeeQueryResult: result,
|
||||||
|
unitDisplay: [result.secondDepart, result.thirdDepart].filter(Boolean).join(' / '),
|
||||||
|
'form.name': result.realname || '',
|
||||||
|
'form.idCard': idCard,
|
||||||
|
'form.gender': sex === 1 ? '男' : (sex === 2 ? '女' : parsed.gender),
|
||||||
|
'form.age': parsed.age,
|
||||||
|
'form.sex': sex,
|
||||||
|
'form.height': result.height ? String(result.height) : '',
|
||||||
|
'form.weight': result.weight ? String(result.weight) : '',
|
||||||
|
birthday: result.birthday || '',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.setData({ employeeQueried: true, employeeNotFound: true, unitDisplay: '', employeeQueryResult: null })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 家庭用户:姓名变更清空查询结果 */
|
||||||
|
onNameInput(e: WechatMiniprogram.Input) {
|
||||||
|
this.setData({
|
||||||
|
'form.name': e.detail.value.trim(),
|
||||||
|
serverResult: null,
|
||||||
|
'form.gender': '',
|
||||||
|
'form.age': '',
|
||||||
|
'form.sex': 0,
|
||||||
|
'form.height': '',
|
||||||
|
'form.weight': '',
|
||||||
|
birthday: '',
|
||||||
|
readonly: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 失焦重新校验 */
|
||||||
|
onNameBlur() {
|
||||||
|
if (!this.data.form.name) return
|
||||||
|
this.validateIdCard()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 家庭用户:身份证变更清空查询结果 */
|
||||||
|
onIdCardInput(e: WechatMiniprogram.Input) {
|
||||||
|
const idCard = (e.detail.value || '').trim().toUpperCase()
|
||||||
|
this.setData({
|
||||||
|
'form.idCard': idCard,
|
||||||
|
serverResult: null,
|
||||||
|
'form.gender': '',
|
||||||
|
'form.age': '',
|
||||||
|
'form.sex': 0,
|
||||||
|
'form.height': '',
|
||||||
|
'form.weight': '',
|
||||||
|
birthday: '',
|
||||||
|
readonly: false,
|
||||||
|
})
|
||||||
|
if (idCard.length === 18) this.validateIdCard()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 身份证合法且姓名已填则查询 */
|
||||||
|
validateIdCard() {
|
||||||
|
const { idCard, name } = this.data.form
|
||||||
|
if (isIdCardValid(idCard) && name) this.fetchUser()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 查询身份证对应的用户信息,101 复用 */
|
||||||
|
fetchUser() {
|
||||||
|
getUserInfoByIdCard({
|
||||||
|
sn: targetSn,
|
||||||
|
idCard: this.data.form.idCard,
|
||||||
|
realname: this.data.form.name,
|
||||||
|
}).then((res) => {
|
||||||
|
const serverResult = res.result
|
||||||
|
const { gender, age, sex, birthday } = parseIdCard(serverResult?.idCard || this.data.form.idCard)
|
||||||
|
this.setData({ 'form.gender': gender, 'form.age': age, 'form.sex': sex, birthday })
|
||||||
|
if (!serverResult) {
|
||||||
|
wx.showToast({ title: res.msg || '未查询到用户信息', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (serverResult.flag === 101) {
|
||||||
|
this.setData({
|
||||||
|
serverResult,
|
||||||
|
'form.name': serverResult.realname ?? '',
|
||||||
|
'form.idCard': serverResult.idCard ?? '',
|
||||||
|
'form.height': serverResult.height ? String(serverResult.height) : '',
|
||||||
|
'form.weight': serverResult.weight ? String(serverResult.weight) : '',
|
||||||
|
readonly: true,
|
||||||
|
showConfirmModal: true,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (serverResult.flag === null) {
|
||||||
|
this.setData({
|
||||||
|
serverResult,
|
||||||
|
'form.height': serverResult.height ? String(serverResult.height) : '',
|
||||||
|
'form.weight': serverResult.weight ? String(serverResult.weight) : '',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 家庭用户:性别切换 */
|
||||||
|
onGenderTap(e: WechatMiniprogram.TouchEvent) {
|
||||||
|
const value = e.currentTarget.dataset.value as string
|
||||||
|
this.setData({ 'form.gender': value, 'form.sex': value === '男' ? 1 : 2 })
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 出生年月变更 */
|
||||||
|
onBirthdayChange(e: WechatMiniprogram.PickerChange) {
|
||||||
|
this.setData({ birthday: e.detail.value as string })
|
||||||
|
},
|
||||||
|
|
||||||
|
onHeightInput(e: WechatMiniprogram.Input) {
|
||||||
|
this.setData({ 'form.height': e.detail.value })
|
||||||
|
},
|
||||||
|
|
||||||
|
onWeightInput(e: WechatMiniprogram.Input) {
|
||||||
|
this.setData({ 'form.weight': e.detail.value })
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 复用已有信息:关弹框直接提交 */
|
||||||
|
onConfirmModalConfirm() {
|
||||||
|
this.setData({ showConfirmModal: false })
|
||||||
|
this.onSubmit()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 不复用:清空整个表单 */
|
||||||
|
onConfirmModalCancel() {
|
||||||
|
this.setData({
|
||||||
|
showConfirmModal: false,
|
||||||
|
readonly: false,
|
||||||
|
serverResult: null,
|
||||||
|
form: { workNo: '', name: '', idCard: '', gender: '', age: '', height: '', weight: '', sex: 0 },
|
||||||
|
birthday: '',
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
onCancel() {
|
onCancel() {
|
||||||
wx.navigateBack({
|
wx.navigateBack()
|
||||||
delta: 1
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onSave() {
|
/** 提交用户 */
|
||||||
// 保存用户信息(待接入)
|
onSubmit() {
|
||||||
|
const { name, idCard, gender, height, weight, sex } = this.data.form
|
||||||
|
const { userType } = this.data
|
||||||
|
const heightNum = parseFloat(height)
|
||||||
|
const weightNum = parseFloat(weight)
|
||||||
|
|
||||||
|
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 userInfo = wx.getStorageSync('userInfo') as Record<string, any> | null
|
||||||
|
// 员工:以查询接口返回为 base;家庭:以身份证查询结果为 base
|
||||||
|
const baseSpread = userType === 'employee'
|
||||||
|
? (this.data.employeeQueryResult ?? {})
|
||||||
|
: (this.data.serverResult ?? {})
|
||||||
|
|
||||||
|
const payload: Record<string, any> = {
|
||||||
|
...baseSpread,
|
||||||
|
dataType: userType === 'family' ? 1 : 0,
|
||||||
|
parentUserId: userInfo?.userId ?? '',
|
||||||
|
sn: targetSn,
|
||||||
|
scaleDeviceId: targetSn,
|
||||||
|
realname: name.trim(),
|
||||||
|
idCard: idCard || null,
|
||||||
|
sex,
|
||||||
|
birthday: this.data.birthday,
|
||||||
|
height: heightNum,
|
||||||
|
weight: isNaN(weightNum) ? 0 : weightNum,
|
||||||
|
}
|
||||||
|
|
||||||
|
addUser(payload)
|
||||||
|
.then(() => {
|
||||||
|
wx.showToast({ title: '添加成功', icon: 'success' })
|
||||||
|
// 调用上一个页面(userManagement)刷新成员列表
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
const prevPage = pages[pages.length - 2] as any
|
||||||
|
prevPage?._loadMembers?.()
|
||||||
|
setTimeout(() => wx.navigateBack(), 1500)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
wx.showToast({ title: '添加失败,请重试', icon: 'none' })
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -27,13 +27,13 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 未查询 -->
|
<!-- 未查询 -->
|
||||||
<view class="workNoDesc">输入员工编号后自动查询员工信息</view>
|
<view class="workNoDesc" wx:if="{{ !employeeQueried }}">输入员工编号后自动查询员工信息</view>
|
||||||
|
|
||||||
<!-- 查询未找到 -->
|
<!-- 查询未找到 -->
|
||||||
<view class="workNoNull">未查询到员工信息,请确认员工编号是否正确</view>
|
<view class="workNoNull" wx:if="{{ employeeQueried && employeeNotFound }}">未查询到员工信息,请确认员工编号是否正确</view>
|
||||||
|
|
||||||
<!-- 查询成功 -->
|
<!-- 查询成功 -->
|
||||||
<view class="workNoInfo">
|
<view class="workNoInfo" wx:if="{{ employeeQueried && !employeeNotFound }}">
|
||||||
<view class="workNoInfo_">
|
<view class="workNoInfo_">
|
||||||
<view class="workNoInfoTitle">用户信息</view>
|
<view class="workNoInfoTitle">用户信息</view>
|
||||||
<view class="workNoInfoContent">
|
<view class="workNoInfoContent">
|
||||||
@@ -182,6 +182,8 @@
|
|||||||
<!-- 保存按钮 -->
|
<!-- 保存按钮 -->
|
||||||
<view class="save-btn">
|
<view class="save-btn">
|
||||||
<view class="btn-cancel" bind:tap="onCancel">取消</view>
|
<view class="btn-cancel" bind:tap="onCancel">取消</view>
|
||||||
<view class="btn-primary" bind:tap="onSave">保存用户信息</view>
|
<view class="btn-primary" bind:tap="onSubmit">保存用户信息</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<user-info-confirm-modal show="{{ showConfirmModal }}" userInfo="{{ serverResult }}" bind:confirm="onConfirmModalConfirm" bind:cancel="onConfirmModalCancel" />
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -291,7 +291,8 @@ Page({
|
|||||||
|
|
||||||
/** 添加用户 */
|
/** 添加用户 */
|
||||||
onTapAddUser() {
|
onTapAddUser() {
|
||||||
wx.navigateTo({ url: '/pages/addUser/addUser' })
|
const sn = targetDevice?.sn || ''
|
||||||
|
wx.navigateTo({ url: `/pages/addUser/addUser?sn=${encodeURIComponent(sn)}` })
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 一键添加本人 */
|
/** 一键添加本人 */
|
||||||
|
|||||||
Reference in New Issue
Block a user