From 2c9f741873c77a402686b7c9b31835dff53a55d7 Mon Sep 17 00:00:00 2001 From: zhaoxing <2558691827@qq.com> Date: Mon, 26 Oct 2026 12:41:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=92=A4=E5=8D=95=E4=B9=8B=E5=90=8E=20?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=8C=87=E6=B4=BE=E7=BB=99=E4=BD=A0=E5=90=8C?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=89=93=E6=89=8B=20=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E8=AE=A2=E5=8D=95=20=E4=B8=8D=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=8F=B7=E4=B8=8D=E6=98=BE=E7=A4=BA=E4=BB=BB?= =?UTF-8?q?=E4=BD=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../worker-platform/work-order-query-repo.ts | 3 +++ .../worker-my-order-service.ts | 13 +++++---- .../worker-platform-service.test.ts | 27 +++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/apps/backend/src/repositories/worker-platform/work-order-query-repo.ts b/apps/backend/src/repositories/worker-platform/work-order-query-repo.ts index 72dbcd70..03a72865 100644 --- a/apps/backend/src/repositories/worker-platform/work-order-query-repo.ts +++ b/apps/backend/src/repositories/worker-platform/work-order-query-repo.ts @@ -1256,6 +1256,9 @@ export function buildWorkOrderWhere({ FROM work_order_shares wos WHERE wos.work_order_id = wo.id AND wos.worker_id = ${workerSharePlaceholder}::bigint + -- 当前接单人就是本人时,旧的已取消份额不能再代表这张单: + -- 撤单后把同一单重新指派给同一打手,否则列表会一直判成「已取消」。 + AND NOT (wos.status = 'cancelled' AND wo.assigned_worker_id = ${workerSharePlaceholder}::bigint) ORDER BY CASE wos.status WHEN 'joined' THEN 0 diff --git a/apps/backend/src/services/worker-platform/worker-my-order-service.ts b/apps/backend/src/services/worker-platform/worker-my-order-service.ts index 76f837a9..11802692 100644 --- a/apps/backend/src/services/worker-platform/worker-my-order-service.ts +++ b/apps/backend/src/services/worker-platform/worker-my-order-service.ts @@ -167,11 +167,14 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker const cancelledShare = cancelledShareByOrderId.get(workOrderId) const timeoutEvent = timeoutEventsByOrderId.get(workOrderId) + const assignedToMe = + item.assigned_worker_id != null && Number(item.assigned_worker_id) === Number(worker.id) + // 当前接单人就是本人时,旧的已取消份额只作历史留痕,不能再参与状态判定: + // 撤单后重新指派给同一打手,否则会被映射成「已取消」,按钮全部不可用。 + const fallbackCancelledShare = assignedToMe ? null : cancelledShare + // 判断当前打手是否仍持有该单(任一有效份额即算持有) - const isOwnerCurrently = - (item.assigned_worker_id != null && - Number(item.assigned_worker_id) === Number(worker.id)) || - activeShares.length > 0 + const isOwnerCurrently = assignedToMe || activeShares.length > 0 // 若不是当前持有人,但有该打手的超时事件或取消份额,则判定为该打手的已超时历史单 const isTimedOutForMe = @@ -219,7 +222,7 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker ...mapWorkOrderForWorker( item, permissions, - activeShare || cancelledShare || null, + activeShare || fallbackCancelledShare || null, noteByOrderId.get(workOrderId) || '', viewedAtByOrderId.get(workOrderId) || null, { isTimedOutForMe, timeoutNotice, myShares: activeShares }, diff --git a/apps/backend/src/services/worker-platform/worker-platform-service.test.ts b/apps/backend/src/services/worker-platform/worker-platform-service.test.ts index 00511954..2ec7c59b 100644 --- a/apps/backend/src/services/worker-platform/worker-platform-service.test.ts +++ b/apps/backend/src/services/worker-platform/worker-platform-service.test.ts @@ -3547,3 +3547,30 @@ test('取消部分:只取消未验收份额并保留已验收,剩余份数 ) assert.ok(mapperSrc.includes('canCancelSharingPart:'), '前端按钮依赖 canCancelSharingPart 能力位') }) + +test('撤单后重派同一打手:旧已取消份额不得把当前接单状态判成已取消', () => { + const querySrc = fs.readFileSync( + new URL('../../repositories/worker-platform/work-order-query-repo.ts', import.meta.url), + 'utf8', + ) + assert.ok( + querySrc.includes( + "AND NOT (wos.status = 'cancelled' AND wo.assigned_worker_id = ${workerSharePlaceholder}::bigint)", + ), + '当前接单人就是本人时,代表份额必须排除已取消份额,否则列表会判成「已取消」', + ) + + const serviceSrc = fs.readFileSync( + new URL('./worker-my-order-service.ts', import.meta.url), + 'utf8', + ) + assert.ok( + serviceSrc.includes('const assignedToMe =') && + serviceSrc.includes('const fallbackCancelledShare = assignedToMe ? null : cancelledShare'), + '当前接单人就是本人时,不得把已取消份额当 myShare 传给映射', + ) + assert.ok( + serviceSrc.includes('activeShare || fallbackCancelledShare || null'), + '列表映射必须使用排除后的已取消份额兜底', + ) +})