feat(settlement): 合伙人账单生成后直接同步并支持打款凭证

去掉总部发送与合伙人确认,财务打款后上传凭证,合伙人即可查看状态。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-26 13:04:03 +08:00
parent cb63d382ad
commit 550697c346
15 changed files with 256 additions and 541 deletions
+8 -21
View File
@@ -6,7 +6,7 @@ import type { PartnerBillDto, PartnerSettlementPreviewDto } from '@dukang/shared
import { isLoggedIn, request } from '../lib/api';
import { formatBillPeriod, formatIssueLabel } from '../lib/settlement';
type StatusFilter = 'all' | 'pending' | 'settled' | 'reviewing' | 'rejected';
type StatusFilter = 'all' | 'unpaid' | 'paid';
function fmtMoney(n: number) {
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
@@ -14,20 +14,16 @@ function fmtMoney(n: number) {
function billStatusLabel(status: string) {
switch (status) {
case 'AWAITING_CONFIRM': return '待确认';
case 'UNPAID': return '未打款';
case 'PAID': return '已打款';
case 'REJECTED': return '已驳回';
default: return status;
}
}
function billStatusClass(status: string) {
switch (status) {
case 'AWAITING_CONFIRM': return 'partner-settlement-status--pending';
case 'UNPAID': return 'partner-settlement-status--reviewing';
case 'PAID': return 'partner-settlement-status--settled';
case 'REJECTED': return 'partner-settlement-status--rejected';
default: return '';
}
}
@@ -57,10 +53,10 @@ export default function SettlementPage() {
}, [navigate, loadBills]);
const summary = useMemo(() => {
const pending = bills.filter((b) => b.status === 'AWAITING_CONFIRM');
const unpaid = bills.filter((b) => b.status === 'UNPAID');
const settled = bills.filter((b) => b.status === 'PAID');
return {
pendingTotal: pending.reduce((s, b) => s + Number(b.totalAmount || 0), 0),
pendingTotal: unpaid.reduce((s, b) => s + Number(b.totalAmount || 0), 0),
settledTotal: settled.reduce((s, b) => s + Number(b.totalAmount || 0), 0),
};
}, [bills]);
@@ -68,10 +64,8 @@ export default function SettlementPage() {
const filteredBills = useMemo(() => {
return bills.filter((b) => {
if (statusFilter === 'all') return true;
if (statusFilter === 'pending') return b.status === 'AWAITING_CONFIRM';
if (statusFilter === 'settled') return b.status === 'PAID';
if (statusFilter === 'reviewing') return b.status === 'UNPAID';
if (statusFilter === 'rejected') return b.status === 'REJECTED';
if (statusFilter === 'unpaid') return b.status === 'UNPAID';
if (statusFilter === 'paid') return b.status === 'PAID';
return true;
});
}, [bills, statusFilter]);
@@ -82,10 +76,8 @@ export default function SettlementPage() {
const statusTabs: Array<{ key: StatusFilter; label: string }> = [
{ key: 'all', label: '全部' },
{ key: 'pending', label: '待确认' },
{ key: 'reviewing', label: '未打款' },
{ key: 'rejected', label: '已驳回' },
{ key: 'settled', label: '已打款' },
{ key: 'unpaid', label: '未打款' },
{ key: 'paid', label: '已打款' },
];
return (
@@ -164,12 +156,7 @@ export default function SettlementPage() {
<span className="partner-settlement-dot" />
订单分佣 ¥{fmtMoney(Number(bill.orderCommission || 0))}
</p>
{bill.status === 'REJECTED' && bill.rejectReason ? (
<p className="label-md text-primary" style={{ marginTop: 6 }}>
驳回:{bill.rejectReason}
</p>
) : null}
<p className={`partner-settlement-item-amount${bill.status === 'AWAITING_CONFIRM' || bill.status === 'REJECTED' ? ' text-primary' : ''}`}>
<p className={`partner-settlement-item-amount${bill.status === 'UNPAID' ? ' text-primary' : ''}`}>
¥{fmtMoney(Number(bill.totalAmount || 0))}
</p>
</div>