优化资金审核与流水展示
This commit is contained in:
@@ -134,6 +134,7 @@ export type WorkerWalletLedgerRow = {
|
|||||||
note: string
|
note: string
|
||||||
payload_json: string | Record<string, unknown>
|
payload_json: string | Record<string, unknown>
|
||||||
created_at: string
|
created_at: string
|
||||||
|
related_platform_order_id?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WorkerFinanceRequestRow = {
|
export type WorkerFinanceRequestRow = {
|
||||||
|
|||||||
@@ -539,8 +539,11 @@ export async function listWorkerWalletLedgers({
|
|||||||
params.push(pageSize, offset)
|
params.push(pageSize, offset)
|
||||||
const itemsResult = await query<WorkerWalletLedgerRow>(
|
const itemsResult = await query<WorkerWalletLedgerRow>(
|
||||||
`
|
`
|
||||||
SELECT *
|
SELECT
|
||||||
|
wwl.*,
|
||||||
|
wo.platform_order_id AS related_platform_order_id
|
||||||
FROM worker_wallet_ledgers wwl
|
FROM worker_wallet_ledgers wwl
|
||||||
|
LEFT JOIN work_orders wo ON wo.id = wwl.related_work_order_id
|
||||||
${whereClause}
|
${whereClause}
|
||||||
ORDER BY wwl.created_at DESC, wwl.id DESC
|
ORDER BY wwl.created_at DESC, wwl.id DESC
|
||||||
LIMIT $${params.length - 1} OFFSET $${params.length}
|
LIMIT $${params.length - 1} OFFSET $${params.length}
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ export function mapWalletLedger(ledger: WorkerWalletLedgerRow | null | undefined
|
|||||||
balanceAfter: Number(ledger.balance_after || 0),
|
balanceAfter: Number(ledger.balance_after || 0),
|
||||||
frozenAfter: Number(ledger.frozen_after || 0),
|
frozenAfter: Number(ledger.frozen_after || 0),
|
||||||
relatedWorkOrderId: ledger.related_work_order_id ? Number(ledger.related_work_order_id) : null,
|
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 || '',
|
auditStatus: ledger.audit_status || '',
|
||||||
note: ledger.note || '',
|
note: ledger.note || '',
|
||||||
payload: safeParseJson(ledger.payload_json),
|
payload: safeParseJson(ledger.payload_json),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import type {
|
|||||||
WorkProductRuleRow,
|
WorkProductRuleRow,
|
||||||
WorkerFinanceRequestRow,
|
WorkerFinanceRequestRow,
|
||||||
WorkerUserRow,
|
WorkerUserRow,
|
||||||
|
WorkerWalletLedgerRow,
|
||||||
} from '../../repositories/worker-platform/index.js'
|
} from '../../repositories/worker-platform/index.js'
|
||||||
import {
|
import {
|
||||||
buildWorkOrderWhere,
|
buildWorkOrderWhere,
|
||||||
@@ -29,6 +30,7 @@ import {
|
|||||||
mapWorkOrderAdmin,
|
mapWorkOrderAdmin,
|
||||||
mapWorkOrderSharingWorkers,
|
mapWorkOrderSharingWorkers,
|
||||||
mapFinanceRequest,
|
mapFinanceRequest,
|
||||||
|
mapWalletLedger,
|
||||||
maskWorkerLeaderboardDisplayName,
|
maskWorkerLeaderboardDisplayName,
|
||||||
resolveCollectSubmitTargetWorkOrder,
|
resolveCollectSubmitTargetWorkOrder,
|
||||||
resolveAdminMaterialRewardAmount,
|
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)}
|
open={Boolean(reviewState)}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
|
width="min(860px, calc(100vw - 32px))"
|
||||||
confirmLoading={reviewing}
|
confirmLoading={reviewing}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setReviewState(null)
|
setReviewState(null)
|
||||||
@@ -509,64 +510,63 @@ export default function FinancePanel() {
|
|||||||
>
|
>
|
||||||
{reviewState ? (
|
{reviewState ? (
|
||||||
<Space direction="vertical" size={16} className="full-width">
|
<Space direction="vertical" size={16} className="full-width">
|
||||||
<Descriptions column={1} bordered size="small">
|
<div className="finance-review-layout">
|
||||||
<Descriptions.Item label="打手">
|
<div className="finance-review-details">
|
||||||
{reviewState.request.worker?.displayName ||
|
<Typography.Text strong>
|
||||||
reviewState.request.worker?.username ||
|
{reviewState.request.requestType === 'withdraw' ? '提现信息' : '充值信息'}
|
||||||
'-'}
|
</Typography.Text>
|
||||||
</Descriptions.Item>
|
<Descriptions column={1} bordered size="small">
|
||||||
<Descriptions.Item label="申请类型">
|
<Descriptions.Item label="打手">
|
||||||
{formatFinanceRequestType(reviewState.request.requestType)}
|
{reviewState.request.worker?.displayName ||
|
||||||
</Descriptions.Item>
|
reviewState.request.worker?.username ||
|
||||||
<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>
|
|
||||||
) : (
|
|
||||||
'-'
|
|
||||||
)}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="支付宝收款二维码">
|
<Descriptions.Item label="申请类型">
|
||||||
<ImagePreviewList
|
{formatFinanceRequestType(reviewState.request.requestType)}
|
||||||
files={getAlipayWithdrawQrCode(reviewState.request)}
|
|
||||||
size={88}
|
|
||||||
/>
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</>
|
<Descriptions.Item label="金额">
|
||||||
) : null}
|
{formatMoney(reviewState.request.amount)}
|
||||||
{reviewState.request.requestType === 'recharge' ? (
|
|
||||||
<>
|
|
||||||
<Descriptions.Item label="付款时间">
|
|
||||||
{getRechargePaidAt(reviewState.request)
|
|
||||||
? formatAdminDateTime(getRechargePaidAt(reviewState.request))
|
|
||||||
: '-'}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="付款凭证">
|
<Descriptions.Item label="收款信息">
|
||||||
<ImagePreviewList files={getRechargeProofs(reviewState.request)} size={88} />
|
{renderFinanceRequestAccountText(reviewState.request)}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</>
|
{reviewState.request.requestType === 'withdraw' ? (
|
||||||
) : null}
|
<Descriptions.Item label="收款账号">
|
||||||
{reviewState.request.requestType === 'withdraw' &&
|
{reviewState.request.accountNo ? (
|
||||||
reviewState.request.accountChannel === 'wechat' ? (
|
<Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
|
||||||
<Descriptions.Item label="微信收款二维码">
|
) : (
|
||||||
<ImagePreviewList
|
'-'
|
||||||
files={getWechatWithdrawQrCode(reviewState.request)}
|
)}
|
||||||
size={88}
|
</Descriptions.Item>
|
||||||
/>
|
) : null}
|
||||||
</Descriptions.Item>
|
{reviewState.request.requestType === 'recharge' ? (
|
||||||
) : null}
|
<Descriptions.Item label="付款时间">
|
||||||
<Descriptions.Item label="申请备注">
|
{getRechargePaidAt(reviewState.request)
|
||||||
{reviewState.request.note || '-'}
|
? formatAdminDateTime(getRechargePaidAt(reviewState.request))
|
||||||
</Descriptions.Item>
|
: '-'}
|
||||||
</Descriptions>
|
</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 form={reviewForm} layout="vertical" onFinish={submitFinanceReview}>
|
||||||
<Form.Item label="审核备注" name="reviewedNote">
|
<Form.Item label="审核备注" name="reviewedNote">
|
||||||
|
|||||||
@@ -420,8 +420,8 @@ export default function WorkerProfilePage() {
|
|||||||
render: (_, row) => (
|
render: (_, row) => (
|
||||||
<div className="cell-stack">
|
<div className="cell-stack">
|
||||||
<Typography.Text>{row.note || '-'}</Typography.Text>
|
<Typography.Text>{row.note || '-'}</Typography.Text>
|
||||||
{row.relatedWorkOrderId ? (
|
{row.relatedPlatformOrderId ? (
|
||||||
<Typography.Text type="secondary">关联工单 #{row.relatedWorkOrderId}</Typography.Text>
|
<Typography.Text type="secondary">订单号 {row.relatedPlatformOrderId}</Typography.Text>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@@ -841,9 +841,9 @@ export default function WorkerProfilePage() {
|
|||||||
{row.note ? (
|
{row.note ? (
|
||||||
<div className="worker-profile-record-note">说明: {row.note}</div>
|
<div className="worker-profile-record-note">说明: {row.note}</div>
|
||||||
) : null}
|
) : null}
|
||||||
{row.relatedWorkOrderId ? (
|
{row.relatedPlatformOrderId ? (
|
||||||
<div className="worker-profile-record-sub">
|
<div className="worker-profile-record-sub">
|
||||||
关联工单 #{row.relatedWorkOrderId}
|
订单号 {row.relatedPlatformOrderId}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="worker-profile-record-time">
|
<div className="worker-profile-record-time">
|
||||||
|
|||||||
@@ -888,6 +888,37 @@
|
|||||||
min-width: 0;
|
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 {
|
.worker-orders-statistics-card {
|
||||||
border-left: 3px solid #ff6a00;
|
border-left: 3px solid #ff6a00;
|
||||||
}
|
}
|
||||||
@@ -1444,6 +1475,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@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 {
|
.users-action-card .ant-card-body {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export type WorkerWalletLedger = {
|
|||||||
balanceAfter: number
|
balanceAfter: number
|
||||||
frozenAfter: number
|
frozenAfter: number
|
||||||
relatedWorkOrderId: number | null
|
relatedWorkOrderId: number | null
|
||||||
|
relatedPlatformOrderId: string | null
|
||||||
auditStatus: string
|
auditStatus: string
|
||||||
note: string
|
note: string
|
||||||
payload: Record<string, unknown>
|
payload: Record<string, unknown>
|
||||||
|
|||||||
Reference in New Issue
Block a user