243 lines
7.1 KiB
JavaScript
243 lines
7.1 KiB
JavaScript
|
|
const app = getApp();
|
|||
|
|
|
|||
|
|
Page({
|
|||
|
|
data: {
|
|||
|
|
// 基础数据
|
|||
|
|
ba: '', // 骨龄
|
|||
|
|
ca: '', // 实际年龄
|
|||
|
|
igf1: '', // IGF-1值
|
|||
|
|
igfbp3: '', // IGFBP-3值
|
|||
|
|
// 计算结果
|
|||
|
|
showResult: false,
|
|||
|
|
probability: null,
|
|||
|
|
calculationDetails: null,
|
|||
|
|
// 参考范围
|
|||
|
|
referenceRanges: {
|
|||
|
|
igf1: {
|
|||
|
|
male: [
|
|||
|
|
{ ageRange: '0-1', min: 55, max: 327 },
|
|||
|
|
{ ageRange: '1-3', min: 51, max: 303 },
|
|||
|
|
{ ageRange: '3-5', min: 49, max: 289 },
|
|||
|
|
{ ageRange: '5-7', min: 52, max: 297 },
|
|||
|
|
{ ageRange: '7-9', min: 57, max: 316 },
|
|||
|
|
{ ageRange: '9-11', min: 88, max: 474 },
|
|||
|
|
{ ageRange: '11-13', min: 110, max: 565 },
|
|||
|
|
{ ageRange: '13-15', min: 202, max: 957 },
|
|||
|
|
{ ageRange: '15-17', min: 193, max: 731 }
|
|||
|
|
],
|
|||
|
|
female: [
|
|||
|
|
{ ageRange: '0-1', min: 55, max: 327 },
|
|||
|
|
{ ageRange: '1-3', min: 51, max: 303 },
|
|||
|
|
{ ageRange: '3-5', min: 49, max: 289 },
|
|||
|
|
{ ageRange: '5-7', min: 52, max: 297 },
|
|||
|
|
{ ageRange: '7-9', min: 57, max: 316 },
|
|||
|
|
{ ageRange: '9-11', min: 88, max: 474 },
|
|||
|
|
{ ageRange: '11-13', min: 183, max: 850 },
|
|||
|
|
{ ageRange: '13-15', min: 261, max: 1096 },
|
|||
|
|
{ ageRange: '15-17', min: 238, max: 996 }
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
igfbp3: {
|
|||
|
|
male: [
|
|||
|
|
{ ageRange: '0-1', min: 0.7, max: 3.6 },
|
|||
|
|
{ ageRange: '1-3', min: 0.8, max: 3.9 },
|
|||
|
|
{ ageRange: '3-5', min: 0.9, max: 4.3 },
|
|||
|
|
{ ageRange: '5-7', min: 1.0, max: 4.7 },
|
|||
|
|
{ ageRange: '7-9', min: 1.1, max: 5.2 },
|
|||
|
|
{ ageRange: '9-11', min: 1.3, max: 5.6 },
|
|||
|
|
{ ageRange: '11-13', min: 1.4, max: 6.1 },
|
|||
|
|
{ ageRange: '13-15', min: 1.6, max: 6.8 },
|
|||
|
|
{ ageRange: '15-17', min: 1.8, max: 7.1 }
|
|||
|
|
],
|
|||
|
|
female: [
|
|||
|
|
{ ageRange: '0-1', min: 0.7, max: 3.6 },
|
|||
|
|
{ ageRange: '1-3', min: 0.8, max: 3.9 },
|
|||
|
|
{ ageRange: '3-5', min: 0.9, max: 4.3 },
|
|||
|
|
{ ageRange: '5-7', min: 1.0, max: 4.7 },
|
|||
|
|
{ ageRange: '7-9', min: 1.1, max: 5.2 },
|
|||
|
|
{ ageRange: '9-11', min: 1.3, max: 5.6 },
|
|||
|
|
{ ageRange: '11-13', min: 1.5, max: 6.3 },
|
|||
|
|
{ ageRange: '13-15', min: 1.7, max: 7.3 },
|
|||
|
|
{ ageRange: '15-17', min: 1.9, max: 7.9 }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 输入处理
|
|||
|
|
inputBA(e) {
|
|||
|
|
// 只允许输入数字和小数点
|
|||
|
|
const value = e.detail.value.replace(/[^\d.]/g, '');
|
|||
|
|
// 确保只有一个小数点
|
|||
|
|
const formattedValue = value.replace(/\.+/g, '.');
|
|||
|
|
this.setData({ ba: formattedValue });
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
inputCA(e) {
|
|||
|
|
const value = e.detail.value.replace(/[^\d.]/g, '');
|
|||
|
|
const formattedValue = value.replace(/\.+/g, '.');
|
|||
|
|
this.setData({ ca: formattedValue });
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
inputIGF1(e) {
|
|||
|
|
const value = e.detail.value.replace(/[^\d.]/g, '');
|
|||
|
|
const formattedValue = value.replace(/\.+/g, '.');
|
|||
|
|
this.setData({ igf1: formattedValue });
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
inputIGFBP3(e) {
|
|||
|
|
const value = e.detail.value.replace(/[^\d.]/g, '');
|
|||
|
|
const formattedValue = value.replace(/\.+/g, '.');
|
|||
|
|
this.setData({ igfbp3: formattedValue });
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 计算GHD概率
|
|||
|
|
calculate() {
|
|||
|
|
const { ba, ca, igf1, igfbp3 } = this.data;
|
|||
|
|
|
|||
|
|
// 输入验证
|
|||
|
|
if (!this.validateInput()) return;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 将字符串转换为数字
|
|||
|
|
const baNum = parseFloat(ba);
|
|||
|
|
const caNum = parseFloat(ca);
|
|||
|
|
const igf1Num = parseFloat(igf1);
|
|||
|
|
const igfbp3Num = parseFloat(igfbp3);
|
|||
|
|
|
|||
|
|
// 计算 BA-CA
|
|||
|
|
const baCaDiff = baNum - caNum;
|
|||
|
|
|
|||
|
|
// 计算 Y = LN(P/1-P)
|
|||
|
|
const y = this.calculateY(baCaDiff, igf1Num, igfbp3Num);
|
|||
|
|
|
|||
|
|
// 计算概率 P
|
|||
|
|
const p = this.calculateProbability(y);
|
|||
|
|
|
|||
|
|
// 计算各因素的贡献
|
|||
|
|
const contributions = this.calculateContributions(baCaDiff, igf1Num, igfbp3Num);
|
|||
|
|
|
|||
|
|
// 显示结果
|
|||
|
|
this.setData({
|
|||
|
|
showResult: true,
|
|||
|
|
probability: p,
|
|||
|
|
calculationDetails: {
|
|||
|
|
steps: [
|
|||
|
|
`步骤1:设置方程右边为 Y`,
|
|||
|
|
`Y = 3.726 - 0.876×(BA-CA) - 0.058×(IGF-1) + 0.229×(IGFBP-3)`,
|
|||
|
|
`Y = 3.726 - 0.876×(${baNum.toFixed(2)} - ${caNum.toFixed(2)}) - 0.058×${igf1Num.toFixed(2)} + 0.229×${igfbp3Num.toFixed(2)}`,
|
|||
|
|
`Y = 3.726 - 0.876×(${baCaDiff.toFixed(2)}) - 0.058×${igf1Num.toFixed(2)} + 0.229×${igfbp3Num.toFixed(2)}`,
|
|||
|
|
`Y = 3.726 - ${(0.876 * baCaDiff).toFixed(4)} - ${(0.058 * igf1Num).toFixed(4)} + ${(0.229 * igfbp3Num).toFixed(4)}`,
|
|||
|
|
`Y = ${y.toFixed(4)}`,
|
|||
|
|
``,
|
|||
|
|
`步骤2:解指数方程`,
|
|||
|
|
`P/(1-P) = e^Y`,
|
|||
|
|
`P/(1-P) = e^${y.toFixed(4)}`,
|
|||
|
|
`P/(1-P) = ${Math.exp(y).toFixed(4)}`,
|
|||
|
|
``,
|
|||
|
|
`步骤3:求概率 P`,
|
|||
|
|
`P = e^Y / (1 + e^Y)`,
|
|||
|
|
`P = ${p.toFixed(4)}`,
|
|||
|
|
``,
|
|||
|
|
`GHD预测概率:${(p * 100).toFixed(2)}%`
|
|||
|
|
].join('\n'),
|
|||
|
|
interpretation: this.getInterpretation(p)
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: error.message || '计算失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 输入验证
|
|||
|
|
validateInput() {
|
|||
|
|
const { ba, ca, igf1, igfbp3 } = this.data;
|
|||
|
|
|
|||
|
|
if (!ba || !ca || !igf1 || !igfbp3) {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '请填写完整信息',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证输入是否为有效数字
|
|||
|
|
const baNum = parseFloat(ba);
|
|||
|
|
const caNum = parseFloat(ca);
|
|||
|
|
const igf1Num = parseFloat(igf1);
|
|||
|
|
const igfbp3Num = parseFloat(igfbp3);
|
|||
|
|
|
|||
|
|
if (isNaN(baNum) || isNaN(caNum) || isNaN(igf1Num) || isNaN(igfbp3Num)) {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '请输入有效数字',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证数值范围
|
|||
|
|
if (baNum <= 0 || caNum <= 0) {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '年龄必须大于0',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 计算Y值
|
|||
|
|
calculateY(baCaDiff, igf1, igfbp3) {
|
|||
|
|
return 3.726 - 0.876 * baCaDiff - 0.058 * igf1 + 0.229 * igfbp3;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 计算概率
|
|||
|
|
calculateProbability(y) {
|
|||
|
|
const expY = Math.exp(y);
|
|||
|
|
return expY / (1 + expY);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 计算各因素的贡献
|
|||
|
|
calculateContributions(baCaDiff, igf1, igfbp3) {
|
|||
|
|
// Implementation of calculateContributions method
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取解释文本
|
|||
|
|
getInterpretation(p) {
|
|||
|
|
const percentage = (p * 100).toFixed(2);
|
|||
|
|
let interpretation = `预测结果显示该患者患有GHD的概率为${percentage}%\n\n`;
|
|||
|
|
|
|||
|
|
if (p >= 0.8) {
|
|||
|
|
interpretation += '预测结果提示GHD可能性较大,建议进一步进行相关检查。';
|
|||
|
|
} else if (p >= 0.5) {
|
|||
|
|
interpretation += '预测结果提示存在GHD可能,建议进行相关检查。';
|
|||
|
|
} else {
|
|||
|
|
interpretation += '预测结果提示GHD可能性较小,但仍需结合临床表现进行综合判断。';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return interpretation;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 重置表单
|
|||
|
|
reset() {
|
|||
|
|
this.setData({
|
|||
|
|
ba: '',
|
|||
|
|
ca: '',
|
|||
|
|
igf1: '',
|
|||
|
|
igfbp3: '',
|
|||
|
|
showResult: false,
|
|||
|
|
probability: null,
|
|||
|
|
calculationDetails: null
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 返回上一页
|
|||
|
|
onClickLeft() {
|
|||
|
|
wx.navigateBack();
|
|||
|
|
}
|
|||
|
|
});
|