[AI Generated]: feat(Views): 优化数据页数据卡交互与样式
This commit is contained in:
@@ -5,14 +5,146 @@
|
|||||||
|
|
||||||
.data-card {
|
.data-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
zoom: 1;
|
||||||
|
position: relative;
|
||||||
padding: 40rpx 30rpx 30rpx;
|
padding: 40rpx 30rpx 30rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 24rpx;
|
border-radius: 24rpx;
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
|
|
||||||
.userInfo {}
|
&::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 姓名 + 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 {
|
.nav {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 72rpx;
|
height: 72rpx;
|
||||||
@@ -41,6 +173,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 统计摘要 4 格 */
|
||||||
.summary {
|
.summary {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -51,25 +184,48 @@
|
|||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
|
|
||||||
.summary-item {
|
.summary-item {
|
||||||
flex: 1
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
// > view:first-of-type {
|
.summary-label {
|
||||||
// width: 94rpx;
|
color: #808080;
|
||||||
// height: 23rpx;
|
height: 24rpx;
|
||||||
// font-family: HarmonyOS Sans SC;
|
font-size: 24rpx;
|
||||||
// font-weight: 400;
|
line-height: 24rpx;
|
||||||
// font-size: 24rpx;
|
margin-bottom: 20rpx;
|
||||||
// color: #808080;
|
}
|
||||||
// margin-bottom: 30rpx;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// > view:last-of-type {
|
.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 {
|
.data-list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@@ -77,7 +233,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
|
|
||||||
> view:first-of-type {
|
>view:first-of-type {
|
||||||
color: #808080;
|
color: #808080;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 24rpx;
|
height: 24rpx;
|
||||||
@@ -86,7 +242,7 @@
|
|||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
> view:last-of-type {
|
>view:last-of-type {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 96rpx;
|
height: 96rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -98,7 +254,7 @@
|
|||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
|
|
||||||
> view {
|
>view {
|
||||||
color: #808080;
|
color: #808080;
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
height: 96rpx;
|
height: 96rpx;
|
||||||
|
|||||||
+140
-47
@@ -1,66 +1,159 @@
|
|||||||
|
/** 时间范围 */
|
||||||
|
type TimeRange = '7d' | '30d' | '3m'
|
||||||
|
|
||||||
|
/** 加载状态机 */
|
||||||
|
type LoadStatus = 'idle' | 'loading' | 'loaded'
|
||||||
|
|
||||||
|
/** 成员信息 */
|
||||||
|
interface MemberInfo {
|
||||||
|
/** 唯一 ID */
|
||||||
|
id: string
|
||||||
|
/** 姓名 */
|
||||||
|
name: string
|
||||||
|
/** 性别 */
|
||||||
|
gender: '男' | '女'
|
||||||
|
/** 年龄 */
|
||||||
|
age: number
|
||||||
|
/** 身高(cm) */
|
||||||
|
height: number
|
||||||
|
/** 头像色块(无图片时使用) */
|
||||||
|
avatar: string
|
||||||
|
/** 是否本人 */
|
||||||
|
isSelf: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 统计指标 */
|
||||||
|
interface StatsData {
|
||||||
|
/** 最高体重(kg) */
|
||||||
|
maxWeight: number
|
||||||
|
/** 最低体重(kg) */
|
||||||
|
minWeight: number
|
||||||
|
/** 平均体重(kg) */
|
||||||
|
avgWeight: number
|
||||||
|
/** 体重变化(kg,正负) */
|
||||||
|
weightDiff: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 时间范围 Tab 项 */
|
||||||
|
interface RangeTab {
|
||||||
|
key: TimeRange
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 单条测量记录 */
|
||||||
|
interface RecordItem {
|
||||||
|
/** 唯一 ID */
|
||||||
|
id: string
|
||||||
|
/** 测量时间,格式 YYYY.MM.DD HH:mm */
|
||||||
|
time: string
|
||||||
|
/** 体重(kg) */
|
||||||
|
weight: number
|
||||||
|
/** BMI */
|
||||||
|
bmi: number
|
||||||
|
/** 体脂率(%) */
|
||||||
|
bodyFat: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 历史数据页
|
||||||
|
* 状态机:idle → loading → loaded
|
||||||
|
* 切换时间范围 / 切换成员 均复用同一加载流程
|
||||||
|
*/
|
||||||
Page({
|
Page({
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
data: {
|
||||||
|
// 加载状态
|
||||||
|
status: 'idle' as LoadStatus,
|
||||||
|
|
||||||
|
// 当前选中的时间范围
|
||||||
|
activeRange: '7d' as TimeRange,
|
||||||
|
|
||||||
|
// 时间范围 Tab 选项
|
||||||
|
rangeTabs: [
|
||||||
|
{ key: '7d', label: '近7天' },
|
||||||
|
{ key: '30d', label: '近30天' },
|
||||||
|
{ key: '3m', label: '近3月' }
|
||||||
|
] as RangeTab[],
|
||||||
|
|
||||||
|
// 当前成员
|
||||||
|
currentMember: {
|
||||||
|
id: 'm-001',
|
||||||
|
name: '陈小飞',
|
||||||
|
gender: '男',
|
||||||
|
age: 28,
|
||||||
|
height: 175,
|
||||||
|
avatar: '#1385FA',
|
||||||
|
isSelf: true
|
||||||
|
} as MemberInfo,
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
stats: {
|
||||||
|
maxWeight: 73.5,
|
||||||
|
minWeight: 71.2,
|
||||||
|
avgWeight: 72.3,
|
||||||
|
weightDiff: -2.3
|
||||||
|
} as StatsData,
|
||||||
|
|
||||||
|
// 历史记录列表
|
||||||
|
recordList: [] as RecordItem[]
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
// idle 起步,通过统一入口触发加载
|
||||||
|
this.loadData()
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
onReady() {},
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
|
||||||
*/
|
|
||||||
onReady() {
|
|
||||||
|
|
||||||
},
|
onShow() {},
|
||||||
|
|
||||||
/**
|
onHide() {},
|
||||||
* 生命周期函数--监听页面显示
|
|
||||||
*/
|
|
||||||
onShow() {
|
|
||||||
|
|
||||||
},
|
onUnload() {},
|
||||||
|
|
||||||
/**
|
onPullDownRefresh() {},
|
||||||
* 生命周期函数--监听页面隐藏
|
|
||||||
*/
|
|
||||||
onHide() {
|
|
||||||
|
|
||||||
},
|
onReachBottom() {},
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面卸载
|
|
||||||
*/
|
|
||||||
onUnload() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面相关事件处理函数--监听用户下拉动作
|
|
||||||
*/
|
|
||||||
onPullDownRefresh() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面上拉触底事件的处理函数
|
|
||||||
*/
|
|
||||||
onReachBottom() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户点击右上角分享
|
|
||||||
*/
|
|
||||||
onShareAppMessage(opts): WechatMiniprogram.Page.ICustomShareContent {
|
onShareAppMessage(opts): WechatMiniprogram.Page.ICustomShareContent {
|
||||||
console.log(opts.target)
|
console.log(opts.target)
|
||||||
return {}
|
return {}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载数据(切 Tab / 切成员 复用)
|
||||||
|
*/
|
||||||
|
loadData() {
|
||||||
|
this.setData({ status: 'loading' })
|
||||||
|
|
||||||
|
// TODO: 后续接入真实接口,这里先用 mock
|
||||||
|
const mockList: RecordItem[] = [
|
||||||
|
{ id: 'r-001', time: '2026.05.12 08:12', weight: 71.2, bmi: 23.2, bodyFat: 18.5 },
|
||||||
|
{ id: 'r-002', time: '2026.05.11 21:30', weight: 71.8, bmi: 23.4, bodyFat: 18.7 },
|
||||||
|
{ id: 'r-003', time: '2026.05.11 08:05', weight: 71.5, bmi: 23.3, bodyFat: 18.6 },
|
||||||
|
{ id: 'r-004', time: '2026.05.10 07:58', weight: 72.0, bmi: 23.5, bodyFat: 18.9 },
|
||||||
|
{ id: 'r-005', time: '2026.05.10 22:10', weight: 72.6, bmi: 23.7, bodyFat: 19.1 },
|
||||||
|
{ id: 'r-006', time: '2026.05.09 08:20', weight: 72.8, bmi: 23.8, bodyFat: 19.2 },
|
||||||
|
{ id: 'r-007', time: '2026.05.08 08:00', weight: 73.5, bmi: 24.0, bodyFat: 19.5 }
|
||||||
|
]
|
||||||
|
|
||||||
|
this.setData({ recordList: mockList, status: 'loaded' })
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换时间范围 Tab
|
||||||
|
*/
|
||||||
|
onTapRange(e: WechatMiniprogram.TouchEvent) {
|
||||||
|
const key = e.currentTarget.dataset.key as TimeRange
|
||||||
|
if (key === this.data.activeRange) return
|
||||||
|
this.setData({ activeRange: key })
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换成员(后续接入成员选择浮层)
|
||||||
|
*/
|
||||||
|
onTapSwitchMember() {
|
||||||
|
// TODO: 接入成员选择浮层
|
||||||
|
wx.showToast({ title: '切换成员', icon: 'none' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,78 +1,79 @@
|
|||||||
<scroll-view class="scrollView" scroll-y>
|
<scroll-view class="scrollView" scroll-y>
|
||||||
<view class="scrollViewContent">
|
<view class="scrollViewContent">
|
||||||
|
|
||||||
|
<!-- 数据卡(成员信息 + 时间 Tab + 统计) -->
|
||||||
<view class="data-card">
|
<view class="data-card">
|
||||||
|
|
||||||
|
<!-- 成员信息 -->
|
||||||
<view class="userInfo">
|
<view class="userInfo">
|
||||||
<view class="avatar"></view>
|
<view class="avatar" style="background: {{ currentMember.avatar }};"></view>
|
||||||
<view class="info">
|
<view class="info">
|
||||||
<view>
|
<view class="info-name-row">
|
||||||
<view>陈小飞</view>
|
<view class="info-name">{{ currentMember.name }}</view>
|
||||||
<view>本人</view>
|
<block wx:if="{{ currentMember.isSelf }}">
|
||||||
|
<view class="badge-self">本人</view>
|
||||||
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view class="info-meta">
|
||||||
<view>男·32岁</view>
|
<view class="meta-text">{{ currentMember.gender }}</view>
|
||||||
<view>|</view>
|
<view class="meta-divider">·</view>
|
||||||
<view>172cm</view>
|
<view class="meta-text">{{ currentMember.age }}岁</view>
|
||||||
|
<view class="meta-divider">|</view>
|
||||||
|
<view class="meta-text">{{ currentMember.height }}cm</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="btn">切换成员</view>
|
<view class="btn" bind:tap="onTapSwitchMember">切换成员</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<view class="card-divider"></view>
|
||||||
|
|
||||||
|
<!-- 时间范围 Tab -->
|
||||||
<view class="nav">
|
<view class="nav">
|
||||||
<view class="active">近7天</view>
|
<block wx:for="{{ rangeTabs }}" wx:key="key">
|
||||||
<view>近30天</view>
|
<view
|
||||||
<view>近3月</view>
|
class="{{ activeRange === item.key ? 'active' : '' }}"
|
||||||
|
data-key="{{ item.key }}"
|
||||||
|
bind:tap="onTapRange"
|
||||||
|
>{{ item.label }}</view>
|
||||||
|
</block>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 统计摘要(4格) -->
|
||||||
<view class="summary">
|
<view class="summary">
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<view>最高体重</view>
|
<view class="summary-label">最高体重</view>
|
||||||
<view>
|
<view class="summary-value">{{ stats.maxWeight }}<text>kg</text></view>
|
||||||
<text></text>
|
|
||||||
62.1
|
|
||||||
<text>kg</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<view>最低体重</view>
|
<view class="summary-label">最低体重</view>
|
||||||
<view>
|
<view class="summary-value">{{ stats.minWeight }}<text>kg</text></view>
|
||||||
<text></text>
|
|
||||||
62.1
|
|
||||||
<text>kg</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<view>平均体重</view>
|
<view class="summary-label">平均体重</view>
|
||||||
<view>
|
<view class="summary-value">{{ stats.avgWeight }}<text>kg</text></view>
|
||||||
<text></text>
|
|
||||||
62.1
|
|
||||||
<text>kg</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<view>体重变化</view>
|
<view class="summary-label">体重变化</view>
|
||||||
<view>
|
<view class="summary-value {{ stats.weightDiff < 0 ? 'value-down' : 'value-up' }}">
|
||||||
<text></text>
|
{{ stats.weightDiff > 0 ? '+' : '' }}{{ stats.weightDiff }}<text>kg</text>
|
||||||
62.1
|
|
||||||
<text>kg</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 历史记录列表 -->
|
||||||
<view class="data-list">
|
<view class="data-list">
|
||||||
|
<block wx:for="{{ recordList }}" wx:key="id">
|
||||||
<view class="list">
|
<view class="list">
|
||||||
<view>2026.05.12 13:44</view>
|
<view>{{ item.time }}</view>
|
||||||
<view>
|
<view>
|
||||||
<view>体重:<text>62.2kg</text></view>
|
<view>体重:<text>{{ item.weight }}kg</text></view>
|
||||||
<view>BMI:<text>22.8</text></view>
|
<view>BMI:<text>{{ item.bmi }}</text></view>
|
||||||
<view>体脂率:<text>21.6%</text></view>
|
<view>体脂率:<text>{{ item.bodyFat }}%</text></view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="list">
|
|
||||||
<view>2026.05.12 13:44</view>
|
|
||||||
<view>
|
|
||||||
<view>体重:<text>62.2kg</text></view>
|
|
||||||
<view>BMI:<text>22.8</text></view>
|
|
||||||
<view>体脂率:<text>21.6%</text></view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</block>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|||||||
Reference in New Issue
Block a user