优化身份证读取逻辑,增加倒计时功能并改进错误处理
This commit is contained in:
@@ -13,40 +13,18 @@ const U1: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [reading, setReading] = useState(false);
|
||||
const [countdown, setCountdown] = useState(6);
|
||||
const timerRef = useRef<number | null>(null);
|
||||
const intervalRef = useRef<number | null>(null);
|
||||
|
||||
const handleStart = () => {
|
||||
// localStorage.setItem("lastIdCardNo", "31010919571209004X");
|
||||
// navigate("/u2");
|
||||
if (reading) return; // 避免重复点击
|
||||
setReading(true);
|
||||
// 启动后端监听;如果启动失败立即恢复 UI 状态
|
||||
// 实时监听身份证读取
|
||||
useEffect(() => {
|
||||
// 启动后端监听
|
||||
window.electronAPI.startIdCardListen().catch((e: any) => {
|
||||
console.error("start_idcard_listen failed", e);
|
||||
window.electronAPI.log("error", `start_idcard_listen failed: ${e}`);
|
||||
setReading(false);
|
||||
});
|
||||
|
||||
// 6 秒超时恢复
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
timerRef.current = window.setTimeout(() => {
|
||||
console.warn("未在 6 秒内读取到身份证信息,恢复初始状态");
|
||||
window.electronAPI.log(
|
||||
"warn",
|
||||
"未在 6 秒内读取到身份证信息,恢复初始状态"
|
||||
);
|
||||
setReading(false);
|
||||
window.electronAPI.stopIdCardListen().catch(() => {});
|
||||
timerRef.current = null;
|
||||
}, 6000);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!reading) return;
|
||||
|
||||
// 监听数据
|
||||
window.electronAPI.onIdCardData((e: any) => {
|
||||
const payload = e.payload;
|
||||
@@ -64,11 +42,18 @@ const U1: React.FC = () => {
|
||||
"info",
|
||||
`Read IDCard success: ${payload.name} ${payload.id_card_no}`
|
||||
);
|
||||
// 成功:清理定时器,停止监听
|
||||
|
||||
// 无论是否点击了开始签到,只要读到卡就跳转
|
||||
// 清理定时器
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
// 停止监听(跳转后不再需要监听)
|
||||
window.electronAPI.stopIdCardListen().catch(() => {});
|
||||
setReading(false);
|
||||
navigate("/u2");
|
||||
@@ -78,20 +63,54 @@ const U1: React.FC = () => {
|
||||
window.electronAPI.onIdCardError((e: any) => {
|
||||
console.error("[idcard-error]", e.payload);
|
||||
window.electronAPI.log("error", `[idcard-error] ${e.payload}`);
|
||||
// 发生错误时立即恢复 UI 状态
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
// 错误不停止监听,继续等待下一次读取,除非是严重错误?
|
||||
// 这里仅记录日志,或者在 reading 状态下提示用户
|
||||
if (reading) {
|
||||
// 如果正在倒计时中出错,可以选择停止倒计时或者忽略
|
||||
// 目前保持监听
|
||||
}
|
||||
setReading(false);
|
||||
window.electronAPI.stopIdCardListen().catch(() => {});
|
||||
alert(`读取身份证失败: ${e.payload}`);
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.electronAPI.stopIdCardListen().catch(() => {});
|
||||
window.electronAPI.removeIdCardListeners();
|
||||
if (timerRef.current) clearTimeout(timerRef.current);
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
};
|
||||
}, [reading, navigate]);
|
||||
}, [navigate, reading]);
|
||||
|
||||
const handleStart = () => {
|
||||
if (reading) return; // 避免重复点击
|
||||
setReading(true);
|
||||
setCountdown(6);
|
||||
|
||||
// 6 秒倒计时逻辑
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
intervalRef.current = window.setInterval(() => {
|
||||
setCountdown((prev) => {
|
||||
if (prev <= 1) {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
return 0;
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
// 6 秒超时恢复
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
timerRef.current = window.setTimeout(() => {
|
||||
console.warn("未在 6 秒内读取到身份证信息,恢复初始状态");
|
||||
setReading(false);
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
timerRef.current = null;
|
||||
}, 6000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="u1-root">
|
||||
@@ -105,7 +124,9 @@ const U1: React.FC = () => {
|
||||
<span className="u1-instruction">请放置身份证在读卡区域</span>
|
||||
<img className="u1-semicircle" alt="start button" src={semicircle} />
|
||||
{!reading && <LongButton text="开始签到" onClick={handleStart} />}
|
||||
{reading && <LongButtonLoading text="身份信息读取中..." />}
|
||||
{reading && (
|
||||
<LongButtonLoading text={`身份信息读取中... ${countdown}s`} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user