Files
yuanhe-checkin-electron/src/pages/U2/u2.tsx

246 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useEffect, useState } from "react";
import "./u2.css";
import { useNavigate } from "react-router-dom";
import DecorLine from "../../components/DecorLine";
import nan from "../../assets/nan.png";
import nv from "../../assets/nv.png";
import semicircle from "../../assets/semicircle.png";
import BackButton from "../../components/BackButton";
import ConfirmButton from "../../components/ConfirmButton";
import {
getPatientInfo,
getVipStatus,
getOptionalItemList,
PatientInfo,
} from "../../api/hisApi";
const U2: React.FC = () => {
const navigate = useNavigate();
const idCardNo = localStorage.getItem("lastIdCardNo");
const [patientInfo, setPatientInfo] = useState<PatientInfo | null>(null);
const [loading, setLoading] = useState<boolean>(() => !!idCardNo);
const [isVip, setIsVip] = useState<number | null>(null);
const vipCalledRef = React.useRef(false);
useEffect(() => {
if (idCardNo) {
setLoading(true);
getPatientInfo(idCardNo)
.then((res) => {
if (res.Status === 200 && res.Data) {
setPatientInfo(res.Data);
localStorage.setItem("name", res.Data.name);
localStorage.setItem("gender", res.Data.gender_name);
} else {
alert(`${res.Message},请联系前台`);
}
})
.catch((err) => {
console.error(err);
alert(`获取用户信息异常: ${err.message}`);
})
.finally(() => {
setLoading(false);
});
}
}, [idCardNo]);
// 获取 VIP 状态,避免重复请求
useEffect(() => {
if (!idCardNo) return;
if (vipCalledRef.current) return;
vipCalledRef.current = true;
getVipStatus(idCardNo)
.then((res) => {
if (res.Status === 200) {
setIsVip(res.Data?.is_vip ?? 0);
} else {
console.warn("获取 VIP 状态失败:", res.Message);
setIsVip(0);
}
})
.catch((err) => {
console.error("getVipStatus error", err);
setIsVip(0);
});
}, [idCardNo]);
const handleBack = () => {
navigate(-1);
};
const handleConfirm = () => {
// 判断是否为有效签到
if (!patientInfo?.is_valid_exam || patientInfo.is_valid_exam !== 1) {
// alert("当前签到无效,请联系前台工作人员处理");
return;
}
if (!idCardNo) {
alert("未获取到身份证号,请重新刷卡");
navigate("/");
return;
}
// 判断是否为 VIP 客户0 否1 是)
if (isVip === 1) {
navigate("/u3");
return;
} else {
// 调用接口判断是否有可选套餐
getOptionalItemList(idCardNo)
.then((res) => {
if (res.Status === 200) {
localStorage.setItem(
"selectedExamId",
res.Data.packageInfo.physical_exam_id.toString() || ""
);
const isPackageUndecided =
res.Data?.packageInfo?.is_optional_package === 1 &&
res.Data?.packageInfo.registration_time?.length > 0;
if (isPackageUndecided) {
navigate("/u4", { state: { optionalData: res.Data } });
} else {
// 如果没有可选套餐,检查是否有错误消息需要提示
if (!res.Data?.packageInfo && res.Message) {
alert(res.Message);
} else {
navigate("/UI6");
}
}
} else {
if (res.Message) {
alert(res.Message);
} else {
navigate("/UI6");
}
}
})
.catch((err) => {
console.error("getOptionalItemList error", err);
navigate("/UI6");
});
}
};
// 根据 gender_name 和姓名生成问候称呼:取姓名第一个字 + (先生|女士)
const getGreeting = () => {
// 在加载中或没有姓名时不返回欢迎语,避免先渲染空的问候
if (loading || !patientInfo?.name) return "";
const name = patientInfo.name.trim();
const firstChar = name ? name.charAt(0) : "";
const genderName = (patientInfo?.gender_name || "").trim();
let title = "";
if (genderName === "男") title = "先生";
else if (genderName === "女") title = "女士";
return `尊敬的${
firstChar ? `${firstChar}${title}` : title
},请确认您的个人信息:`;
};
// 返回头像地址:使用 gender_name 字段("女" 显示女性头像),忽略 photo_path
const getAvatarSrc = () => {
const genderName = (patientInfo?.gender_name || "").trim();
if (genderName === "女") return nv;
return nan;
};
// 根据 gender_name 返回显示的性别标签(用于界面展示)
const getGenderLabel = () => {
const genderName = (patientInfo?.gender_name || "").trim();
if (!genderName) return "";
return genderName;
};
// 脱敏证件号保留前6后4其余替换为*
const maskIdCard = (id?: string | null) => {
if (!id) return "---";
const s = String(id).trim();
if (s.length <= 10) return s.replace(/.(?!.{4})/g, "*");
const head = s.slice(0, 6);
const tail = s.slice(-4);
const middleLen = s.length - 10;
return head + "*".repeat(middleLen) + tail;
};
// 在数据加载时显示占位,加载完成后再渲染完整内容
if (loading) {
return <></>;
}
return (
<div className="u2-root">
<span className="u2-title">{getGreeting()}</span>
<DecorLine />
<div className="u2-info-card">
<div className="u2-info-top">
<div className="u2-avatar-container">
<img className="u2-avatar" src={getAvatarSrc()} alt="avatar" />
</div>
<div className="u2-details-list">
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : patientInfo?.name || "---"}
</div>
</div>
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : getGenderLabel()}
</div>
</div>
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : patientInfo?.age || "---"}
</div>
</div>
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : maskIdCard(idCardNo || patientInfo?.IdCard)}
</div>
</div>
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : patientInfo?.phone || "---"}
</div>
</div>
<div className="u2-detail-row">
<div className="u2-detail-bar" />
<div className="u2-detail-text">
{loading ? "" : patientInfo?.marital_name || "---"}
</div>
</div>
</div>
</div>
{!patientInfo?.is_valid_exam || patientInfo.is_valid_exam !== 1 ? (
<div className="u2-error-msg">
!
</div>
) : (
""
)}
</div>
<span className="u2-instruction">
<span className="u2-asterisk">*</span>
</span>
<img className="u2-semicircle" alt="start button" src={semicircle} />
<div className="u2-confirm-section">
<BackButton text="返回" onClick={handleBack} />
<ConfirmButton text="确认" onClick={handleConfirm} />
</div>
</div>
);
};
export default U2;