diff --git a/pages/heightSdsCalculator/heightSdsCalculator.js b/pages/heightSdsCalculator/heightSdsCalculator.js index 38964d8..e39e3a9 100644 --- a/pages/heightSdsCalculator/heightSdsCalculator.js +++ b/pages/heightSdsCalculator/heightSdsCalculator.js @@ -1,45 +1,106 @@ const app = getApp(); -const math = require('../../utils/math.js'); + +// 添加正态分布相关的数学函数 +const normalDistribution = { + // 误差函数的近似计算 + erf(x) { + // 误差函数的系数 + const a1 = 0.254829592; + const a2 = -0.284496736; + const a3 = 1.421413741; + const a4 = -1.453152027; + const a5 = 1.061405429; + const p = 0.3275911; + + // 取绝对值 + const sign = (x >= 0) ? 1 : -1; + x = Math.abs(x); + + // 误差函数近似公式的计算 + const t = 1.0 / (1.0 + p * x); + const y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x); + + return sign * y; + }, + + // 计算百分位数 + calculatePercentile(sds) { + return (1 + this.erf(sds / Math.sqrt(2))) / 2 * 100; + } +}; Page({ data: { + // 基础数据 age: '', height: '', gender: 'male', + // 计算结果 showResult: false, sdsValue: null, - percentile: null, + calculationDetails: null, growthEvaluation: '', - chartData: null + // 参考数据 + standardData: { + male: [ + { age: 1, mean: 76.5, sd: 3.0 }, + { age: 2, mean: 88.5, sd: 3.5 }, + { age: 3, mean: 96.8, sd: 3.8 }, + { age: 4, mean: 103.5, sd: 4.2 }, + { age: 5, mean: 110.0, sd: 4.5 }, + { age: 6, mean: 116.5, sd: 4.8 }, + { age: 7, mean: 124.0, sd: 5.0 }, + { age: 8, mean: 129.5, sd: 5.2 }, + { age: 9, mean: 134.5, sd: 5.5 }, + { age: 10, mean: 138.5, sd: 5.8 }, + { age: 11, mean: 143.0, sd: 6.0 }, + { age: 12, mean: 150.0, sd: 6.5 }, + { age: 13, mean: 156.5, sd: 7.0 }, + { age: 14, mean: 163.0, sd: 7.2 }, + { age: 15, mean: 168.0, sd: 6.2 }, + { age: 16, mean: 171.5, sd: 5.8 }, + { age: 17, mean: 173.5, sd: 5.5 }, + { age: 18, mean: 174.5, sd: 5.2 } + ], + female: [ + { age: 1, mean: 75.0, sd: 2.9 }, + { age: 2, mean: 87.2, sd: 3.4 }, + { age: 3, mean: 95.6, sd: 3.7 }, + { age: 4, mean: 102.5, sd: 4.0 }, + { age: 5, mean: 108.5, sd: 4.3 }, + { age: 6, mean: 115.0, sd: 4.6 }, + { age: 7, mean: 122.5, sd: 4.8 }, + { age: 8, mean: 127.5, sd: 5.0 }, + { age: 9, mean: 132.5, sd: 5.2 }, + { age: 10, mean: 137.0, sd: 5.5 }, + { age: 11, mean: 142.0, sd: 5.8 }, + { age: 12, mean: 148.0, sd: 6.0 }, + { age: 13, mean: 154.0, sd: 6.2 }, + { age: 14, mean: 158.5, sd: 5.8 }, + { age: 15, mean: 160.5, sd: 5.5 }, + { age: 16, mean: 161.5, sd: 5.2 }, + { age: 17, mean: 162.0, sd: 5.0 }, + { age: 18, mean: 162.5, sd: 4.8 } + ] + } }, - // 输入年龄 + // 输入处理 inputAge(e) { this.setData({ - age: Number(e.detail.value) // 确保age是数字 + age: Number(e.detail.value) }); }, - // 输入身高 inputHeight(e) { this.setData({ - height: Number(e.detail.value) // 确保height是数字 + height: Number(e.detail.value) }); }, - // 选择性别 selectGender(e) { - const gender = e.currentTarget.dataset.gender; - this.setData({ gender }); - }, - - // 重置表单 - reset() { this.setData({ - age: '', - height: '', - gender: 'male', - showResult: false + gender: e.currentTarget.dataset.gender }); }, @@ -48,53 +109,45 @@ Page({ const { age, height, gender } = this.data; // 输入验证 - if (!age || !height) { - wx.showToast({ - title: '请填写完整信息', - icon: 'none' - }); - return; - } + if (!this.validateInput(age, height)) return; - // 直接使用本地生长数据 - this.useLocalGrowthData(); - }, - - // 处理生长数据 - processGrowthData(growthData) { try { - const { age, height, gender } = this.data; + // 获取标准数据 + const standardData = this.getStandardData(age, gender); + if (!standardData) { + throw new Error('未找到对应年龄的标准数据'); + } + + // 计算SDS + const sds = this.calculateSDS( + Number(height), + Number(standardData.mean), + Number(standardData.sd) + ); - // 计算SDS值并获取标准数据 - const { sds, standard } = this.calculateSDS(height, age, gender, growthData); - console.log('SDS计算详情:', { - height, - age, - gender, - mean: standard.mean, - sd: standard.sd, - sds - }); + // 计算中间值,用于显示 + const difference = Number(height) - Number(standardData.mean); - // 显示计算公式 - console.log(`计算公式:SDS = (${height} - ${standard.mean}) / ${standard.sd} = ${sds.toFixed(2)}`); - - // 计算百分位数 - const percentile = this.calculatePercentile(sds); - - // 获取生长评价 + // 获取评价 const evaluation = this.getGrowthEvaluation(sds); - - // 更新结果 + + // 显示结果 this.setData({ showResult: true, - sdsValue: Number(sds.toFixed(2)), // 确保sdsValue是数字类型 - percentile: percentile, + sdsValue: Number(sds.toFixed(2)), + calculationDetails: { + height: Number(height).toFixed(1), + mean: Number(standardData.mean).toFixed(1), + sd: Number(standardData.sd).toFixed(1), + formula: `身高SDS = (${height} - ${standardData.mean}) / ${standardData.sd}`, + calculation: ` = (${height} - ${standardData.mean}) / ${standardData.sd}`, + difference: ` = ${difference.toFixed(1)} / ${standardData.sd}`, + result: ` = ${sds.toFixed(2)}`, + interpretation: this.getInterpretation(sds) + }, growthEvaluation: evaluation }); - - // 绘制生长曲线 - this.drawGrowthChart(growthData); + } catch (error) { wx.showToast({ title: error.message || '计算失败', @@ -103,70 +156,118 @@ Page({ } }, - // 使用本地生长数据 - useLocalGrowthData() { - try { - const localData = require('./growthData.js'); - // 确保数据类型一致 - const processedData = localData.map(item => ({ - ...item, - age: Number(item.age) - })); - this.processGrowthData(processedData); - } catch (error) { + // 输入验证 + validateInput(age, height) { + if (!age || !height) { wx.showToast({ - title: '本地数据加载失败', + title: '请填写完整信息', icon: 'none' }); + return false; } + + if (age < 1 || age > 18) { + wx.showToast({ + title: '年龄必须在1-18岁之间', + icon: 'none' + }); + return false; + } + + if (height <= 0) { + wx.showToast({ + title: '身高必须大于0', + icon: 'none' + }); + return false; + } + + return true; + }, + + // 获取标准数据 + getStandardData(age, gender) { + return this.data.standardData[gender].find(item => item.age === age); }, // 计算SDS值 - calculateSDS(height, age, gender, growthData) { - // 根据年龄和性别获取标准值 - const standard = growthData.find(d => - Number(d.age) === Number(age) && - d.gender === gender - ); - - if (!standard) { - throw new Error('未找到对应年龄和性别的标准数据'); + calculateSDS(height, mean, sd) { + // 输入验证 + if (typeof height !== 'number' || typeof mean !== 'number' || typeof sd !== 'number') { + throw new Error('输入参数必须为数字'); } - - // SDS = (实际值 - 平均值) / 标准差 - const sds = (height - standard.mean) / standard.sd; - return { sds, standard }; - }, - // 计算百分位数 - calculatePercentile(sds) { - // 使用标准正态分布计算百分位数 - const percentile = 100 * (1 + math.erf(sds / Math.sqrt(2))) / 2; - return percentile.toFixed(1); + // SDS = (个体身高 - 平均身高) / 标准差 + const sds = (height - mean) / sd; + + // 验证计算结果 + if (isNaN(sds) || !isFinite(sds)) { + throw new Error('计算结果无效'); + } + + // 添加计算过程日志 + console.log('SDS计算过程:', { + 个体身高: height.toFixed(1), + 平均身高: mean.toFixed(1), + 标准差: sd.toFixed(1), + 计算公式: `(${height.toFixed(1)} - ${mean.toFixed(1)}) / ${sd.toFixed(1)}`, + 计算结果: sds.toFixed(2) + }); + + return sds; }, // 获取生长评价 getGrowthEvaluation(sds) { + // 根据标准更新评价标准 if (sds < -2) { - return '生长迟缓'; - } else if (sds >= -2 && sds <= 2) { - return '正常范围'; + return '可能存在生长迟缓'; + } else if (sds > 2) { + return '可能存在生长过快'; } else { - return '生长过快'; + return '正常范围'; } }, - // 绘制生长曲线 - drawGrowthChart(growthData) { - const ctx = wx.createCanvasContext('growthChart'); - - // 绘制逻辑... - - ctx.draw(); + // 重置表单 + reset() { + this.setData({ + age: '', + height: '', + gender: 'male', + showResult: false, + sdsValue: null, + calculationDetails: null, + growthEvaluation: '' + }); }, - // 返回 + // 返回上一页 onClickLeft() { wx.navigateBack(); + }, + + // 修改计算百分位数的方法 + calculatePercentile(sds) { + const percentile = normalDistribution.calculatePercentile(sds); + return percentile.toFixed(1); + }, + + // 获取解释文本 + getInterpretation(sds) { + const percentile = this.calculatePercentile(sds); + let interpretation = `身高SDS值:${sds.toFixed(2)}\n`; + interpretation += `该儿童身高位于同年龄同性别儿童的第${percentile}百分位\n`; + + // 根据SDS值添加解释 + if (sds === 0) { + interpretation += '身高等于平均值'; + } else if (sds > 0) { + interpretation += `高于平均值${(Math.abs(sds) * 100).toFixed(1)}%`; + } else { + interpretation += `低于平均值${(Math.abs(sds) * 100).toFixed(1)}%`; + } + + return interpretation; } }); diff --git a/pages/heightSdsCalculator/heightSdsCalculator.wxml b/pages/heightSdsCalculator/heightSdsCalculator.wxml index 6fd97cf..0106af3 100644 --- a/pages/heightSdsCalculator/heightSdsCalculator.wxml +++ b/pages/heightSdsCalculator/heightSdsCalculator.wxml @@ -61,21 +61,20 @@ 计算结果 - - 身高SDS值 - - {{sdsValue.toFixed(2)}} - + + + 计算过程: + + {{calculationDetails.formula}} + {{calculationDetails.calculation}} + {{calculationDetails.difference}} + {{calculationDetails.result}} + - - 百分位数 - {{percentile}}% - - - - 生长评价 - {{growthEvaluation}} + + + {{calculationDetails.interpretation}} diff --git a/pages/heightSdsCalculator/heightSdsCalculator.wxss b/pages/heightSdsCalculator/heightSdsCalculator.wxss index aebf939..ae9a0ab 100644 --- a/pages/heightSdsCalculator/heightSdsCalculator.wxss +++ b/pages/heightSdsCalculator/heightSdsCalculator.wxss @@ -133,3 +133,43 @@ margin-top: 20rpx; line-height: 1.6; } + +.calculation-process { + margin: 20rpx 0; + padding: 20rpx; + background-color: #f8f8f8; + border-radius: 10rpx; +} + +.process-title { + font-size: 28rpx; + color: #333; + margin-bottom: 10rpx; +} + +.process-steps { + display: flex; + flex-direction: column; + font-family: monospace; + font-size: 28rpx; + color: #666; +} + +.process-steps text { + margin: 5rpx 0; + white-space: pre; +} + +.result-interpretation { + margin: 20rpx 0; + padding: 20rpx; + background-color: #fff; + border-radius: 10rpx; + border: 1px solid #eee; +} + +.interpretation-text { + font-size: 28rpx; + color: #333; + white-space: pre-line; +}