修复拼单工单打手展示
This commit is contained in:
@@ -255,7 +255,7 @@ async function publishWorkOrderSnapshots(input: {
|
|||||||
.reduce((sum, share) => sum + Number(share.quantity || 0), 0)
|
.reduce((sum, share) => sum + Number(share.quantity || 0), 0)
|
||||||
const pendingSubmissionCount = shares.filter((share) => share.status === 'joined').length
|
const pendingSubmissionCount = shares.filter((share) => share.status === 'joined').length
|
||||||
const adminSnapshot = {
|
const adminSnapshot = {
|
||||||
...mapWorkOrderAdmin(workOrder),
|
...mapWorkOrderAdmin(workOrder, shares),
|
||||||
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(workOrderId) || 0,
|
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(workOrderId) || 0,
|
||||||
sharingProgress: {
|
sharingProgress: {
|
||||||
joinedQuantity,
|
joinedQuantity,
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
listWorkerUsers,
|
listWorkerUsers,
|
||||||
listWorkerWithdrawalAccounts,
|
listWorkerWithdrawalAccounts,
|
||||||
listWorkOrderShares,
|
listWorkOrderShares,
|
||||||
|
listWorkOrderSharesByOrderIds,
|
||||||
sumPendingUnfreezeByOrderIds,
|
sumPendingUnfreezeByOrderIds,
|
||||||
resolveProblemWorkOrder,
|
resolveProblemWorkOrder,
|
||||||
reviewWorkerFinanceRequest,
|
reviewWorkerFinanceRequest,
|
||||||
@@ -1300,10 +1301,18 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
|
|||||||
const pendingUnfreezeByOrderId = await sumPendingUnfreezeByOrderIds(
|
const pendingUnfreezeByOrderId = await sumPendingUnfreezeByOrderIds(
|
||||||
items.map((item) => Number(item.id)),
|
items.map((item) => Number(item.id)),
|
||||||
)
|
)
|
||||||
|
const shares = await listWorkOrderSharesByOrderIds(items.map((item) => Number(item.id)))
|
||||||
|
const sharesByOrderId = new Map<number, typeof shares>()
|
||||||
|
for (const share of shares) {
|
||||||
|
const workOrderId = Number(share.work_order_id)
|
||||||
|
const current = sharesByOrderId.get(workOrderId) || []
|
||||||
|
current.push(share)
|
||||||
|
sharesByOrderId.set(workOrderId, current)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
items: items.map((item) => {
|
items: items.map((item) => {
|
||||||
return {
|
return {
|
||||||
...mapWorkOrderAdmin(item),
|
...mapWorkOrderAdmin(item, sharesByOrderId.get(Number(item.id)) || []),
|
||||||
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(Number(item.id)) || 0,
|
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(Number(item.id)) || 0,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -1377,7 +1386,7 @@ export async function getAdminWorkOrderSharing(workOrderId: number | string) {
|
|||||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||||
const shares = await listWorkOrderShares(workOrder.id)
|
const shares = await listWorkOrderShares(workOrder.id)
|
||||||
return {
|
return {
|
||||||
order: mapWorkOrderAdmin(workOrder),
|
order: mapWorkOrderAdmin(workOrder, shares),
|
||||||
shares: shares.map(mapWorkOrderShare),
|
shares: shares.map(mapWorkOrderShare),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2428,7 +2437,7 @@ export async function syncWorkerOrdersForSourceOrder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
created: created.map(mapWorkOrderAdmin),
|
created: created.map((workOrder) => mapWorkOrderAdmin(workOrder)),
|
||||||
skipped,
|
skipped,
|
||||||
createdCount: created.length,
|
createdCount: created.length,
|
||||||
skippedCount: skipped.length,
|
skippedCount: skipped.length,
|
||||||
|
|||||||
@@ -341,7 +341,33 @@ export function resolveWorkOrderOperationalStatus(workOrder: WorkOrderRow): stri
|
|||||||
return workOrder.status
|
return workOrder.status
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapWorkOrderAdmin(workOrder: WorkOrderRow) {
|
/** 汇总拼单参与者,已撤销份额不应继续展示为当前打手。 */
|
||||||
|
export function mapWorkOrderSharingWorkers(shares: WorkOrderShareRow[]) {
|
||||||
|
const workers = new Map<
|
||||||
|
number,
|
||||||
|
{ workerId: number; username: string; displayName: string; quantity: number }
|
||||||
|
>()
|
||||||
|
for (const share of shares) {
|
||||||
|
if (share.status === 'cancelled') continue
|
||||||
|
const workerId = Number(share.worker_id || 0)
|
||||||
|
if (workerId <= 0) continue
|
||||||
|
const existing = workers.get(workerId)
|
||||||
|
if (existing) {
|
||||||
|
existing.quantity += Number(share.quantity || 0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const username = String(share.worker_username || '').trim()
|
||||||
|
workers.set(workerId, {
|
||||||
|
workerId,
|
||||||
|
username,
|
||||||
|
displayName: String(share.worker_display_name || username || `打手#${workerId}`).trim(),
|
||||||
|
quantity: Number(share.quantity || 0),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return [...workers.values()]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapWorkOrderAdmin(workOrder: WorkOrderRow, shares?: WorkOrderShareRow[]) {
|
||||||
const activeShareQuantity = Math.max(0, Number(workOrder.active_share_quantity || 0))
|
const activeShareQuantity = Math.max(0, Number(workOrder.active_share_quantity || 0))
|
||||||
const pendingShareCount = Math.max(0, Number(workOrder.pending_share_count || 0))
|
const pendingShareCount = Math.max(0, Number(workOrder.pending_share_count || 0))
|
||||||
const sharingTotalQuantity = Math.max(1, Number(workOrder.sharing_total_quantity || 1))
|
const sharingTotalQuantity = Math.max(1, Number(workOrder.sharing_total_quantity || 1))
|
||||||
@@ -437,6 +463,7 @@ export function mapWorkOrderAdmin(workOrder: WorkOrderRow) {
|
|||||||
displayName: workOrder.worker_display_name || '',
|
displayName: workOrder.worker_display_name || '',
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
...(shares ? { sharingWorkers: mapWorkOrderSharingWorkers(shares) } : {}),
|
||||||
publishedAt: workOrder.published_at,
|
publishedAt: workOrder.published_at,
|
||||||
pinnedAt: workOrder.pinned_at,
|
pinnedAt: workOrder.pinned_at,
|
||||||
assignedAt: workOrder.assigned_at,
|
assignedAt: workOrder.assigned_at,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
normalizeRequirementFields,
|
normalizeRequirementFields,
|
||||||
mapWorkOrderForWorker,
|
mapWorkOrderForWorker,
|
||||||
mapWorkOrderAdmin,
|
mapWorkOrderAdmin,
|
||||||
|
mapWorkOrderSharingWorkers,
|
||||||
maskWorkerLeaderboardDisplayName,
|
maskWorkerLeaderboardDisplayName,
|
||||||
resolveCollectSubmitTargetWorkOrder,
|
resolveCollectSubmitTargetWorkOrder,
|
||||||
resolveAdminMaterialRewardAmount,
|
resolveAdminMaterialRewardAmount,
|
||||||
@@ -733,6 +734,20 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
|
|||||||
assert.equal(filled.capabilities.canUnpublish, false)
|
assert.equal(filled.capabilities.canUnpublish, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('拼单打手汇总展示当前参与者并合并同一打手的份数', () => {
|
||||||
|
const workers = mapWorkOrderSharingWorkers([
|
||||||
|
buildWorkOrderShareRow({ worker_id: 1, quantity: 2, worker_username: 'alpha' }),
|
||||||
|
buildWorkOrderShareRow({ id: 2, worker_id: 1, quantity: 3, worker_username: 'alpha' }),
|
||||||
|
buildWorkOrderShareRow({ id: 3, worker_id: 2, quantity: 1, worker_display_name: 'Beta' }),
|
||||||
|
buildWorkOrderShareRow({ id: 4, worker_id: 3, quantity: 9, status: 'cancelled' }),
|
||||||
|
])
|
||||||
|
|
||||||
|
assert.deepEqual(workers, [
|
||||||
|
{ workerId: 1, username: 'alpha', displayName: 'alpha', quantity: 5 },
|
||||||
|
{ workerId: 2, username: '', displayName: 'Beta', quantity: 1 },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('拼单份额撤单只允许未验收份额并让母工单回到大厅状态', () => {
|
test('拼单份额撤单只允许未验收份额并让母工单回到大厅状态', () => {
|
||||||
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'joined'), 'open')
|
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'joined'), 'open')
|
||||||
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'submitted'), 'open')
|
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'submitted'), 'open')
|
||||||
|
|||||||
@@ -793,7 +793,7 @@ export default function WorkOrdersPanel() {
|
|||||||
{
|
{
|
||||||
title: '打手',
|
title: '打手',
|
||||||
width: 140,
|
width: 140,
|
||||||
render: (_, row) => row.worker?.displayName || row.worker?.username || '-',
|
render: (_, row) => renderWorkOrderWorkers(row),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '资料',
|
title: '资料',
|
||||||
@@ -1125,7 +1125,7 @@ export default function WorkOrdersPanel() {
|
|||||||
</Tag>
|
</Tag>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="打手">
|
<Descriptions.Item label="打手">
|
||||||
{detailOrder.worker?.displayName || detailOrder.worker?.username || '-'}
|
{renderWorkOrderWorkers(detailOrder)}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="接单金额">
|
<Descriptions.Item label="接单金额">
|
||||||
{formatMoney(detailOrder.rewardAmount)}
|
{formatMoney(detailOrder.rewardAmount)}
|
||||||
@@ -1928,6 +1928,24 @@ function formatUserPaymentAmount(order: WorkOrder): string {
|
|||||||
return paymentFen === null ? '-' : formatMoney(paymentFen)
|
return paymentFen === null ? '-' : formatMoney(paymentFen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 拼单母单没有单一 assigned worker,改为展示当前参与打手及其承接份数。 */
|
||||||
|
function renderWorkOrderWorkers(order: WorkOrder) {
|
||||||
|
if (order.worker) return order.worker.displayName || order.worker.username || '-'
|
||||||
|
if (!order.sharing?.enabled || !order.sharingWorkers?.length) return '-'
|
||||||
|
const names = order.sharingWorkers
|
||||||
|
.map((worker) => worker.displayName || worker.username || `打手#${worker.workerId}`)
|
||||||
|
.join('、')
|
||||||
|
const quantity = order.sharingWorkers.reduce((sum, worker) => sum + Number(worker.quantity || 0), 0)
|
||||||
|
return (
|
||||||
|
<div className="cell-stack">
|
||||||
|
<Typography.Text ellipsis={{ tooltip: names }}>{names}</Typography.Text>
|
||||||
|
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||||
|
{order.sharingWorkers.length} 人 · {quantity} 份
|
||||||
|
</Typography.Text>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function getDisplayOrderNo(order: Pick<WorkOrder, 'platformOrderId'> | null | undefined): string {
|
function getDisplayOrderNo(order: Pick<WorkOrder, 'platformOrderId'> | null | undefined): string {
|
||||||
return String(order?.platformOrderId || '').trim() || '-'
|
return String(order?.platformOrderId || '').trim() || '-'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,6 +400,13 @@ export type WorkOrder = {
|
|||||||
username: string
|
username: string
|
||||||
displayName: string
|
displayName: string
|
||||||
}
|
}
|
||||||
|
/** 拼单订单的当前参与打手,普通整单不返回该字段。 */
|
||||||
|
sharingWorkers?: Array<{
|
||||||
|
workerId: number
|
||||||
|
username: string
|
||||||
|
displayName: string
|
||||||
|
quantity: number
|
||||||
|
}>
|
||||||
publishedAt: string | null
|
publishedAt: string | null
|
||||||
/** 置顶时间;非空表示该工单在抢单大厅置顶展示 */
|
/** 置顶时间;非空表示该工单在抢单大厅置顶展示 */
|
||||||
pinnedAt?: string | null
|
pinnedAt?: string | null
|
||||||
|
|||||||
Reference in New Issue
Block a user