From 5c923bf19a5a14b663cf2a029fce5f8de7e51db3 Mon Sep 17 00:00:00 2001
From: 17792275749 <812100002@qq.com>
Date: Mon, 11 May 2026 17:10:42 +0800
Subject: [PATCH] =?UTF-8?q?[AI=20Generated]:=20feat(Views):=20=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E5=AE=8C=E5=96=84=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF?=
=?UTF-8?q?=E9=A1=B5=E8=A1=A8=E5=8D=95=E5=8F=8A=E8=BA=AB=E4=BB=BD=E8=AF=81?=
=?UTF-8?q?=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
miniprogram/app.json | 2 +-
miniprogram/app.less | 11 ++
.../pages/connectedWifi/connectedWifi.js | 96 +++++++++-
.../pages/connectedWifi/connectedWifi.less | 154 +++++++++++++++
.../supplementPersonal/supplementPersonal.js | 130 ++++++++++++-
.../supplementPersonal.json | 3 +-
.../supplementPersonal.less | 176 ++++++++++++++++++
.../supplementPersonal.wxml | 107 ++++++++++-
8 files changed, 671 insertions(+), 8 deletions(-)
diff --git a/miniprogram/app.json b/miniprogram/app.json
index 951caaa..342a6ac 100644
--- a/miniprogram/app.json
+++ b/miniprogram/app.json
@@ -1,9 +1,9 @@
{
"pages": [
+ "pages/connectedWifi/connectedWifi",
"pages/login/login",
"pages/searchDevice/searchDevice",
"pages/connectedDevice/connectedDevice",
- "pages/connectedWifi/connectedWifi",
"pages/supplementPersonal/supplementPersonal",
"pages/home/home",
"pages/equipment/equipment",
diff --git a/miniprogram/app.less b/miniprogram/app.less
index 46d816e..5b367e6 100644
--- a/miniprogram/app.less
+++ b/miniprogram/app.less
@@ -19,4 +19,15 @@ page {
image {
width: 100%;
height: 100%;
+}
+
+/* 全局 scroll-view 通用样式:同时兼容两种结构
+ * - page 内直接放 scroll-view:靠 height: 100% 撑满
+ * - page 内为 flex 列布局(header + scrollView + footer):靠 flex: 1 撑满剩余空间
+ */
+.scrollView {
+ flex: 1;
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
}
\ No newline at end of file
diff --git a/miniprogram/pages/connectedWifi/connectedWifi.js b/miniprogram/pages/connectedWifi/connectedWifi.js
index 0217210..3b53721 100644
--- a/miniprogram/pages/connectedWifi/connectedWifi.js
+++ b/miniprogram/pages/connectedWifi/connectedWifi.js
@@ -1,4 +1,96 @@
+// 是否 mock 配网成功,false 则走失败态
+const MOCK_CONFIG_SUCCESS = true
+
+// 模拟配网耗时(毫秒)
+const MOCK_CONFIG_DURATION = 2000
+
Page({
- data: {},
- onLoad() {}
+ data: {
+ /**
+ * 页面状态
+ * - idle: 未配网(进入页面默认态)
+ * - configuring: 配网中
+ * - success: 配网成功
+ * - failed: 配网失败
+ */
+ status: 'idle',
+
+ /* 配网表单 */
+ form: {
+ ssid: '', // WiFi 名称
+ password: '', // WiFi 密码
+ showPwd: false, // 是否明文显示密码
+ },
+ },
+
+ onLoad() {
+
+ },
+
+ onUnload() {
+ /* 清除配网定时器,防止页面卸载后还触发 setData */
+ if (this._configTimer) {
+ clearTimeout(this._configTimer)
+ this._configTimer = null
+ }
+ },
+
+ /* 输入 WiFi 名称 */
+ onInputSsid(e) {
+ this.setData({ 'form.ssid': e.detail.value })
+ },
+
+ /* 输入 WiFi 密码 */
+ onInputPwd(e) {
+ this.setData({ 'form.password': e.detail.value })
+ },
+
+ /* 切换密码明文/密文 */
+ onTogglePwd() {
+ this.setData({ 'form.showPwd': !this.data.form.showPwd })
+ },
+
+ /* 主按钮:根据 status 路由到不同动作 */
+ onSubmit() {
+ const { status } = this.data
+ if (status === 'configuring') return
+ if (status === 'success') {
+ this.onFinish()
+ return
+ }
+ /* idle / failed 均触发开始配网 */
+ this.onStartConfig()
+ },
+
+ /* 开始配网 / 重新配网 */
+ onStartConfig() {
+ const { ssid, password } = this.data.form
+ if (!ssid) {
+ wx.showToast({ title: '请输入 WiFi 名称', icon: 'none' })
+ return
+ }
+ if (!password) {
+ wx.showToast({ title: '请输入 WiFi 密码', icon: 'none' })
+ return
+ }
+
+ this.setData({ status: 'configuring' })
+
+ /* 模拟配网,后续接入真实配网 API 时删除 */
+ this._configTimer = setTimeout(() => {
+ this.setData({ status: MOCK_CONFIG_SUCCESS ? 'success' : 'failed' })
+ }, MOCK_CONFIG_DURATION)
+ },
+
+ /* 配网成功后点击完成 */
+ onFinish() {
+ /* TODO: 接入真实跳转逻辑,例如回到设备首页 */
+ wx.navigateBack({ delta: 1 })
+ },
+
+ /* 查看帮助 */
+ onOpenHelp() {
+ console.log('查看帮助')
+ /* TODO: 跳帮助页 */
+ },
})
diff --git a/miniprogram/pages/connectedWifi/connectedWifi.less b/miniprogram/pages/connectedWifi/connectedWifi.less
index e69de29..74e7076 100644
--- a/miniprogram/pages/connectedWifi/connectedWifi.less
+++ b/miniprogram/pages/connectedWifi/connectedWifi.less
@@ -0,0 +1,154 @@
+/* WiFi 配网页 —— 四态(idle / configuring / success / failed)共用 */
+.connected-wifi {
+ width: 100%;
+ height: 100%;
+ padding: 48rpx 30rpx 0;
+ box-sizing: border-box;
+
+ .ripple {
+ width: 300rpx;
+ height: 300rpx;
+ border-radius: 50%;
+ margin: 0 auto 48rpx;
+ background-color: red;
+ }
+
+ .hero {
+ width: 300rpx;
+ height: 300rpx;
+ border-radius: 50%;
+ margin: 0 auto 48rpx;
+ background-color: rgba(19, 133, 250, 0.1);
+ }
+
+ .title {
+ color: #252535;
+ width: 100%;
+ height: 36rpx;
+ font-size: 36rpx;
+ font-weight: bold;
+ line-height: 36rpx;
+ text-align: center;
+ margin-bottom: 22rpx;
+ }
+
+ .sub-title {
+ color: #808080;
+ width: 100%;
+ font-size: 30rpx;
+ text-align: center;
+ line-height: 42rpx;
+ margin-bottom: 40rpx;
+ }
+
+ .wifi-form {
+ width: 100%;
+ background-color: #FFFFFF;
+ border: 2rpx solid #E6E6EA;
+ border-radius: 16rpx;
+ box-sizing: border-box;
+ padding: 0 30rpx;
+ margin-bottom: 32rpx;
+
+ .form-row {
+ width: 100%;
+ height: 100rpx;
+ display: flex;
+ align-items: center;
+ border-bottom: 2rpx solid #F5F5F5;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ .form-label {
+ color: #252535;
+ width: 160rpx;
+ font-size: 30rpx;
+ font-weight: 500;
+ line-height: 30rpx;
+ flex-shrink: 0;
+ }
+
+ .form-input {
+ flex: 1;
+ color: #252535;
+ font-size: 30rpx;
+ line-height: 30rpx;
+ }
+
+ .form-placeholder {
+ color: #B0B0B0;
+ font-size: 30rpx;
+ }
+
+ .form-eye {
+ color: #1385FA;
+ font-size: 28rpx;
+ line-height: 28rpx;
+ padding-left: 24rpx;
+ flex-shrink: 0;
+ }
+ }
+ }
+
+ .result-success {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-bottom: 40rpx;
+
+ .result-icon-success {
+ width: 120rpx;
+ height: 120rpx;
+ border-radius: 50%;
+ background-color: rgba(42, 199, 159, 0.1);
+ margin-bottom: 24rpx;
+ }
+
+ .result-text {
+ color: #2AC79F;
+ font-size: 30rpx;
+ font-weight: 500;
+ line-height: 30rpx;
+ }
+ }
+
+ .submit-btn {
+ color: #FFFFFF;
+ width: 580rpx;
+ height: 88rpx;
+ font-size: 32rpx;
+ font-weight: bold;
+ text-align: center;
+ line-height: 88rpx;
+ border-radius: 44rpx;
+ margin: 0 auto 32rpx;
+ background-color: #1385FA;
+ }
+
+ .submit-btn-disabled {
+ background-color: #A8C9F0;
+ }
+
+ .help {
+ width: 100%;
+ height: 30rpx;
+ text-align: center;
+ line-height: 30rpx;
+ margin-bottom: 60rpx;
+
+ .help-text {
+ color: #808080;
+ font-size: 30rpx;
+ line-height: 30rpx;
+ }
+
+ .help-link {
+ color: #1385FA;
+ font-size: 30rpx;
+ line-height: 30rpx;
+ }
+ }
+}
diff --git a/miniprogram/pages/supplementPersonal/supplementPersonal.js b/miniprogram/pages/supplementPersonal/supplementPersonal.js
index 0217210..e408ecf 100644
--- a/miniprogram/pages/supplementPersonal/supplementPersonal.js
+++ b/miniprogram/pages/supplementPersonal/supplementPersonal.js
@@ -1,4 +1,128 @@
+/**
+ * 完善个人信息页
+ * 收集姓名、身份证号、身高,并根据身份证自动解析性别与年龄
+ * 提交后进入首页(tabBar)
+ */
Page({
- data: {},
- onLoad() {}
-})
+ data: {
+ // 表单数据
+ form: {
+ name: '', // 姓名
+ idCard: '', // 身份证号
+ gender: '', // 性别(由身份证解析,只读)
+ age: '', // 年龄(由身份证解析,只读)
+ height: '' // 身高(cm)
+ }
+ },
+
+ /**
+ * 姓名输入
+ */
+ onNameInput(e) {
+ this.setData({
+ 'form.name': e.detail.value
+ });
+ },
+
+ /**
+ * 身份证号输入
+ * 长度满 18 位时自动解析性别与年龄,否则清空
+ */
+ onIdCardInput(e) {
+ const idCard = (e.detail.value || '').trim().toUpperCase();
+ const parsed = this.parseIdCard(idCard);
+
+ this.setData({
+ 'form.idCard': idCard,
+ 'form.gender': parsed.gender,
+ 'form.age': parsed.age
+ });
+ },
+
+ /**
+ * 身高输入
+ */
+ onHeightInput(e) {
+ this.setData({
+ 'form.height': e.detail.value
+ });
+ },
+
+ /**
+ * 解析身份证号,返回性别与年龄
+ * @param {string} idCard 18 位身份证号
+ * @returns {{ gender: string, age: string }}
+ */
+ parseIdCard(idCard) {
+ // 简单校验:18 位且前 17 位为数字
+ const reg = /^\d{17}[\dX]$/;
+ if (!reg.test(idCard)) {
+ return { gender: '', age: '' };
+ }
+
+ // 性别:第 17 位奇数为男,偶数为女
+ const genderCode = parseInt(idCard.charAt(16), 10);
+ const gender = genderCode % 2 === 1 ? '男' : '女';
+
+ // 出生日期:第 7-14 位
+ const year = parseInt(idCard.substr(6, 4), 10);
+ const month = parseInt(idCard.substr(10, 2), 10);
+ const day = parseInt(idCard.substr(12, 2), 10);
+
+ // 基本合法性校验
+ if (
+ !year || !month || !day ||
+ month < 1 || month > 12 ||
+ day < 1 || day > 31
+ ) {
+ return { gender: '', age: '' };
+ }
+
+ // 计算周岁(看是否过了今年生日)
+ const now = new Date();
+ let age = now.getFullYear() - year;
+ const nowMonth = now.getMonth() + 1;
+ const nowDay = now.getDate();
+ if (nowMonth < month || (nowMonth === month && nowDay < day)) {
+ age -= 1;
+ }
+
+ if (age < 0 || age > 150) {
+ return { gender: '', age: '' };
+ }
+
+ return { gender, age: String(age) };
+ },
+
+ /**
+ * 提交表单
+ * 必填:姓名、身份证号(18 位且解析成功)、身高
+ * 未通过时 toast 提示,通过后进入首页(tabBar)
+ */
+ onSubmit() {
+ const { name, idCard, gender, age, height } = this.data.form;
+ const heightNum = parseFloat(height);
+
+ if (!name.trim()) {
+ wx.showToast({ title: '请填写姓名', icon: 'none' });
+ return;
+ }
+ if (idCard.length !== 18) {
+ wx.showToast({ title: '请填写正确的身份证号', icon: 'none' });
+ return;
+ }
+ if (!gender || !age) {
+ wx.showToast({ title: '身份证号有误,请检查', icon: 'none' });
+ return;
+ }
+ if (!height || isNaN(heightNum) || heightNum <= 0) {
+ wx.showToast({ title: '请填写身高', icon: 'none' });
+ return;
+ }
+
+ // TODO: 此处后续接入用户信息保存接口
+ wx.switchTab({
+ url: '/pages/home/home'
+ });
+ }
+});
diff --git a/miniprogram/pages/supplementPersonal/supplementPersonal.json b/miniprogram/pages/supplementPersonal/supplementPersonal.json
index a97367d..1e48fa5 100644
--- a/miniprogram/pages/supplementPersonal/supplementPersonal.json
+++ b/miniprogram/pages/supplementPersonal/supplementPersonal.json
@@ -1,3 +1,4 @@
{
- "usingComponents": {}
+ "usingComponents": {},
+ "navigationBarTitleText": "完善个人信息"
}
diff --git a/miniprogram/pages/supplementPersonal/supplementPersonal.less b/miniprogram/pages/supplementPersonal/supplementPersonal.less
index e69de29..de168f8 100644
--- a/miniprogram/pages/supplementPersonal/supplementPersonal.less
+++ b/miniprogram/pages/supplementPersonal/supplementPersonal.less
@@ -0,0 +1,176 @@
+.supplement-personal {
+ width: 100%;
+ height: 100%;
+
+ /* 顶部蓝色提示条 */
+ .tips {
+ width: 100%;
+ height: 56rpx;
+ display: flex;
+ margin-bottom: 24rpx;
+ padding-left: 30rpx;
+ align-items: center;
+ box-sizing: border-box;
+ background-color: rgba(19, 133, 250, 0.2);
+
+ .tips-icon {
+ color: #1385FA;
+ width: 28rpx;
+ height: 28rpx;
+ font-size: 20rpx;
+ font-weight: bold;
+ margin-right: 10rpx;
+ line-height: 24rpx;
+ text-align: center;
+ border-radius: 50%;
+ box-sizing: border-box;
+ border: 1rpx solid #1385FA;
+ }
+
+ .tips-text {
+ color: #1385FA;
+ height: 24rpx;
+ font-size: 24rpx;
+ line-height: 24rpx;
+ }
+ }
+
+ .form {
+ width: 100%;
+ padding: 0 30rpx;
+ margin-bottom: 40rpx;
+ box-sizing: border-box;
+
+ /* 表单卡片 */
+ .form-card {
+ width: 100%;
+ padding: 40rpx 30rpx;
+ border-radius: 16rpx;
+ box-sizing: border-box;
+ background-color: #FFFFFF;
+
+ .form-row {
+ width: 100%;
+ margin-bottom: 40rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .form-label {
+ width: 100%;
+ height: 40rpx;
+ display: flex;
+ flex-wrap: nowrap;
+ margin-bottom: 18rpx;
+
+ .label-text {
+ color: #252535;
+ height: 40rpx;
+ font-size: 28rpx;
+ line-height: 40rpx;
+ font-weight: bold;
+ margin-right: 6rpx;
+ }
+
+ .label-star {
+ color: #FF4D4F;
+ height: 40rpx;
+ font-weight: 500;
+ font-size: 28rpx;
+ line-height: 40rpx;
+ }
+ }
+
+ .form-control {
+ width: 100%;
+ }
+
+ /* 可输入区域 */
+ .form-input {
+ width: 100%;
+ height: 88rpx;
+ padding: 0 30rpx;
+ color: #252535;
+ font-size: 26rpx;
+ border-radius: 16rpx;
+ box-sizing: border-box;
+ background-color: #FFFFFF;
+ border: 2rpx solid #E6E6EA;
+ }
+
+ .form-placeholder {
+ color: #B6B6B6;
+ font-size: 26rpx;
+ }
+
+ /* 输入框 + 后缀容器(身高 cm) */
+ .form-input-wrap {
+ position: relative;
+ width: 630rpx;
+
+ .form-input-with-suffix {
+ padding-right: 80rpx;
+ }
+
+ .form-suffix-inside {
+ position: absolute;
+ right: 30rpx;
+ top: 0;
+ height: 88rpx;
+ color: #77849E;
+ font-size: 26rpx;
+ line-height: 88rpx;
+ }
+ }
+
+ /* 只读区域(性别 / 年龄) */
+ .form-readonly {
+ width: 630rpx;
+ height: 88rpx;
+ box-sizing: border-box;
+ padding: 0 24rpx;
+ background: #F6F6F6;
+ border-radius: 16rpx;
+ display: flex;
+ align-items: center;
+
+ .readonly-text {
+ color: #252535;
+ font-size: 26rpx;
+ }
+
+ .readonly-placeholder {
+ color: #B6B6B6;
+ font-size: 26rpx;
+ }
+ }
+
+ .form-readonly-with-suffix {
+ justify-content: space-between;
+
+ .form-suffix {
+ color: #77849E;
+ height: 88rpx;
+ font-size: 26rpx;
+ line-height: 88rpx;
+ }
+ }
+ }
+ }
+
+ /* 底部提交按钮 */
+ .submit-btn {
+ color: #FFFFFF;
+ width: 580rpx;
+ height: 88rpx;
+ font-size: 32rpx;
+ font-weight: bold;
+ line-height: 88rpx;
+ text-align: center;
+ background-color: #1385FA;
+ border-radius: 44rpx;
+ margin: 0 auto;
+ }
+}
diff --git a/miniprogram/pages/supplementPersonal/supplementPersonal.wxml b/miniprogram/pages/supplementPersonal/supplementPersonal.wxml
index 3acee47..05ce9b3 100644
--- a/miniprogram/pages/supplementPersonal/supplementPersonal.wxml
+++ b/miniprogram/pages/supplementPersonal/supplementPersonal.wxml
@@ -1 +1,106 @@
-supplementPersonal 占位
+
+
+
+
+ !
+ 请完整填写信息,用于精准计算体脂数据
+
+
+
+
+
+
+
+
+
+ 姓名
+ *
+
+
+
+
+
+
+
+
+
+ 身份证号
+ *
+
+
+
+
+
+
+
+
+
+ 性别
+
+
+
+
+ {{ form.gender }}
+
+
+ 自动生成,无需填写
+
+
+
+
+
+
+
+
+ 年龄
+
+
+
+
+ {{ form.age }}
+
+
+ 自动生成,无需填写
+
+ 岁
+
+
+
+
+
+
+
+ *
+ 身高
+
+
+
+
+ cm
+
+
+
+
+
+
+
+ 完成并进入首页
+