接入 ESLint 并清理未使用代码
- 前后端接入 ESLint 10 扁平配置(typescript-eslint 类型感知检查 + react-hooks/react-refresh),新增 lint / lint:check / lint:fix 脚本并纳入 check 链路 - 清理全部 no-unused-vars 与 no-useless-assignment 警告,修复 floating promises、正则转义等问题 - 删除确认无引用的死代码(markKuaishouCloudBindUrlRefreshFailed、未使用 helper 等)
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import eslint from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: ['dist/**', 'node_modules/**', 'data/**'],
|
||||
},
|
||||
{
|
||||
files: ['src/**/*.ts', 'scripts/**/*.ts'],
|
||||
extends: [eslint.configs.recommended, ...tseslint.configs.recommended],
|
||||
languageOptions: {
|
||||
globals: globals.node,
|
||||
parserOptions: {
|
||||
project: './tsconfig.eslint.json',
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-floating-promises': [
|
||||
'error',
|
||||
{
|
||||
ignoreIIFE: true,
|
||||
ignoreVoid: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-misused-promises': 'error',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
destructuredArrayIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'no-useless-assignment': 'warn',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/**/*.test.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'no-control-regex': 'off',
|
||||
'no-regex-spaces': 'off',
|
||||
},
|
||||
},
|
||||
)
|
||||
Generated
+1085
-1
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,11 @@
|
||||
"db:migrate:create": "tsx scripts/create-migration.ts",
|
||||
"db:migrate:status": "tsx scripts/migration-status.ts",
|
||||
"dev": "tsx watch --clear-screen=false src/index.ts",
|
||||
"format": "prettier --config ../../.prettierrc.json --ignore-path ../../.prettierignore --write \"src/**/*.{ts,js,json}\" \"scripts/**/*.{ts,js}\" package.json tsconfig.json tsconfig.build.json",
|
||||
"format:check": "prettier --config ../../.prettierrc.json --ignore-path ../../.prettierignore --check \"src/**/*.{ts,js,json}\" \"scripts/**/*.{ts,js}\" package.json tsconfig.json tsconfig.build.json",
|
||||
"format": "prettier --config ../../.prettierrc.json --ignore-path ../../.prettierignore --write \"src/**/*.{ts,js,json}\" \"scripts/**/*.{ts,js}\" eslint.config.js package.json tsconfig.json tsconfig.build.json tsconfig.eslint.json",
|
||||
"format:check": "prettier --config ../../.prettierrc.json --ignore-path ../../.prettierignore --check \"src/**/*.{ts,js,json}\" \"scripts/**/*.{ts,js}\" eslint.config.js package.json tsconfig.json tsconfig.build.json tsconfig.eslint.json",
|
||||
"lint": "eslint \"src/**/*.ts\" \"scripts/**/*.ts\"",
|
||||
"lint:check": "npm run lint -- --quiet",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"mock:claim": "tsx scripts/mock-kuaishou-cloud-claim.ts",
|
||||
"mock:open91": "tsx scripts/mock-open91-order.ts",
|
||||
"test": "node --import tsx --test $(find src \\( -name '*.test.ts' -o -name '*.test.js' \\) -print)",
|
||||
@@ -20,7 +23,7 @@
|
||||
"test:industry:gen": "tsx scripts/gen-test-cases.ts",
|
||||
"test:industry:curl": "tsx scripts/curl-send-callback.ts",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"check": "npm run format:check && npm run typecheck && npm test && npm run build",
|
||||
"check": "npm run format:check && npm run lint:check && npm run typecheck && npm test && npm run build",
|
||||
"start": "node dist/index.js",
|
||||
"start:src": "tsx src/index.ts",
|
||||
"mock:feifei": "tsx scripts/mock-feifei-claim.ts"
|
||||
@@ -37,12 +40,16 @@
|
||||
"sharp": "^0.35.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "10.0.1",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/multer": "^2.2.0",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/pg": "^8.20.0",
|
||||
"eslint": "10.8.1",
|
||||
"globals": "17.11.0",
|
||||
"prettier": "3.8.3",
|
||||
"tsx": "^4.22.3",
|
||||
"typescript": "^6.0.2"
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "8.67.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ async function call(endpoint: string, params: JsonObject) {
|
||||
|
||||
const started = Date.now()
|
||||
let status = 0
|
||||
let json: JsonObject = {}
|
||||
let json: JsonObject
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
@@ -136,10 +136,6 @@ function paramsToForm(params: JsonObject): string {
|
||||
return p.join('&') + `¶m=${encodeURIComponent(String(params.param || '{}'))}` + signPart
|
||||
}
|
||||
|
||||
function pp(v: unknown): string {
|
||||
return JSON.stringify(v, null, 2)
|
||||
}
|
||||
|
||||
// ───── 先准备订单 ─────
|
||||
console.log('---')
|
||||
console.log('准备测试订单...\n')
|
||||
|
||||
@@ -372,7 +372,7 @@ async function post(
|
||||
|
||||
const startedAt = Date.now()
|
||||
let status = 0
|
||||
let data: JsonObject = {}
|
||||
let data: JsonObject
|
||||
let ok = false
|
||||
|
||||
try {
|
||||
|
||||
@@ -312,7 +312,7 @@ export function resolveInitialPaidTaskStatus(
|
||||
| null
|
||||
| undefined,
|
||||
): TaskStatus {
|
||||
if (Boolean(profile?.requires_claim)) {
|
||||
if (profile?.requires_claim) {
|
||||
return TASK_STATUS.PAID
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TASK_STATUS } from '../domain/task-status.js'
|
||||
import { maskCode } from '../utils/masking.js'
|
||||
import { parseTaskContext } from '../utils/task-json.js'
|
||||
import { normalizeTimestampIso } from '../utils/time.js'
|
||||
import type { JsonObject, JsonRecord } from '../types/json.js'
|
||||
import type { JsonRecord } from '../types/json.js'
|
||||
|
||||
type QueryExecutor = (text: string, params?: unknown[]) => Promise<{ rows: unknown[] }>
|
||||
export type KuaishouCloudSourceLoadStat = {
|
||||
|
||||
@@ -150,7 +150,7 @@ export async function verifyAdminSessionToken(token: unknown): Promise<AdminSess
|
||||
})
|
||||
}
|
||||
|
||||
let payload: JsonObject | null = null
|
||||
let payload: JsonObject | null
|
||||
|
||||
try {
|
||||
payload = JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf8'))
|
||||
|
||||
@@ -5,7 +5,7 @@ import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
|
||||
import { getOrderById, listOrders } from '../../repositories/order-repo.js'
|
||||
import { getTaskById, listTasks, listTasksByOrderId } from '../../repositories/task-repo.js'
|
||||
import { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
|
||||
import type { JsonObject, JsonRecord } from '../../types/json.js'
|
||||
import type { JsonRecord } from '../../types/json.js'
|
||||
import {
|
||||
listKuaishouIndustryVouchersByOid,
|
||||
listKuaishouIndustryVouchersByTaskId,
|
||||
@@ -474,7 +474,7 @@ function buildCloudSourceLabelMap() {
|
||||
|
||||
export async function getAdminTaskScreenshotPath(
|
||||
taskId: AdminEntityIdInput,
|
||||
session: AdminViewerSessionInput | null = null,
|
||||
_session: AdminViewerSessionInput | null = null,
|
||||
): Promise<string> {
|
||||
const task = await getRequiredTask(taskId)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { safeParseJson } from './admin-query-utils.js'
|
||||
import { normalizeAdminRole } from './admin-auth-service.js'
|
||||
import { asJsonObject, type JsonObject, JsonRecord } from '../../types/json.js'
|
||||
import { asJsonObject, type JsonRecord } from '../../types/json.js'
|
||||
import {
|
||||
parseTaskContext as parseTaskContextValue,
|
||||
parseTaskState as parseTaskStateValue,
|
||||
@@ -379,7 +379,7 @@ export function createAdminViewerContext(
|
||||
|
||||
export async function resolveAdminTaskScreenshotUrl(
|
||||
task: TaskLike,
|
||||
viewerContext: AdminViewerContext,
|
||||
_viewerContext: AdminViewerContext,
|
||||
): Promise<string> {
|
||||
if (task.screenshot_path || task.runtime_session_id) {
|
||||
return `/api/v1/admin/tasks/${task.id}/screenshot`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getTaskById } from '../../repositories/task-repo.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { safeParseJson } from './admin-query-utils.js'
|
||||
import { asJsonObject, type JsonObject, JsonRecord } from '../../types/json.js'
|
||||
import { asJsonObject, type JsonRecord } from '../../types/json.js'
|
||||
import {
|
||||
TASK_STATUS,
|
||||
isTaskFulfillmentCompletedStatus,
|
||||
|
||||
@@ -583,7 +583,7 @@ export async function submitAffiliateDashClaim(
|
||||
const now = nowIso()
|
||||
const isMock = Boolean(flow.mock?.enabled)
|
||||
const gameAccount = expectedGameAccount
|
||||
let latestFlow = flow
|
||||
const latestFlow = flow
|
||||
|
||||
if (!isMock && flow.bindUuid) {
|
||||
// 提交前不再额外请求 bind-result:平台侧曾出现 GET 后 submit 的 bind_verify 异常。
|
||||
|
||||
@@ -931,7 +931,6 @@ function buildLewanMockContext(input: {
|
||||
timestamp: string
|
||||
}) {
|
||||
const roleReady = ['binding', 'confirm', 'result'].includes(input.step)
|
||||
const roleConfirmed = ['confirm', 'result'].includes(input.step)
|
||||
const completed = input.step === 'result'
|
||||
const boundUid = roleReady ? input.expectedUid || '10001' : ''
|
||||
const primaryItem = input.deliveryItems[0] || {
|
||||
|
||||
@@ -197,7 +197,7 @@ export async function syncAffiliateDashTaskStatus(
|
||||
let resultMessage = task.result_message
|
||||
let lastError = task.last_error
|
||||
const nextFlow = mergeAffiliateDashOrder(flow, order, { syncedAt: now })
|
||||
let nextIndustryVoucher = taskContext.kuaishouIndustryVoucher
|
||||
const nextIndustryVoucher = taskContext.kuaishouIndustryVoucher
|
||||
|
||||
switch (order.orderStatus) {
|
||||
case 'paid':
|
||||
|
||||
@@ -96,7 +96,7 @@ export async function selectCloudtentaclesSourceForFulfillment(
|
||||
const ranked = []
|
||||
let lastCapacityError: unknown = null
|
||||
for (const [index, context] of contexts.entries()) {
|
||||
let occupiedCount = 0
|
||||
let occupiedCount
|
||||
try {
|
||||
// CT's VN list is the authoritative count; DB counters can lag after crashes/restarts.
|
||||
const listed = await listVirtualNumbers({
|
||||
|
||||
@@ -78,7 +78,7 @@ export async function prepareKuaishouCloudBindResourceWithFallback(input: JsonOb
|
||||
|
||||
for (const vnKey of candidates) {
|
||||
let vnId = 0
|
||||
let vnPhone = ''
|
||||
let vnPhone
|
||||
const cooldownKey = `${sourceKey}|${vnKey}`
|
||||
|
||||
const cooldownUntil = appointQuotaCooldowns.get(cooldownKey) || 0
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { createTaskEvent } from '../../../repositories/task-event-repo.js'
|
||||
import { updateTask } from '../../../repositories/task-repo.js'
|
||||
import { probeCloudtentaclesBindUrl } from '../../platforms/cloudtentacles/virtual-number-service.js'
|
||||
import { resolveCloudtentaclesConfig } from '../../platforms/cloudtentacles/helpers.js'
|
||||
import { notifyKuaishouCloudBindUrlRefreshFailed } from '../../notification/domain-notifications.js'
|
||||
import { createHttpError } from '../../../utils/http.js'
|
||||
import { nowIso } from '../../../utils/time.js'
|
||||
import { TASK_STATUS } from '../../../domain/task-status.js'
|
||||
import {
|
||||
isKuaishouCloudBindUrlFresh,
|
||||
isKuaishouCloudBindingMutationFrozen,
|
||||
@@ -14,8 +11,7 @@ import {
|
||||
normalizeKuaishouCloudRoleInfo,
|
||||
type JsonObject,
|
||||
} from './domain.js'
|
||||
import { resolvePersistedCloudtentaclesContextBySourceKeys } from './cloudtentacles-context.js'
|
||||
import { normalizeActor, parseTaskContext } from './task-context.js'
|
||||
import { parseTaskContext } from './task-context.js'
|
||||
import { buildRoleStateFromCurrentInfo } from './role-state.js'
|
||||
import { refreshKuaishouCloudTaskBindUrl } from './prepare-fulfillment.js'
|
||||
import type { TaskRow } from '../../../types/repository/rows.js'
|
||||
@@ -118,70 +114,3 @@ export async function probeKuaishouCloudTaskBindUrl(task: TaskRow, options: Json
|
||||
probe,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} task
|
||||
* @param {{ taskContext?: any, flow?: any, now?: string, actor?: any, error?: unknown }} [input]
|
||||
*/
|
||||
async function markKuaishouCloudBindUrlRefreshFailed(
|
||||
task: TaskRow,
|
||||
{ taskContext, flow, now, actor, error }: JsonObject = {},
|
||||
) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error || '新绑定链接准备失败')
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
...flow,
|
||||
binding: {
|
||||
...flow.binding,
|
||||
prepareStatus: 'pending',
|
||||
vnId: 0,
|
||||
vnPhone: '',
|
||||
bindUrl: '',
|
||||
bindPreparedAt: null,
|
||||
bindExpiresAt: null,
|
||||
bindProbeAt: now,
|
||||
bindProbeStatus: 'refresh_failed',
|
||||
bindProbeMessage: errorMessage,
|
||||
roleName: '',
|
||||
roleId: '',
|
||||
},
|
||||
role: {
|
||||
status: 'pending',
|
||||
name: '',
|
||||
rid: '',
|
||||
refreshedAt: now,
|
||||
errorMessage: '绑定链接已过期,旧号码已退还,新链接准备失败,请稍后刷新或联系客服处理',
|
||||
rawInfo: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const updatedTask = await updateTask(task.id, {
|
||||
task_status: TASK_STATUS.PENDING_BINDING_PREPARE,
|
||||
role_id: '',
|
||||
role_name: '',
|
||||
last_error: `绑定链接过期,旧号码已退还,新链接准备失败:${errorMessage}`,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
updated_at: now,
|
||||
})
|
||||
|
||||
await createTaskEvent(
|
||||
task.id,
|
||||
'kuaishou_cloud_bind_url_refresh_failed',
|
||||
{
|
||||
source: 'system_refresh_expired_bind_url',
|
||||
errorMessage,
|
||||
actor,
|
||||
},
|
||||
now,
|
||||
)
|
||||
|
||||
await notifyKuaishouCloudBindUrlRefreshFailed({
|
||||
task: updatedTask,
|
||||
errorMessage,
|
||||
})
|
||||
|
||||
return updatedTask
|
||||
}
|
||||
|
||||
@@ -188,7 +188,6 @@ export async function rebindKuaishouCloudTaskRole(task: TaskRow, options: JsonOb
|
||||
now,
|
||||
)
|
||||
} catch (error) {
|
||||
oldNumberBackStatus = 'failed'
|
||||
oldNumberBackError = error instanceof Error ? error.message : String(error || '退号失败')
|
||||
const wrapped = wrapCloudtentaclesOperationError(error, {
|
||||
action: 'vn_back',
|
||||
@@ -451,7 +450,7 @@ async function rebindByRefreshingExistingVnBindUrl(input: {
|
||||
now,
|
||||
} = input
|
||||
|
||||
let bindUrl = ''
|
||||
let bindUrl
|
||||
try {
|
||||
const bindUrlResult = await getCloudtentaclesBindUrl({
|
||||
...cloudContext,
|
||||
|
||||
@@ -84,7 +84,7 @@ export async function returnKuaishouCloudFulfillmentTask(task: TaskRow, options:
|
||||
}
|
||||
|
||||
const ticketCode = String(flow.ticket.code || '').trim()
|
||||
let consumeStatus = 'pending'
|
||||
let consumeStatus
|
||||
let consumeErrorMessage = ''
|
||||
let consumedAt: string | null = null
|
||||
let nextTaskStatus: TaskStatus = TASK_STATUS.COMPLETED
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export function normalizeCloudtentaclesMatchName(value: unknown) {
|
||||
return String(value || '')
|
||||
.toLowerCase()
|
||||
.replace(/[【】\[\]()()]/g, ' ')
|
||||
.replace(/[【】[\]()()]/g, ' ')
|
||||
.replace(/(自动发货|秒发|极速发货|官方直充|官方充值)/gi, ' ')
|
||||
.replace(/[^\p{L}\p{N}]+/gu, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
|
||||
@@ -48,7 +48,7 @@ export function encryptCloudtentaclesPayload(payload: JsonObject = {}, options:
|
||||
r: randomValue,
|
||||
plaintext,
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
throw createHttpError('cloudtentacles 加密失败', {
|
||||
statusCode: 500,
|
||||
errorCode: 'cloudtentacles_encrypt_failed',
|
||||
|
||||
@@ -220,11 +220,6 @@ function normalizePositiveInteger(value: unknown, fallback: number) {
|
||||
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback
|
||||
}
|
||||
|
||||
function normalizeInteger(value: unknown, fallback: number) {
|
||||
const parsed = Number(value)
|
||||
return Number.isInteger(parsed) ? parsed : fallback
|
||||
}
|
||||
|
||||
function normalizeHeaderMap(extra: unknown) {
|
||||
if (!extra || typeof extra !== 'object') {
|
||||
return {}
|
||||
|
||||
@@ -339,7 +339,7 @@ async function waitForCloudtentaclesSlot(bucketKey: string, intervalMs: number)
|
||||
|
||||
await previousQueue
|
||||
|
||||
let waitMs = 0
|
||||
let waitMs
|
||||
try {
|
||||
const now = Date.now()
|
||||
const nextAvailableAt = bucketNextAvailableAt.get(bucketKey) || 0
|
||||
|
||||
@@ -227,7 +227,7 @@ function assertCommonPayload(
|
||||
accessToken: string
|
||||
paramRaw: string
|
||||
},
|
||||
config = assertKuaishouIndustryConfig(),
|
||||
_config = assertKuaishouIndustryConfig(),
|
||||
) {
|
||||
if (!payload.signMethod) {
|
||||
throw createHttpError('缺少 signMethod', {
|
||||
|
||||
@@ -377,7 +377,7 @@ async function saveTokenPayload(
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeTokenResponse(json: JsonObject, currentConfig: KuaishouIndustrySourceConfig) {
|
||||
function normalizeTokenResponse(json: JsonObject, _currentConfig: KuaishouIndustrySourceConfig) {
|
||||
const payload = isPlainObject(json.data) ? json.data : json
|
||||
const accessToken = pickFirstString(payload, ['access_token', 'accessToken', 'accessTokenValue'])
|
||||
const refreshToken = pickFirstString(payload, [
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import crypto from 'node:crypto'
|
||||
|
||||
import { runtimeConfig } from '../../config/runtime.js'
|
||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||
import {
|
||||
acceptWorkOrderAndSettle,
|
||||
@@ -9,45 +6,27 @@ import {
|
||||
cancelAssignedWorkOrder,
|
||||
returnAssignedWorkOrderToHall,
|
||||
unassignWorkOrder,
|
||||
countWorkerAcceptedOrders,
|
||||
countWorkerActiveOrders,
|
||||
countWorkCategoryUsages,
|
||||
countWorkerLevelUsages,
|
||||
countWorkOrderPendingSharingSubmissions,
|
||||
countTimeoutEventsByWorkerIds,
|
||||
cancelWorkerWorkOrder,
|
||||
countWorkerCancellationsSince,
|
||||
createWorkOrder,
|
||||
createWorkOrderEvent,
|
||||
createWorkerFinanceRequest,
|
||||
createWorkerUser,
|
||||
deductPendingDepositUnfreeze,
|
||||
deleteWorkCategory,
|
||||
deleteWorkProductRule,
|
||||
deleteWorkOrder,
|
||||
deleteWorkerLevel,
|
||||
getWorkerFinanceRequestById,
|
||||
getWorkerFinanceRequestSummary,
|
||||
getWorkCategoryById,
|
||||
getWorkCategoryByKey,
|
||||
getWorkerLevelById,
|
||||
getWorkerLevelByKey,
|
||||
getWorkerUserByInviteCode,
|
||||
getWorkerUserById,
|
||||
getWorkerUserByUsername,
|
||||
getWorkOrderById,
|
||||
getWorkOrderByOrderItemId,
|
||||
getWorkOrderShare,
|
||||
getWorkProductRuleByKey,
|
||||
grabWorkOrder,
|
||||
incrementWorkerSessionVersion,
|
||||
joinWorkOrderShare,
|
||||
listAllWorkCategories,
|
||||
listPendingMaterialWorkOrdersByPlatformOrderId,
|
||||
listWorkerFinanceRequests,
|
||||
listWorkerSharesByWorker,
|
||||
listWorkerWalletLedgers,
|
||||
listWorkCategories,
|
||||
listWorkOrders,
|
||||
listWorkProductRules,
|
||||
listWorkerLevels,
|
||||
@@ -57,36 +36,21 @@ import {
|
||||
sumPendingUnfreezeByOrderIds,
|
||||
resolveProblemWorkOrder,
|
||||
reviewWorkerFinanceRequest,
|
||||
submitWorkOrderShareAcceptance,
|
||||
updateWorkOrder,
|
||||
updateWorkOrderBasic,
|
||||
updateWorkerPassword,
|
||||
updateWorkerUser,
|
||||
upsertWorkCategory,
|
||||
upsertWorkProductRule,
|
||||
upsertWorkerLevel,
|
||||
type WorkCategoryRow,
|
||||
type WorkerFinanceRequestRow,
|
||||
type WorkOrderRow,
|
||||
type WorkProductRuleRow,
|
||||
type WorkerLevelRow,
|
||||
type WorkOrderShareRow,
|
||||
type WorkerWalletLedgerRow,
|
||||
type WorkerUserRow,
|
||||
type GrabWorkOrderFailureReason,
|
||||
type ProblemWorkOrderResolutionAction,
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import type { OrderItemRow, OrderRow } from '../../types/repository/rows.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { randomId } from '../../utils/random.js'
|
||||
import { nowIso, addHours } from '../../utils/time.js'
|
||||
import { nowIso } from '../../utils/time.js'
|
||||
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
|
||||
import {
|
||||
normalizeStoredFileUrl,
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
import {
|
||||
consumeIndustryVouchersBeforeWorkOrderAssign,
|
||||
|
||||
@@ -1,61 +1,8 @@
|
||||
import crypto from 'node:crypto'
|
||||
|
||||
import { runtimeConfig } from '../../config/runtime.js'
|
||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
|
||||
import { findLatestOrderByAnyPlatformOrderId, getOrderById } from '../../repositories/order-repo.js'
|
||||
import {
|
||||
acceptWorkOrderAndSettle,
|
||||
addWorkerWalletCredit,
|
||||
countWorkerAcceptedOrders,
|
||||
countWorkerActiveOrders,
|
||||
countWorkCategoryUsages,
|
||||
countWorkerLevelUsages,
|
||||
countWorkOrderPendingSharingSubmissions,
|
||||
cancelWorkerWorkOrder,
|
||||
countWorkerCancellationsSince,
|
||||
createWorkOrder,
|
||||
createWorkOrderEvent,
|
||||
createWorkerFinanceRequest,
|
||||
createWorkerUser,
|
||||
deleteWorkCategory,
|
||||
deleteWorkerLevel,
|
||||
getWorkerFinanceRequestById,
|
||||
getWorkerFinanceRequestSummary,
|
||||
getWorkCategoryById,
|
||||
getWorkCategoryByKey,
|
||||
getWorkerLevelById,
|
||||
getWorkerLevelByKey,
|
||||
getWorkerUserByInviteCode,
|
||||
getWorkerUserById,
|
||||
getWorkerUserByUsername,
|
||||
getWorkOrderById,
|
||||
getWorkOrderByOrderItemId,
|
||||
getWorkOrderShare,
|
||||
grabWorkOrder,
|
||||
incrementWorkerSessionVersion,
|
||||
joinWorkOrderShare,
|
||||
listAllWorkCategories,
|
||||
listPendingMaterialWorkOrdersByPlatformOrderId,
|
||||
listWorkerFinanceRequests,
|
||||
listWorkerSharesByWorker,
|
||||
listWorkerWalletLedgers,
|
||||
listWorkCategories,
|
||||
listWorkOrders,
|
||||
listWorkProductRules,
|
||||
listWorkerLevels,
|
||||
listWorkerUsers,
|
||||
listWorkOrderShares,
|
||||
listWorkOrderSharesByOrderIds,
|
||||
resolveProblemWorkOrder,
|
||||
reviewWorkerFinanceRequest,
|
||||
submitWorkOrderShareAcceptance,
|
||||
updateWorkOrder,
|
||||
updateWorkerPassword,
|
||||
updateWorkerUser,
|
||||
upsertWorkCategory,
|
||||
upsertWorkProductRule,
|
||||
upsertWorkerLevel,
|
||||
type WorkCategoryRow,
|
||||
type WorkerFinanceRequestRow,
|
||||
type WorkOrderRow,
|
||||
@@ -70,15 +17,13 @@ import {
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import type { OrderItemRow, OrderRow } from '../../types/repository/rows.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { randomId } from '../../utils/random.js'
|
||||
import { nowIso, addHours } from '../../utils/time.js'
|
||||
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
|
||||
import { safeParseJson } from '../admin/admin-query-utils.js'
|
||||
import {
|
||||
normalizeStoredFileUrl,
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
|
||||
export const DEFAULT_LEVEL_KEY = 'vip1'
|
||||
export const DEFAULT_LEVEL_NAME = 'VIP1'
|
||||
@@ -414,8 +359,8 @@ export function mapWorkOrderForWorker(
|
||||
) {
|
||||
const mapped = mapWorkOrderAdmin(workOrder)
|
||||
const {
|
||||
requiredDepositAmount,
|
||||
depositThresholdAmount,
|
||||
requiredDepositAmount: _requiredDepositAmount,
|
||||
depositThresholdAmount: _depositThresholdAmount,
|
||||
worker: _worker,
|
||||
orderId: _orderId,
|
||||
orderItemId: _orderItemId,
|
||||
|
||||
@@ -2,32 +2,21 @@ import crypto from 'node:crypto'
|
||||
|
||||
import { runtimeConfig } from '../../config/runtime.js'
|
||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
|
||||
import { findLatestOrderByAnyPlatformOrderId, getOrderById } from '../../repositories/order-repo.js'
|
||||
import {
|
||||
acceptWorkOrderAndSettle,
|
||||
addWorkerWalletCredit,
|
||||
countWorkerAcceptedOrders,
|
||||
countWorkerActiveOrders,
|
||||
countWorkerTimeoutEvents,
|
||||
countWorkerWithdrawRequestsOnDay,
|
||||
countWorkCategoryUsages,
|
||||
countWorkerLevelUsages,
|
||||
countWorkOrderPendingSharingSubmissions,
|
||||
countWorkerSmsCodesOnDay,
|
||||
consumeWorkerSmsCode,
|
||||
createWorkerSmsCode,
|
||||
createWorkOrder,
|
||||
createWorkOrderEvent,
|
||||
createWorkerFinanceRequest,
|
||||
createWorkerUser,
|
||||
deleteWorkCategory,
|
||||
deleteWorkerLevel,
|
||||
getWorkerFinanceRequestById,
|
||||
getWorkerFinanceRequestSummary,
|
||||
getWorkCategoryById,
|
||||
getWorkCategoryByKey,
|
||||
getWorkerLevelById,
|
||||
getWorkerLevelByKey,
|
||||
getLatestWorkerSmsCode,
|
||||
getWorkerUserByInviteCode,
|
||||
@@ -36,12 +25,10 @@ import {
|
||||
getWorkerUserByUsername,
|
||||
getWorkerUserByDisplayName,
|
||||
getWorkOrderById,
|
||||
getWorkOrderByOrderItemId,
|
||||
getWorkOrderShare,
|
||||
grabWorkOrder,
|
||||
incrementWorkerSessionVersion,
|
||||
joinWorkOrderShare,
|
||||
listAllWorkCategories,
|
||||
listPendingMaterialWorkOrdersByPlatformOrderId,
|
||||
listWorkerFinanceRequests,
|
||||
listWorkerCompletionLeaderboard,
|
||||
@@ -50,16 +37,10 @@ import {
|
||||
listWorkerWorkOrderNotes,
|
||||
listWorkCategories,
|
||||
listWorkOrders,
|
||||
listWorkProductRules,
|
||||
listWorkerLevels,
|
||||
listWorkerUsers,
|
||||
listWorkOrderShares,
|
||||
listWorkOrderSharesByOrderIds,
|
||||
listDueDepositUnfreezes,
|
||||
listOverdueWorkOrders,
|
||||
releaseDepositUnfreeze,
|
||||
resolveProblemWorkOrder,
|
||||
reviewWorkerFinanceRequest,
|
||||
settleOverdueWorkOrder,
|
||||
submitWorkOrderShareAcceptance,
|
||||
updateWorkOrder,
|
||||
@@ -69,34 +50,18 @@ import {
|
||||
updateWorkOrderShareDraftAcceptance,
|
||||
upsertWorkerWorkOrderNote,
|
||||
updateWorkerPassword,
|
||||
updateWorkerUser,
|
||||
upsertWorkCategory,
|
||||
upsertWorkProductRule,
|
||||
upsertWorkerLevel,
|
||||
type WorkCategoryRow,
|
||||
type WorkerFinanceRequestRow,
|
||||
type WorkOrderRow,
|
||||
type WorkProductRuleRow,
|
||||
type WorkerLevelRow,
|
||||
type WorkOrderShareRow,
|
||||
type WorkerWalletLedgerRow,
|
||||
type WorkerUserRow,
|
||||
type GrabWorkOrderFailureReason,
|
||||
type ProblemWorkOrderResolutionAction,
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import type { OrderItemRow, OrderRow } from '../../types/repository/rows.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { randomId } from '../../utils/random.js'
|
||||
import { nowIso, addHours } from '../../utils/time.js'
|
||||
import { nowIso } from '../../utils/time.js'
|
||||
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
|
||||
import { getSmsProvider } from '../sms/index.js'
|
||||
import {
|
||||
normalizeStoredFileUrl,
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
import { getWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
|
||||
import {
|
||||
DEFAULT_CATEGORY_KEY,
|
||||
@@ -139,7 +104,6 @@ import {
|
||||
signWorkerPayload,
|
||||
throwGrabWorkOrderFailure,
|
||||
validateWorkerPassword,
|
||||
validateWorkerUsername,
|
||||
verifyWorkerPassword,
|
||||
} from './mappers.js'
|
||||
|
||||
@@ -355,7 +319,7 @@ function hashSmsCode(code: string): string {
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
async function generateInviteCode(now: string): Promise<string> {
|
||||
async function generateInviteCode(_now: string): Promise<string> {
|
||||
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
||||
for (let attempt = 0; attempt < INVITE_CODE_RETRY_LIMIT; attempt++) {
|
||||
const candidate = Array.from(
|
||||
@@ -464,7 +428,7 @@ export async function verifyWorkerSessionToken(token: unknown): Promise<WorkerSe
|
||||
})
|
||||
}
|
||||
|
||||
let payload: JsonObject = {}
|
||||
let payload: JsonObject
|
||||
try {
|
||||
payload = JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf8'))
|
||||
} catch {
|
||||
|
||||
@@ -16,7 +16,6 @@ export type StrictJsonObject = { [key: string]: StrictJson }
|
||||
* 宽松 JSON 对象袋(兼容既有履约 context / 平台响应)。
|
||||
* 值使用 any 仅为兼容深层属性链;新增代码优先 TaskContext 或 StrictJsonObject。
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type JsonObject = Record<string, any>
|
||||
|
||||
/** @deprecated 使用 JsonObject */
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "scripts/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist", "data"]
|
||||
}
|
||||
Reference in New Issue
Block a user