import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import QRCode from 'qrcode'; import PageHeader from '@dukang/shared-ui/PageHeader'; import { invokeWechatPay } from '@dukang/weixin-sdk'; import type { PartnerProxyOrderListItem, ProxyOrderPayResponse, ProxyPayMethod } from '@dukang/shared-types'; import { getToken, request } from '../lib/api'; import { proxyOrderPayLabel, proxyOrderStatusColor, proxyOrderStatusLabel, } from '../lib/proxyOrderStatus'; import { toastError, toastSuccess } from '../lib/toast'; import { isWechatEnv } from '../lib/weixin'; import { fetchPartnerProfile, partnerHasWechatBinding } from '../lib/wechat-auth'; function fmtMoney(n: number) { return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } function fmtTime(value: string | undefined) { if (!value) return '—'; const d = new Date(value); if (Number.isNaN(d.getTime())) return value; const pad = (n: number) => String(n).padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`; } function deliveryLabel(order: PartnerProxyOrderListItem) { const t = String(order.deliveryType || '').toUpperCase(); if (t === 'ON_SITE_PICKUP') return '现场提货'; if (t === 'CROSS_CITY') return '跨城配送'; if (t === 'LOCAL') return '同城配送'; return '代下单'; } type TrackNode = { time?: string; status?: string; description?: string; }; type TrackResult = { nodes?: TrackNode[]; trackingNo?: string | null; provider?: string | null; manualQueryUrl?: string | null; }; export default function ProxyOrderDetailPage() { const { id } = useParams(); const navigate = useNavigate(); const [order, setOrder] = useState(null); const [error, setError] = useState(''); const [track, setTrack] = useState(null); const [trackError, setTrackError] = useState(''); const [paying, setPaying] = useState(false); const [payMsg, setPayMsg] = useState(''); const [payMethod, setPayMethod] = useState('NATIVE'); const [codeUrl, setCodeUrl] = useState(null); const [qrDataUrl, setQrDataUrl] = useState(null); const [cancelling, setCancelling] = useState(false); const pollRef = useRef(null); function stopPoll() { if (pollRef.current != null) { window.clearInterval(pollRef.current); pollRef.current = null; } } useEffect(() => () => stopPoll(), []); useEffect(() => { document.title = '代下单详情'; }, []); useEffect(() => { if (!id) return; void request('PARTNER_H5', `/partner/proxy-orders/${id}`) .then((data) => { setOrder(data); if (data.proxyPayMethod) { setPayMethod(data.proxyPayMethod); } }) .catch((e) => setError(e instanceof Error ? e.message : '加载失败')); }, [id]); useEffect(() => { if (!id || !order) return; const dt = String(order.deliveryType || '').toUpperCase(); if (dt === 'ON_SITE_PICKUP' || order.payStatus !== 'PAID') { setTrack(null); return; } void request('PARTNER_H5', `/partner/proxy-orders/${id}/track`, { silent: true }) .then(setTrack) .catch((e) => setTrackError(e instanceof Error ? e.message : '物流暂不可用')); }, [id, order]); useEffect(() => { if (!codeUrl) { setQrDataUrl(null); return; } void QRCode.toDataURL(codeUrl, { width: 220, margin: 1 }) .then(setQrDataUrl) .catch(() => setQrDataUrl(null)); }, [codeUrl]); const unpaid = order?.payStatus === 'UNPAID' || order?.status === 'PENDING_PAY'; function startPoll(orderId: string) { stopPoll(); pollRef.current = window.setInterval(() => { void request<{ payStatus: string; orderNo: string }>( 'PARTNER_H5', `/partner/proxy-orders/${orderId}/pay-status`, { silent: true }, ) .then((st) => { if (st.payStatus === 'PAID') { stopPoll(); toastSuccess(`支付成功:${st.orderNo}`); void request('PARTNER_H5', `/partner/proxy-orders/${orderId}`) .then(setOrder) .catch(() => undefined); setCodeUrl(null); } }) .catch(() => undefined); }, 2000); } async function startPay(method: ProxyPayMethod) { if (!id) return; const locked = order?.proxyPayMethod; if (locked && locked !== method) { setPayMsg( locked === 'JSAPI' ? '该订单已发起微信代付,请先取消支付后重新下单' : '该订单已生成收款码,请先取消支付后重新下单', ); return; } setPaying(true); setPayMsg(''); setPayMethod(method); try { if (method === 'JSAPI') { if (!isWechatEnv()) { throw new Error('请在微信内打开合伙人端以使用微信代付'); } const profile = await fetchPartnerProfile(); if (!partnerHasWechatBinding(profile)) { throw new Error('请先绑定微信后再代付'); } } const pay = await request( 'PARTNER_H5', `/partner/proxy-orders/${id}/pay`, { method: 'POST', body: JSON.stringify({ payMethod: method }), silent: true, }, ); if (pay.mode === 'mock') { toastSuccess('支付成功'); const refreshed = await request( 'PARTNER_H5', `/partner/proxy-orders/${id}`, ); setOrder(refreshed); setCodeUrl(null); return; } if (pay.mode === 'native' && pay.codeUrl) { setCodeUrl(pay.codeUrl); setOrder((prev) => (prev ? { ...prev, proxyPayMethod: method } : prev)); startPoll(id); return; } if (pay.mode === 'jsapi' && pay.prepay) { setCodeUrl(null); setOrder((prev) => (prev ? { ...prev, proxyPayMethod: method } : prev)); await invokeWechatPay(pay.prepay, { apiBase: '/api/v1', clientApp: 'PARTNER_H5', getAccessToken: getToken, platform: 'wechat-h5', }); startPoll(id); return; } throw new Error('支付发起失败'); } catch (e) { setPayMsg(e instanceof Error ? e.message : '支付失败'); toastError(e instanceof Error ? e.message : '支付失败'); } finally { setPaying(false); } } async function cancelPay() { if (!id) return; setCancelling(true); setPayMsg(''); stopPoll(); try { await request('PARTNER_H5', `/partner/proxy-orders/${id}/cancel-pay`, { method: 'POST', body: '{}', }); toastSuccess('已取消支付,可重新下单并选择其他支付方式'); navigate('/center/proxy-orders'); } catch (e) { setPayMsg(e instanceof Error ? e.message : '取消失败'); toastError(e instanceof Error ? e.message : '取消失败'); } finally { setCancelling(false); } } const lockedPayMethod = order?.proxyPayMethod ?? null; const img = order?.imageResource?.url || ''; const isOnSite = String(order?.deliveryType || '').toUpperCase() === 'ON_SITE_PICKUP'; return (
navigate('/center/proxy-orders')} /> {error && (

{error}

)} {!order && !error &&

加载中…

} {order && (
NO. {order.orderNo} {proxyOrderStatusLabel(order.status)}
{!img && liquor}

{order.productName || '杜康好酒'}

{order.productSpec && (

{order.productSpec}

)}

×{order.quantity} · ¥{fmtMoney(Number(order.payAmount || 0))}

权益 ¥{fmtMoney(Number(order.benefitAmount || 0))}

客户信息

姓名:{order.receiverName || '—'}

手机:{order.receiverPhone || '—'}

地址:{order.receiverAddress || (isOnSite ? '现场提货' : '—')}

订单信息

配送方式:{deliveryLabel(order)}

下单时间:{fmtTime(order.createdAt)}

支付状态:{proxyOrderPayLabel(order.payStatus)}

订单状态:{proxyOrderStatusLabel(order.status)}

{unpaid ? (

继续支付

{lockedPayMethod ? (

已选择{lockedPayMethod === 'NATIVE' ? '收款码' : '微信代付'},切换方式请先取消支付

) : (

请选择支付方式并点击下方按钮发起支付

)} {payMethod === 'NATIVE' ? (
{qrDataUrl ? ( 收款码 ) : (

{paying ? '生成收款码中…' : '暂无收款码'}

)}

请使用微信扫码支付,支付成功后自动更新

) : (

将调起微信支付,由合伙人微信完成代付

)} {payMsg ? (

{payMsg}

) : null}
) : null} {!isOnSite && order.payStatus === 'PAID' ? (

物流信息

{trackError ? (

{trackError}

) : !track ? (

加载物流…

) : ( <> {track.trackingNo ? (

运单号:{track.trackingNo} {track.provider ? `(${track.provider})` : ''}

) : null} {track.manualQueryUrl ? (

查看物流官网

) : null} {(track.nodes ?? []).length === 0 ? (

暂无物流轨迹(待总部发货后更新)

) : (
    {(track.nodes ?? []).map((n, i) => (
  • {fmtTime(n.time)}
    {n.description || n.status || '—'}
  • ))}
)} )}
) : null}
)}
); }