246 lines
7.9 KiB
TypeScript
246 lines
7.9 KiB
TypeScript
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;
|