From 7be787c2329bd908a241e0636f496c5029bb715d Mon Sep 17 00:00:00 2001 From: yml Date: Thu, 21 May 2026 17:26:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=E8=BF=81=E7=A7=BB=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E4=BB=BB=E5=8A=A1=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/routes/admin/{tasks.js => tasks.ts} | 261 +++++++++--------- docs/backend-typescript-migration-plan.md | 7 + 2 files changed, 142 insertions(+), 126 deletions(-) rename apps/backend/src/routes/admin/{tasks.js => tasks.ts} (51%) diff --git a/apps/backend/src/routes/admin/tasks.js b/apps/backend/src/routes/admin/tasks.ts similarity index 51% rename from apps/backend/src/routes/admin/tasks.js rename to apps/backend/src/routes/admin/tasks.ts index 2284752e..75a60fc6 100644 --- a/apps/backend/src/routes/admin/tasks.js +++ b/apps/backend/src/routes/admin/tasks.ts @@ -1,5 +1,3 @@ -// @ts-check - import { Router } from 'express' import { @@ -23,22 +21,33 @@ import { getAdminTasks, } from '../../services/admin/admin-read-service.js' import { createFileHandler, createJsonHandler, requireAdminRoles } from './shared.js' - -/** @typedef {import('../../types/admin-route-inputs.js').AdminRouteAdminSession} AdminRouteAdminSession */ -/** @typedef {import('../../types/admin-route-inputs.js').AdminTaskKuaishouCloudDispatchRouteBody} AdminTaskKuaishouCloudDispatchRouteBody */ -/** @typedef {import('../../types/admin-route-inputs.js').AdminTaskManualDispatchRouteBody} AdminTaskManualDispatchRouteBody */ -/** @typedef {import('../../types/admin-route-inputs.js').AdminTaskRouteParams} AdminTaskRouteParams */ -/** @typedef {import('../../types/admin-route-inputs.js').AdminTaskRouteQuery} AdminTaskRouteQuery */ -/** @typedef {import('../../types/admin-write-models.js').AdminTaskActionResponse} AdminTaskActionResponse */ -/** @typedef {import('../../types/admin-write-models.js').AdminTaskBindingReleaseResponse} AdminTaskBindingReleaseResponse */ -/** @typedef {import('../../types/admin-write-models.js').AdminTaskManualDispatchResponse} AdminTaskManualDispatchResponse */ +import type { AdminExpressRequest } from './shared.js' +import type { + AdminTaskKuaishouCloudDispatchRouteBody, + AdminTaskManualDispatchRouteBody, + AdminTaskRouteParams, + AdminTaskRouteQuery, +} from '../../types/admin-route-inputs.js' +import type { + AdminTaskActionResponse, + AdminTaskBindingReleaseResponse, + AdminTaskManualDispatchResponse, +} from '../../types/admin-write-models.js' const router = Router() +function getTaskId(req: AdminExpressRequest): string | undefined { + return (req.params as AdminTaskRouteParams).taskId +} + +function getBindingId(req: AdminExpressRequest): string | undefined { + return (req.params as AdminTaskRouteParams).bindingId +} + router.get('/tasks', createJsonHandler( (req) => getAdminTasks( - /** @type {AdminTaskRouteQuery} */ (req.query), - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + req.query as AdminTaskRouteQuery, + req.adminSession || null, ), { successMessage: 'ok', @@ -49,8 +58,8 @@ router.get('/tasks', createJsonHandler( router.get('/tasks/:taskId', createJsonHandler( (req) => getAdminTaskDetail( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: 'ok', @@ -61,8 +70,8 @@ router.get('/tasks/:taskId', createJsonHandler( router.get('/tasks/:taskId/screenshot', createFileHandler( (req) => getAdminTaskScreenshotPath( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { errorMessage: '读取任务截图失败', @@ -71,7 +80,7 @@ router.get('/tasks/:taskId/screenshot', createFileHandler( )) router.post('/tasks/:taskId/retry', requireAdminRoles(['admin', 'operator']), createJsonHandler( - (req) => retryAdminTask((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + (req) => retryAdminTask(getTaskId(req)), { successMessage: '任务已重试', errorMessage: '重试任务失败', @@ -80,22 +89,22 @@ router.post('/tasks/:taskId/retry', requireAdminRoles(['admin', 'operator']), cr )) router.post('/tasks/:taskId/release-inventory', requireAdminRoles(['admin']), createJsonHandler( - (req) => releaseAdminTaskInventory((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + (req) => releaseAdminTaskInventory(getTaskId(req)), { successMessage: '库存凭据已释放', errorMessage: '释放库存凭据失败', scope: '[admin/tasks/:taskId/release-inventory]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_release_inventory', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - inventoryItemId: result.task.inventoryItemId, - }, + action: 'task_release_inventory', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + inventoryItemId: result.task.inventoryItemId, + }, } }, }, @@ -103,25 +112,25 @@ router.post('/tasks/:taskId/release-inventory', requireAdminRoles(['admin']), cr router.post('/tasks/:taskId/inventory-bindings/:bindingId/release', requireAdminRoles(['admin']), createJsonHandler( (req) => releaseAdminTaskInventoryBinding( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - (/** @type {AdminTaskRouteParams} */ (req.params)).bindingId, + getTaskId(req), + getBindingId(req), ), { successMessage: '库存绑定已释放', errorMessage: '释放库存绑定失败', scope: '[admin/tasks/:taskId/inventory-bindings/:bindingId/release]', audit: (req, data) => { - const result = /** @type {AdminTaskBindingReleaseResponse} */ (data) + const result = data as AdminTaskBindingReleaseResponse return { - action: 'task_release_inventory_binding', - targetType: 'task_inventory_binding', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).bindingId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - bindingId: result.bindingId, - inventoryItemId: result.inventoryItemId, - }, + action: 'task_release_inventory_binding', + targetType: 'task_inventory_binding', + targetId: String(getBindingId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + bindingId: result.bindingId, + inventoryItemId: result.inventoryItemId, + }, } }, }, @@ -129,24 +138,24 @@ router.post('/tasks/:taskId/inventory-bindings/:bindingId/release', requireAdmin router.post('/tasks/:taskId/regenerate-claim-link', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => regenerateAdminTaskClaimLink( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '领取链接已重新生成', errorMessage: '重新生成领取链接失败', scope: '[admin/tasks/:taskId/regenerate-claim-link]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_regenerate_claim_link', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - primaryClaimTokenId: result.task.primaryClaimTokenId, - }, + action: 'task_regenerate_claim_link', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + primaryClaimTokenId: result.task.primaryClaimTokenId, + }, } }, }, @@ -154,24 +163,24 @@ router.post('/tasks/:taskId/regenerate-claim-link', requireAdminRoles(['admin', router.post('/tasks/:taskId/support-confirm-role', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => confirmAdminTaskAssistedRole( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '角色已确认', errorMessage: '客服确认角色失败', scope: '[admin/tasks/:taskId/support-confirm-role]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_support_confirm_role', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - status: result.task.status, - }, + action: 'task_support_confirm_role', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + status: result.task.status, + }, } }, }, @@ -179,69 +188,69 @@ router.post('/tasks/:taskId/support-confirm-role', requireAdminRoles(['admin', ' router.post('/tasks/:taskId/support-redeem', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => redeemAdminTaskAssisted( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '兑换任务已启动', errorMessage: '客服发起兑换失败', scope: '[admin/tasks/:taskId/support-redeem]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_support_redeem', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - status: result.task.status, - deliveryStatus: result.task.deliveryStatus, - }, + action: 'task_support_redeem', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + status: result.task.status, + deliveryStatus: result.task.deliveryStatus, + }, } }, }, )) router.post('/tasks/:taskId/close', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( - (req) => closeAdminTask((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + (req) => closeAdminTask(getTaskId(req)), { successMessage: '任务已关闭', errorMessage: '关闭任务失败', scope: '[admin/tasks/:taskId/close]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_closed', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - status: result.task.status, - }, + action: 'task_closed', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + status: result.task.status, + }, } }, }, )) router.post('/tasks/:taskId/mark-manual-review', requireAdminRoles(['admin', 'operator']), createJsonHandler( - (req) => markAdminTaskManualReview((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + (req) => markAdminTaskManualReview(getTaskId(req)), { successMessage: '任务已转人工处理', errorMessage: '标记人工处理失败', scope: '[admin/tasks/:taskId/mark-manual-review]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { - action: 'task_mark_manual_review', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - status: result.task.status, - }, + action: 'task_mark_manual_review', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + status: result.task.status, + }, } }, }, @@ -249,27 +258,27 @@ router.post('/tasks/:taskId/mark-manual-review', requireAdminRoles(['admin', 'op router.post('/tasks/:taskId/complete-manual-dispatch', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => completeAdminTaskManualDispatch( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminTaskManualDispatchRouteBody} */ (req.body), - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.body as AdminTaskManualDispatchRouteBody, + req.adminSession || null, ), { successMessage: '人工履约结果已回写', errorMessage: '回写人工履约结果失败', scope: '[admin/tasks/:taskId/complete-manual-dispatch]', audit: (req, data) => { - const result = /** @type {AdminTaskManualDispatchResponse} */ (data) + const result = data as AdminTaskManualDispatchResponse return { - action: 'task_complete_manual_dispatch', - targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), - data: { - taskId: result.task.taskId, - taskNo: result.task.taskNo, - outcome: result.outcome, - deliveryStatus: result.task.deliveryStatus, - resultCode: result.task.resultCode, - }, + action: 'task_complete_manual_dispatch', + targetType: 'task', + targetId: String(getTaskId(req)), + data: { + taskId: result.task.taskId, + taskNo: result.task.taskNo, + outcome: result.outcome, + deliveryStatus: result.task.deliveryStatus, + resultCode: result.task.resultCode, + }, } }, }, @@ -277,19 +286,19 @@ router.post('/tasks/:taskId/complete-manual-dispatch', requireAdminRoles(['admin router.post('/tasks/:taskId/kuaishou-cloud/prepare', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => prepareAdminTaskKuaishouCloudFulfillment( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '绑定资源已准备完成', errorMessage: '准备绑定资源失败', scope: '[admin/tasks/:taskId/kuaishou-cloud/prepare]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { action: 'task_kuaishou_cloud_prepare', targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + targetId: String(getTaskId(req)), data: { taskId: result.task.taskId, taskNo: result.task.taskNo, @@ -302,19 +311,19 @@ router.post('/tasks/:taskId/kuaishou-cloud/prepare', requireAdminRoles(['admin', router.post('/tasks/:taskId/kuaishou-cloud/refresh-role-info', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => refreshAdminTaskKuaishouCloudRoleInfo( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '角色信息已刷新', errorMessage: '刷新角色信息失败', scope: '[admin/tasks/:taskId/kuaishou-cloud/refresh-role-info]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { action: 'task_kuaishou_cloud_role_info_refreshed', targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + targetId: String(getTaskId(req)), data: { taskId: result.task.taskId, taskNo: result.task.taskNo, @@ -327,21 +336,21 @@ router.post('/tasks/:taskId/kuaishou-cloud/refresh-role-info', requireAdminRoles router.post('/tasks/:taskId/kuaishou-cloud/dispatch', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => dispatchAdminTaskKuaishouCloudFulfillment( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminTaskKuaishouCloudDispatchRouteBody} */ (req.body), - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.body as AdminTaskKuaishouCloudDispatchRouteBody, + req.adminSession || null, ), { successMessage: '已完成绑定确认并发货', errorMessage: '执行发货失败', scope: '[admin/tasks/:taskId/kuaishou-cloud/dispatch]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) - const body = /** @type {AdminTaskKuaishouCloudDispatchRouteBody} */ (req.body) + const result = data as AdminTaskActionResponse + const body = req.body as AdminTaskKuaishouCloudDispatchRouteBody return { action: 'task_kuaishou_cloud_dispatch', targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + targetId: String(getTaskId(req)), data: { taskId: result.task.taskId, taskNo: result.task.taskNo, @@ -356,19 +365,19 @@ router.post('/tasks/:taskId/kuaishou-cloud/dispatch', requireAdminRoles(['admin' router.post('/tasks/:taskId/kuaishou-cloud/return-number', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => returnNumberAdminTaskKuaishouCloudFulfillment( - (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, - /** @type {AdminRouteAdminSession | null} */ (req.adminSession), + getTaskId(req), + req.adminSession || null, ), { successMessage: '号码已退还', errorMessage: '退还号码失败', scope: '[admin/tasks/:taskId/kuaishou-cloud/return-number]', audit: (req, data) => { - const result = /** @type {AdminTaskActionResponse} */ (data) + const result = data as AdminTaskActionResponse return { action: 'task_kuaishou_cloud_return_number', targetType: 'task', - targetId: String((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), + targetId: String(getTaskId(req)), data: { taskId: result.task.taskId, taskNo: result.task.taskNo, diff --git a/docs/backend-typescript-migration-plan.md b/docs/backend-typescript-migration-plan.md index 2969010e..db88a461 100644 --- a/docs/backend-typescript-migration-plan.md +++ b/docs/backend-typescript-migration-plan.md @@ -836,6 +836,13 @@ - `npm run typecheck` - `npm run build` - `npm test` 共 139 个用例通过 +218. 后台任务管理路由迁移到 `.ts`: + - `src/routes/admin/tasks.ts` +219. 后台任务列表 / 详情 / 截图、重试、库存释放、绑定释放、领取链接重建、客服确认 / 兑换、关闭、转人工、人工履约回写、快手 Cloud 准备 / 刷新角色 / 发货 / 退号路由已进入 TS 编译链路;route query、params、manual dispatch body、kuaishou cloud dispatch body、task action response、binding release response 与 manual dispatch response 补齐类型,并收敛 taskId / bindingId 解析 helper +220. Docker 内验证通过: + - `npm run typecheck` + - `npm run build` + - `npm test` 共 139 个用例通过 ## 下一步建议