// @ts-check import { Router } from 'express' import { closeAdminTask, completeAdminTaskManualDispatch, confirmAdminTaskAssistedRole, markAdminTaskManualReview, regenerateAdminTaskClaimLink, redeemAdminTaskAssisted, releaseAdminTaskInventoryBinding, releaseAdminTaskInventory, retryAdminTask, } from '../../services/admin/admin-write-service.js' import { getAdminTaskDetail, getAdminTaskScreenshotPath, 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').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 */ const router = Router() router.get('/tasks', createJsonHandler( (req) => getAdminTasks( /** @type {AdminTaskRouteQuery} */ (req.query), /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { successMessage: 'ok', errorMessage: '读取任务列表失败', scope: '[admin/tasks]', }, )) router.get('/tasks/:taskId', createJsonHandler( (req) => getAdminTaskDetail( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { successMessage: 'ok', errorMessage: '读取任务详情失败', scope: '[admin/tasks/:taskId]', }, )) router.get('/tasks/:taskId/screenshot', createFileHandler( (req) => getAdminTaskScreenshotPath( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { errorMessage: '读取任务截图失败', scope: '[admin/tasks/:taskId/screenshot]', }, )) router.post('/tasks/:taskId/retry', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => retryAdminTask((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), { successMessage: '任务已重试', errorMessage: '重试任务失败', scope: '[admin/tasks/:taskId/retry]', }, )) router.post('/tasks/:taskId/release-inventory', requireAdminRoles(['admin']), createJsonHandler( (req) => releaseAdminTaskInventory((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), { successMessage: '库存凭据已释放', errorMessage: '释放库存凭据失败', scope: '[admin/tasks/:taskId/release-inventory]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/inventory-bindings/:bindingId/release', requireAdminRoles(['admin']), createJsonHandler( (req) => releaseAdminTaskInventoryBinding( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, (/** @type {AdminTaskRouteParams} */ (req.params)).bindingId, ), { successMessage: '库存绑定已释放', errorMessage: '释放库存绑定失败', scope: '[admin/tasks/:taskId/inventory-bindings/:bindingId/release]', audit: (req, data) => { const result = /** @type {AdminTaskBindingReleaseResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/regenerate-claim-link', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => regenerateAdminTaskClaimLink( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { successMessage: '领取链接已重新生成', errorMessage: '重新生成领取链接失败', scope: '[admin/tasks/:taskId/regenerate-claim-link]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/support-confirm-role', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => confirmAdminTaskAssistedRole( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { successMessage: '角色已确认', errorMessage: '客服确认角色失败', scope: '[admin/tasks/:taskId/support-confirm-role]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/support-redeem', requireAdminRoles(['admin', 'operator', 'support']), createJsonHandler( (req) => redeemAdminTaskAssisted( (/** @type {AdminTaskRouteParams} */ (req.params)).taskId, /** @type {AdminRouteAdminSession | null} */ (req.adminSession), ), { successMessage: '兑换任务已启动', errorMessage: '客服发起兑换失败', scope: '[admin/tasks/:taskId/support-redeem]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/close', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => closeAdminTask((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), { successMessage: '任务已关闭', errorMessage: '关闭任务失败', scope: '[admin/tasks/:taskId/close]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) router.post('/tasks/:taskId/mark-manual-review', requireAdminRoles(['admin', 'operator']), createJsonHandler( (req) => markAdminTaskManualReview((/** @type {AdminTaskRouteParams} */ (req.params)).taskId), { successMessage: '任务已转人工处理', errorMessage: '标记人工处理失败', scope: '[admin/tasks/:taskId/mark-manual-review]', audit: (req, data) => { const result = /** @type {AdminTaskActionResponse} */ (data) 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, }, } }, }, )) 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), ), { successMessage: '人工履约结果已回写', errorMessage: '回写人工履约结果失败', scope: '[admin/tasks/:taskId/complete-manual-dispatch]', audit: (req, data) => { const result = /** @type {AdminTaskManualDispatchResponse} */ (data) 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, }, } }, }, )) export default router