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 + + + + + + + + 完成并进入首页 +