优化资金审核与流水展示
This commit is contained in:
@@ -134,6 +134,7 @@ export type WorkerWalletLedgerRow = {
|
||||
note: string
|
||||
payload_json: string | Record<string, unknown>
|
||||
created_at: string
|
||||
related_platform_order_id?: string | null
|
||||
}
|
||||
|
||||
export type WorkerFinanceRequestRow = {
|
||||
|
||||
@@ -539,8 +539,11 @@ export async function listWorkerWalletLedgers({
|
||||
params.push(pageSize, offset)
|
||||
const itemsResult = await query<WorkerWalletLedgerRow>(
|
||||
`
|
||||
SELECT *
|
||||
SELECT
|
||||
wwl.*,
|
||||
wo.platform_order_id AS related_platform_order_id
|
||||
FROM worker_wallet_ledgers wwl
|
||||
LEFT JOIN work_orders wo ON wo.id = wwl.related_work_order_id
|
||||
${whereClause}
|
||||
ORDER BY wwl.created_at DESC, wwl.id DESC
|
||||
LIMIT $${params.length - 1} OFFSET $${params.length}
|
||||
|
||||
@@ -354,6 +354,7 @@ export function mapWalletLedger(ledger: WorkerWalletLedgerRow | null | undefined
|
||||
balanceAfter: Number(ledger.balance_after || 0),
|
||||
frozenAfter: Number(ledger.frozen_after || 0),
|
||||
relatedWorkOrderId: ledger.related_work_order_id ? Number(ledger.related_work_order_id) : null,
|
||||
relatedPlatformOrderId: String(ledger.related_platform_order_id || '').trim() || null,
|
||||
auditStatus: ledger.audit_status || '',
|
||||
note: ledger.note || '',
|
||||
payload: safeParseJson(ledger.payload_json),
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
WorkProductRuleRow,
|
||||
WorkerFinanceRequestRow,
|
||||
WorkerUserRow,
|
||||
WorkerWalletLedgerRow,
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
import {
|
||||
buildWorkOrderWhere,
|
||||
@@ -29,6 +30,7 @@ import {
|
||||
mapWorkOrderAdmin,
|
||||
mapWorkOrderSharingWorkers,
|
||||
mapFinanceRequest,
|
||||
mapWalletLedger,
|
||||
maskWorkerLeaderboardDisplayName,
|
||||
resolveCollectSubmitTargetWorkOrder,
|
||||
resolveAdminMaterialRewardAmount,
|
||||
@@ -1088,3 +1090,22 @@ test('resolveCollectSubmitTargetWorkOrder rejects unknown workOrderId', () => {
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
test('资金流水映射展示关联的平台订单号', () => {
|
||||
const ledger = {
|
||||
id: 1,
|
||||
worker_id: 1,
|
||||
ledger_type: 'reward_settlement',
|
||||
amount: 2500,
|
||||
balance_after: 2500,
|
||||
frozen_after: 0,
|
||||
related_work_order_id: 44,
|
||||
related_platform_order_id: '2623301845665410',
|
||||
audit_status: 'approved',
|
||||
note: '验收通过结算报酬',
|
||||
payload_json: {},
|
||||
created_at: '2026-08-21T00:00:00.000Z',
|
||||
} satisfies WorkerWalletLedgerRow
|
||||
|
||||
assert.equal(mapWalletLedger(ledger)?.relatedPlatformOrderId, '2623301845665410')
|
||||
})
|
||||
|
||||
@@ -500,6 +500,7 @@ export default function FinancePanel() {
|
||||
}
|
||||
open={Boolean(reviewState)}
|
||||
destroyOnHidden
|
||||
width="min(860px, calc(100vw - 32px))"
|
||||
confirmLoading={reviewing}
|
||||
onCancel={() => {
|
||||
setReviewState(null)
|
||||
@@ -509,64 +510,63 @@ export default function FinancePanel() {
|
||||
>
|
||||
{reviewState ? (
|
||||
<Space direction="vertical" size={16} className="full-width">
|
||||
<Descriptions column={1} bordered size="small">
|
||||
<Descriptions.Item label="打手">
|
||||
{reviewState.request.worker?.displayName ||
|
||||
reviewState.request.worker?.username ||
|
||||
'-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="申请类型">
|
||||
{formatFinanceRequestType(reviewState.request.requestType)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="金额">
|
||||
{formatMoney(reviewState.request.amount)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="收款信息">
|
||||
{renderFinanceRequestAccountText(reviewState.request)}
|
||||
</Descriptions.Item>
|
||||
{reviewState.request.requestType === 'withdraw' &&
|
||||
reviewState.request.accountChannel === 'alipay' ? (
|
||||
<>
|
||||
<Descriptions.Item label="支付宝账号">
|
||||
{reviewState.request.accountNo ? (
|
||||
<Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
<div className="finance-review-layout">
|
||||
<div className="finance-review-details">
|
||||
<Typography.Text strong>
|
||||
{reviewState.request.requestType === 'withdraw' ? '提现信息' : '充值信息'}
|
||||
</Typography.Text>
|
||||
<Descriptions column={1} bordered size="small">
|
||||
<Descriptions.Item label="打手">
|
||||
{reviewState.request.worker?.displayName ||
|
||||
reviewState.request.worker?.username ||
|
||||
'-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="支付宝收款二维码">
|
||||
<ImagePreviewList
|
||||
files={getAlipayWithdrawQrCode(reviewState.request)}
|
||||
size={88}
|
||||
/>
|
||||
<Descriptions.Item label="申请类型">
|
||||
{formatFinanceRequestType(reviewState.request.requestType)}
|
||||
</Descriptions.Item>
|
||||
</>
|
||||
) : null}
|
||||
{reviewState.request.requestType === 'recharge' ? (
|
||||
<>
|
||||
<Descriptions.Item label="付款时间">
|
||||
{getRechargePaidAt(reviewState.request)
|
||||
? formatAdminDateTime(getRechargePaidAt(reviewState.request))
|
||||
: '-'}
|
||||
<Descriptions.Item label="金额">
|
||||
{formatMoney(reviewState.request.amount)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="付款凭证">
|
||||
<ImagePreviewList files={getRechargeProofs(reviewState.request)} size={88} />
|
||||
<Descriptions.Item label="收款信息">
|
||||
{renderFinanceRequestAccountText(reviewState.request)}
|
||||
</Descriptions.Item>
|
||||
</>
|
||||
) : null}
|
||||
{reviewState.request.requestType === 'withdraw' &&
|
||||
reviewState.request.accountChannel === 'wechat' ? (
|
||||
<Descriptions.Item label="微信收款二维码">
|
||||
<ImagePreviewList
|
||||
files={getWechatWithdrawQrCode(reviewState.request)}
|
||||
size={88}
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
<Descriptions.Item label="申请备注">
|
||||
{reviewState.request.note || '-'}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
{reviewState.request.requestType === 'withdraw' ? (
|
||||
<Descriptions.Item label="收款账号">
|
||||
{reviewState.request.accountNo ? (
|
||||
<Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
{reviewState.request.requestType === 'recharge' ? (
|
||||
<Descriptions.Item label="付款时间">
|
||||
{getRechargePaidAt(reviewState.request)
|
||||
? formatAdminDateTime(getRechargePaidAt(reviewState.request))
|
||||
: '-'}
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
<Descriptions.Item label="申请备注">
|
||||
{reviewState.request.note || '-'}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
<div className="finance-review-evidence">
|
||||
<Typography.Text strong>
|
||||
{reviewState.request.requestType === 'withdraw'
|
||||
? `${formatFinanceChannel(reviewState.request.accountChannel)}收款二维码`
|
||||
: '付款凭证'}
|
||||
</Typography.Text>
|
||||
<ImagePreviewList
|
||||
files={
|
||||
reviewState.request.requestType === 'withdraw'
|
||||
? getWithdrawQrCode(reviewState.request)
|
||||
: getRechargeProofs(reviewState.request)
|
||||
}
|
||||
size={280}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Form form={reviewForm} layout="vertical" onFinish={submitFinanceReview}>
|
||||
<Form.Item label="审核备注" name="reviewedNote">
|
||||
|
||||
@@ -420,8 +420,8 @@ export default function WorkerProfilePage() {
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<Typography.Text>{row.note || '-'}</Typography.Text>
|
||||
{row.relatedWorkOrderId ? (
|
||||
<Typography.Text type="secondary">关联工单 #{row.relatedWorkOrderId}</Typography.Text>
|
||||
{row.relatedPlatformOrderId ? (
|
||||
<Typography.Text type="secondary">订单号 {row.relatedPlatformOrderId}</Typography.Text>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
@@ -841,9 +841,9 @@ export default function WorkerProfilePage() {
|
||||
{row.note ? (
|
||||
<div className="worker-profile-record-note">说明: {row.note}</div>
|
||||
) : null}
|
||||
{row.relatedWorkOrderId ? (
|
||||
{row.relatedPlatformOrderId ? (
|
||||
<div className="worker-profile-record-sub">
|
||||
关联工单 #{row.relatedWorkOrderId}
|
||||
订单号 {row.relatedPlatformOrderId}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="worker-profile-record-time">
|
||||
|
||||
@@ -888,6 +888,37 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.finance-review-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 304px;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.finance-review-details,
|
||||
.finance-review-evidence {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.finance-review-evidence {
|
||||
justify-items: center;
|
||||
padding: 12px;
|
||||
border: 1px solid #edf0f5;
|
||||
border-radius: 6px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.finance-review-evidence .image-preview-list {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.finance-review-evidence .ant-image,
|
||||
.finance-review-evidence img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.worker-orders-statistics-card {
|
||||
border-left: 3px solid #ff6a00;
|
||||
}
|
||||
@@ -1444,6 +1475,18 @@
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.finance-review-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.finance-review-evidence {
|
||||
justify-items: start;
|
||||
}
|
||||
|
||||
.finance-review-evidence .image-preview-list {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.users-action-card .ant-card-body {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ export type WorkerWalletLedger = {
|
||||
balanceAfter: number
|
||||
frozenAfter: number
|
||||
relatedWorkOrderId: number | null
|
||||
relatedPlatformOrderId: string | null
|
||||
auditStatus: string
|
||||
note: string
|
||||
payload: Record<string, unknown>
|
||||
|
||||
Reference in New Issue
Block a user