Files
memind/health-symptoms.mjs
T
john f96fdcb3b9 feat(health): add P0 health channel kernel and encrypted health zone.
Lock health recording behind confirm-only state machines, reject public publishes for the health category, and ship the 14-day experiment Page Data templates with tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 18:04:26 +08:00

50 lines
1.4 KiB
JavaScript

export const HEALTH_SYMPTOM_CODES = Object.freeze([
'none',
'dizziness',
'headache',
'chest_tightness',
'palpitation',
'fatigue',
'shortness_of_breath',
'leg_edema',
'insomnia',
'other',
]);
export const HEALTH_SYMPTOM_LABELS = Object.freeze({
none: '无',
dizziness: '头晕',
headache: '头痛',
chest_tightness: '胸闷',
palpitation: '心慌心悸',
fatigue: '乏力',
shortness_of_breath: '气短',
leg_edema: '下肢水肿',
insomnia: '失眠',
other: '其他',
});
export const HEALTH_SYMPTOM_SEVERITIES = Object.freeze([1, 2, 3]);
export function normalizeSymptomCode(value) {
const raw = String(value ?? '').trim();
if (HEALTH_SYMPTOM_CODES.includes(raw)) return raw;
const byLabel = Object.entries(HEALTH_SYMPTOM_LABELS).find(([, label]) => label === raw);
return byLabel ? byLabel[0] : null;
}
export function assertSymptomRecord({ code, severity, note = '' } = {}) {
const symptom = normalizeSymptomCode(code);
if (!symptom) {
return { ok: false, error: 'unknown_symptom' };
}
if (symptom === 'none') {
return { ok: true, code: 'none', severity: null, note: String(note ?? '').trim() || null };
}
const level = Number(severity);
if (!HEALTH_SYMPTOM_SEVERITIES.includes(level)) {
return { ok: false, error: 'invalid_severity' };
}
return { ok: true, code: symptom, severity: level, note: String(note ?? '').trim() || null };
}