import { useEffect, useMemo, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import PageHeader from '@dukang/shared-ui/PageHeader'; import type { PartnerBillDto } from '@dukang/shared-types'; import { isLoggedIn, request } from '../lib/api'; import { toastError, toastSuccess } from '../lib/toast'; function fmtMoney(n: number) { return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } function billStatusLabel(status: string) { switch (status) { case 'DRAFT': return '待确认'; case 'CONFIRMED': return '审核中'; case 'PAID': return '已结算'; case 'REJECTED': return '已驳回'; default: return status; } } function canApplyPayment(status: string) { return status === 'DRAFT' || status === 'REJECTED'; } export default function BillsPage() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const [bills, setBills] = useState([]); const [confirmed, setConfirmed] = useState(false); const [submitting, setSubmitting] = useState(false); const [loading, setLoading] = useState(true); async function loadBills() { setLoading(true); try { const list = await request('PARTNER_H5', '/partner/settlement/bills'); setBills(Array.isArray(list) ? list : []); } catch { setBills([]); } finally { setLoading(false); } } useEffect(() => { if (!isLoggedIn()) { navigate('/login'); return; } void loadBills(); }, [navigate]); const billId = searchParams.get('id'); const actionable = useMemo( () => bills.filter((b) => canApplyPayment(b.status)), [bills], ); const bill = billId ? bills.find((b) => String(b.id) === billId) ?? actionable[0] ?? bills[0] : actionable[0] ?? bills[0]; const status = String(bill?.status || ''); const showApplyForm = !!bill && canApplyPayment(status); const isReviewing = status === 'CONFIRMED'; const isRejected = status === 'REJECTED'; const isPaid = status === 'PAID'; async function confirmBill() { if (!bill || !confirmed || !canApplyPayment(String(bill.status))) return; setSubmitting(true); try { await request('PARTNER_H5', `/partner/settlement/bills/${bill.id}/confirm`, { method: 'POST', }); toastSuccess('申请已提交,请耐心等待总部打款审核'); setConfirmed(false); await loadBills(); } catch (e) { toastError(e instanceof Error ? e.message : '提交失败'); } finally { setSubmitting(false); } } return (
navigate('/center/settlement')} />
check
数据核算
{showApplyForm && !confirmed ? '2' : ( check )}
账单确认
{isPaid ? ( check ) : '3'}
{isRejected ? '已驳回' : isPaid ? '已打款' : '申请打款'}
{loading &&
加载中…
} {!loading && !bill &&
暂无账单
} {bill && (

SETTLEMENT PERIOD

{String(bill.billNo || '月度结算账单')}

{billStatusLabel(status)}
{isRejected && bill.rejectReason && (
error

打款申请已驳回

{bill.rejectReason}

)} {isReviewing && (
hourglass_top

您已提交打款申请,总部审核中,请耐心等待。

)}

应结总金额

¥ {fmtMoney(Number(bill.totalAmount || 0))}
订单分佣收入 ¥ {fmtMoney(Number(bill.orderCommission || 0))}
核销权益分佣 ¥ {fmtMoney(Number(bill.redeemCommission || 0))}
)} {bills.length > 1 && (

全部账单

{bills.map((b) => ( ))}
)} {showApplyForm && ( <>
info

{isRejected ? '请根据驳回理由核对后重新确认并申请打款。' : '账单确认后将正式进入打款审核。如有异议,请在确认前联系城市运营经理核实数据。'}

)}
); }