feat(equipmentMember): 用户列表拆分本人/员工/家庭成员三个分区
- 按 dataType 拆分:0=员工 1=家庭成员,relationType=1 归入本人 - 本人区块保留设备容量头部,仅支持编辑 - 员工/家庭成员区块独立显示,空列表自动隐藏 - badge 规则:本人/他人添加显示,自己添加不显示 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
485725a486
commit
099b7613fe
@@ -118,9 +118,11 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 20rpx;
|
||||||
border-radius: 20rpx;
|
|
||||||
background-color: #FFFFFF;
|
&:first-of-type {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* 容量小标题 */
|
/* 容量小标题 */
|
||||||
.member-card-header {
|
.member-card-header {
|
||||||
@@ -129,6 +131,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 30rpx;
|
padding: 0 30rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
background-color: #FFFFFF;
|
||||||
border-bottom: 1rpx solid #EAECF1;
|
border-bottom: 1rpx solid #EAECF1;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
@@ -149,16 +153,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.member-card-title {
|
||||||
|
height: 60rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 60rpx;
|
||||||
|
padding-left: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.member-item {
|
.member-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-bottom: 1rpx solid #F0F0F2;
|
margin-bottom: 24rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
|
||||||
&:last-child {
|
&:last-of-type {
|
||||||
border-bottom: none;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member-avatar {
|
.member-avatar {
|
||||||
@@ -244,13 +258,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my {
|
||||||
|
border-radius: 0 0 24rpx 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 通用 badge(本人 / 他人添加) */
|
/* 通用 badge(本人 / 他人添加) */
|
||||||
.badge {
|
.badge {
|
||||||
height: 40rpx;
|
height: 40rpx;
|
||||||
padding: 0 18rpx;
|
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
line-height: 40rpx;
|
line-height: 40rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
@@ -258,17 +275,18 @@
|
|||||||
|
|
||||||
.badge-self {
|
.badge-self {
|
||||||
color: #1385FA;
|
color: #1385FA;
|
||||||
|
padding: 0 18rpx;
|
||||||
background-color: rgba(19, 133, 250, 0.12);
|
background-color: rgba(19, 133, 250, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge-my {
|
.badge-my {
|
||||||
color: #1385FA;
|
color: #1385FA;
|
||||||
|
padding: 0 18rpx;
|
||||||
background-color: rgba(19, 133, 250, 0.08);
|
background-color: rgba(19, 133, 250, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge-other {
|
.badge-other {
|
||||||
color: #77849E;
|
color: #808080;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ interface MemberDisplay {
|
|||||||
sex: number
|
sex: number
|
||||||
/** 周岁数值,供 lefu 层使用 */
|
/** 周岁数值,供 lefu 层使用 */
|
||||||
age: number
|
age: number
|
||||||
|
/** 0=员工 1=家庭成员 */
|
||||||
|
dataType: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 设备卡展示模型 */
|
/** 设备卡展示模型 */
|
||||||
@@ -95,9 +97,11 @@ const toDeviceMember = (m: MemberDisplay): DeviceMember => ({
|
|||||||
const syncToDevice = (members: MemberDisplay[]): void => {
|
const syncToDevice = (members: MemberDisplay[]): void => {
|
||||||
const deviceMembers = members.map(toDeviceMember)
|
const deviceMembers = members.map(toDeviceMember)
|
||||||
const total = deviceMembers.length
|
const total = deviceMembers.length
|
||||||
wx.showLoading({ title: `正在下发第1/${total}个用户...`, mask: true })
|
wx.showLoading({ title: `加载中...`, mask: true })
|
||||||
|
console.log(`正在下发第1/${total}个用户...`)
|
||||||
lefuService.syncMembersToDevice(deviceMembers, (current, t) => {
|
lefuService.syncMembersToDevice(deviceMembers, (current, t) => {
|
||||||
wx.showLoading({ title: `正在下发第${current}/${t}个用户...`, mask: true })
|
wx.showLoading({ title: `加载中...`, mask: true })
|
||||||
|
console.log(`正在下发第${current}/${t}个用户...`)
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
wx.hideLoading()
|
wx.hideLoading()
|
||||||
@@ -127,7 +131,12 @@ Page({
|
|||||||
capacityUsed: 0,
|
capacityUsed: 0,
|
||||||
capacityTotal: 10,
|
capacityTotal: 10,
|
||||||
} as DeviceCard,
|
} as DeviceCard,
|
||||||
memberList: [] as MemberDisplay[],
|
/** 本人(单个) */
|
||||||
|
selfMember: null as MemberDisplay | null,
|
||||||
|
/** 员工列表 */
|
||||||
|
employeeList: [] as MemberDisplay[],
|
||||||
|
/** 家庭成员列表 */
|
||||||
|
familyList: [] as MemberDisplay[],
|
||||||
/** 自定义删除确认弹窗 */
|
/** 自定义删除确认弹窗 */
|
||||||
showDeleteModal: false,
|
showDeleteModal: false,
|
||||||
deleteTarget: null as MemberDisplay | null,
|
deleteTarget: null as MemberDisplay | null,
|
||||||
@@ -155,7 +164,7 @@ Page({
|
|||||||
sn: info.serialNumber ?? '',
|
sn: info.serialNumber ?? '',
|
||||||
'deviceCard.name': info.modelNumber ?? '智能体重秤',
|
'deviceCard.name': info.modelNumber ?? '智能体重秤',
|
||||||
})
|
})
|
||||||
if (!this.data.memberList.length && info.serialNumber) {
|
if (!this.data.selfMember && !this.data.employeeList.length && !this.data.familyList.length && info.serialNumber) {
|
||||||
this._loadData(info.serialNumber)
|
this._loadData(info.serialNumber)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -198,18 +207,19 @@ Page({
|
|||||||
avatar: item.avatar,
|
avatar: item.avatar,
|
||||||
sex: item.sex,
|
sex: item.sex,
|
||||||
age,
|
age,
|
||||||
|
dataType: item.dataType,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const selfMember = list.find(m => m.relationType === 1) || null
|
||||||
|
const employeeList = list.filter(m => m.relationType !== 1 && m.dataType === 0)
|
||||||
|
const familyList = list.filter(m => m.relationType !== 1 && m.dataType === 1)
|
||||||
this.setData({
|
this.setData({
|
||||||
memberList: list,
|
selfMember,
|
||||||
|
employeeList,
|
||||||
|
familyList,
|
||||||
'deviceCard.capacityUsed': list.length,
|
'deviceCard.capacityUsed': list.length,
|
||||||
})
|
})
|
||||||
// 首次加载不同步,后续数据变更触发的刷新才同步
|
|
||||||
// if (this._firstLoad) {
|
|
||||||
// this._firstLoad = false
|
|
||||||
// } else {
|
|
||||||
syncToDevice(list)
|
syncToDevice(list)
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.setData({ loading: false })
|
this.setData({ loading: false })
|
||||||
@@ -225,18 +235,18 @@ Page({
|
|||||||
/** 删除用户:弹出自定义确认弹窗 */
|
/** 删除用户:弹出自定义确认弹窗 */
|
||||||
onTapDelete(e: WechatMiniprogram.TouchEvent) {
|
onTapDelete(e: WechatMiniprogram.TouchEvent) {
|
||||||
const id = e.currentTarget.dataset.id as string
|
const id = e.currentTarget.dataset.id as string
|
||||||
const target = this.data.memberList.find(m => m.id === id)
|
const target = this.data.employeeList.find(m => m.id === id)
|
||||||
|
|| this.data.familyList.find(m => m.id === id)
|
||||||
if (!target) return
|
if (!target) return
|
||||||
|
|
||||||
// 未连接设备不允许删除
|
|
||||||
if (!this.data.connected) {
|
if (!this.data.connected) {
|
||||||
wx.showToast({ title: '请先连接设备', icon: 'none' })
|
wx.showToast({ title: '请先连接设备', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主用户有子用户时不允许删除
|
|
||||||
if (target.userType === 1) {
|
if (target.userType === 1) {
|
||||||
const hasSubUser = this.data.memberList.some(m => m.userType !== 1)
|
const hasSubUser = this.data.employeeList.some(m => m.userType !== 1)
|
||||||
|
|| this.data.familyList.some(m => m.userType !== 1)
|
||||||
if (hasSubUser) {
|
if (hasSubUser) {
|
||||||
wx.showToast({ title: '请先删除所有普通用户', icon: 'none' })
|
wx.showToast({ title: '请先删除所有普通用户', icon: 'none' })
|
||||||
return
|
return
|
||||||
@@ -264,22 +274,28 @@ Page({
|
|||||||
|
|
||||||
const id = target.id
|
const id = target.id
|
||||||
|
|
||||||
// 1. 从列表中移除该用户(立即更新 UI)
|
const newEmployeeList = this.data.employeeList.filter(m => m.id !== id)
|
||||||
const newList = this.data.memberList.filter(m => m.id !== id)
|
const newFamilyList = this.data.familyList.filter(m => m.id !== id)
|
||||||
|
const merged: MemberDisplay[] = [
|
||||||
|
...(this.data.selfMember ? [this.data.selfMember] : []),
|
||||||
|
...newEmployeeList,
|
||||||
|
...newFamilyList,
|
||||||
|
]
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
memberList: newList,
|
employeeList: newEmployeeList,
|
||||||
'deviceCard.capacityUsed': newList.length,
|
familyList: newFamilyList,
|
||||||
|
'deviceCard.capacityUsed': merged.length,
|
||||||
showDeleteModal: false,
|
showDeleteModal: false,
|
||||||
deleteTarget: null,
|
deleteTarget: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
wx.showLoading({ title: '正在同步设备数据...', mask: true })
|
wx.showLoading({ title: '正在同步设备数据...', mask: true })
|
||||||
|
|
||||||
// 2. 同步设备
|
|
||||||
let devicePromise: Promise<void>
|
let devicePromise: Promise<void>
|
||||||
if (newList.length) {
|
if (merged.length) {
|
||||||
devicePromise = lefuService.syncMembersToDevice(
|
devicePromise = lefuService.syncMembersToDevice(
|
||||||
newList.map(toDeviceMember),
|
merged.map(toDeviceMember),
|
||||||
(current, total) => {
|
(current, total) => {
|
||||||
wx.showLoading({ title: `正在同步设备数据 ${current}/${total}...`, mask: true })
|
wx.showLoading({ title: `正在同步设备数据 ${current}/${total}...`, mask: true })
|
||||||
},
|
},
|
||||||
@@ -290,7 +306,6 @@ Page({
|
|||||||
|
|
||||||
devicePromise
|
devicePromise
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// 3. 调用删除接口
|
|
||||||
return del('weighingScale/v2/del/user', { id }, { loading: false })
|
return del('weighingScale/v2/del/user', { id }, { loading: false })
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -299,7 +314,6 @@ Page({
|
|||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
wx.hideLoading()
|
wx.hideLoading()
|
||||||
// 失败时重新拉取列表恢复数据
|
|
||||||
this._loadData(this.data.sn)
|
this._loadData(this.data.sn)
|
||||||
wx.showToast({ title: err.message || '删除失败,请重试', icon: 'none' })
|
wx.showToast({ title: err.message || '删除失败,请重试', icon: 'none' })
|
||||||
})
|
})
|
||||||
@@ -311,7 +325,8 @@ Page({
|
|||||||
/** 添加用户:未连接态禁用 */
|
/** 添加用户:未连接态禁用 */
|
||||||
onTapAddMember() {
|
onTapAddMember() {
|
||||||
if (!this.data.connected) return
|
if (!this.data.connected) return
|
||||||
if (this.data.memberList.length >= 10) {
|
const total = (this.data.selfMember ? 1 : 0) + this.data.employeeList.length + this.data.familyList.length
|
||||||
|
if (total >= 10) {
|
||||||
wx.showToast({ title: '超过最大用户限制', icon: 'none' })
|
wx.showToast({ title: '超过最大用户限制', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,24 +36,38 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
<!-- 本人 -->
|
||||||
|
<view class="member-item my" wx:if="{{ selfMember }}">
|
||||||
|
<view class="member-avatar">{{ selfMember.realname[0] }}</view>
|
||||||
|
<view class="member-info">
|
||||||
|
<view class="member-name-row">
|
||||||
|
<view class="member-name">{{ selfMember.realname }}</view>
|
||||||
|
<view class="badge badge-self">本人</view>
|
||||||
|
</view>
|
||||||
|
<view class="member-meta">
|
||||||
|
<text class="meta-text">{{ selfMember.sex_dictText }}</text>
|
||||||
|
<text class="meta-divider">·</text>
|
||||||
|
<text class="meta-text">{{ selfMember.ageDisplay }}岁</text>
|
||||||
|
<text class="meta-divider">|</text>
|
||||||
|
<text class="meta-text">{{ selfMember.height }}cm</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="member-actions">
|
||||||
|
<view class="action-text" data-id="{{ selfMember.id }}" bind:tap="onTapEdit">编辑</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 用户列表 -->
|
<!-- 员工 -->
|
||||||
<block wx:for="{{ memberList }}" wx:key="id">
|
<view class="member-card" wx:if="{{ employeeList.length }}">
|
||||||
|
<view class="member-card-title" style="color: #10B981;">员工</view>
|
||||||
|
<block wx:for="{{ employeeList }}" wx:key="id">
|
||||||
<view class="member-item">
|
<view class="member-item">
|
||||||
<!-- 头像:取名字第一个字 -->
|
|
||||||
<view class="member-avatar">{{ item.realname[0] }}</view>
|
<view class="member-avatar">{{ item.realname[0] }}</view>
|
||||||
|
|
||||||
<!-- 信息列 -->
|
|
||||||
<view class="member-info">
|
<view class="member-info">
|
||||||
<view class="member-name-row">
|
<view class="member-name-row">
|
||||||
<view class="member-name">{{ item.realname }}</view>
|
<view class="member-name">{{ item.realname }}</view>
|
||||||
<block wx:if="{{ item.relationType == 1 }}">
|
<block wx:if="{{ item.relationType == 3 }}">
|
||||||
<view class="badge badge-self">本人</view>
|
|
||||||
</block>
|
|
||||||
<block wx:elif="{{ item.relationType == 2 }}">
|
|
||||||
<!-- <view class="badge badge-my">自己添加</view>-->
|
|
||||||
</block>
|
|
||||||
<block wx:elif="{{ item.relationType == 3 }}">
|
|
||||||
<view class="badge badge-other">他人添加</view>
|
<view class="badge badge-other">他人添加</view>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
@@ -65,13 +79,39 @@
|
|||||||
<text class="meta-text">{{ item.height }}cm</text>
|
<text class="meta-text">{{ item.height }}cm</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="member-actions">
|
<view class="member-actions">
|
||||||
<view class="action-text" data-id="{{ item.id }}" bind:tap="onTapEdit">编辑</view>
|
<view class="action-text" data-id="{{ item.id }}" bind:tap="onTapEdit">编辑</view>
|
||||||
<block wx:if="{{ item.relationType != 1 }}">
|
|
||||||
<view class="action-text action-text-danger" data-id="{{ item.id }}" bind:tap="onTapDelete">删除</view>
|
<view class="action-text action-text-danger" data-id="{{ item.id }}" bind:tap="onTapDelete">删除</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 家庭成员 -->
|
||||||
|
<view class="member-card" wx:if="{{ familyList.length }}">
|
||||||
|
<view class="member-card-title" style="color: #F59E0B;">家庭成员</view>
|
||||||
|
<block wx:for="{{ familyList }}" wx:key="id">
|
||||||
|
<view class="member-item">
|
||||||
|
<view class="member-avatar">{{ item.realname[0] }}</view>
|
||||||
|
<view class="member-info">
|
||||||
|
<view class="member-name-row">
|
||||||
|
<view class="member-name">{{ item.realname }}</view>
|
||||||
|
<block wx:if="{{ item.relationType == 3 }}">
|
||||||
|
<view class="badge badge-other">他人添加</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
<view class="member-meta">
|
||||||
|
<text class="meta-text">{{ item.sex_dictText }}</text>
|
||||||
|
<text class="meta-divider">·</text>
|
||||||
|
<text class="meta-text">{{ item.ageDisplay }}岁</text>
|
||||||
|
<text class="meta-divider">|</text>
|
||||||
|
<text class="meta-text">{{ item.height }}cm</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="member-actions">
|
||||||
|
<view class="action-text" data-id="{{ item.id }}" bind:tap="onTapEdit">编辑</view>
|
||||||
|
<view class="action-text action-text-danger" data-id="{{ item.id }}" bind:tap="onTapDelete">删除</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
Reference in New Issue
Block a user