[AI Generated]: refactor(*): 重构用户初始化流程,接口化用户管理并支持增量下发设备

- 重构 configureDevice 步骤0:新增双条件控制(deviceInfo + codeSyncTime),确保连接完成且 mac 就绪后才进入下一步
- 重构 configureDevice_2:移除 userInfo 缓存读取,改为接口获取用户列表,支持动态渲染、删除用户
- 新增 configureDevice_2_addUser 组件:支持工号查询用户信息并添加到设备
- 优化用户下发逻辑:先通过 dataFetchUserID 获取设备端已有用户,仅下发新增用户
- 删除废弃页面 deviceInfo、userInfo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
17792275749
2026-03-10 14:32:47 +08:00
co-authored by Claude Opus 4.6
parent 1e3f1934b1
commit e20638030b
27 changed files with 775 additions and 1646 deletions
@@ -0,0 +1,145 @@
import $ from "../../utils/request";
const app = getApp();
Component({
properties: {
},
data: {
animationData: null,
modalStatus: false,
workNo: "",
userInfo: null,
},
lifetimes: {
// 在组件实例进入页面节点树时执行
attached() {
},
// 在组件实例被从页面节点树移除时执行
detached() {
},
},
methods: {
// 显示对话框
showModal() {
// 显示遮罩层
let animation = wx.createAnimation({
duration: 200,
timingFunction: "linear",
delay: 0
})
this.animation = animation;
animation.translateY(1100).step();
this.setData({
animationData: animation.export(),
modalStatus: true
})
setTimeout(() => {
animation.translateY(0).step();
this.setData({
animationData: animation.export()
})
}, 200);
},
//隐藏对话框
hideModal() {
// 隐藏遮罩层
let animation = wx.createAnimation({
duration: 200,
timingFunction: "linear",
delay: 0
})
this.animation = animation;
animation.translateY(1100).step();
this.setData({
animationData: animation.export(),
})
setTimeout(() => {
animation.translateY(0).step();
this.setData({
animationData: animation.export(),
modalStatus: false
})
}, 200);
},
// 关闭弹窗并重置数据
closeModal() {
this.setData({
workNo: "",
userInfo: null,
});
this.hideModal();
},
// 监听工号输入
onWorkNoInput(e) {
this.setData({ workNo: e.detail.value });
},
// 根据工号查询用户信息
searchUser() {
let workNo = this.data.workNo.trim();
if (!workNo) {
wx.showToast({
title: "请输入工号",
icon: "none"
})
return;
}
$.ajax("weighingScale/v2/getUserInfoByWkno", { workNo }, "GET", true, "正在查询...").then(res => {
if (res.result) {
this.setData({ userInfo: res.result });
} else {
this.setData({ userInfo: null });
wx.showToast({
title: "未查询到该工号的用户信息",
icon: "none"
})
}
}).catch(() => {
wx.showToast({
title: "查询失败,请重试",
icon: "none"
})
})
},
// 确定提交
submit() {
if (!this.data.userInfo) {
wx.showToast({
title: "请先查询用户信息",
icon: "none"
})
return;
}
let sn = app.globalData.ppScale.device.mac.replace(/:/g, '');
let user = this.data.userInfo;
$.ajax("weighingScale/v2/edit/user", {
sn,
realname: user.realname,
sex: user.sex,
birthday: user.birthday,
height: user.height,
weight: user.weight
}, "POST", true, "正在添加...").then(res => {
wx.showToast({
title: "添加成功",
icon: "success"
})
this.triggerEvent('returnDate', { userInfo: user });
this.closeModal();
}).catch(() => {
wx.showToast({
title: "添加失败,请重试",
icon: "none"
})
})
}
}
});
@@ -0,0 +1,3 @@
{
"component": true
}
@@ -0,0 +1,58 @@
<!--屏幕背景变暗的背景 -->
<view class="modalBg" wx:if="{{modalStatus}}" bindtap="hideModal"></view>
<!--弹出框 -->
<view animation="{{animationData}}" class="modal" wx:if="{{modalStatus}}">
<view class="header">
<view></view>
<view>添加用户</view>
</view>
<view class="seaction">
<view class="input">
<view>工号:</view>
<view>
<input type="text" placeholder="输入工号自动显示员工信息" value="{{workNo}}" bindinput="onWorkNoInput" bindconfirm="searchUser" />
</view>
<!-- <view class="searchBtn" bind:tap="searchUser">查询</view>-->
</view>
<view class="only">
<view>姓名:</view>
<view>
<view>{{userInfo.realname || ''}}</view>
<view></view>
</view>
</view>
<view class="only">
<view>性别:</view>
<view>
<view>{{userInfo.sex === 1 ? '男' : userInfo.sex === 2 ? '女' : ''}}</view>
<view></view>
</view>
</view>
<view class="only">
<view>生日:</view>
<view>
<view>{{userInfo.birthday || ''}}</view>
<view></view>
</view>
</view>
<view class="only">
<view>身高:</view>
<view>
<view>{{userInfo.height || ''}}</view>
<view wx:if="{{userInfo.height}}">cm</view>
</view>
</view>
<view class="only">
<view>体重:</view>
<view>
<view>{{userInfo.weight || ''}}</view>
<view wx:if="{{userInfo.weight}}">kg</view>
</view>
</view>
</view>
<view class="footer">
<view bind:tap="closeModal">取消</view>
<view bind:tap="submit">确定</view>
</view>
</view>
@@ -0,0 +1,172 @@
.modalBg {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
opacity: 0.2;
overflow: hidden;
z-index: 10;
}
.modal {
height: 1100rpx;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 11;
display: flex;
flex-flow: column;
overflow: hidden;
background-color: #ffffff;
border-radius: 30rpx 30rpx 0 0;
}
.header {
height: 150rpx;
width: 100%;
padding-top: 30rpx;
box-sizing: border-box;
}
.header>view:nth-of-type(1) {
width: 72rpx;
height: 6rpx;
border-radius: 3rpx;
margin: 0 auto 40rpx;
background-color: #77849E;
}
.header>view:nth-of-type(2) {
color: #252535;
height: 32rpx;
font-size: 32rpx;
font-weight: bold;
line-height: 32rpx;
text-align: center;
}
.seaction {
flex: 1;
padding: 0 30rpx;
overflow: hidden;
}
.only,
.input {
width: 100%;
height: 104rpx;
display: flex;
flex-wrap: nowrap;
margin-bottom: 32rpx;
}
.only>view:nth-of-type(1),
.input>view:nth-of-type(1) {
color: #333333;
height: 104rpx;
font-size: 32rpx;
line-height: 104rpx;
}
.only>view:nth-of-type(2) {
flex: 1;
width: 0;
height: 104rpx;
padding: 0 30rpx;
border-radius: 16rpx;
display: flex;
flex-wrap: nowrap;
align-items: center;
background-color: #F5F7FB;
border: 1rpx solid #E6E6EA;
}
.only>view:nth-of-type(2)>view:nth-of-type(1) {
flex: 1;
width: 0;
color: #252535;
font-size: 32rpx;
font-weight: 500;
height: 100rpx;
line-height: 100rpx;
}
.only>view:nth-of-type(2)>view:nth-of-type(2) {
color: #77849E;
height: 28rpx;
font-size: 28rpx;
line-height: 28rpx;
}
.input>view:nth-of-type(2) {
flex: 1;
width: 0;
height: 104rpx;
padding: 0 30rpx;
border-radius: 16rpx;
border: 1rpx solid #E6E6EA;
}
.input>view:nth-of-type(2) input {
width: 100%;
height: 100%;
color: #252535;
font-size: 32rpx;
font-weight: 500;
}
.searchBtn {
color: #FFFFFF;
width: 120rpx;
height: 104rpx;
font-size: 28rpx;
font-weight: bold;
text-align: center;
line-height: 104rpx;
margin-left: 16rpx;
border-radius: 16rpx;
background-color: #1385FA;
}
.footer {
width: 100%;
padding: 0 30rpx;
height: 120rpx;
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
background-color: #FFFFFF;
border-top: 1rpx solid #EAECF1;
}
.footer>view:nth-of-type(1) {
color: #1385FA;
width: 330rpx;
height: 88rpx;
font-size: 32rpx;
font-weight: bold;
border-radius: 44rpx;
text-align: center;
line-height: 86rpx;
box-sizing: border-box;
border: 1rpx solid #1385FA;
}
.footer>view:nth-of-type(2) {
color: #FFFFFF;
width: 330rpx;
height: 88rpx;
font-size: 32rpx;
font-weight: bold;
border-radius: 44rpx;
text-align: center;
line-height: 86rpx;
box-sizing: border-box;
background-color: #1385FA;
border: 1rpx solid #1385FA;
}