refactor(miniprogram): 体征阈值改用动态 API — 替代硬编码参考范围
- health.ts 新增 getHealthThresholds/findThreshold/DEFAULT_THRESHOLDS - 24h storage 缓存 + 降级到内置默认值 - health/index.tsx: REF_RANGES → buildRefRange(thresholds) - pkg-health/input: WARN_THRESHOLDS → getWarnForIndicator(thresholds)
This commit is contained in:
@@ -3,7 +3,7 @@ import { View, Text, Input } from '@tarojs/components';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import { useHealthStore } from '../../stores/health';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { inputVitalSign, getTrend } from '../../services/health';
|
||||
import { inputVitalSign, getTrend, getHealthThresholds, findThreshold, DEFAULT_THRESHOLDS, type HealthThreshold } from '../../services/health';
|
||||
import { listPendingSuggestions, type AiSuggestionItem } from '../../services/ai-analysis';
|
||||
import Loading from '../../components/Loading';
|
||||
import './index.scss';
|
||||
@@ -17,12 +17,21 @@ const VITAL_TABS: { key: VitalType; label: string }[] = [
|
||||
{ key: 'weight', label: '体重' },
|
||||
];
|
||||
|
||||
const REF_RANGES: Record<VitalType, { range: string; warn: string }> = {
|
||||
blood_pressure: { range: '收缩压 90-140 / 舒张压 60-90 mmHg', warn: '血压偏高,确认提交?' },
|
||||
heart_rate: { range: '60-100 bpm', warn: '心率异常,确认提交?' },
|
||||
blood_sugar: { range: '空腹 3.9-6.1 / 餐后 <7.8 mmol/L', warn: '血糖偏高,确认提交?' },
|
||||
weight: { range: '根据 BMI 18.5-24 计算', warn: '' },
|
||||
};
|
||||
/** 根据阈值列表构建参考范围文案 */
|
||||
function buildRefRange(t: HealthThreshold[]): Record<VitalType, string> {
|
||||
const bpSys = findThreshold(t, 'systolic_bp', 'high')?.threshold_value ?? 140;
|
||||
const bpDia = findThreshold(t, 'diastolic_bp', 'high')?.threshold_value ?? 90;
|
||||
const hrHigh = findThreshold(t, 'heart_rate', 'high')?.threshold_value ?? 100;
|
||||
const hrLow = findThreshold(t, 'heart_rate', 'low')?.threshold_value ?? 60;
|
||||
const bsFasting = findThreshold(t, 'blood_sugar_fasting', 'high')?.threshold_value ?? 6.1;
|
||||
const bsPp = findThreshold(t, 'blood_sugar_postprandial', 'high')?.threshold_value ?? 7.8;
|
||||
return {
|
||||
blood_pressure: `收缩压 90-${bpSys} / 舒张压 60-${bpDia} mmHg`,
|
||||
heart_rate: `${hrLow}-${hrHigh} bpm`,
|
||||
blood_sugar: `空腹 3.9-${bsFasting} / 餐后 <${bsPp} mmol/L`,
|
||||
weight: '根据 BMI 18.5-24 计算',
|
||||
};
|
||||
}
|
||||
|
||||
interface TrendPoint {
|
||||
date: string;
|
||||
@@ -43,11 +52,13 @@ export default function Health() {
|
||||
const [trendData, setTrendData] = useState<TrendPoint[]>([]);
|
||||
const [trendLoading, setTrendLoading] = useState(false);
|
||||
const [aiSuggestions, setAiSuggestions] = useState<AiSuggestionItem[]>([]);
|
||||
const [thresholds, setThresholds] = useState<HealthThreshold[]>(DEFAULT_THRESHOLDS);
|
||||
|
||||
useDidShow(() => {
|
||||
refreshToday();
|
||||
loadTrend(activeTab);
|
||||
loadAiSuggestions();
|
||||
getHealthThresholds().then((t) => { if (t.length > 0) setThresholds(t); });
|
||||
});
|
||||
|
||||
const loadAiSuggestions = async () => {
|
||||
@@ -86,18 +97,29 @@ export default function Health() {
|
||||
if (type === 'blood_pressure') {
|
||||
const sys = parseFloat(systolic);
|
||||
const dia = parseFloat(diastolic);
|
||||
if (sys > 140 || dia > 90) return REF_RANGES.blood_pressure.warn;
|
||||
const sysMax = findThreshold(thresholds, 'systolic_bp', 'high')?.threshold_value ?? 140;
|
||||
const diaMax = findThreshold(thresholds, 'diastolic_bp', 'high')?.threshold_value ?? 90;
|
||||
if (sys > sysMax || dia > diaMax) return '血压偏高,确认提交?';
|
||||
} else if (type === 'heart_rate') {
|
||||
const val = parseFloat(heartRateVal);
|
||||
if (val > 100 || val < 60) return REF_RANGES.heart_rate.warn;
|
||||
const hrHigh = findThreshold(thresholds, 'heart_rate', 'high')?.threshold_value ?? 100;
|
||||
const hrLow = findThreshold(thresholds, 'heart_rate', 'low')?.threshold_value ?? 60;
|
||||
if (val > hrHigh || val < hrLow) return '心率异常,确认提交?';
|
||||
} else if (type === 'blood_sugar') {
|
||||
const val = parseFloat(sugarVal);
|
||||
if (sugarPeriod === 'fasting' && val > 6.1) return REF_RANGES.blood_sugar.warn;
|
||||
if (sugarPeriod === 'postprandial' && val > 7.8) return REF_RANGES.blood_sugar.warn;
|
||||
if (sugarPeriod === 'fasting') {
|
||||
const bsMax = findThreshold(thresholds, 'blood_sugar_fasting', 'high')?.threshold_value ?? 6.1;
|
||||
if (val > bsMax) return '血糖偏高,确认提交?';
|
||||
} else {
|
||||
const bsMax = findThreshold(thresholds, 'blood_sugar_postprandial', 'high')?.threshold_value ?? 7.8;
|
||||
if (val > bsMax) return '血糖偏高,确认提交?';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const refRanges = buildRefRange(thresholds);
|
||||
|
||||
const handleSave = async () => {
|
||||
const patientId = currentPatient?.id;
|
||||
if (!patientId) {
|
||||
@@ -245,7 +267,7 @@ export default function Health() {
|
||||
value={diastolic}
|
||||
onInput={(e) => setDiastolic(e.detail.value)}
|
||||
/>
|
||||
<Text className='input-ref'>{REF_RANGES.blood_pressure.range}</Text>
|
||||
<Text className='input-ref'>{refRanges.blood_pressure}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -259,7 +281,7 @@ export default function Health() {
|
||||
value={heartRateVal}
|
||||
onInput={(e) => setHeartRateVal(e.detail.value)}
|
||||
/>
|
||||
<Text className='input-ref'>{REF_RANGES.heart_rate.range}</Text>
|
||||
<Text className='input-ref'>{refRanges.heart_rate}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -287,7 +309,7 @@ export default function Health() {
|
||||
<Text className='period-btn-text'>餐后 2h</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text className='input-ref'>{REF_RANGES.blood_sugar.range}</Text>
|
||||
<Text className='input-ref'>{refRanges.blood_sugar}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -301,7 +323,7 @@ export default function Health() {
|
||||
value={weightVal}
|
||||
onInput={(e) => setWeightVal(e.detail.value)}
|
||||
/>
|
||||
<Text className='input-ref'>{REF_RANGES.weight.range}</Text>
|
||||
<Text className='input-ref'>{refRanges.weight}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user