From 7aef1a6d50d573ce9154211909485da3677ddef7 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Tue, 26 May 2026 08:45:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=90=AF=E5=90=8E=E7=AB=AF=E4=B8=A5?= =?UTF-8?q?=E6=A0=BC=E7=A9=BA=E5=80=BC=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend/src/routes/admin/orders.ts | 2 +- .../routes/admin/platform-config/ninetyone.ts | 4 +-- apps/backend/src/routes/admin/shared.ts | 11 +++++++ apps/backend/src/routes/admin/tasks.ts | 4 +-- apps/backend/src/routes/admin/users.ts | 8 ++--- .../src/services/admin/admin-auth-service.ts | 30 +++++++++++++++++-- .../src/services/admin/admin-read-service.ts | 3 +- .../admin/admin-read-shared-helpers.ts | 2 +- .../platform-config/cloudtentacles-service.ts | 4 +-- .../claim/kuaishou-cloud-claim-context.ts | 2 +- .../claim/kuaishou-cloud-claim-service.ts | 2 +- .../claim/kuaishou-cloud-sync-service.ts | 4 +-- .../kuaishou-cloud-task-service.ts | 4 +-- .../kuaishou-cloud/cloudtentacles-context.ts | 10 ++++++- .../kuaishou-cloud/task-finalization.ts | 6 ++++ .../services/order/delivery-task-service.ts | 26 ++++++++++------ .../cloudtentacles/debug-flow-service.ts | 6 ++-- .../kuaishou-eticket/source-config-service.ts | 2 +- .../src/services/scheduler/config-service.ts | 4 ++- apps/backend/src/utils/http.ts | 4 +-- apps/backend/tsconfig.json | 1 + 21 files changed, 101 insertions(+), 38 deletions(-) diff --git a/apps/backend/src/routes/admin/orders.ts b/apps/backend/src/routes/admin/orders.ts index bbdbc471..eb4f9d6d 100644 --- a/apps/backend/src/routes/admin/orders.ts +++ b/apps/backend/src/routes/admin/orders.ts @@ -19,7 +19,7 @@ router.get('/orders', createJsonHandler( )) router.get('/orders/:orderId', createJsonHandler( - (req) => getAdminOrderDetail((req.params as AdminOrderRouteParams).orderId), + (req) => getAdminOrderDetail(String((req.params as AdminOrderRouteParams).orderId || '')), { successMessage: 'ok', errorMessage: '读取订单详情失败', diff --git a/apps/backend/src/routes/admin/platform-config/ninetyone.ts b/apps/backend/src/routes/admin/platform-config/ninetyone.ts index 1da89d08..767112fe 100644 --- a/apps/backend/src/routes/admin/platform-config/ninetyone.ts +++ b/apps/backend/src/routes/admin/platform-config/ninetyone.ts @@ -23,7 +23,7 @@ router.get( router.post( "/ninetyone/orders/:id/retry", createJsonHandler( - (req) => retryAdminNinetyoneOrder((req.params as AdminEntityRouteParams).id), + (req) => retryAdminNinetyoneOrder(String((req.params as AdminEntityRouteParams).id || "")), { successMessage: "91卡券订单已重试", errorMessage: "重试 91卡券订单失败", @@ -49,7 +49,7 @@ router.post( createJsonHandler( (req) => failAdminNinetyoneOrder( - (req.params as AdminEntityRouteParams).id, + String((req.params as AdminEntityRouteParams).id || ""), req.body as { reason?: string } ), { diff --git a/apps/backend/src/routes/admin/shared.ts b/apps/backend/src/routes/admin/shared.ts index a00e302f..5bd5d5a3 100644 --- a/apps/backend/src/routes/admin/shared.ts +++ b/apps/backend/src/routes/admin/shared.ts @@ -73,6 +73,17 @@ export function requireAdminRoles(allowedRoles: string[]) { } } +export function getRequiredAdminSession(req: Request): AdminSession { + if (req.adminSession) { + return req.adminSession + } + + throw createHttpError('未登录或登录已失效', { + statusCode: 401, + errorCode: 'admin_auth_required', + }) +} + async function recordAdminAudit( session: AdminSession | null | undefined, req: Request, diff --git a/apps/backend/src/routes/admin/tasks.ts b/apps/backend/src/routes/admin/tasks.ts index 038d89af..68ccc81d 100644 --- a/apps/backend/src/routes/admin/tasks.ts +++ b/apps/backend/src/routes/admin/tasks.ts @@ -24,8 +24,8 @@ import type { AdminTaskActionResponse } from "../../types/admin-write-models.js" const router = Router(); -function getTaskId(req: Request): string | undefined { - return (req.params as AdminTaskRouteParams).taskId; +function getTaskId(req: Request): string { + return String((req.params as AdminTaskRouteParams).taskId || ""); } router.get( diff --git a/apps/backend/src/routes/admin/users.ts b/apps/backend/src/routes/admin/users.ts index 45f532b5..66f16973 100644 --- a/apps/backend/src/routes/admin/users.ts +++ b/apps/backend/src/routes/admin/users.ts @@ -7,7 +7,7 @@ import { updateManagedAdminUserRole, updateManagedAdminUserStatus, } from '../../services/admin/admin-auth-service.js' -import { createJsonHandler, requireAdminRoles } from './shared.js' +import { createJsonHandler, getRequiredAdminSession, requireAdminRoles } from './shared.js' type AdminUserMutationResult = { user: { @@ -54,7 +54,7 @@ router.post('/users', createJsonHandler( )) router.post('/users/:userId/role', createJsonHandler( - (req) => updateManagedAdminUserRole(String(req.params.userId), req.body, req.adminSession), + (req) => updateManagedAdminUserRole(String(req.params.userId || ''), req.body, getRequiredAdminSession(req)), { successMessage: '用户角色已更新', errorMessage: '更新用户角色失败', @@ -75,7 +75,7 @@ router.post('/users/:userId/role', createJsonHandler( )) router.post('/users/:userId/status', createJsonHandler( - (req) => updateManagedAdminUserStatus(String(req.params.userId), req.body, req.adminSession), + (req) => updateManagedAdminUserStatus(String(req.params.userId || ''), req.body, getRequiredAdminSession(req)), { successMessage: '用户状态已更新', errorMessage: '更新用户状态失败', @@ -96,7 +96,7 @@ router.post('/users/:userId/status', createJsonHandler( )) router.post('/users/:userId/reset-password', createJsonHandler( - (req) => resetManagedAdminUserPassword(String(req.params.userId), req.body), + (req) => resetManagedAdminUserPassword(String(req.params.userId || ''), req.body), { successMessage: '用户密码已重置', errorMessage: '重置用户密码失败', diff --git a/apps/backend/src/services/admin/admin-auth-service.ts b/apps/backend/src/services/admin/admin-auth-service.ts index 13d2294a..4fb558ba 100644 --- a/apps/backend/src/services/admin/admin-auth-service.ts +++ b/apps/backend/src/services/admin/admin-auth-service.ts @@ -171,8 +171,8 @@ export async function getAdminSessionSummary(token: unknown): Promise> { +): Promise { return syncDeliveryTasksForOrderWithDeps(order, orderItems) } @@ -77,7 +77,7 @@ export async function syncDeliveryTasksForOrderWithDeps( order: OrderRow, orderItems: OrderItemRow[], deps: DeliveryTaskDeps = {}, -): Promise> { +): Promise { const { createTask: createDeliveryTask = createTask, listTasksByOrderId: listTasks = listTasksByOrderId, @@ -104,11 +104,12 @@ export async function syncDeliveryTasksForOrderWithDeps( } const itemMap = new Map(orderItems.map((item) => [item.id, item])) - return Promise.all(existingTasks.map((task) => preparePaidTask({ + const preparedTasks = await Promise.all(existingTasks.map((task) => preparePaidTask({ ...task, skuCode: itemMap.get(task.order_item_id)?.sku_code || '', skuName: itemMap.get(task.order_item_id)?.sku_name || '', }, runtimeDeps))) + return preparedTasks.filter(isTaskRow) } const tasks: DeliveryTaskRow[] = [] @@ -243,11 +244,13 @@ export async function syncDeliveryTasksForOrderWithDeps( updatedAt: createdAt, }) - tasks.push({ - ...task, - skuCode: item.sku_code, - skuName: item.sku_name, - }) + if (task) { + tasks.push({ + ...task, + skuCode: item.sku_code, + skuName: item.sku_name, + }) + } } } @@ -255,7 +258,8 @@ export async function syncDeliveryTasksForOrderWithDeps( return tasks } - return Promise.all(tasks.map((task) => preparePaidTask(task, runtimeDeps))) + const preparedTasks = await Promise.all(tasks.map((task) => preparePaidTask(task, runtimeDeps))) + return preparedTasks.filter(isTaskRow) } async function preparePaidTask( @@ -380,6 +384,10 @@ function parseJsonObject(value: unknown): JsonObject { } } +function isTaskRow(task: TaskRow | DeliveryTaskRow | null | undefined): task is TaskRow { + return Boolean(task && Number(task.id || 0) > 0) +} + function isKuaishouCloudExecutor(value: unknown): boolean { return String(value || '').trim() === 'kuaishou_ct_assisted' } diff --git a/apps/backend/src/services/platforms/cloudtentacles/debug-flow-service.ts b/apps/backend/src/services/platforms/cloudtentacles/debug-flow-service.ts index affde4f3..4f933f65 100644 --- a/apps/backend/src/services/platforms/cloudtentacles/debug-flow-service.ts +++ b/apps/backend/src/services/platforms/cloudtentacles/debug-flow-service.ts @@ -181,8 +181,10 @@ async function runFlowStep( runner: () => Promise, options: FlowStepOptions = {}, ) { - const retries = Number.isInteger(options.retries) && options.retries > 0 ? options.retries : 0 - const retryDelayMs = Number.isFinite(options.retryDelayMs) && options.retryDelayMs > 0 ? options.retryDelayMs : 1000 + const rawRetries = Number(options.retries) + const rawRetryDelayMs = Number(options.retryDelayMs) + const retries = Number.isInteger(rawRetries) && rawRetries > 0 ? rawRetries : 0 + const retryDelayMs = Number.isFinite(rawRetryDelayMs) && rawRetryDelayMs > 0 ? rawRetryDelayMs : 1000 for (let attempt = 0; attempt <= retries; attempt += 1) { try { diff --git a/apps/backend/src/services/platforms/kuaishou-eticket/source-config-service.ts b/apps/backend/src/services/platforms/kuaishou-eticket/source-config-service.ts index 2e2a2c08..716ce122 100644 --- a/apps/backend/src/services/platforms/kuaishou-eticket/source-config-service.ts +++ b/apps/backend/src/services/platforms/kuaishou-eticket/source-config-service.ts @@ -100,7 +100,7 @@ function normalizeKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticke baseUrl: String(source.baseUrl || DEFAULT_BASE_URL).trim() || DEFAULT_BASE_URL, shops: shops .map((item) => normalizeKuaishouEticketShopConfig(item)) - .filter(Boolean), + .filter((item): item is KuaishouEticketShopConfig => Boolean(item)), } } diff --git a/apps/backend/src/services/scheduler/config-service.ts b/apps/backend/src/services/scheduler/config-service.ts index 3aa053da..21a11a05 100644 --- a/apps/backend/src/services/scheduler/config-service.ts +++ b/apps/backend/src/services/scheduler/config-service.ts @@ -37,7 +37,9 @@ function loadScheduledJobsConfigFromFile() { export function normalizeScheduledJobsConfig(rawValue: unknown) { const source = isPlainObject(rawValue) ? rawValue : {} const rawJobs = Array.isArray(source.jobs) ? source.jobs : [] - const jobs = rawJobs.map((item) => normalizeScheduledJob(item)).filter(Boolean) + const jobs = rawJobs + .map((item) => normalizeScheduledJob(item)) + .filter((item): item is ReturnType => Boolean(item)) const hasCloudtentaclesHealth = jobs.some((item) => item.id === CLOUDTENTACLES_HEALTH_JOB_ID) if (!hasCloudtentaclesHealth) { diff --git a/apps/backend/src/utils/http.ts b/apps/backend/src/utils/http.ts index 15c9f918..7e1c0569 100644 --- a/apps/backend/src/utils/http.ts +++ b/apps/backend/src/utils/http.ts @@ -45,8 +45,8 @@ export function buildErrorPayload(error: unknown, fallbackMessage: string) { export function sendRouteError( res: Response, error: unknown, - fallbackMessage: string, - scope: string + fallbackMessage = "服务内部错误", + scope = "[route]" ): void { const classification = classifyRouteError(error); const logger = classification.statusCode >= 500 ? logError : logWarn; diff --git a/apps/backend/tsconfig.json b/apps/backend/tsconfig.json index cb7c5ef6..da0b9aed 100644 --- a/apps/backend/tsconfig.json +++ b/apps/backend/tsconfig.json @@ -8,6 +8,7 @@ "noEmit": true, "strict": false, "noImplicitAny": true, + "strictNullChecks": true, "skipLibCheck": true, "types": ["node"], "lib": ["ES2022"]