import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import type { RedeemPhoneDirectPrepareResult } from '@dukang/shared-types'; import { request } from '../lib/api'; function formatAmount(n: number) { return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } export default function PhoneRedeemPage() { const navigate = useNavigate(); const [phone, setPhone] = useState(''); const [amount, setAmount] = useState(''); const [confirmCode, setConfirmCode] = useState(''); const [prepared, setPrepared] = useState(null); const [storeName, setStoreName] = useState(''); const [storeClosed, setStoreClosed] = useState(false); const [msg, setMsg] = useState(''); const [loading, setLoading] = useState(false); const [confirmCooldown, setConfirmCooldown] = useState(0); useEffect(() => { request>('SHOP_H5', '/shop/store') .then((s) => { setStoreName(String(s.name || '当前门店')); if (s.status && s.status !== 'OPEN') setStoreClosed(true); }) .catch(() => setStoreName('当前门店')); }, []); useEffect(() => { if (confirmCooldown <= 0) return; const timer = window.setTimeout(() => setConfirmCooldown((v) => v - 1), 1000); return () => window.clearTimeout(timer); }, [confirmCooldown]); async function sendConfirmSms() { if (!/^1\d{10}$/.test(phone.trim())) { setMsg('请输入正确的手机号'); return; } if (storeClosed) { setMsg('门店未营业,无法核销'); return; } const value = Number(amount); if (!Number.isFinite(value) || value <= 0) { setMsg('请输入有效核销金额'); return; } setLoading(true); setMsg(''); try { const result = await request('SHOP_H5', '/shop/redeem/phone/prepare-direct', { method: 'POST', body: JSON.stringify({ phone: phone.trim(), amount: value }), }); setPrepared(result); setConfirmCode(''); setConfirmCooldown(60); setMsg(`验证码已发送至 ${result.maskedPhone},验证成功后将直接核销`); } catch (e) { setPrepared(null); setMsg(e instanceof Error ? e.message : '发送验证码失败'); } finally { setLoading(false); } } async function confirmRedeem() { if (!prepared) { setMsg('请先发送核销验证码'); return; } if (!confirmCode.trim()) { setMsg('请输入确认验证码'); return; } setLoading(true); setMsg(''); try { const result = await request>('SHOP_H5', '/shop/redeem/phone/confirm', { method: 'POST', body: JSON.stringify({ sessionId: prepared.sessionId, code: confirmCode.trim(), }), }); sessionStorage.setItem('lastRedeemResult', JSON.stringify(result)); navigate('/redeem/success', { state: { result, storeName, user: prepared.user }, }); } catch (e) { setMsg(e instanceof Error ? e.message : '核销失败'); } finally { setLoading(false); } } const amountValue = Number(amount); const canSendCode = /^1\d{10}$/.test(phone.trim()) && Number.isFinite(amountValue) && amountValue > 0; return (

手机号核销

{storeClosed && (

门店当前未营业,无法核销

)}
smartphone

当前登录核销门店

{storeName}

{ setPhone(e.target.value.replace(/\D/g, '')); setPrepared(null); setConfirmCode(''); setConfirmCooldown(0); }} />
{ setAmount(e.target.value); setPrepared(null); setConfirmCode(''); setConfirmCooldown(0); }} />
setConfirmCode(e.target.value.replace(/\D/g, ''))} />

验证码将发送到用户手机号,验证成功后直接完成核销。

{msg &&

{msg}

}
); }