diff --git a/miniprogram/components/selectMemberDrawer/selectMemberDrawer.json b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/miniprogram/components/selectMemberDrawer/selectMemberDrawer.less b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.less new file mode 100644 index 0000000..976f2cd --- /dev/null +++ b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.less @@ -0,0 +1,263 @@ +/* 遮罩层 */ +.drawer-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(37, 37, 53, 0.6); + z-index: 100; + opacity: 0; + transition: opacity 0.3s ease; + + &--visible { + opacity: 1; + } +} + +/* 抽屉面板 */ +.drawer-panel { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + /* 最大高度约 75% 屏幕 */ + height: 85vh; + background-color: #FFFFFF; + border-radius: 24rpx 24rpx 0 0; + z-index: 101; + display: flex; + flex-direction: column; + transform: translateY(100%); + transition: transform 0.3s ease; + + &--visible { + transform: translateY(0); + } +} + +/* 拖拽把手 */ +.drawer-handle { + width: 72rpx; + height: 6rpx; + background-color: #77849E; + border-radius: 3rpx; + margin: 32rpx auto 40rpx; +} + +/* 标题栏 */ +.drawer-header { + width: 100%; + height: 32rpx; + padding: 0 30rpx; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: space-between; + + .drawer-title { + color: #252535; + height: 32rpx; + font-size: 32rpx; + font-weight: 700; + line-height: 32rpx; + } + + /* 关闭按钮 */ + + .drawer-close { + width: 32rpx; + height: 32rpx; + display: flex; + align-items: center; + justify-content: center; + + .drawer-close-icon { + width: 28rpx; + height: 28rpx; + position: relative; + + &::before, + &::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 3rpx; + background-color: #252535; + border-radius: 2rpx; + } + + &::before { + transform: translate(-50%, -50%) rotate(45deg); + } + + &::after { + transform: translate(-50%, -50%) rotate(-45deg); + } + } + } +} + +/* 顶部分隔线 */ +.drawer-divider { + width: 690rpx; + height: 2rpx; + background-color: #EAEDF1; + margin: 39rpx 30rpx 0; + flex-shrink: 0; +} + +/* 用户滚动列表 */ +.drawer-list { + flex: 1; + overflow: hidden; + padding-bottom: env(safe-area-inset-bottom); +} + +/* 用户行 */ +.member-item { + width: 100%; + height: 90rpx; + padding: 0 30rpx; + box-sizing: border-box; + display: flex; + flex-direction: row; + align-items: center; + margin-top: 24rpx; + + /* 有图片头像 */ + + .member-avatar { + width: 90rpx; + height: 90rpx; + border-radius: 24rpx; + flex-shrink: 0; + + &--selected { + border: 3rpx solid #50A6FF; + } + } + + /* 纯色占位头像 */ + + .member-avatar-placeholder { + width: 90rpx; + height: 90rpx; + border-radius: 24rpx; + flex-shrink: 0; + + /* 男:蓝色 */ + + &--male { + background-color: #C6E6FF; + } + + /* 女:粉色 */ + + &--female { + background-color: #FFD5E3; + } + + /* 选中男 */ + + &--selected-male { + border: 3rpx solid #50A6FF; + width: 96rpx; + height: 96rpx; + margin: -3rpx 0 0 -3rpx; + } + + /* 选中女 */ + + &--selected-female { + border: 3rpx solid #FF8FB5; + width: 96rpx; + height: 96rpx; + margin: -3rpx 0 0 -3rpx; + } + } + + /* 姓名 + 副标题 */ + + .member-info { + flex: 1; + height: 78rpx; + display: flex; + flex-direction: column; + justify-content: space-between; + margin-left: 23rpx; + + .member-name { + color: #333333; + font-size: 32rpx; + font-weight: 500; + line-height: 32rpx; + white-space: nowrap; + } + + .member-sub { + color: #77849E; + font-size: 26rpx; + line-height: 34rpx; + white-space: nowrap; + } + } + + .member-type { + height: 40rpx; + flex-shrink: 0; + + .member-type-tag { + height: 40rpx; + padding: 0 14rpx; + font-size: 22rpx; + line-height: 40rpx; + border-radius: 6rpx; + } + + .member-type-tag--self { + color: #1385FA; + background-color: rgba(19, 133, 250, 0.12); + } + + .member-type-tag--employee { + color: #10B981; + background-color: rgba(16, 185, 129, 0.12); + } + + .member-type-tag--family { + color: #F59E0B; + background-color: rgba(245, 158, 11, 0.12); + } + } +} + +/* 行间水平分隔线 */ +.member-separator { + width: 690rpx; + height: 2rpx; + background-color: #EAEDF1; + margin: 24rpx 30rpx 0; +} + +/* 空态占位 */ +.drawer-empty { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 80rpx; + + .drawer-empty-icon { + width: 193rpx; + height: 138rpx; + margin-bottom: 30rpx; + } + + .drawer-empty-text { + color: #808080; + font-size: 28rpx; + line-height: 28rpx; + } +} diff --git a/miniprogram/components/selectMemberDrawer/selectMemberDrawer.ts b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.ts new file mode 100644 index 0000000..aae634c --- /dev/null +++ b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.ts @@ -0,0 +1,190 @@ +import { get } from '../../utils/request/index' +import { lefuService } from '../../lefu/index' +import { calcAge } from '../../utils/common' + +/** GET /weighingScale/v3/select/addMembers/user 返回的单条结构 */ +interface AddMemberApiItem { + id: string + realname: string + sex_dictText: '男' | '女' + birthday: string + height: number + weight: number + idCard: string | null + avatar: string | null + dataType?: number + relationType?: number | string | null +} + +/** GET /weighingScale/v3/select/history/user 返回的单条结构 */ +interface HistoryApiItem { + id: string + userId: string + realname: string + sex: number + height: number + birthday: string + avatar: string | null + relationType: number | string | null + dataType?: number +} + +/** 抽屉内部用户项(含回填所需全量字段) */ +interface ExistingMember { + id: string + name: string + gender: '男' | '女' + age: number + height: number + weight: number + idCard: string + avatar?: string + selected?: boolean + /** history 模式额外携带,供页面构建 userInfo */ + userId?: string + sex?: number + birthday?: string + relationType?: number | string | null + /** 0=员工 1=家庭成员 */ + dataType?: number +} + +/** + * 选择已有用户抽屉组件 + * Properties: show(控制显示) + * Events: close(关闭), select(选中用户,携带 ExistingMember) + */ +Component({ + properties: { + /** 是否显示抽屉 */ + show: { + type: Boolean, + value: false + }, + /** 数据来源模式:addMember=新增用户选择 / history=历史数据切换用户 */ + source: { + type: String, + value: 'addMember' + }, + /** 需要排除的用户 ID(history 模式下排除当前查看的用户) */ + excludeUserId: { + type: String, + value: '' + } + }, + + data: { + /** 控制 wx:if,DOM 是否存在 */ + innerShow: false, + /** 控制 --visible 类,触发 CSS transition */ + animVisible: false, + /** 用户列表(组件内部拉取) */ + members: [] as ExistingMember[] + }, + + observers: { + /** + * 监听外部 show 变化: + * 打开时先拉数据再展示抽屉;关闭时移除动画类后移除 DOM + */ + show(val: boolean) { + if (val) { + this._fetchMembers() + this.setData({ innerShow: true }) + setTimeout(() => { + this.setData({ animVisible: true }) + }, 20) + } else { + this.setData({ animVisible: false }) + setTimeout(() => { + this.setData({ innerShow: false }) + }, 300) + } + } + }, + + methods: { + /** 调接口获取可选用户列表,根据 source 调不同接口 */ + _fetchMembers() { + const userInfo = wx.getStorageSync('userInfo') as { userId?: string } | null + const userId = userInfo?.userId ?? '' + + wx.showLoading({ title: '加载中...', mask: true }) + + if (this.properties.source === 'history') { + const params: Record = { userId } + if (this.properties.excludeUserId) { + params.userIdExclude = this.properties.excludeUserId + } + get('weighingScale/v3/select/history/user', params, { loading: false }) + .then((res: any) => { + const members: ExistingMember[] = (res.result ?? []).map((item: HistoryApiItem) => ({ + id: item.id, + name: item.realname, + gender: item.sex === 1 ? '男' : '女', + age: calcAge(item.birthday), + height: item.height, + weight: 0, + idCard: '', + avatar: item.avatar ?? '', + userId: item.userId, + sex: item.sex, + birthday: item.birthday, + relationType: item.relationType, + dataType: item.dataType, + })) + this.setData({ members }) + }) + .catch(() => { + wx.showToast({ title: '加载失败', icon: 'none' }) + }) + .finally(() => { + wx.hideLoading() + }) + } else { + const sn = lefuService.deviceInfo?.serialNumber ?? '' + get('weighingScale/v5/select/addMembers/user', { userId, sn }, { loading: false }) + .then((res: any) => { + const members: ExistingMember[] = (res.result ?? []).map((item: AddMemberApiItem) => ({ + id: item.id, + name: item.realname, + gender: item.sex_dictText, + age: calcAge(item.birthday), + height: item.height, + weight: item.weight, + idCard: item.idCard ?? '', + avatar: item.avatar ?? '', + relationType: item.relationType, + dataType: item.dataType, + })) + this.setData({ members }) + }) + .catch(() => { + wx.showToast({ title: '加载失败', icon: 'none' }) + }) + .finally(() => { + wx.hideLoading() + }) + } + }, + + /** 点击遮罩关闭 */ + onTapMask() { + this.triggerEvent('close') + }, + + /** 点击关闭按钮 */ + onTapClose() { + this.triggerEvent('close') + }, + + /** + * 点击用户行,触发 select 事件 + * @param e 携带 data-member 的点击事件 + */ + onTapMember(e: WechatMiniprogram.TouchEvent) { + const member = e.currentTarget.dataset.member as ExistingMember + this.triggerEvent('select', member) + } + } +}) diff --git a/miniprogram/components/selectMemberDrawer/selectMemberDrawer.wxml b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.wxml new file mode 100644 index 0000000..cfe1365 --- /dev/null +++ b/miniprogram/components/selectMemberDrawer/selectMemberDrawer.wxml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + 选择已有用户 + + + + + + + + + + + + + + + + + + + + + + + + {{ item.name }} + {{ item.gender }}·{{ item.age }}岁 丨 {{ item.height }}cm + + + + + 本人 + + + 员工 + + + 家庭用户 + + + + + + + + + + + + + + + 暂无可选用户 + + + + diff --git a/miniprogram/images/my/bg.png b/miniprogram/images/my/bg.png new file mode 100644 index 0000000..c9889a8 Binary files /dev/null and b/miniprogram/images/my/bg.png differ diff --git a/miniprogram/images/my/help.png b/miniprogram/images/my/help.png new file mode 100644 index 0000000..b594b93 Binary files /dev/null and b/miniprogram/images/my/help.png differ diff --git a/miniprogram/images/my/individual.png b/miniprogram/images/my/individual.png new file mode 100644 index 0000000..fadc909 Binary files /dev/null and b/miniprogram/images/my/individual.png differ diff --git a/miniprogram/pages/data/data.json b/miniprogram/pages/data/data.json index 8583a1b..2a8eb39 100644 --- a/miniprogram/pages/data/data.json +++ b/miniprogram/pages/data/data.json @@ -1,5 +1,6 @@ { "usingComponents": {}, - "navigationBarTitleText": "black" , + "navigationBarTitleText": "历史数据", + "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#FFFFFF" } \ No newline at end of file diff --git a/miniprogram/pages/data/data.less b/miniprogram/pages/data/data.less index 0fc8a7a..bb35273 100644 --- a/miniprogram/pages/data/data.less +++ b/miniprogram/pages/data/data.less @@ -1 +1,304 @@ -/* pages/data/data.wxss */ \ No newline at end of file +.scrollViewContent { + width: 100%; + padding: 24rpx 30rpx; + box-sizing: border-box; + + .data-card { + width: 100%; + overflow: hidden; + zoom: 1; + position: relative; + padding: 40rpx 30rpx 30rpx; + box-sizing: border-box; + border-radius: 24rpx; + margin-bottom: 30rpx; + background-color: #FFFFFF; + + &::before { + content: ""; + position: absolute; + top: 2rpx; + left: 2rpx; + right: 2rpx; + height: 88rpx; + background: linear-gradient(180deg, #D3E9FF 0%, #FCFBFD 100%); + } + + + /* 用户信息行 */ + .userInfo { + position: relative; + z-index: 2; + width: 100%; + display: flex; + align-items: center; + margin-bottom: 30rpx; + + /* 头像色块(展示姓名首字) */ + .avatar { + width: 90rpx; + height: 90rpx; + margin-right: 24rpx; + border-radius: 18rpx; + color: #FFFFFF; + font-size: 36rpx; + font-weight: bold; + line-height: 90rpx; + text-align: center; + background-color: #1385FA; + } + + /* 姓名 + meta */ + .info { + flex: 1; + + .info-name-row { + height: 40rpx; + display: flex; + align-items: center; + margin-bottom: 10rpx; + + .info-name { + color: #252535; + height: 40rpx; + font-size: 30rpx; + font-weight: bold; + line-height: 40rpx; + margin-right: 20rpx; + } + + /* 本人 badge */ + .badge-self { + color: #1385FA; + height: 40rpx; + padding: 0 18rpx; + font-size: 24rpx; + line-height: 40rpx; + border-radius: 8rpx; + background-color: rgba(19, 133, 250, 0.2); + } + } + + .info-meta { + height: 26rpx; + display: flex; + align-items: center; + + .meta-text { + color: #808080; + height: 26rpx; + font-size: 24rpx; + line-height: 26rpx; + } + + .meta-divider { + color: #CCCCCC; + font-size: 24rpx; + line-height: 26rpx; + margin: 0 12rpx; + } + } + } + + /* 切换用户按钮 */ + .btn { + color: #1385FA; + width: 120rpx; + height: 48rpx; + font-size: 24rpx; + font-weight: 500; + line-height: 48rpx; + border-radius: 8rpx; + text-align: center; + border: 2rpx solid #1385FA; + } + } + + .card-divider { + position: relative; + z-index: 2; + width: calc(100% + 60rpx); + left: -30rpx; + height: 1rpx; + margin-bottom: 30rpx; + border-bottom: 2rpx dashed #EAECF1; + + &::before { + content: ""; + position: absolute; + left: -15rpx; + top: 0; + bottom: 0; + margin: auto; + width: 30rpx; + height: 30rpx; + background-color: #F5F7FB; + border-radius: 50%; + } + + &::after { + content: ""; + position: absolute; + right: -15rpx; + top: 0; + bottom: 0; + margin: auto; + width: 30rpx; + height: 30rpx; + background-color: #F5F7FB; + border-radius: 50%; + } + } + + /* 时间范围 Tab */ + .nav { + width: 100%; + height: 72rpx; + padding: 4rpx; + box-sizing: border-box; + display: flex; + flex-wrap: nowrap; + background-color: #E8EBF2; + border-radius: 16rpx; + margin-bottom: 24rpx; + + >view { + flex: 1; + height: 64rpx; + border-radius: 16rpx; + font-size: 28rpx; + color: #808080; + line-height: 64rpx; + text-align: center; + + &.active { + color: #FFFFFF; + font-weight: bold; + background-color: #1385FA; + } + } + } + + /* 统计摘要 4 格 */ + .summary { + width: 100%; + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + padding: 24rpx 0; + background-color: #F3F4F6; + border-radius: 16rpx; + + .summary-item { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + + .summary-label { + color: #808080; + height: 24rpx; + font-size: 24rpx; + line-height: 24rpx; + margin-bottom: 20rpx; + } + + .summary-value { + color: #252535; + height: 32rpx; + font-size: 32rpx; + font-weight: bold; + line-height: 32rpx; + + text { + color: #808080; + font-size: 24rpx; + font-weight: normal; + margin-left: 4rpx; + } + } + + /* 体重下降(利好) */ + .value-down { + color: #2AC79F; + } + + /* 体重上升(警示) */ + .value-up { + color: #FF4D4F; + } + } + } + } + + /* 历史记录列表 */ + .data-list { + width: 100%; + + .list { + width: 100%; + margin-bottom: 30rpx; + + >view:first-of-type { + color: #808080; + width: 100%; + height: 24rpx; + font-size: 24rpx; + line-height: 24rpx; + margin-bottom: 20rpx; + } + + >view:last-of-type { + width: 100%; + height: 96rpx; + display: flex; + justify-content: space-between; + padding-left: 30rpx; + padding-right: 50rpx; + box-sizing: border-box; + flex-wrap: nowrap; + border-radius: 16rpx; + background-color: #FFFFFF; + + >view { + color: #808080; + font-size: 26rpx; + height: 96rpx; + line-height: 96rpx; + + text { + color: #252535; + font-weight: bold; + } + } + } + } + } + + /* ===== 空态 ===== */ + .empty-state { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + padding-top: 160rpx; + + .empty-icon { + width: 193rpx; + height: 138rpx; + margin-bottom: 40rpx; + + image { + width: 100%; + height: 100%; + } + } + + .empty-text { + color: #808080; + height: 30rpx; + font-size: 30rpx; + line-height: 30rpx; + } + } +} diff --git a/miniprogram/pages/data/data.wxml b/miniprogram/pages/data/data.wxml index 417d32e..46a123d 100644 --- a/miniprogram/pages/data/data.wxml +++ b/miniprogram/pages/data/data.wxml @@ -1,2 +1,92 @@ - -pages/data/data.wxml \ No newline at end of file + + + + + + + + + + + + 张晓敏 + 本人 + + + 男·36岁 + | + 170cm + + + 切换用户 + + + + + + + 近7日 + 近30日 + 近90日 + + + + + + 最高体重 + 89.6kg + + + 最低体重 + 89.6kg + + + 平均体重 + 89.6kg + + + 体重变化 + + {{ stats.weightChange > 0 ? '+' : '' }}{{ stats.weightChange }}kg + + + + + + + + + + + {{ item.examTime }} + + 体重:{{ item.weight }}kg + BMI:{{ item.bmi }} + 体脂率:{{ item.fatRate }}% + + + + + + + + + + + + + + diff --git a/miniprogram/pages/home/home.less b/miniprogram/pages/home/home.less index 9ece5e3..dafffe8 100644 --- a/miniprogram/pages/home/home.less +++ b/miniprogram/pages/home/home.less @@ -27,6 +27,7 @@ color: #1A3F68; height: 48rpx; font-size: 48rpx; + font-weight: bolder; line-height: 48rpx; margin-bottom: 24rpx; } @@ -35,6 +36,7 @@ color: #446D99; height: 26rpx; font-size: 26rpx; + font-weight: bolder; line-height: 26rpx; } } diff --git a/miniprogram/pages/my/my.less b/miniprogram/pages/my/my.less index 1c3fe88..572e876 100644 --- a/miniprogram/pages/my/my.less +++ b/miniprogram/pages/my/my.less @@ -1 +1,131 @@ -/* pages/my/my.wxss */ \ No newline at end of file +.my { + width: 100%; + height: 100%; + + .header { + width: 100%; + height: 320rpx; + margin-bottom: 26rpx; + + .bg { + width: 100%; + height: 100%; + } + + .user { + position: absolute; + top: 185rpx; + left: 40rpx; + right: 40rpx; + width: 100%; + display: flex; + box-sizing: border-box; + + .userAvatar { + width: 120rpx; + height: 120rpx; + margin-right: 30rpx; + border-radius: 24rpx; + color: #FFFFFF; + font-size: 48rpx; + font-weight: bold; + line-height: 110rpx; + text-align: center; + box-sizing: border-box; + border: 5rpx solid #ffffff; + background-color: #1385FA; + } + + .userInfo { + flex: 1; + display: flex; + flex-flow: column; + justify-content: center; + overflow: hidden; + + .userName { + color: #252536; + height: 40rpx; + font-weight: bold; + font-size: 40rpx; + line-height: 40rpx; + margin-bottom: 22rpx; + } + + .userSex { + height: 28rpx; + display: flex; + align-items: center; + + .meta-text { + color: #77849E; + height: 28rpx; + font-size: 28rpx; + line-height: 28rpx; + } + + .meta-divider { + color: #B6B6B6; + height: 28rpx; + font-size: 28rpx; + line-height: 28rpx; + margin: 0 12rpx; + } + } + } + } + } + + .page-container { + width: 100%; + box-sizing: border-box; + + .list { + width: 100%; + padding: 0 30rpx; + border-radius: 16rpx; + box-sizing: border-box; + background-color: #ffffff; + margin-bottom: 750rpx; + + .list-item { + width: 100%; + height: 110rpx; + display: flex; + flex-wrap: nowrap; + align-items: center; + border-bottom: 2rpx solid #EAECF1; + + &:last-of-type { + border-bottom: none; + } + + > view:nth-of-type(1) { + width: 44rpx; + height: 44rpx; + margin-right: 22rpx; + } + + > view:nth-of-type(2) { + flex: 1; + height: 32rpx; + color: #394356; + font-weight: bold; + font-size: 32rpx; + line-height: 32rpx; + } + } + } + + .exitBtn { + color: #252535; + width: 100%; + height: 110rpx; + font-size: 32rpx; + text-align: center; + line-height: 110rpx; + border-radius: 24rpx; + background-color: #FFFFFF; + } + } +} \ No newline at end of file diff --git a/miniprogram/pages/my/my.wxml b/miniprogram/pages/my/my.wxml index 19fb6c7..cbdf0d8 100644 --- a/miniprogram/pages/my/my.wxml +++ b/miniprogram/pages/my/my.wxml @@ -1,2 +1,40 @@ - -pages/my/my.wxml \ No newline at end of file + + + + + + + + + + 陈沐辰 + + 男·36岁 + | + 172cm + + + + + + + + + + + + 个人信息 + + + + + + + 帮助中心 + + + + + 退出登录 + + \ No newline at end of file