From a27467bfadec689bca87fbe7b88569942c2737c4 Mon Sep 17 00:00:00 2001 From: yml Date: Thu, 21 May 2026 16:51:32 +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=E7=AE=A1=E7=90=86=E5=86=99=E4=BE=A7=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/write/{shared.js => shared.ts} | 52 ++++++++++++------- .../{webhook-events.js => webhook-events.ts} | 10 ++-- docs/backend-typescript-migration-plan.md | 9 ++++ 3 files changed, 45 insertions(+), 26 deletions(-) rename apps/backend/src/services/admin/write/{shared.js => shared.ts} (70%) rename apps/backend/src/services/admin/write/{webhook-events.js => webhook-events.ts} (67%) diff --git a/apps/backend/src/services/admin/write/shared.js b/apps/backend/src/services/admin/write/shared.ts similarity index 70% rename from apps/backend/src/services/admin/write/shared.js rename to apps/backend/src/services/admin/write/shared.ts index e44ab606..2f6d6ca1 100644 --- a/apps/backend/src/services/admin/write/shared.js +++ b/apps/backend/src/services/admin/write/shared.ts @@ -1,5 +1,3 @@ -// @ts-check - import { buildClaimUrl, createTaskClaimToken } from '../../claim/claim-service.js' import { createHttpError } from '../../../utils/http.js' import { @@ -9,7 +7,27 @@ import { parseTaskContext, } from '../admin-read-shared-helpers.js' -export function maskPhone(value) { +import type { TaskRow } from '../../../types/repository-rows.js' + +type AssistedTaskAction = 'confirm' | 'redeem' + +type AdminViewerContextLike = { + canOperateAssistedTask?: boolean + [key: string]: unknown +} + +type TaskClaimLink = { + token: string + expiredAt: string | null + claimUrl: string +} + +type ErrorLike = { + errorCode?: string + code?: string +} + +export function maskPhone(value: unknown): string { const text = String(value || '').trim() if (!text) { return '' @@ -22,7 +40,7 @@ export function maskPhone(value) { return `${text.slice(0, 3)}****${text.slice(-4)}` } -export function maskCode(value) { +export function maskCode(value: unknown): string { const text = String(value || '').trim() if (!text) { return '' @@ -35,18 +53,17 @@ export function maskCode(value) { return `${text.slice(0, 4)}****${text.slice(-4)}` } -export function resolveTaskInventoryGroupCodes(task) { +export function resolveTaskInventoryGroupCodes(task: TaskRow): string[] | null { const taskContext = parseTaskContext(task) const inventoryGroupCode = String(taskContext?.inventoryGroupCode || '').trim() return inventoryGroupCode ? [inventoryGroupCode] : null } -/** - * @param {any} task - * @param {any} viewerContext - * @param {'confirm' | 'redeem'} action - */ -export function ensureViewerCanOperateAssistedTask(task, viewerContext, action) { +export function ensureViewerCanOperateAssistedTask( + task: TaskRow, + viewerContext: AdminViewerContextLike, + action: AssistedTaskAction, +): void { if (!viewerContext.canOperateAssistedTask || !isAssistedClaimTask(task)) { throw createHttpError('当前账号没有此操作权限', { statusCode: 403, @@ -69,12 +86,12 @@ export function ensureViewerCanOperateAssistedTask(task, viewerContext, action) } } -export function isRecoverableTaskSessionCloseError(error) { +export function isRecoverableTaskSessionCloseError(error: ErrorLike | null | undefined): boolean { const errorCode = String(error?.errorCode || error?.code || '').trim() return errorCode === 'session_not_found' || errorCode === 'session_closed' } -export function normalizeManualDispatchOutcome(value) { +export function normalizeManualDispatchOutcome(value: unknown): 'delivered' | 'failed' { const normalized = String(value || '').trim().toLowerCase() if (normalized === 'failed') { @@ -84,14 +101,11 @@ export function normalizeManualDispatchOutcome(value) { return 'delivered' } -export function getTaskClaimExpiresAt(task) { +export function getTaskClaimExpiresAt(task: Partial | null | undefined): string | null { return task?.claim_expires_at || task?.primary_claim_expires_at || null } -/** - * @param {any} task - */ -export async function ensureTaskClaimLink(task) { +export async function ensureTaskClaimLink(task: TaskRow): Promise { const tokenStatus = String(task?.primary_claim_token_status || '').trim() const token = String(task?.primary_claim_token || task?.claim_token || '').trim() const expiredAt = getTaskClaimExpiresAt(task) @@ -112,7 +126,7 @@ export async function ensureTaskClaimLink(task) { } } -function isClaimExpired(expiredAt) { +function isClaimExpired(expiredAt: string | null): boolean { if (!expiredAt) { return false } diff --git a/apps/backend/src/services/admin/write/webhook-events.js b/apps/backend/src/services/admin/write/webhook-events.ts similarity index 67% rename from apps/backend/src/services/admin/write/webhook-events.js rename to apps/backend/src/services/admin/write/webhook-events.ts index 72acb1e0..b0f7bdef 100644 --- a/apps/backend/src/services/admin/write/webhook-events.js +++ b/apps/backend/src/services/admin/write/webhook-events.ts @@ -1,15 +1,11 @@ -// @ts-check - import { getWebhookEventById } from '../../../repositories/webhook-event-repo.js' import { replayAgisoTradeWebhookEvent } from '../../order/webhook-service.js' import { createHttpError } from '../../../utils/http.js' -/** @typedef {import('../../../types/admin-read-inputs.js').AdminEntityIdInput} AdminEntityIdInput */ -/** @typedef {import('../../../types/admin-write-models.js').AdminWebhookReplayResponse} AdminWebhookReplayResponse */ +import type { AdminEntityIdInput } from '../../../types/admin-read-inputs.js' +import type { AdminWebhookReplayResponse } from '../../../types/admin-write-models.js' -/** @returns {Promise} */ -/** @param {AdminEntityIdInput} eventId */ -export async function replayAdminWebhookEvent(eventId) { +export async function replayAdminWebhookEvent(eventId: AdminEntityIdInput): Promise { const event = await getWebhookEventById(Number(eventId)) if (!event) { diff --git a/docs/backend-typescript-migration-plan.md b/docs/backend-typescript-migration-plan.md index 9f432509..b0a12273 100644 --- a/docs/backend-typescript-migration-plan.md +++ b/docs/backend-typescript-migration-plan.md @@ -726,6 +726,15 @@ - `npm run typecheck` - `npm run build` - `npm test` 共 139 个用例通过 +180. 后台 Admin 写侧共享 helper 与 Webhook 重放入口迁移到 `.ts`: + - `src/services/admin/write/shared.ts` + - `src/services/admin/write/webhook-events.ts` +181. Admin 脱敏、任务库存组解析、辅助领取权限校验、任务 claim 链接补齐、手动发货结果归一化、Webhook 重放入口已进入 TS 编译链路;任务 row、viewer context、错误对象、entity id 与重放响应补齐类型 +182. Docker 内验证通过: + - `src/services/admin/*.test.js` 共 8 个用例通过 + - `npm run typecheck` + - `npm run build` + - `npm test` 共 139 个用例通过 ## 下一步建议