统一前后端代码格式化配置
This commit is contained in:
@@ -87,17 +87,57 @@ import {
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import {
|
||||
getWorkerFinanceConfig,
|
||||
saveWorkerFinanceConfig,
|
||||
} from './worker-finance-config-service.js'
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
import {
|
||||
consumeIndustryVouchersBeforeWorkOrderAssign,
|
||||
consumeIndustryVouchersBeforeWorkOrderPublish,
|
||||
} from './publish-voucher-service.js'
|
||||
|
||||
import { DEFAULT_CATEGORY_KEY, DEFAULT_DEPOSIT_THRESHOLD_AMOUNT, DEFAULT_LEVEL_KEY, DEFAULT_LEVEL_NAME, mapFinanceRequest, mapWallet, mapWorkCategory, mapWorkOrderAdmin, mapWorkOrderShare, mapWorkProductRule, mapWorkerLevel, mapWorkerUser, normalizeAdminFinanceReviewStatus, normalizeAmountFen, normalizeBoolean, normalizeEnabledStatus, normalizeFinanceRequestStatus, normalizeFinanceRequestType, normalizeInteger, normalizeMatchType, normalizeOptionalId, normalizePositiveInteger, normalizeProblemResolutionAction, normalizeRequirementFields, normalizeRequirementFieldsFromPayload, normalizeReviewStatus, normalizeSessionVersion, normalizeSlugKey, normalizeStatuses, normalizeSubmittedFields, normalizeUploadedFiles, normalizeWorkerType, resolveFreezeDepositAmount, resolveMatchingProductRule, resolveRequirementFields, resolveSkuNameQuantity, resolveWorkerPermissions } from './mappers.js'
|
||||
import { ensureWorkerPlatformDefaults, getRequiredWorkOrder, getRequiredWorker, normalizeWorkOrderTimeoutPolicy } from './worker-service.js'
|
||||
import {
|
||||
DEFAULT_CATEGORY_KEY,
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
DEFAULT_LEVEL_KEY,
|
||||
DEFAULT_LEVEL_NAME,
|
||||
mapFinanceRequest,
|
||||
mapWallet,
|
||||
mapWorkCategory,
|
||||
mapWorkOrderAdmin,
|
||||
mapWorkOrderShare,
|
||||
mapWorkProductRule,
|
||||
mapWorkerLevel,
|
||||
mapWorkerUser,
|
||||
normalizeAdminFinanceReviewStatus,
|
||||
normalizeAmountFen,
|
||||
normalizeBoolean,
|
||||
normalizeEnabledStatus,
|
||||
normalizeFinanceRequestStatus,
|
||||
normalizeFinanceRequestType,
|
||||
normalizeInteger,
|
||||
normalizeMatchType,
|
||||
normalizeOptionalId,
|
||||
normalizePositiveInteger,
|
||||
normalizeProblemResolutionAction,
|
||||
normalizeRequirementFields,
|
||||
normalizeRequirementFieldsFromPayload,
|
||||
normalizeReviewStatus,
|
||||
normalizeSessionVersion,
|
||||
normalizeSlugKey,
|
||||
normalizeStatuses,
|
||||
normalizeSubmittedFields,
|
||||
normalizeUploadedFiles,
|
||||
normalizeWorkerType,
|
||||
resolveFreezeDepositAmount,
|
||||
resolveMatchingProductRule,
|
||||
resolveRequirementFields,
|
||||
resolveSkuNameQuantity,
|
||||
resolveWorkerPermissions,
|
||||
} from './mappers.js'
|
||||
import {
|
||||
ensureWorkerPlatformDefaults,
|
||||
getRequiredWorkOrder,
|
||||
getRequiredWorker,
|
||||
normalizeWorkOrderTimeoutPolicy,
|
||||
} from './worker-service.js'
|
||||
|
||||
export async function listAdminWorkerLevels() {
|
||||
await ensureWorkerPlatformDefaults()
|
||||
@@ -229,10 +269,7 @@ export async function saveAdminWorkProductRule(payload: JsonObject = {}) {
|
||||
payload.unitPrice === undefined && payload.unitPriceYuan === undefined
|
||||
? 0
|
||||
: normalizeAmountFen(payload.unitPrice ?? payload.unitPriceYuan, 0)
|
||||
const sharingEnabled = normalizeBoolean(
|
||||
payload.sharingEnabled ?? payload.sharing_enabled,
|
||||
false,
|
||||
)
|
||||
const sharingEnabled = normalizeBoolean(payload.sharingEnabled ?? payload.sharing_enabled, false)
|
||||
const sharingUnitReward = normalizeAmountFen(
|
||||
payload.sharingUnitReward ?? payload.sharingUnitRewardYuan,
|
||||
0,
|
||||
@@ -337,9 +374,7 @@ export async function listAdminWorkerUsers(query: JsonObject = {}) {
|
||||
status: String(query.status || '').trim(),
|
||||
keyword: String(query.keyword || '').trim(),
|
||||
})
|
||||
const timeoutCounts = await countTimeoutEventsByWorkerIds(
|
||||
items.map((item) => Number(item.id)),
|
||||
)
|
||||
const timeoutCounts = await countTimeoutEventsByWorkerIds(items.map((item) => Number(item.id)))
|
||||
return {
|
||||
items: items.map((item) => {
|
||||
const worker = mapWorkerUser(item)
|
||||
@@ -389,10 +424,7 @@ export async function assignAdminWorkOrderToWorker(
|
||||
payload: JsonObject = {},
|
||||
) {
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
if (
|
||||
!['unassigned', 'open'].includes(workOrder.status) ||
|
||||
workOrder.assigned_worker_id
|
||||
) {
|
||||
if (!['unassigned', 'open'].includes(workOrder.status) || workOrder.assigned_worker_id) {
|
||||
throw createHttpError('只有未分配或待抢单且未指派打手的订单才能指派', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_not_assignable',
|
||||
@@ -627,9 +659,7 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
|
||||
const joinedQuantity = orderShares
|
||||
.filter((share) => share.status !== 'cancelled')
|
||||
.reduce((sum, share) => sum + Number(share.quantity || 0), 0)
|
||||
const pendingSubmissionCount = orderShares.filter(
|
||||
(share) => share.status === 'joined',
|
||||
).length
|
||||
const pendingSubmissionCount = orderShares.filter((share) => share.status === 'joined').length
|
||||
return {
|
||||
...mapWorkOrderAdmin(item),
|
||||
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(Number(item.id)) || 0,
|
||||
@@ -713,7 +743,13 @@ export async function updateAdminWorkOrderSharing(
|
||||
payload: JsonObject = {},
|
||||
) {
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
if (![WORK_ORDER_STATUS.PENDING_MATERIAL, WORK_ORDER_STATUS.UNASSIGNED, WORK_ORDER_STATUS.OPEN].includes(workOrder.status as never)) {
|
||||
if (
|
||||
![
|
||||
WORK_ORDER_STATUS.PENDING_MATERIAL,
|
||||
WORK_ORDER_STATUS.UNASSIGNED,
|
||||
WORK_ORDER_STATUS.OPEN,
|
||||
].includes(workOrder.status as never)
|
||||
) {
|
||||
throw createHttpError('只有待完善、未分配或待抢单的工单可以配置拼单', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_sharing_config_status_invalid',
|
||||
@@ -787,9 +823,7 @@ export async function submitAdminWorkOrderMaterial(
|
||||
WORK_ORDER_STATUS.PENDING_MATERIAL,
|
||||
WORK_ORDER_STATUS.UNASSIGNED,
|
||||
WORK_ORDER_STATUS.IN_PROGRESS,
|
||||
].includes(
|
||||
workOrder.status as never,
|
||||
)
|
||||
].includes(workOrder.status as never)
|
||||
) {
|
||||
throw createHttpError('当前状态不能更新订单资料', {
|
||||
statusCode: 409,
|
||||
@@ -985,14 +1019,12 @@ export async function updateAdminWorkOrder(
|
||||
const categoryId =
|
||||
payload.categoryId === undefined || payload.categoryId === null || payload.categoryId === ''
|
||||
? workOrder.category_id
|
||||
: normalizeOptionalId(payload.categoryId) ?? workOrder.category_id
|
||||
: (normalizeOptionalId(payload.categoryId) ?? workOrder.category_id)
|
||||
|
||||
const now = nowIso()
|
||||
const updated = await updateWorkOrderBasic(workOrder.id, {
|
||||
productName: String(payload.productName ?? workOrder.product_name).trim(),
|
||||
platformOrderId: String(
|
||||
payload.platformOrderId ?? workOrder.platform_order_id ?? '',
|
||||
).trim(),
|
||||
platformOrderId: String(payload.platformOrderId ?? workOrder.platform_order_id ?? '').trim(),
|
||||
categoryId,
|
||||
rewardAmount,
|
||||
requiredDepositAmount,
|
||||
@@ -1298,7 +1330,9 @@ export async function acceptAdminWorkOrders(payload: JsonObject = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
const workOrders = await Promise.all(workOrderIds.map((workOrderId) => getRequiredWorkOrder(workOrderId)))
|
||||
const workOrders = await Promise.all(
|
||||
workOrderIds.map((workOrderId) => getRequiredWorkOrder(workOrderId)),
|
||||
)
|
||||
if (workOrders.some((workOrder) => workOrder.status !== WORK_ORDER_STATUS.PENDING_ACCEPTANCE)) {
|
||||
throw createHttpError('选中的订单包含非待验收状态,请刷新后重试', {
|
||||
statusCode: 409,
|
||||
@@ -1325,10 +1359,7 @@ export async function acceptAdminWorkOrders(payload: JsonObject = {}) {
|
||||
|
||||
export async function unassignAdminWorkOrder(workOrderId: number | string) {
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
if (
|
||||
workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS ||
|
||||
!workOrder.assigned_worker_id
|
||||
) {
|
||||
if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) {
|
||||
throw createHttpError('只有进行中且已指派打手的订单可以取消指派', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_unassign_status_invalid',
|
||||
@@ -1360,15 +1391,9 @@ export async function unassignAdminWorkOrder(workOrderId: number | string) {
|
||||
return { order: mapWorkOrderAdmin(updated) }
|
||||
}
|
||||
|
||||
export async function cancelAdminWorkOrder(
|
||||
workOrderId: number | string,
|
||||
payload: JsonObject = {},
|
||||
) {
|
||||
export async function cancelAdminWorkOrder(workOrderId: number | string, payload: JsonObject = {}) {
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
if (
|
||||
workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS ||
|
||||
!workOrder.assigned_worker_id
|
||||
) {
|
||||
if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) {
|
||||
throw createHttpError('只有代练中且已接单的订单可以撤单', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_cancel_status_invalid',
|
||||
|
||||
@@ -78,12 +78,7 @@ import {
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import {
|
||||
getWorkerFinanceConfig,
|
||||
saveWorkerFinanceConfig,
|
||||
} from './worker-finance-config-service.js'
|
||||
|
||||
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
|
||||
export const DEFAULT_LEVEL_KEY = 'vip1'
|
||||
export const DEFAULT_LEVEL_NAME = 'VIP1'
|
||||
@@ -309,9 +304,7 @@ export function mapWalletLedger(ledger: WorkerWalletLedgerRow | null | undefined
|
||||
amount: Number(ledger.amount || 0),
|
||||
balanceAfter: Number(ledger.balance_after || 0),
|
||||
frozenAfter: Number(ledger.frozen_after || 0),
|
||||
relatedWorkOrderId: ledger.related_work_order_id
|
||||
? Number(ledger.related_work_order_id)
|
||||
: null,
|
||||
relatedWorkOrderId: ledger.related_work_order_id ? Number(ledger.related_work_order_id) : null,
|
||||
auditStatus: ledger.audit_status || '',
|
||||
note: ledger.note || '',
|
||||
payload: safeParseJson(ledger.payload_json),
|
||||
@@ -536,10 +529,38 @@ export function normalizeRequirementFields(value: unknown) {
|
||||
return fields
|
||||
}
|
||||
return [
|
||||
{ key: 'gameId', label: '游戏编号', required: true, type: 'text', options: [], mockValue: 'test_uid' },
|
||||
{ key: 'gameNickname', label: '游戏昵称', required: true, type: 'text', options: [], mockValue: '测试角色' },
|
||||
{ key: 'system', label: '系统', required: false, type: 'select', options: ['安卓', '苹果'], mockValue: '安卓' },
|
||||
{ key: 'serverZone', label: '区服', required: false, type: 'select', options: ['QQ区', '微信区'], mockValue: 'QQ区' },
|
||||
{
|
||||
key: 'gameId',
|
||||
label: '游戏编号',
|
||||
required: true,
|
||||
type: 'text',
|
||||
options: [],
|
||||
mockValue: 'test_uid',
|
||||
},
|
||||
{
|
||||
key: 'gameNickname',
|
||||
label: '游戏昵称',
|
||||
required: true,
|
||||
type: 'text',
|
||||
options: [],
|
||||
mockValue: '测试角色',
|
||||
},
|
||||
{
|
||||
key: 'system',
|
||||
label: '系统',
|
||||
required: false,
|
||||
type: 'select',
|
||||
options: ['安卓', '苹果'],
|
||||
mockValue: '安卓',
|
||||
},
|
||||
{
|
||||
key: 'serverZone',
|
||||
label: '区服',
|
||||
required: false,
|
||||
type: 'select',
|
||||
options: ['QQ区', '微信区'],
|
||||
mockValue: 'QQ区',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -685,9 +706,7 @@ export function resolveSkuNameQuantity(productName: unknown): number {
|
||||
if (Number.isSafeInteger(parsed) && parsed > 0) return parsed
|
||||
}
|
||||
|
||||
const chineseMatch = text.match(
|
||||
/([零一二三四五六七八九十百千两]+)\s*(?:个|份|张|枚)/,
|
||||
)
|
||||
const chineseMatch = text.match(/([零一二三四五六七八九十百千两]+)\s*(?:个|份|张|枚)/)
|
||||
if (chineseMatch?.[1]) {
|
||||
const parsed = parseChineseNumber(chineseMatch[1])
|
||||
if (parsed > 0) return parsed
|
||||
@@ -730,7 +749,8 @@ function parseChineseNumber(text: string): number {
|
||||
return section + digit
|
||||
}
|
||||
|
||||
export function matchesOptionalText(ruleValue: unknown, sourceValue: unknown) { const ruleText = String(ruleValue || '')
|
||||
export function matchesOptionalText(ruleValue: unknown, sourceValue: unknown) {
|
||||
const ruleText = String(ruleValue || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
if (!ruleText) {
|
||||
@@ -771,13 +791,7 @@ export function normalizeStatuses(value: unknown): string[] {
|
||||
: value === undefined || value === null
|
||||
? []
|
||||
: [value]
|
||||
return [
|
||||
...new Set(
|
||||
rawList
|
||||
.map((item) => String(item || '').trim())
|
||||
.filter(Boolean),
|
||||
),
|
||||
]
|
||||
return [...new Set(rawList.map((item) => String(item || '').trim()).filter(Boolean))]
|
||||
}
|
||||
|
||||
export function normalizeUploadedFiles(value: unknown) {
|
||||
|
||||
@@ -61,9 +61,7 @@ export function normalizeWorkerFinanceConfig(rawValue: unknown): WorkerFinanceCo
|
||||
channelName: String(recharge.channelName || recharge.channel_name || '').trim(),
|
||||
accountName: String(recharge.accountName || recharge.account_name || '').trim(),
|
||||
accountNo: String(recharge.accountNo || recharge.account_no || '').trim(),
|
||||
qrCodeImage: normalizeUploadedFileForStorage(
|
||||
recharge.qrCodeImage || recharge.qr_code_image,
|
||||
),
|
||||
qrCodeImage: normalizeUploadedFileForStorage(recharge.qrCodeImage || recharge.qr_code_image),
|
||||
instructions: String(recharge.instructions || '').trim(),
|
||||
},
|
||||
adminContact: {
|
||||
@@ -144,10 +142,7 @@ function normalizeUploadedFileForStorage(
|
||||
return {
|
||||
objectKey,
|
||||
url: normalizeStoredFileUrl(value.url, objectKey),
|
||||
thumbnailUrl: normalizeStoredFileUrl(
|
||||
value.thumbnailUrl || value.thumbnail_url,
|
||||
objectKey,
|
||||
),
|
||||
thumbnailUrl: normalizeStoredFileUrl(value.thumbnailUrl || value.thumbnail_url, objectKey),
|
||||
mediumUrl: normalizeStoredFileUrl(value.mediumUrl || value.medium_url, objectKey),
|
||||
filename: String(value.filename || '').trim() || fallbackFilename,
|
||||
contentType: String(value.contentType || value.content_type || '').trim(),
|
||||
|
||||
@@ -39,9 +39,9 @@ test('assertWorkerLoginAllowed blocks rejected (frozen) workers with worker_reje
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_rejected',
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_rejected',
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -52,9 +52,9 @@ test('assertWorkerLoginAllowed blocks pending review workers with worker_pending
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_pending_review',
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_pending_review',
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -65,9 +65,9 @@ test('assertWorkerLoginAllowed blocks disabled workers with worker_disabled', ()
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_disabled',
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_disabled',
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -119,10 +119,7 @@ test('resolveSkuNameQuantity falls back to 1 when no quantity is found', () => {
|
||||
assert.equal(resolveSkuNameQuantity('指挥官秘钥礼包'), 1)
|
||||
})
|
||||
|
||||
|
||||
function buildWorkOrderRow(
|
||||
overrides: Partial<WorkOrderRow> = {},
|
||||
): WorkOrderRow {
|
||||
function buildWorkOrderRow(overrides: Partial<WorkOrderRow> = {}): WorkOrderRow {
|
||||
return {
|
||||
id: 1,
|
||||
work_order_no: 'WO0001',
|
||||
@@ -168,9 +165,9 @@ test('resolveCollectSubmitTargetWorkOrder requires explicit work order id when m
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 409 &&
|
||||
(error as { errorCode?: string }).errorCode === 'collect_work_order_required',
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 409 &&
|
||||
(error as { errorCode?: string }).errorCode === 'collect_work_order_required',
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -193,9 +190,9 @@ test('resolveCollectSubmitTargetWorkOrder rejects unknown workOrderId', () => {
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 404 &&
|
||||
(error as { errorCode?: string }).errorCode === 'collect_work_order_not_found',
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 404 &&
|
||||
(error as { errorCode?: string }).errorCode === 'collect_work_order_not_found',
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -96,12 +96,52 @@ import {
|
||||
refreshStoredFileUrl,
|
||||
refreshUploadedFileUrls,
|
||||
} from '../file-storage/file-storage-service.js'
|
||||
import {
|
||||
getWorkerFinanceConfig,
|
||||
saveWorkerFinanceConfig,
|
||||
} from './worker-finance-config-service.js'
|
||||
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'
|
||||
|
||||
import { DEFAULT_CATEGORY_KEY, DEFAULT_LEVEL_KEY, DEFAULT_LEVEL_NAME, INVITE_CODE_LENGTH, INVITE_CODE_RETRY_LIMIT, createWorkerSession, ensureWorkerAuthConfigured, hashWorkerPassword, isIgnorableWorkerAuthError, mapCollectLookupOrder, mapFinanceRequest, mapWalletLedger, mapWorkCategory, mapWorkOrderForWorker, mapWorkOrderPublic, mapWorkOrderShare, mapWorkerUser, normalizeAmountFen, normalizeFinanceRequestStatus, normalizeFinanceRequestType, normalizeInteger, normalizeOptionalId, normalizePassword, normalizePositiveInteger, normalizeProofFiles, normalizeSessionVersion, normalizeStatuses, normalizeStringArray, normalizeSubmittedFields, normalizeUploadedFiles, normalizeUsername, normalizeWalletLedgerType, normalizeWithdrawChannel, resolveFreezeDepositAmount, resolveRequirementFields, resolveWorkerPermissions, safeCompare, signWorkerPayload, throwGrabWorkOrderFailure, validateWorkerPassword, validateWorkerUsername, verifyWorkerPassword } from './mappers.js'
|
||||
import {
|
||||
DEFAULT_CATEGORY_KEY,
|
||||
DEFAULT_LEVEL_KEY,
|
||||
DEFAULT_LEVEL_NAME,
|
||||
INVITE_CODE_LENGTH,
|
||||
INVITE_CODE_RETRY_LIMIT,
|
||||
createWorkerSession,
|
||||
ensureWorkerAuthConfigured,
|
||||
hashWorkerPassword,
|
||||
isIgnorableWorkerAuthError,
|
||||
mapCollectLookupOrder,
|
||||
mapFinanceRequest,
|
||||
mapWalletLedger,
|
||||
mapWorkCategory,
|
||||
mapWorkOrderForWorker,
|
||||
mapWorkOrderPublic,
|
||||
mapWorkOrderShare,
|
||||
mapWorkerUser,
|
||||
normalizeAmountFen,
|
||||
normalizeFinanceRequestStatus,
|
||||
normalizeFinanceRequestType,
|
||||
normalizeInteger,
|
||||
normalizeOptionalId,
|
||||
normalizePassword,
|
||||
normalizePositiveInteger,
|
||||
normalizeProofFiles,
|
||||
normalizeSessionVersion,
|
||||
normalizeStatuses,
|
||||
normalizeStringArray,
|
||||
normalizeSubmittedFields,
|
||||
normalizeUploadedFiles,
|
||||
normalizeUsername,
|
||||
normalizeWalletLedgerType,
|
||||
normalizeWithdrawChannel,
|
||||
resolveFreezeDepositAmount,
|
||||
resolveRequirementFields,
|
||||
resolveWorkerPermissions,
|
||||
safeCompare,
|
||||
signWorkerPayload,
|
||||
throwGrabWorkOrderFailure,
|
||||
validateWorkerPassword,
|
||||
validateWorkerUsername,
|
||||
verifyWorkerPassword,
|
||||
} from './mappers.js'
|
||||
|
||||
export type WorkerSession = {
|
||||
sessionId: string
|
||||
@@ -112,7 +152,6 @@ export type WorkerSession = {
|
||||
sessionVersion: number
|
||||
}
|
||||
|
||||
|
||||
export async function ensureWorkerPlatformDefaults() {
|
||||
const now = nowIso()
|
||||
const existingLevel = await getWorkerLevelByKey(DEFAULT_LEVEL_KEY)
|
||||
@@ -196,7 +235,9 @@ export async function registerWorker(payload: JsonObject = {}) {
|
||||
const code = String(payload.code || payload.smsCode || '').trim()
|
||||
const password = normalizePassword(payload.password)
|
||||
const displayName = String(payload.displayName || payload.nickname || '').trim()
|
||||
const inviteCode = String(payload.inviteCode || '').trim().toUpperCase()
|
||||
const inviteCode = String(payload.inviteCode || '')
|
||||
.trim()
|
||||
.toUpperCase()
|
||||
|
||||
validateWorkerPassword(password)
|
||||
if (!displayName) {
|
||||
@@ -215,9 +256,9 @@ export async function registerWorker(payload: JsonObject = {}) {
|
||||
const latest = await getLatestWorkerSmsCode(phone, 'register')
|
||||
const codeValid = Boolean(
|
||||
latest &&
|
||||
!latest.consumed_at &&
|
||||
new Date(latest.expires_at).getTime() > Date.now() &&
|
||||
latest.code_hash === hashSmsCode(code),
|
||||
!latest.consumed_at &&
|
||||
new Date(latest.expires_at).getTime() > Date.now() &&
|
||||
latest.code_hash === hashSmsCode(code),
|
||||
)
|
||||
if (!codeValid) {
|
||||
throw createHttpError('短信验证码错误或已过期', {
|
||||
@@ -308,7 +349,10 @@ function generateSmsCode(): string {
|
||||
}
|
||||
|
||||
function hashSmsCode(code: string): string {
|
||||
return crypto.createHash('sha256').update(String(code || '')).digest('hex')
|
||||
return crypto
|
||||
.createHash('sha256')
|
||||
.update(String(code || ''))
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
async function generateInviteCode(now: string): Promise<string> {
|
||||
@@ -495,13 +539,14 @@ export function requireActiveWorkerSession(session: WorkerSession | null | undef
|
||||
|
||||
export async function getWorkerProfile(session: WorkerSession) {
|
||||
const worker = await getRequiredWorker(session.workerId)
|
||||
const [financeSummary, acceptedOrderCount, activeOrderCount, timeoutOrderCount, financeConfig] = await Promise.all([
|
||||
getWorkerFinanceRequestSummary(session.workerId),
|
||||
countWorkerAcceptedOrders(session.workerId),
|
||||
countWorkerActiveOrders(session.workerId),
|
||||
countWorkerTimeoutEvents(session.workerId),
|
||||
Promise.resolve(getWorkerFinanceConfig()),
|
||||
])
|
||||
const [financeSummary, acceptedOrderCount, activeOrderCount, timeoutOrderCount, financeConfig] =
|
||||
await Promise.all([
|
||||
getWorkerFinanceRequestSummary(session.workerId),
|
||||
countWorkerAcceptedOrders(session.workerId),
|
||||
countWorkerActiveOrders(session.workerId),
|
||||
countWorkerTimeoutEvents(session.workerId),
|
||||
Promise.resolve(getWorkerFinanceConfig()),
|
||||
])
|
||||
const permissions = resolveWorkerPermissions(worker)
|
||||
const levelProgress = await resolveLevelProgress(worker, acceptedOrderCount)
|
||||
return {
|
||||
@@ -533,9 +578,16 @@ async function resolveLevelProgress(
|
||||
const active = levels.filter((level) => level.status === 'active')
|
||||
const current = active.find((level) => Number(level.id) === Number(worker.level_id))
|
||||
if (!current) return null
|
||||
const currentThreshold = normalizeInteger(safeParseJson(current.permission_json).upgradeThreshold, 0)
|
||||
const currentThreshold = normalizeInteger(
|
||||
safeParseJson(current.permission_json).upgradeThreshold,
|
||||
0,
|
||||
)
|
||||
const next = active
|
||||
.filter((level) => normalizeInteger(safeParseJson(level.permission_json).upgradeThreshold, 0) > currentThreshold)
|
||||
.filter(
|
||||
(level) =>
|
||||
normalizeInteger(safeParseJson(level.permission_json).upgradeThreshold, 0) >
|
||||
currentThreshold,
|
||||
)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
normalizeInteger(safeParseJson(a.permission_json).upgradeThreshold, 0) -
|
||||
@@ -692,9 +744,7 @@ export async function createWorkerWithdrawRequest(
|
||||
})
|
||||
}
|
||||
|
||||
const accountChannel = normalizeWithdrawChannel(
|
||||
payload.accountChannel || payload.channel,
|
||||
)
|
||||
const accountChannel = normalizeWithdrawChannel(payload.accountChannel || payload.channel)
|
||||
const accountName = String(payload.accountName || payload.realName || '').trim()
|
||||
const accountNo = String(payload.accountNo || payload.account || '').trim()
|
||||
if (!accountName) {
|
||||
@@ -712,10 +762,7 @@ export async function createWorkerWithdrawRequest(
|
||||
|
||||
const financeSummary = await getWorkerFinanceRequestSummary(worker.id)
|
||||
const availableAmount = Number(worker.available_amount || 0)
|
||||
const availableForWithdraw = Math.max(
|
||||
0,
|
||||
availableAmount - financeSummary.pendingWithdrawAmount,
|
||||
)
|
||||
const availableForWithdraw = Math.max(0, availableAmount - financeSummary.pendingWithdrawAmount)
|
||||
if (amount > availableForWithdraw) {
|
||||
throw createHttpError('可提现余额不足,请先减少提现金额或等待已提交申请处理', {
|
||||
statusCode: 409,
|
||||
@@ -751,14 +798,9 @@ export async function createWorkerWithdrawRequest(
|
||||
}
|
||||
}
|
||||
|
||||
export async function changeWorkerPassword(
|
||||
payload: JsonObject = {},
|
||||
session: WorkerSession,
|
||||
) {
|
||||
export async function changeWorkerPassword(payload: JsonObject = {}, session: WorkerSession) {
|
||||
const worker = await getRequiredWorker(session.workerId)
|
||||
const currentPassword = normalizePassword(
|
||||
payload.currentPassword || payload.oldPassword,
|
||||
)
|
||||
const currentPassword = normalizePassword(payload.currentPassword || payload.oldPassword)
|
||||
const nextPassword = normalizePassword(payload.newPassword || payload.password)
|
||||
|
||||
if (!currentPassword) {
|
||||
@@ -814,9 +856,7 @@ export async function listWorkerHallOrders(query: JsonObject = {}, session: Work
|
||||
const permissions = resolveWorkerPermissions(worker)
|
||||
const visibleDelaySeconds = Number(permissions.visibleDelaySeconds || 0)
|
||||
const visibleAfterIso =
|
||||
visibleDelaySeconds > 0
|
||||
? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString()
|
||||
: ''
|
||||
visibleDelaySeconds > 0 ? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString() : ''
|
||||
const { items, total } = await listWorkOrders({
|
||||
page,
|
||||
pageSize,
|
||||
@@ -902,10 +942,7 @@ export async function grabWorkerHallOrder(workOrderId: number | string, session:
|
||||
return { order: mapWorkOrderForWorker(grabbed.order, permissions) }
|
||||
}
|
||||
|
||||
function resolveWorkOrderDeadlineAt(
|
||||
workOrder: WorkOrderRow,
|
||||
now: string,
|
||||
): string | null {
|
||||
function resolveWorkOrderDeadlineAt(workOrder: WorkOrderRow, now: string): string | null {
|
||||
const timeoutMinutes = Number(workOrder.timeout_minutes || 0)
|
||||
if (timeoutMinutes <= 0) return null
|
||||
return new Date(new Date(now).getTime() + timeoutMinutes * 60 * 1000).toISOString()
|
||||
@@ -947,17 +984,14 @@ export async function settleDueDepositUnfreezes(
|
||||
function resolveChinaDayRange(): { start: string; end: string } {
|
||||
const utcNow = new Date()
|
||||
const utcDayStartMs =
|
||||
Date.UTC(utcNow.getUTCFullYear(), utcNow.getUTCMonth(), utcNow.getUTCDate()) -
|
||||
8 * 3_600_000
|
||||
Date.UTC(utcNow.getUTCFullYear(), utcNow.getUTCMonth(), utcNow.getUTCDate()) - 8 * 3_600_000
|
||||
return {
|
||||
start: new Date(utcDayStartMs).toISOString(),
|
||||
end: new Date(utcDayStartMs + 86_400_000).toISOString(),
|
||||
}
|
||||
}
|
||||
|
||||
export async function settleOverdueWorkOrders(
|
||||
options: { limit?: number; workerId?: number } = {},
|
||||
) {
|
||||
export async function settleOverdueWorkOrders(options: { limit?: number; workerId?: number } = {}) {
|
||||
const overdue = await listOverdueWorkOrders({
|
||||
limit: Math.max(1, Number(options.limit || 50)),
|
||||
workerId: Number(options.workerId || 0),
|
||||
@@ -999,9 +1033,7 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker
|
||||
})
|
||||
const permissions = resolveWorkerPermissions(worker)
|
||||
const myShares = await listWorkerSharesByWorker(worker.id)
|
||||
const myShareByOrderId = new Map(
|
||||
myShares.map((share) => [Number(share.work_order_id), share]),
|
||||
)
|
||||
const myShareByOrderId = new Map(myShares.map((share) => [Number(share.work_order_id), share]))
|
||||
const notes = await listWorkerWorkOrderNotes(
|
||||
worker.id,
|
||||
items.map((item) => Number(item.id)),
|
||||
@@ -1089,7 +1121,14 @@ export async function joinWorkerSharingOrder(
|
||||
}
|
||||
|
||||
function resolveWorkOrderShareJoinError(
|
||||
failureReason: 'work_order_not_open' | 'sharing_disabled' | 'work_order_owner_conflict' | 'sharing_quantity_full' | 'worker_active_order_limit' | 'worker_deposit_insufficient' | null,
|
||||
failureReason:
|
||||
| 'work_order_not_open'
|
||||
| 'sharing_disabled'
|
||||
| 'work_order_owner_conflict'
|
||||
| 'sharing_quantity_full'
|
||||
| 'worker_active_order_limit'
|
||||
| 'worker_deposit_insufficient'
|
||||
| null,
|
||||
): Error {
|
||||
const messages: Record<string, string> = {
|
||||
work_order_not_open: '该订单当前不可拼单',
|
||||
@@ -1215,10 +1254,7 @@ export async function submitWorkerOrderAcceptance(
|
||||
}
|
||||
}
|
||||
return {
|
||||
order: mapWorkOrderForWorker(
|
||||
updated || workOrder,
|
||||
resolveWorkerPermissions(worker),
|
||||
),
|
||||
order: mapWorkOrderForWorker(updated || workOrder, resolveWorkerPermissions(worker)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user