From 844f071aab29433b9763b1c7d4c7a93c65a9dafd Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sun, 23 Aug 2026 16:51:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=90=E7=8E=B0=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E5=86=BB=E7=BB=93=E4=BD=99=E9=A2=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/060_worker_withdraw_freeze.sql | 11 + .../src/repositories/worker-platform/types.ts | 3 + .../worker-platform/worker-finance-repo.ts | 237 +++++++++++++++++- .../worker-finance-withdraw-review.test.ts | 123 +++++++++ .../admin-worker-finance-service.ts | 2 +- .../worker-finance-request-service.ts | 40 ++- .../worker-platform-normalizers.ts | 2 + .../pages/admin/panels/WorkerDetailDrawer.tsx | 6 +- .../src/pages/worker/WorkerProfileRecords.tsx | 7 +- .../worker/worker-profile-view-utils.tsx | 20 +- 10 files changed, 409 insertions(+), 42 deletions(-) create mode 100644 apps/backend/src/db/migrations/060_worker_withdraw_freeze.sql create mode 100644 apps/backend/src/repositories/worker-platform/worker-finance-withdraw-review.test.ts diff --git a/apps/backend/src/db/migrations/060_worker_withdraw_freeze.sql b/apps/backend/src/db/migrations/060_worker_withdraw_freeze.sql new file mode 100644 index 00000000..26699273 --- /dev/null +++ b/apps/backend/src/db/migrations/060_worker_withdraw_freeze.sql @@ -0,0 +1,11 @@ +-- 提现申请改为"申请即冻结"资金模型: +-- 1) worker_wallets 新增 frozen_withdraw_amount,申请提现立即从 available_amount 划转到该字段; +-- 2) worker_finance_requests 新增 frozen_amount 标记该笔申请是否已冻结资金(0=旧数据未冻结), +-- 审核通过/拒绝按此标记选择解冻或旧口径扣款,保证存量数据平滑过渡; +-- 3) 仅对迁移后创建的申请生效,存量申请仍按旧口径在审核通过时扣款。 + +ALTER TABLE worker_wallets + ADD COLUMN IF NOT EXISTS frozen_withdraw_amount INTEGER NOT NULL DEFAULT 0; + +ALTER TABLE worker_finance_requests + ADD COLUMN IF NOT EXISTS frozen_amount INTEGER NOT NULL DEFAULT 0; diff --git a/apps/backend/src/repositories/worker-platform/types.ts b/apps/backend/src/repositories/worker-platform/types.ts index a4134637..1f8884c0 100644 --- a/apps/backend/src/repositories/worker-platform/types.ts +++ b/apps/backend/src/repositories/worker-platform/types.ts @@ -64,6 +64,7 @@ export type WorkerWalletRow = { worker_id: number available_amount: number frozen_deposit_amount: number + frozen_withdraw_amount: number pending_unfreeze_amount: number total_credited_amount: number total_settled_amount: number @@ -204,6 +205,8 @@ export type WorkerFinanceRequestRow = { request_type: string status: string amount: number + /** 申请时已冻结的资金额度;0 表示旧数据未冻结(迁移前遗留)。 */ + frozen_amount: number account_channel: string account_name: string account_no: string diff --git a/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts b/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts index c0c45744..d75a2a73 100644 --- a/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts +++ b/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts @@ -67,6 +67,91 @@ export async function createWorkerFinanceRequest(input: { return result.rows[0] || null } +/** + * 创建提现申请并在同一事务内立即冻结资金: + * available_amount 划入 frozen_withdraw_amount,杜绝"待提现 + 接单押金"双重占用余额。 + */ +export async function createWorkerWithdrawRequestWithFreeze(input: { + workerId: number + amount: number + accountChannel: string + accountName: string + accountNo: string + note: string + payloadJson: string + now: string +}): Promise< + | { + request: WorkerFinanceRequestRow | null + failureReason: 'withdraw_insufficient' + } + | { request: WorkerFinanceRequestRow; failureReason: null } +> { + return withTransaction(async (client) => { + await ensureWorkerWalletWithClient(client, Number(input.workerId), input.now) + const wallet = await getWorkerWalletWithClient(client, Number(input.workerId)) + const availableAmount = Number(wallet?.available_amount || 0) + const frozenWithdrawAmount = Number(wallet?.frozen_withdraw_amount || 0) + + if (availableAmount < input.amount) { + return { request: null, failureReason: 'withdraw_insufficient' } + } + + const nextAvailable = availableAmount - input.amount + const nextFrozenWithdraw = frozenWithdrawAmount + input.amount + await client.query( + ` + UPDATE worker_wallets + SET available_amount = $1, frozen_withdraw_amount = $2, updated_at = $3 + WHERE worker_id = $4 + `, + [nextAvailable, nextFrozenWithdraw, input.now, Number(input.workerId)], + ) + await client.query( + ` + INSERT INTO worker_wallet_ledgers ( + worker_id, ledger_type, amount, balance_after, frozen_after, + note, payload_json, created_at + ) VALUES ($1, 'withdraw_freeze', $2, $3, $4, $5, '{}'::jsonb, $6) + `, + [ + Number(input.workerId), + -input.amount, + nextAvailable, + nextFrozenWithdraw, + '提现申请冻结余额', + input.now, + ], + ) + + const createdResult = await client.query( + ` + INSERT INTO worker_finance_requests ( + worker_id, request_type, status, amount, frozen_amount, + account_channel, account_name, account_no, + note, reviewed_note, payload_json, created_at, updated_at + ) VALUES ($1, 'withdraw', 'pending', $2, $2, $3, $4, $5, $6, '', $7::jsonb, $8, $8) + RETURNING * + `, + [ + Number(input.workerId), + input.amount, + input.accountChannel, + input.accountName, + input.accountNo, + input.note, + input.payloadJson, + input.now, + ], + ) + const request = createdResult.rows[0] || null + if (!request) { + throw new Error('提现申请创建失败') + } + return { request, failureReason: null } + }) +} + export async function getWorkerWithdrawalAccount( workerId: number | string, accountChannel: string, @@ -314,20 +399,30 @@ export async function reviewWorkerFinanceRequest(input: { (current.request_type === 'withdraw' ? '提现申请审核通过' : '充值申请审核通过') if (current.request_type === 'withdraw') { - if (availableAmount < amount) { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: Number(current.frozen_amount || 0), + frozenWithdrawAmount: Number(wallet?.frozen_withdraw_amount || 0), + availableAmount, + amount, + }) + if (!plan.ok) { return { request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), - failureReason: 'withdraw_insufficient', + failureReason: plan.reason, } } - const nextAvailable = availableAmount - amount await client.query( ` UPDATE worker_wallets - SET available_amount = $1, updated_at = $2 - WHERE worker_id = $3 + SET available_amount = $1, frozen_withdraw_amount = $2, updated_at = $3 + WHERE worker_id = $4 `, - [nextAvailable, input.now, Number(current.worker_id)], + [ + plan.nextAvailableAmount, + plan.nextFrozenWithdrawAmount, + input.now, + Number(current.worker_id), + ], ) await client.query( ` @@ -338,10 +433,10 @@ export async function reviewWorkerFinanceRequest(input: { `, [ Number(current.worker_id), - -amount, - nextAvailable, - frozenAmount, - note, + plan.ledgerAmount, + plan.nextAvailableAmount, + plan.nextFrozenWithdrawAmount, + plan.mode === 'frozen' ? `${note}(申请时已冻结,本次确认打款)` : note, JSON.stringify({ requestId: Number(current.id), requestType: current.request_type, @@ -385,6 +480,59 @@ export async function reviewWorkerFinanceRequest(input: { ], ) } + } else if ( + input.status === 'rejected' && + current.request_type === 'withdraw' && + Number(current.frozen_amount || 0) > 0 + ) { + // 新口径:拒绝提现申请时把申请冻结的资金退回可用余额。 + await ensureWorkerWalletWithClient(client, Number(current.worker_id), input.now) + const wallet = await getWorkerWalletWithClient(client, Number(current.worker_id)) + const release = resolveWithdrawRejectionPlan({ + requestFrozenAmount: Number(current.frozen_amount || 0), + frozenWithdrawAmount: Number(wallet?.frozen_withdraw_amount || 0), + availableAmount: Number(wallet?.available_amount || 0), + }) + if (!release.ok) { + return { + request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), + failureReason: release.reason, + } + } + await client.query( + ` + UPDATE worker_wallets + SET available_amount = $1, frozen_withdraw_amount = $2, updated_at = $3 + WHERE worker_id = $4 + `, + [ + release.nextAvailableAmount, + release.nextFrozenWithdrawAmount, + input.now, + Number(current.worker_id), + ], + ) + await client.query( + ` + INSERT INTO worker_wallet_ledgers ( + worker_id, ledger_type, amount, balance_after, frozen_after, + audit_status, note, payload_json, created_at + ) VALUES ($1, 'withdraw_release', $2, $3, $4, 'approved', $5, $6::jsonb, $7) + `, + [ + Number(current.worker_id), + release.releaseAmount, + release.nextAvailableAmount, + release.nextFrozenWithdrawAmount, + `${input.reviewedNote || '提现申请审核未通过'},冻结余额已退回`, + JSON.stringify({ + requestId: Number(current.id), + requestType: current.request_type, + source: 'admin_finance_review', + }), + input.now, + ], + ) } await client.query( @@ -525,3 +673,72 @@ function buildWorkerFinanceRequestWhere({ params, } } + +export type WithdrawApprovalPlan = + | { + ok: true + mode: 'frozen' | 'legacy' + nextAvailableAmount: number + nextFrozenWithdrawAmount: number + ledgerAmount: number + } + | { ok: false; reason: 'withdraw_insufficient' } + +/** + * 提现审核通过的资金划转计划。 + * - frozen 模式(新数据):申请时已冻结,打款确认仅解冻,不动可用余额; + * - legacy 模式(迁移前旧数据 frozen_amount=0):沿用"确认时从可用余额扣款"口径。 + */ +export function resolveWithdrawApprovalPlan(input: { + requestFrozenAmount: number + frozenWithdrawAmount: number + availableAmount: number + amount: number +}): WithdrawApprovalPlan { + if (input.requestFrozenAmount > 0) { + if (input.frozenWithdrawAmount < input.requestFrozenAmount) { + return { ok: false, reason: 'withdraw_insufficient' } + } + return { + ok: true, + mode: 'frozen', + nextAvailableAmount: input.availableAmount, + nextFrozenWithdrawAmount: input.frozenWithdrawAmount - input.requestFrozenAmount, + ledgerAmount: 0, + } + } + if (input.availableAmount < input.amount) { + return { ok: false, reason: 'withdraw_insufficient' } + } + return { + ok: true, + mode: 'legacy', + nextAvailableAmount: input.availableAmount - input.amount, + nextFrozenWithdrawAmount: input.frozenWithdrawAmount, + ledgerAmount: -input.amount, + } +} + +/** 提现审核拒绝时的资金退回计划。 */ +export function resolveWithdrawRejectionPlan(input: { + requestFrozenAmount: number + frozenWithdrawAmount: number + availableAmount: number +}): + | { + ok: true + releaseAmount: number + nextAvailableAmount: number + nextFrozenWithdrawAmount: number + } + | { ok: false; reason: 'withdraw_insufficient' } { + if (input.frozenWithdrawAmount < input.requestFrozenAmount) { + return { ok: false, reason: 'withdraw_insufficient' } + } + return { + ok: true, + releaseAmount: input.requestFrozenAmount, + nextAvailableAmount: input.availableAmount + input.requestFrozenAmount, + nextFrozenWithdrawAmount: input.frozenWithdrawAmount - input.requestFrozenAmount, + } +} diff --git a/apps/backend/src/repositories/worker-platform/worker-finance-withdraw-review.test.ts b/apps/backend/src/repositories/worker-platform/worker-finance-withdraw-review.test.ts new file mode 100644 index 00000000..29c5ec0d --- /dev/null +++ b/apps/backend/src/repositories/worker-platform/worker-finance-withdraw-review.test.ts @@ -0,0 +1,123 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { resolveWithdrawApprovalPlan, resolveWithdrawRejectionPlan } from './worker-finance-repo.js' + +test('提现通过(新口径):申请时已冻结,确认打款只解冻不动可用余额', () => { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: 8_000, + frozenWithdrawAmount: 8_000, + availableAmount: 2_000, + amount: 8_000, + }) + assert.deepEqual(plan, { + ok: true, + mode: 'frozen', + nextAvailableAmount: 2_000, + nextFrozenWithdrawAmount: 0, + ledgerAmount: 0, + }) +}) + +test('提现通过(新口径):多笔待审时只解冻当前申请的冻结额度', () => { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: 3_000, + frozenWithdrawAmount: 11_000, + availableAmount: 5_000, + amount: 3_000, + }) + assert.deepEqual(plan, { + ok: true, + mode: 'frozen', + nextAvailableAmount: 5_000, + nextFrozenWithdrawAmount: 8_000, + ledgerAmount: 0, + }) +}) + +test('提现通过(新口径):冻结额度异常不足时拒绝并保持现状', () => { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: 8_000, + frozenWithdrawAmount: 1_000, + availableAmount: 9_000, + amount: 8_000, + }) + assert.deepEqual(plan, { ok: false, reason: 'withdraw_insufficient' }) +}) + +test('提现通过(旧数据兜底):未冻结申请沿用确认时扣款口径', () => { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: 0, + frozenWithdrawAmount: 0, + availableAmount: 10_000, + amount: 8_000, + }) + assert.deepEqual(plan, { + ok: true, + mode: 'legacy', + nextAvailableAmount: 2_000, + nextFrozenWithdrawAmount: 0, + ledgerAmount: -8_000, + }) +}) + +test('提现通过(旧数据兜底):可用余额不足时拒绝', () => { + const plan = resolveWithdrawApprovalPlan({ + requestFrozenAmount: 0, + frozenWithdrawAmount: 0, + availableAmount: 5_000, + amount: 8_000, + }) + assert.deepEqual(plan, { ok: false, reason: 'withdraw_insufficient' }) +}) + +test('提现拒绝(新口径):冻结资金全额退回可用余额', () => { + const plan = resolveWithdrawRejectionPlan({ + requestFrozenAmount: 8_000, + frozenWithdrawAmount: 8_000, + availableAmount: 2_000, + }) + assert.deepEqual(plan, { + ok: true, + releaseAmount: 8_000, + nextAvailableAmount: 10_000, + nextFrozenWithdrawAmount: 0, + }) +}) + +test('提现拒绝(新口径):多笔待审时只退回当前申请额度', () => { + const plan = resolveWithdrawRejectionPlan({ + requestFrozenAmount: 3_000, + frozenWithdrawAmount: 11_000, + availableAmount: 4_000, + }) + assert.deepEqual(plan, { + ok: true, + releaseAmount: 3_000, + nextAvailableAmount: 7_000, + nextFrozenWithdrawAmount: 8_000, + }) +}) + +test('提现拒绝(旧数据):未冻结申请不退回资金', () => { + const plan = resolveWithdrawRejectionPlan({ + requestFrozenAmount: 0, + frozenWithdrawAmount: 0, + availableAmount: 2_000, + }) + assert.deepEqual(plan, { + ok: true, + releaseAmount: 0, + nextAvailableAmount: 2_000, + nextFrozenWithdrawAmount: 0, + }) +}) + +test('提现拒绝: 冻结额度异常不足时保持申请待处理', () => { + const plan = resolveWithdrawRejectionPlan({ + requestFrozenAmount: 8_000, + frozenWithdrawAmount: 1_000, + availableAmount: 9_000, + }) + assert.deepEqual(plan, { ok: false, reason: 'withdraw_insufficient' }) +}) diff --git a/apps/backend/src/services/worker-platform/admin-worker-finance-service.ts b/apps/backend/src/services/worker-platform/admin-worker-finance-service.ts index 19acff5b..3efb29c1 100644 --- a/apps/backend/src/services/worker-platform/admin-worker-finance-service.ts +++ b/apps/backend/src/services/worker-platform/admin-worker-finance-service.ts @@ -251,7 +251,7 @@ export async function reviewAdminWorkerFinanceRequest( publishWorkerFinanceRealtimeChange({ requestId: Number(reviewed.request.id), workerId: Number(reviewed.request.worker_id), - walletChanged: reviewed.request.request_type === 'withdraw' && status === 'approved', + walletChanged: reviewed.request.request_type === 'withdraw', }) return { diff --git a/apps/backend/src/services/worker-platform/worker-finance-request-service.ts b/apps/backend/src/services/worker-platform/worker-finance-request-service.ts index 962780d0..f6eb1489 100644 --- a/apps/backend/src/services/worker-platform/worker-finance-request-service.ts +++ b/apps/backend/src/services/worker-platform/worker-finance-request-service.ts @@ -1,7 +1,7 @@ import { countWorkerWithdrawRequestsOnDay, createWorkerFinanceRequest, - getWorkerFinanceRequestSummary, + createWorkerWithdrawRequestWithFreeze, getWorkerWithdrawalAccount, listDueDepositUnfreezes, releaseDepositUnfreeze, @@ -164,20 +164,9 @@ export async function createWorkerWithdrawRequest( }) } - const financeSummary = await getWorkerFinanceRequestSummary(worker.id) - const availableAmount = Number(worker.available_amount || 0) - const availableForWithdraw = Math.max(0, availableAmount - financeSummary.pendingWithdrawAmount) - if (amount > availableForWithdraw) { - throw createHttpError('可提现余额不足,请先减少提现金额或等待已提交申请处理', { - statusCode: 409, - errorCode: 'worker_withdraw_amount_insufficient', - }) - } - const note = String(payload.note || payload.remark || '').trim() - const created = await createWorkerFinanceRequest({ + const created = await createWorkerWithdrawRequestWithFreeze({ workerId: worker.id, - requestType: 'withdraw', amount, accountChannel, accountName: withdrawalAccount.account_name, @@ -192,25 +181,30 @@ export async function createWorkerWithdrawRequest( }), now: nowIso(), }) - if (!created) { - throw createHttpError('提现申请创建失败', { - statusCode: 500, - errorCode: 'worker_withdraw_request_create_failed', + if (created.failureReason === 'withdraw_insufficient') { + throw createHttpError('可提现余额不足,请先减少提现金额或等待已提交申请处理', { + statusCode: 409, + errorCode: 'worker_withdraw_amount_insufficient', }) } + const request = created.request await createWorkerWithdrawAdminNotification({ - requestId: Number(created.id), + requestId: Number(request.id), workerName: worker.display_name || worker.username, - amountFen: Number(created.amount || amount), - channel: created.account_channel, + amountFen: Number(request.amount || amount), + channel: request.account_channel, }) publishWorkerFinanceRealtimeChange({ - requestId: Number(created.id), + requestId: Number(request.id), workerId: Number(worker.id), }) + publishWorkerWalletRealtimeChange(Number(worker.id)) return { - request: mapFinanceRequest(created), - availableForWithdraw, + request: mapFinanceRequest(request), + availableForWithdraw: Math.max( + 0, + Number(worker.available_amount || 0) - Number(request.amount || amount), + ), } } diff --git a/apps/backend/src/services/worker-platform/worker-platform-normalizers.ts b/apps/backend/src/services/worker-platform/worker-platform-normalizers.ts index 12aaa838..b12cad8c 100644 --- a/apps/backend/src/services/worker-platform/worker-platform-normalizers.ts +++ b/apps/backend/src/services/worker-platform/worker-platform-normalizers.ts @@ -68,7 +68,9 @@ export function normalizeWalletLedgerType(value: unknown) { if ( [ 'manual_credit', + 'withdraw_freeze', 'withdraw_paid', + 'withdraw_release', 'deposit_freeze', 'deposit_release', 'deposit_pending_unfreeze', diff --git a/apps/frontend/src/pages/admin/panels/WorkerDetailDrawer.tsx b/apps/frontend/src/pages/admin/panels/WorkerDetailDrawer.tsx index 5924484b..ab957fa6 100644 --- a/apps/frontend/src/pages/admin/panels/WorkerDetailDrawer.tsx +++ b/apps/frontend/src/pages/admin/panels/WorkerDetailDrawer.tsx @@ -22,7 +22,9 @@ import { formatMoney, formatStatus, formatWorkerStatus, resolveStatusColor } fro /** 与打手端 worker-profile-view-utils 的流水文案保持一致;未知类型原样展示。 */ const LEDGER_TYPE_LABELS: Record = { manual_credit: '人工充值', + withdraw_freeze: '提现冻结', withdraw_paid: '提现打款', + withdraw_release: '提现退回', deposit_freeze: '冻结押金', deposit_release: '释放押金', deposit_pending_unfreeze: '待解冻金额', @@ -57,7 +59,9 @@ function resolveLedgerTagColor(ledgerType: string) { return 'red' if (['reward_settlement', 'sharing_reward'].includes(ledgerType)) return 'cyan' if (ledgerType === 'manual_credit') return 'blue' + if (ledgerType === 'withdraw_freeze') return 'orange' if (ledgerType === 'withdraw_paid') return 'purple' + if (ledgerType === 'withdraw_release') return 'green' return 'default' } @@ -287,7 +291,7 @@ function LedgersSection({ workerId }: { workerId: number }) { render: (_, row) => formatMoney(row.balanceAfter), }, { - title: '冻结押金', + title: '冻结金额', width: 110, render: (_, row) => formatMoney(row.frozenAfter), }, diff --git a/apps/frontend/src/pages/worker/WorkerProfileRecords.tsx b/apps/frontend/src/pages/worker/WorkerProfileRecords.tsx index 2595124c..284f2f38 100644 --- a/apps/frontend/src/pages/worker/WorkerProfileRecords.tsx +++ b/apps/frontend/src/pages/worker/WorkerProfileRecords.tsx @@ -17,6 +17,7 @@ import { formatWithdrawChannel, maskAccountNo, renderRechargeRequestSummary, + resolveLedgerFrozenAmountLabel, resolveLedgerTagColor, resolveRequestStatusColor, workerFinanceRequestColumns, @@ -26,7 +27,9 @@ import { const LEDGER_TYPE_OPTIONS = [ { value: '', label: '全部流水' }, { value: 'manual_credit', label: '人工充值' }, + { value: 'withdraw_freeze', label: '提现冻结' }, { value: 'withdraw_paid', label: '提现打款' }, + { value: 'withdraw_release', label: '提现退回' }, { value: 'deposit_freeze', label: '冻结押金' }, { value: 'deposit_release', label: '释放押金' }, { value: 'deposit_pending_unfreeze', label: '待解冻金额' }, @@ -132,7 +135,9 @@ export function WorkerProfileMobileLedgerRecords({
变动后余额: {formatMoney(row.balanceAfter)} - 冻结押金: {formatMoney(row.frozenAfter)} + + {resolveLedgerFrozenAmountLabel(row.ledgerType)}: {formatMoney(row.frozenAfter)} +
{row.note ?
说明: {row.note}
: null} {row.relatedPlatformOrderId ? ( diff --git a/apps/frontend/src/pages/worker/worker-profile-view-utils.tsx b/apps/frontend/src/pages/worker/worker-profile-view-utils.tsx index 340d6ff6..bf500eaa 100644 --- a/apps/frontend/src/pages/worker/worker-profile-view-utils.tsx +++ b/apps/frontend/src/pages/worker/worker-profile-view-utils.tsx @@ -11,12 +11,10 @@ import { formatDateTime } from '@/utils/date-time' export function resolveAvailableForWithdraw( worker: WorkerUser | undefined, - summary: WorkerProfileSummary | undefined, + _summary: WorkerProfileSummary | undefined, ) { - return Math.max( - 0, - Number(worker?.wallet.availableAmount || 0) - Number(summary?.pendingWithdrawAmount || 0), - ) + // 提现申请即冻结 available_amount,可提现口径就是当前可用余额,无需再减待处理申请。 + return Math.max(0, Number(worker?.wallet.availableAmount || 0)) } export function resolveWorkerInitial(worker: WorkerUser | undefined) { @@ -49,7 +47,9 @@ export function resolveWorkerStatusColor(status: string) { export function formatLedgerType(ledgerType: string) { const labels: Record = { manual_credit: '人工充值', + withdraw_freeze: '提现冻结', withdraw_paid: '提现打款', + withdraw_release: '提现退回', deposit_freeze: '冻结押金', deposit_release: '释放押金', deposit_pending_unfreeze: '待解冻金额', @@ -67,7 +67,9 @@ export function formatLedgerType(ledgerType: string) { export function resolveLedgerTagColor(ledgerType: string) { if (ledgerType === 'manual_credit') return 'blue' + if (ledgerType === 'withdraw_freeze') return 'orange' if (ledgerType === 'withdraw_paid') return 'purple' + if (ledgerType === 'withdraw_release') return 'green' if (ledgerType === 'deposit_freeze') return 'gold' if (ledgerType === 'deposit_release') return 'green' if (ledgerType === 'deposit_pending_unfreeze') return 'orange' @@ -82,6 +84,12 @@ export function resolveLedgerTagColor(ledgerType: string) { return 'default' } +export function resolveLedgerFrozenAmountLabel(ledgerType: string) { + return ['withdraw_freeze', 'withdraw_paid', 'withdraw_release'].includes(ledgerType) + ? '提现冻结' + : '冻结押金' +} + export function formatRequestType(requestType: string) { if (requestType === 'recharge') return '充值申请' if (requestType === 'withdraw') return '提现申请' @@ -180,7 +188,7 @@ export const workerLedgerColumns: TableColumnsType = [ ), }, { title: '余额', width: 120, render: (_, row) => formatMoney(row.balanceAfter) }, - { title: '冻结押金', width: 120, render: (_, row) => formatMoney(row.frozenAfter) }, + { title: '冻结金额', width: 120, render: (_, row) => formatMoney(row.frozenAfter) }, { title: '说明', minWidth: 260,