fix(health+web): PII 解密日志 + 负年龄防护 + 随访页面中文 placeholder
- helper.rs: 提取 decrypt_field 辅助函数,解密失败时输出 warn 日志而非静默返回 None - format.ts: calcAge 负年龄(未来出生日期)返回 '--' 而非 '-72岁' - FollowUpTaskList.tsx: DatePicker.RangePicker 添加中文 placeholder Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -56,34 +56,20 @@ pub(crate) fn model_to_resp(m: patient::Model) -> PatientResp {
|
||||
/// 详情用 — 解密 Tier 1 字段
|
||||
pub(crate) fn model_to_resp_decrypted(crypto: &PiiCrypto, m: patient::Model) -> PatientResp {
|
||||
let kek = crypto.kek();
|
||||
let decrypted_id_number = m
|
||||
.id_number
|
||||
.as_ref()
|
||||
.map(|enc| pii::decrypt(kek, enc))
|
||||
.transpose()
|
||||
.ok()
|
||||
.flatten();
|
||||
let decrypted_allergy = m
|
||||
.allergy_history
|
||||
.as_ref()
|
||||
.map(|enc| pii::decrypt(kek, enc))
|
||||
.transpose()
|
||||
.ok()
|
||||
.flatten();
|
||||
let decrypted_medical = m
|
||||
.medical_history_summary
|
||||
.as_ref()
|
||||
.map(|enc| pii::decrypt(kek, enc))
|
||||
.transpose()
|
||||
.ok()
|
||||
.flatten();
|
||||
let decrypted_phone = m
|
||||
.emergency_contact_phone
|
||||
.as_ref()
|
||||
.map(|enc| pii::decrypt(kek, enc))
|
||||
.transpose()
|
||||
.ok()
|
||||
.flatten();
|
||||
let decrypted_id_number = decrypt_field(kek, &m.id_number, "id_number", m.id);
|
||||
let decrypted_allergy = decrypt_field(kek, &m.allergy_history, "allergy_history", m.id);
|
||||
let decrypted_medical = decrypt_field(
|
||||
kek,
|
||||
&m.medical_history_summary,
|
||||
"medical_history_summary",
|
||||
m.id,
|
||||
);
|
||||
let decrypted_phone = decrypt_field(
|
||||
kek,
|
||||
&m.emergency_contact_phone,
|
||||
"emergency_contact_phone",
|
||||
m.id,
|
||||
);
|
||||
PatientResp {
|
||||
id: m.id,
|
||||
user_id: m.user_id,
|
||||
@@ -105,3 +91,22 @@ pub(crate) fn model_to_resp_decrypted(crypto: &PiiCrypto, m: patient::Model) ->
|
||||
version: m.version,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解密单个 PII 字段,失败时输出 warn 日志并返回 None
|
||||
fn decrypt_field(
|
||||
kek: &[u8; 32],
|
||||
field: &Option<String>,
|
||||
name: &str,
|
||||
patient_id: Uuid,
|
||||
) -> Option<String> {
|
||||
field
|
||||
.as_ref()
|
||||
.map(|enc| pii::decrypt(kek, enc))
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
tracing::warn!(patient_id = %patient_id, field = name, error = %e, "PII decrypt failed");
|
||||
e
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user