优化后端-接单平台部分逻辑

This commit is contained in:
yml2213
2026-07-28 14:06:31 +08:00
parent b505b6b85e
commit 6e635b2499
9 changed files with 1389 additions and 20 deletions
@@ -19,6 +19,7 @@ import {
Descriptions,
Empty,
Form,
Image,
Input,
InputNumber,
Modal,
@@ -113,6 +114,7 @@ export default function WorkerProfilePage() {
const worker = profileQuery.data?.data.worker
const summary = profileQuery.data?.data.summary
const financeConfig = profileQuery.data?.data.financeConfig
const canUseFinanceActions = worker?.status === 'active'
const ledgersQuery = useQuery({
@@ -179,6 +181,30 @@ export default function WorkerProfilePage() {
setActiveTab('requests')
}
function openRechargeModal() {
if (!canUseFinanceActions) {
message.warning('当前账号尚未通过审核,暂时不能发起充值申请')
return
}
if (financeConfig?.recharge.enabled === false) {
message.warning('当前充值入口暂未开放,请联系管理员')
return
}
setRechargeOpen(true)
}
function openWithdrawModal() {
if (!canUseFinanceActions) {
message.warning('当前账号尚未通过审核,暂时不能发起提现申请')
return
}
if (financeConfig?.withdraw.enabled === false) {
message.warning('当前提现入口暂未开放,请联系管理员')
return
}
setWithdrawOpen(true)
}
async function submitRecharge(values: RechargeFormValues) {
setSubmittingRecharge(true)
try {
@@ -327,7 +353,7 @@ export default function WorkerProfilePage() {
</Typography.Text>
</div>
) : (
<Typography.Text type="secondary">线</Typography.Text>
renderRechargeRequestSummary(row)
),
},
{
@@ -452,7 +478,7 @@ export default function WorkerProfilePage() {
type="primary"
icon={<WalletOutlined />}
disabled={!canUseFinanceActions}
onClick={() => setRechargeOpen(true)}
onClick={openRechargeModal}
>
</Button>
@@ -460,7 +486,7 @@ export default function WorkerProfilePage() {
type="primary"
icon={<BankOutlined />}
disabled={!canUseFinanceActions}
onClick={() => setWithdrawOpen(true)}
onClick={openWithdrawModal}
>
</Button>
@@ -549,6 +575,7 @@ export default function WorkerProfilePage() {
options={[
{ value: '', label: '全部流水' },
{ value: 'manual_credit', label: '人工充值' },
{ value: 'withdraw_paid', label: '提现打款' },
{ value: 'deposit_freeze', label: '冻结押金' },
{ value: 'deposit_release', label: '释放押金' },
{ value: 'deposit_deduction', label: '扣除押金' },
@@ -697,6 +724,51 @@ export default function WorkerProfilePage() {
initialValues={{ amount: undefined, note: '' }}
onFinish={submitRecharge}
>
<Alert
showIcon
type={hasRechargeConfig(financeConfig) ? 'info' : 'warning'}
message={
hasRechargeConfig(financeConfig)
? '请先按下方收款信息完成转账,再提交充值申请,管理员核对后会手动入账。'
: '管理员暂未配置完整收款信息,如无法转账请先联系管理员确认。'
}
/>
<Space
direction="vertical"
size={12}
className="full-width"
style={{ marginTop: 16, marginBottom: 16 }}
>
{financeConfig?.recharge.qrCodeImage ? (
<Image
width={180}
src={
financeConfig.recharge.qrCodeImage.mediumUrl ||
financeConfig.recharge.qrCodeImage.url
}
/>
) : null}
<Descriptions column={1} bordered size="small">
<Descriptions.Item label="收款通道">
{financeConfig?.recharge.channelName || '-'}
</Descriptions.Item>
<Descriptions.Item label="收款人">
{financeConfig?.recharge.accountName || '-'}
</Descriptions.Item>
<Descriptions.Item label="收款账号">
{financeConfig?.recharge.accountNo ? (
<Typography.Text copyable>
{financeConfig.recharge.accountNo}
</Typography.Text>
) : (
'-'
)}
</Descriptions.Item>
<Descriptions.Item label="充值说明">
{financeConfig?.recharge.instructions || '请转账后填写备注说明,方便管理员核对。'}
</Descriptions.Item>
</Descriptions>
</Space>
<Form.Item
label="充值金额"
name="amount"
@@ -730,6 +802,14 @@ export default function WorkerProfilePage() {
initialValues={{ accountChannel: 'alipay' }}
onFinish={submitWithdraw}
>
{financeConfig?.withdraw.instructions ? (
<Alert
showIcon
type="info"
message={financeConfig.withdraw.instructions}
style={{ marginBottom: 16 }}
/>
) : null}
<Form.Item label="可提现余额">
<Typography.Text strong>
{formatMoney(resolveAvailableForWithdraw(worker, summary))}
@@ -962,6 +1042,7 @@ function resolveWorkerStatusColor(status: string) {
function formatLedgerType(ledgerType: string) {
const labels: Record<string, string> = {
manual_credit: '人工充值',
withdraw_paid: '提现打款',
deposit_freeze: '冻结押金',
deposit_release: '释放押金',
deposit_deduction: '扣除押金',
@@ -972,6 +1053,7 @@ function formatLedgerType(ledgerType: string) {
function resolveLedgerTagColor(ledgerType: string) {
if (ledgerType === 'manual_credit') return 'blue'
if (ledgerType === 'withdraw_paid') return 'purple'
if (ledgerType === 'deposit_freeze') return 'gold'
if (ledgerType === 'deposit_release') return 'green'
if (ledgerType === 'deposit_deduction') return 'red'
@@ -995,6 +1077,46 @@ function formatRequestStatus(status: string) {
return labels[status] || status || '-'
}
function hasRechargeConfig(
financeConfig: {
recharge?: { accountName?: string; accountNo?: string; qrCodeImage?: unknown }
} | undefined,
) {
return Boolean(
financeConfig?.recharge?.accountName ||
financeConfig?.recharge?.accountNo ||
financeConfig?.recharge?.qrCodeImage,
)
}
function renderRechargeRequestSummary(row: WorkerFinanceRequest) {
const snapshot = getRechargeSnapshot(row)
if (!snapshot.channelName && !snapshot.accountName && !snapshot.accountNo) {
return <Typography.Text type="secondary">线</Typography.Text>
}
return (
<div className="cell-stack">
<Typography.Text>
{[snapshot.channelName, snapshot.accountName].filter(Boolean).join(' / ') || '线下充值'}
</Typography.Text>
<Typography.Text type="secondary">
{snapshot.accountNo ? maskAccountNo(snapshot.accountNo) : '等待管理员核对'}
</Typography.Text>
</div>
)
}
function getRechargeSnapshot(row: WorkerFinanceRequest) {
const payload = asRecord(row.payload)
const financeConfig = asRecord(payload.financeConfig)
return {
channelName: String(financeConfig.channelName || '').trim(),
accountName: String(financeConfig.accountName || '').trim(),
accountNo: String(financeConfig.accountNo || '').trim(),
}
}
function resolveRequestStatusColor(status: string) {
if (status === 'approved') return 'green'
if (status === 'pending') return 'gold'
@@ -1016,3 +1138,9 @@ function maskAccountNo(value: string) {
if (text.length <= 8) return text
return `${text.slice(0, 4)} **** ${text.slice(-4)}`
}
function asRecord(value: unknown): Record<string, unknown> {
return value && typeof value === 'object' && !Array.isArray(value)
? (value as Record<string, unknown>)
: {}
}