后端迁移后台管理任务写操作

This commit is contained in:
yml
2026-05-21 17:02:50 +08:00
parent 4c92c3711d
commit cbf6b90313
2 changed files with 60 additions and 46 deletions
@@ -1,5 +1,3 @@
// @ts-check
import { import {
markInventoryItemDelivered, markInventoryItemDelivered,
releaseReservedInventoryItem, releaseReservedInventoryItem,
@@ -41,15 +39,31 @@ import {
resolveTaskInventoryGroupCodes, resolveTaskInventoryGroupCodes,
} from './shared.js' } from './shared.js'
/** @typedef {import('../../../types/admin-read-inputs.js').AdminEntityIdInput} AdminEntityIdInput */ import type {
/** @typedef {import('../../../types/admin-read-inputs.js').AdminViewerSessionInput} AdminViewerSessionInput */ AdminEntityIdInput,
/** @typedef {import('../../../types/admin-write-models.js').AdminTaskActionResponse} AdminTaskActionResponse */ AdminViewerSessionInput,
/** @typedef {import('../../../types/admin-write-models.js').AdminTaskBindingReleaseResponse} AdminTaskBindingReleaseResponse */ } from '../../../types/admin-read-inputs.js'
/** @typedef {import('../../../types/admin-write-models.js').AdminTaskManualDispatchResponse} AdminTaskManualDispatchResponse */ import type { AdminTaskManualDispatchInput } from '../../../types/admin-write-inputs.js'
import type {
AdminTaskActionResponse,
AdminTaskBindingReleaseResponse,
AdminTaskManualDispatchResponse,
} from '../../../types/admin-write-models.js'
import type { TaskRow } from '../../../types/repository-rows.js'
import type { TaskUpdatePatch } from '../../../types/repository-inputs.js'
/** @returns {Promise<AdminTaskActionResponse>} */ type CloseAdminTaskDeps = {
/** @param {AdminEntityIdInput} taskId */ getRequiredTask?: (taskId: AdminEntityIdInput) => Promise<TaskRow>
export async function releaseAdminTaskInventory(taskId) { listTaskInventoryBindingsByTaskId?: (taskId: AdminEntityIdInput) => Promise<any[]>
releaseReservedInventoryItem?: (inventoryItemId: AdminEntityIdInput, updatedAt: string) => Promise<unknown>
updateClaimToken?: (tokenId: AdminEntityIdInput, patch: Record<string, unknown>) => Promise<unknown>
updateTask?: (taskId: AdminEntityIdInput, patch: TaskUpdatePatch) => Promise<any>
createTaskEvent?: (taskId: AdminEntityIdInput, eventType: string, payload: Record<string, unknown>, createdAt: string) => Promise<unknown>
closeTencentBrowserSession?: (sessionId: string) => Promise<unknown>
nowIso?: () => string
}
export async function releaseAdminTaskInventory(taskId: AdminEntityIdInput): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const primaryInventoryItemId = getTaskPrimaryInventoryItemId(task) const primaryInventoryItemId = getTaskPrimaryInventoryItemId(task)
@@ -81,10 +95,10 @@ export async function releaseAdminTaskInventory(taskId) {
} }
} }
/** @returns {Promise<AdminTaskBindingReleaseResponse>} */ export async function releaseAdminTaskInventoryBinding(
/** @param {AdminEntityIdInput} taskId */ taskId: AdminEntityIdInput,
/** @param {AdminEntityIdInput} bindingId */ bindingId: AdminEntityIdInput,
export async function releaseAdminTaskInventoryBinding(taskId, bindingId) { ): Promise<AdminTaskBindingReleaseResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const binding = await getTaskInventoryBindingById(Number(bindingId)) const binding = await getTaskInventoryBindingById(Number(bindingId))
@@ -151,10 +165,10 @@ export async function releaseAdminTaskInventoryBinding(taskId, bindingId) {
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function regenerateAdminTaskClaimLink(
/** @param {AdminEntityIdInput} taskId */ taskId: AdminEntityIdInput,
/** @param {AdminViewerSessionInput | null} [session] */ session: AdminViewerSessionInput | null = null,
export async function regenerateAdminTaskClaimLink(taskId, session = null) { ): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const primaryClaimTokenId = getTaskPrimaryClaimTokenId(task) const primaryClaimTokenId = getTaskPrimaryClaimTokenId(task)
const viewerContext = createAdminViewerContext(session) const viewerContext = createAdminViewerContext(session)
@@ -204,10 +218,10 @@ export async function regenerateAdminTaskClaimLink(taskId, session = null) {
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function confirmAdminTaskAssistedRole(
/** @param {AdminEntityIdInput} taskId */ taskId: AdminEntityIdInput,
/** @param {AdminViewerSessionInput | null} [session] */ session: AdminViewerSessionInput | null = null,
export async function confirmAdminTaskAssistedRole(taskId, session = null) { ): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const viewerContext = createAdminViewerContext(session) const viewerContext = createAdminViewerContext(session)
ensureViewerCanOperateAssistedTask(task, viewerContext, 'confirm') ensureViewerCanOperateAssistedTask(task, viewerContext, 'confirm')
@@ -219,10 +233,10 @@ export async function confirmAdminTaskAssistedRole(taskId, session = null) {
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function redeemAdminTaskAssisted(
/** @param {AdminEntityIdInput} taskId */ taskId: AdminEntityIdInput,
/** @param {AdminViewerSessionInput | null} [session] */ session: AdminViewerSessionInput | null = null,
export async function redeemAdminTaskAssisted(taskId, session = null) { ): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const viewerContext = createAdminViewerContext(session) const viewerContext = createAdminViewerContext(session)
ensureViewerCanOperateAssistedTask(task, viewerContext, 'redeem') ensureViewerCanOperateAssistedTask(task, viewerContext, 'redeem')
@@ -234,16 +248,12 @@ export async function redeemAdminTaskAssisted(taskId, session = null) {
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function closeAdminTask(taskId: AdminEntityIdInput): Promise<AdminTaskActionResponse> {
/** @param {AdminEntityIdInput} taskId */
export async function closeAdminTask(taskId) {
return closeAdminTaskWithDeps(taskId) return closeAdminTaskWithDeps(taskId)
} }
/** @returns {Promise<AdminTaskActionResponse>} */
/** @param {AdminEntityIdInput} taskId */
export async function closeAdminTaskWithDeps( export async function closeAdminTaskWithDeps(
taskId, taskId: AdminEntityIdInput,
{ {
getRequiredTask: getTask = getRequiredTask, getRequiredTask: getTask = getRequiredTask,
listTaskInventoryBindingsByTaskId: listBindings = listTaskInventoryBindingsByTaskId, listTaskInventoryBindingsByTaskId: listBindings = listTaskInventoryBindingsByTaskId,
@@ -253,8 +263,8 @@ export async function closeAdminTaskWithDeps(
createTaskEvent: createEvent = createTaskEvent, createTaskEvent: createEvent = createTaskEvent,
closeTencentBrowserSession: closeSession = closeTencentBrowserSession, closeTencentBrowserSession: closeSession = closeTencentBrowserSession,
nowIso: getNowIso = nowIso, nowIso: getNowIso = nowIso,
} = {}, }: CloseAdminTaskDeps = {},
) { ): Promise<AdminTaskActionResponse> {
const task = await getTask(taskId) const task = await getTask(taskId)
if (task.task_status === 'redeemed') { if (task.task_status === 'redeemed') {
@@ -326,9 +336,7 @@ export async function closeAdminTaskWithDeps(
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function markAdminTaskManualReview(taskId: AdminEntityIdInput): Promise<AdminTaskActionResponse> {
/** @param {AdminEntityIdInput} taskId */
export async function markAdminTaskManualReview(taskId) {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const updatedTask = await updateTask(task.id, { const updatedTask = await updateTask(task.id, {
task_status: 'manual_review', task_status: 'manual_review',
@@ -342,9 +350,7 @@ export async function markAdminTaskManualReview(taskId) {
} }
} }
/** @returns {Promise<AdminTaskActionResponse>} */ export async function retryAdminTask(taskId: AdminEntityIdInput): Promise<AdminTaskActionResponse> {
/** @param {AdminEntityIdInput} taskId */
export async function retryAdminTask(taskId) {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
const now = nowIso() const now = nowIso()
@@ -408,7 +414,7 @@ export async function retryAdminTask(taskId) {
updated_at: now, updated_at: now,
}) })
const response = { const response: AdminTaskActionResponse = {
task: mapTaskActionPayload(updatedTask), task: mapTaskActionPayload(updatedTask),
} }
@@ -420,11 +426,11 @@ export async function retryAdminTask(taskId) {
return response return response
} }
/** @returns {Promise<AdminTaskManualDispatchResponse>} */ export async function completeAdminTaskManualDispatch(
/** @param {AdminEntityIdInput} taskId */ taskId: AdminEntityIdInput,
/** @param {{ outcome?: string, resultMessage?: string, deliveryReference?: string, deliveredCredential?: string }} [payload] */ payload: AdminTaskManualDispatchInput = {},
/** @param {AdminViewerSessionInput | null} [session] */ session: AdminViewerSessionInput | null = null,
export async function completeAdminTaskManualDispatch(taskId, payload = {}, session = null) { ): Promise<AdminTaskManualDispatchResponse> {
const task = await getRequiredTask(taskId) const task = await getRequiredTask(taskId)
if (!isManualDispatchTask(task)) { if (!isManualDispatchTask(task)) {
@@ -768,6 +768,14 @@
- `npm run typecheck` - `npm run typecheck`
- `npm run build` - `npm run build`
- `npm test` 共 139 个用例通过 - `npm test` 共 139 个用例通过
195. 后台 Admin 任务写操作迁移到 `.ts`
- `src/services/admin/write/task-actions.ts`
196. Admin 任务库存释放、绑定释放、领取链接重建、半自动确认 / 兑换、关闭任务、转人工复核、重试、人工履约回写已进入 TS 编译链路;entity id、viewer session、手动履约 input、action response、binding release response、依赖注入 close deps 与 task patch 补齐类型
197. Docker 内验证通过:
- `src/services/admin/*.test.js` 共 8 个用例通过
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
## 下一步建议 ## 下一步建议