fix(h5-shop): 修复闭店/休息中扫码核销弹窗不触发
CI / verify (push) Has been cancelled

- 根因:门店非OPEN时后端 preview 拦截,preview 为 null 导致确认按钮 disabled,弹窗永远触发不了
- RedeemConfirmPage:storeClosed 时确认按钮可点→弹开张框;开张后重拉预览并继续核销
- 弹窗文案对齐「门店目前休息中无法核销,是否开启营业」

Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
This commit is contained in:
2026-08-17 22:50:22 +08:00
parent cd1e9ae488
commit 3ac008a217
2 changed files with 34 additions and 24 deletions
+3 -3
View File
@@ -139,7 +139,7 @@ export default function PhoneRedeemPage() {
<main className="shop-redeem-main"> <main className="shop-redeem-main">
{storeClosed && ( {storeClosed && (
<p className="shop-redeem-error" style={{ marginBottom: 12 }}></p> <p className="shop-redeem-error" style={{ marginBottom: 12 }}></p>
)} )}
<section className="shop-redeem-card"> <section className="shop-redeem-card">
@@ -234,8 +234,8 @@ export default function PhoneRedeemPage() {
{showOpenModal && ( {showOpenModal && (
<div className="shop-redeem-modal" role="dialog" aria-modal="true"> <div className="shop-redeem-modal" role="dialog" aria-modal="true">
<div className="shop-redeem-modal-card"> <div className="shop-redeem-modal-card">
<h4 className="shop-redeem-modal-title"></h4> <h4 className="shop-redeem-modal-title"></h4>
<p className="shop-redeem-modal-desc"></p> <p className="shop-redeem-modal-desc"></p>
<div className="shop-redeem-modal-actions"> <div className="shop-redeem-modal-actions">
<button <button
type="button" type="button"
+31 -21
View File
@@ -50,27 +50,34 @@ export default function RedeemConfirmPage() {
setToken(scanned); setToken(scanned);
}, [searchParams, navigate]); }, [searchParams, navigate]);
useEffect(() => { async function loadPreview() {
if (!token.trim()) { if (!token.trim()) {
setPreview(null); setPreview(null);
return; return;
} }
request<Preview>('SHOP_H5', '/shop/redeem/preview', { try {
method: 'POST', const p = await request<Preview>('SHOP_H5', '/shop/redeem/preview', {
body: JSON.stringify({ token }), method: 'POST',
}) body: JSON.stringify({ token }),
.then(setPreview)
.catch(async (e) => {
setPreview(null);
setMsg(e instanceof Error ? e.message : '无法预览核销码');
const report = await reportRedeemFailure(token, 'preview', e);
if (report?.thresholdReached) {
setFailCount(report.failCount);
setShowWeakNet(true);
} else if (report) {
setFailCount(report.failCount);
}
}); });
setPreview(p);
setMsg('');
} catch (e) {
setPreview(null);
setMsg(e instanceof Error ? e.message : '无法预览核销码');
const report = await reportRedeemFailure(token, 'preview', e);
if (report?.thresholdReached) {
setFailCount(report.failCount);
setShowWeakNet(true);
} else if (report) {
setFailCount(report.failCount);
}
}
}
useEffect(() => {
void loadPreview();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token]); }, [token]);
async function doConfirm() { async function doConfirm() {
@@ -119,6 +126,9 @@ export default function RedeemConfirmPage() {
}); });
setStoreClosed(false); setStoreClosed(false);
setShowOpenModal(false); setShowOpenModal(false);
setMsg('');
// 开张后重新拉取预览(门店已 OPEN,后端不再拦截),再继续核销
await loadPreview();
await doConfirm(); await doConfirm();
} catch (e) { } catch (e) {
setShowOpenModal(false); setShowOpenModal(false);
@@ -142,7 +152,7 @@ export default function RedeemConfirmPage() {
<main className="shop-redeem-main"> <main className="shop-redeem-main">
{storeClosed && ( {storeClosed && (
<p className="shop-redeem-error" style={{ marginBottom: 12 }}></p> <p className="shop-redeem-error" style={{ marginBottom: 12 }}></p>
)} )}
<section className="shop-redeem-card"> <section className="shop-redeem-card">
<div className="shop-redeem-banner"> <div className="shop-redeem-banner">
@@ -214,13 +224,13 @@ export default function RedeemConfirmPage() {
<button <button
type="button" type="button"
className={`shop-redeem-confirm-btn${loading ? ' success' : ''}`} className={`shop-redeem-confirm-btn${loading ? ' success' : ''}`}
disabled={loading || !preview} disabled={loading || (!preview && !storeClosed)}
onClick={() => void confirm()} onClick={() => void confirm()}
> >
<span className="material-symbols-outlined shop-fill-icon"> <span className="material-symbols-outlined shop-fill-icon">
{loading ? 'sync' : 'check_circle'} {loading ? 'sync' : 'check_circle'}
</span> </span>
<span>{loading ? '正在核销...' : preview ? `确认核销 ¥${formatAmount(previewAmount)}` : '加载中…'}</span> <span>{loading ? '正在核销...' : preview ? `确认核销 ¥${formatAmount(previewAmount)}` : storeClosed ? '确认核销' : '加载中…'}</span>
</button> </button>
<p className="shop-redeem-hint"></p> <p className="shop-redeem-hint"></p>
</> </>
@@ -242,8 +252,8 @@ export default function RedeemConfirmPage() {
{showOpenModal && ( {showOpenModal && (
<div className="shop-redeem-modal" role="dialog" aria-modal="true"> <div className="shop-redeem-modal" role="dialog" aria-modal="true">
<div className="shop-redeem-modal-card"> <div className="shop-redeem-modal-card">
<h4 className="shop-redeem-modal-title"></h4> <h4 className="shop-redeem-modal-title"></h4>
<p className="shop-redeem-modal-desc"></p> <p className="shop-redeem-modal-desc"></p>
<div className="shop-redeem-modal-actions"> <div className="shop-redeem-modal-actions">
<button <button
type="button" type="button"