Index.html
<view class="container">
<!-- 头图卡片 -->
<view class="hero-card">
<icon type="info" size="28" color="#ffffff"></icon>
<view class="hero-text-wrap">
<text class="hero-title">BMI 健康测量仪</text>
<text class="hero-desc">输入您的身高体重,计算您的体质指数</text>
</view>
</view>
<!-- 身长、体重选择面板 -->
<view class="card">
<view class="card-title">身高 (cm)</view>
<view class="slider-box">
<slider bindchange="onHeightChange" min="100" max="220" value="{{height}}" show-value="true" activeColor="#07C160" />
</view>
<view class="input-row">
<text class="label">精准身高:</text>
<input type="number" bindinput="onHeightInput" value="{{height}}" placeholder="输入身高" class="fine-input" />
<text class="unit">cm</text>
</view>
</view>
<view class="card">
<view class="card-title">体重 (kg)</view>
<view class="slider-box">
<slider bindchange="onWeightChange" min="30" max="150" value="{{weight}}" show-value="true" activeColor="#07C160" />
</view>
<view class="input-row">
<text class="label">精准体重:</text>
<input type="number" bindinput="onWeightInput" value="{{weight}}" placeholder="输入体重" class="fine-input" />
<text class="unit">kg</text>
</view>
</view>
<!-- 计算控制台 -->
<view class="btn-group">
<button class="btn btn-primary" bindtap="calculateBMI">开始计算指数</button>
<button class="btn btn-secondary" bindtap="resetAll">清空数据</button>
</view>
<!-- 结果分析展示 -->
<view class="card result-card" wx:if="{{bmiResult}}">
<view class="result-label">您的计算结果 BMI</view>
<view class="result-value text-{{statusColorClass}}">{{bmiResult}}</view>
<view class="result-status-badge bg-{{statusColorClass}}">{{bmiStatus}}</view>
<view class="divider"></view>
<view class="advice-title">健康建议:</view>
<text class="advice-text">{{advice}}</text>
</view>
<!-- 历史小账本 -->
<view class="card history-card" wx:if="{{historyList.length > 0}}">
<view class="history-header">
<text class="card-title">测算历史</text>
<text class="clear-history" bindtap="clearHistory">清空</text>
</view>
<view class="history-list">
<view class="history-item" wx:for="{{historyList}}" wx:key="time">
<text class="history-time">{{item.time}}</text>
<text class="history-params">{{item.height}}cm / {{item.weight}}kg</text>
<text class="history-bmi {{item.colorClass}}">BMI: {{item.bmi}}</text>
</view>
</view>
</view>
</view>
Index.wxss
.container {
padding: 30rpx;
background-color: #f7f7f7;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica;
}
.hero-card {
display: flex;
align-items: center;
background: linear-gradient(135deg, #07c160, #0abf7d);
color: white;
padding: 40rpx 30rpx;
border-radius: 20rpx;
margin-bottom: 30rpx;
box-shadow: 0 10rpx 30rpx rgba(7, 193, 96, 0.2);
}
.hero-text-wrap {
margin-left: 20rpx;
}
.hero-title {
font-size: 38rpx;
font-weight: bold;
display: block;
margin-bottom: 8rpx;
}
.hero-desc {
font-size: 24rpx;
opacity: 0.9;
}
.card {
background-color: white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}
.card-title {
font-size: 30rpx;
color: #333333;
margin-bottom: 20rpx;
font-weight: 600;
}
.slider-box {
margin-bottom: 20rpx;
}
.input-row {
display: flex;
align-items: center;
border-top: 1rpx solid #eeeeee;
padding-top: 20rpx;
}
.label {
font-size: 26rpx;
color: #666666;
width: 150rpx;
}
.fine-input {
flex: 1;
font-size: 28rpx;
color: #333333;
border: 1rpx solid #dddddd;
border-radius: 8rpx;
padding: 8rpx 16rpx;
}
.unit {
font-size: 26rpx;
color: #888888;
margin-left: 15rpx;
font-weight: 500;
}
.btn-group {
display: flex;
gap: 20rpx;
margin-bottom: 40rpx;
}
.btn {
flex: 1;
border-radius: 50rpx;
font-size: 30rpx;
padding: 24rpx 0;
text-align: center;
font-weight: 500;
transition: opacity 0.2s;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
}
.btn-primary {
background-color: #07c160;
color: white;
}
.btn-secondary {
background-color: #e5e5e5;
color: #555555;
}
.result-card {
text-align: center;
padding: 50rpx 40rpx;
animation: fadeIn 0.4s ease;
}
.result-label {
font-size: 26rpx;
color: #888888;
letter-spacing: 2rpx;
text-transform: uppercase;
}
.result-value {
font-size: 80rpx;
font-weight: bold;
margin: 15rpx 0;
}
.result-status-badge {
display: inline-block;
color: white;
font-size: 28rpx;
padding: 8rpx 32rpx;
border-radius: 50rpx;
font-weight: 600;
margin-bottom: 30rpx;
}
/* Status colors map */
.text-normal { color: #07c160; }
.bg-normal { background-color: #07c160; }
.text-under { color: #5bc0de; }
.bg-under { background-color: #5bc0de; }
.text-over { color: #f0ad4e; }
.bg-over { background-color: #f0ad4e; }
.text-obese { color: #d9534f; }
.bg-obese { background-color: #d9534f; }
.divider {
height: 1rpx;
background-color: #eeeeee;
margin: 30rpx 0;
}
.advice-title {
font-size: 28rpx;
font-weight: bold;
color: #333333;
text-align: left;
margin-bottom: 10rpx;
}
.advice-text {
font-size: 26rpx;
color: #666666;
text-align: left;
line-height: 1.6;
display: block;
}
.history-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
}
.clear-history {
font-size: 24rpx;
color: #ff4d4f;
background-color: #fff1f0;
padding: 6rpx 16rpx;
border-radius: 6rpx;
}
.history-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.history-item {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid #f2f2f2;
padding-bottom: 16rpx;
}
.history-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.history-time {
font-size: 24rpx;
color: #999999;
}
.history-params {
font-size: 26rpx;
color: #333333;
}
.history-bmi {
font-size: 26rpx;
font-weight: bold;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10rpx); }
to { opacity: 1; transform: translateY(0); }
}
Index.js
Page({
data: {
height: 166,
weight:52,
bmiResult: "",
bmiStatus: "",
statusColorClass: "",
advice: "",
historyList: []
},
onLoad: function() {
console.log("BMI健康的体质页面载入");
this.setData({
historyList: [
{ time: "2026-06-01 10:22", height: 172, weight: 70, bmi: "23.66", colorClass: "text-normal" },
{ time: "2026-05-15 08:45", height: 172, weight: 74, bmi: "25.01", colorClass: "text-over" }
]
});
},
onHeightChange: function(e) {
this.setData({
height: parseInt(e.detail.value)
});
},
onHeightInput: function(e) {
this.setData({
height: e.detail.value
});
},
onWeightChange: function(e) {
this.setData({
weight: parseInt(e.detail.value)
});
},
onWeightInput: function(e) {
this.setData({
weight: e.detail.value
});
},
calculateBMI: function() {
const rawHeight = parseFloat(this.data.height);
const rawWeight = parseFloat(this.data.weight);
if (isNaN(rawHeight) || rawHeight < 55 || rawHeight > 280) {
wx.showModal({
title: "输入提示",
content: "请输入合理的精准身高 (55 ~ 280 cm)",
showCancel: false
});
return;
}
if (isNaN(rawWeight) || rawWeight < 10 || rawWeight > 400) {
wx.showModal({
title: "输入提示",
content: "请输入合理的精准体重 (10 ~ 400 kg)",
showCancel: false
});
return;
}
const heightM = rawHeight / 100;
const bmiVal = rawWeight / (heightM * heightM);
const bmiFixed = bmiVal.toFixed(2);
let status = "";
let colorClass = "";
let adviceTxt = "";
if (bmiVal < 18.5) {
status = "偏瘦 (体重过轻)";
colorClass = "under";
adviceTxt = "您的体重有些偏轻,建议保证营养均衡,多吃富含蛋白质的高能量食品,并配合适度的阻力训练以增强肌肉。";
} else if (bmiVal < 24) {
status = "正常 (健康身形)";
colorClass = "normal";
adviceTxt = "恭喜您!您的体质处于黄金健康范围内,请继续保持良好的膳食习惯、充足的水分摄入以及每周规律的中等强度运动状态。";
} else if (bmiVal < 28) {
status = "过重 (轻度超重)";
colorClass = "over";
adviceTxt = "您的体重略高于健康范畴,建议减少高糖分及饱和油脂食物的摄入,坚持每日进行30分钟以上的有氧运动(如慢跑、游泳)。";
} else {
status = "肥胖 (重度超额)";
colorClass = "obese";
adviceTxt = "目前的体重水平可能对心脑血管构成负担。我们强烈建议咨询医学健康顾问,科学制定低卡路里膳食指南,循序渐进开启运动日程。";
}
const newHistory = {
time: this.getFormattedDate(),
height: rawHeight,
weight: rawWeight,
bmi: bmiFixed,
colorClass: "text-" + colorClass
};
const currentList = this.data.historyList;
currentList.unshift(newHistory);
this.setData({
bmiResult: bmiFixed,
bmiStatus: status,
statusColorClass: colorClass,
advice: adviceTxt,
historyList: currentList,
height: rawHeight,
weight: rawWeight
});
wx.showToast({
title: "测算成功!",
icon: "success",
duration: 1500
});
},
resetAll: function() {
this.setData({
height: 170,
weight: 65,
bmiResult: "",
bmiStatus: "",
statusColorClass: "",
advice: ""
});
wx.showToast({
title: "数据已清空",
icon: "info"
});
},
clearHistory: function() {
this.setData({
historyList: []
});
wx.showToast({
title: "历史已删除",
icon: "success"
});
},
getFormattedDate: function() {
const now = new Date();
const Y = now.getFullYear();
const M = String(now.getMonth() + 1).padStart(2, '0');
const D = String(now.getDate()).padStart(2, '0');
const h = String(now.getHours()).padStart(2, '0');
const m = String(now.getMinutes()).padStart(2, '0');
return Y + "-" + M + "-" + D + " " + h + ":" + m;
}
})