217 lines
7.0 KiB
TypeScript
217 lines
7.0 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
||
import "./u2.css";
|
||
import { useNavigate } from "react-router-dom";
|
||
import DecorLine from "../../components/DecorLine";
|
||
import avatar from "../../assets/avatar.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 (!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");
|
||
});
|
||
}
|
||
};
|
||
|
||
// 根据性别和姓名生成问候称呼:取姓名第一个字 + (先生|女士|先生/女士)
|
||
const getGreeting = () => {
|
||
// 在加载中或没有姓名时不返回欢迎语,避免先渲染空的问候
|
||
if (loading || !patientInfo?.name) return "";
|
||
const name = patientInfo.name.trim();
|
||
const firstChar = name ? name.charAt(0) : "";
|
||
const genderName = (patientInfo?.gender_name || "").trim();
|
||
const sex = (patientInfo as any)?.sex;
|
||
let title = "";
|
||
if (genderName === "男" || sex === "1" || sex === 1) title = "先生";
|
||
else if (genderName === "女" || sex === "2" || sex === 2) title = "女士";
|
||
return `尊敬的${
|
||
firstChar ? `${firstChar} ${title}` : title
|
||
},欢迎您的到来:`;
|
||
};
|
||
|
||
// 返回头像地址:优先使用读到的本地照片路径(file:///),否则使用默认 avatar
|
||
const getAvatarSrc = () => {
|
||
const photoPath = (patientInfo as any)?.photo_path || "";
|
||
if (!photoPath) return avatar;
|
||
// 如果已经是 file:// 协议,直接返回
|
||
if (photoPath.startsWith("file://")) return photoPath;
|
||
// 将 Windows 路径转换为 file:/// 格式(把反斜杠改为斜杠)
|
||
const normalized = photoPath.replace(/\\/g, "/").replace(/\\/g, "/");
|
||
return `file:///${normalized}`;
|
||
};
|
||
|
||
// 在数据加载时显示占位,加载完成后再渲染完整内容
|
||
if (loading) {
|
||
return <></>;
|
||
}
|
||
|
||
return (
|
||
<div className="u2-root">
|
||
<span className="u2-title">{getGreeting()}</span>
|
||
<DecorLine />
|
||
<div className="u2-info-card">
|
||
<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 ? "" : patientInfo?.gender_name || "---"}
|
||
</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">
|
||
证件号:{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>
|
||
<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;
|