增加管理员联系二维码

This commit is contained in:
yml2213
2026-08-15 16:24:36 +08:00
parent 521cbe9d38
commit 00491daf5b
9 changed files with 72 additions and 105 deletions
@@ -17,6 +17,9 @@ export type WorkerFinanceConfig = {
qrCodeImage: UploadedFileDto | null
instructions: string
}
adminContact: {
wechatQrCodeImage: UploadedFileDto | null
}
withdraw: {
enabled: boolean
instructions: string
@@ -44,6 +47,11 @@ export async function saveWorkerFinanceConfig(rawValue: unknown): Promise<Worker
export function normalizeWorkerFinanceConfig(rawValue: unknown): WorkerFinanceConfig {
const source = isPlainObject(rawValue) ? rawValue : {}
const recharge = isPlainObject(source.recharge) ? source.recharge : {}
const adminContact = isPlainObject(source.adminContact)
? source.adminContact
: isPlainObject(source.admin_contact)
? source.admin_contact
: {}
const withdraw = isPlainObject(source.withdraw) ? source.withdraw : {}
return {
@@ -58,6 +66,12 @@ export function normalizeWorkerFinanceConfig(rawValue: unknown): WorkerFinanceCo
),
instructions: String(recharge.instructions || '').trim(),
},
adminContact: {
wechatQrCodeImage: normalizeUploadedFileForStorage(
adminContact.wechatQrCodeImage || adminContact.wechat_qr_code_image,
'管理员微信二维码',
),
},
withdraw: {
enabled: typeof withdraw.enabled === 'boolean' ? withdraw.enabled : true,
instructions: String(withdraw.instructions || '').trim(),
@@ -76,6 +90,9 @@ export function createDefaultWorkerFinanceConfig(): WorkerFinanceConfig {
qrCodeImage: null,
instructions: '',
},
adminContact: {
wechatQrCodeImage: null,
},
withdraw: {
enabled: true,
instructions: '',
@@ -92,6 +109,11 @@ function refreshWorkerFinanceConfig(config: WorkerFinanceConfig): WorkerFinanceC
? (refreshUploadedFileUrls(config.recharge.qrCodeImage) as UploadedFileDto)
: null,
},
adminContact: {
wechatQrCodeImage: config.adminContact.wechatQrCodeImage
? (refreshUploadedFileUrls(config.adminContact.wechatQrCodeImage) as UploadedFileDto)
: null,
},
withdraw: {
...config.withdraw,
},
@@ -106,7 +128,10 @@ function normalizeRangeInteger(value: unknown, fallback: number, min: number, ma
return Math.min(max, Math.max(min, parsed))
}
function normalizeUploadedFileForStorage(value: unknown): UploadedFileDto | null {
function normalizeUploadedFileForStorage(
value: unknown,
fallbackFilename = '收款二维码',
): UploadedFileDto | null {
if (!isPlainObject(value)) {
return null
}
@@ -124,7 +149,7 @@ function normalizeUploadedFileForStorage(value: unknown): UploadedFileDto | null
objectKey,
),
mediumUrl: normalizeStoredFileUrl(value.mediumUrl || value.medium_url, objectKey),
filename: String(value.filename || '').trim() || '收款二维码',
filename: String(value.filename || '').trim() || fallbackFilename,
contentType: String(value.contentType || value.content_type || '').trim(),
size: Math.max(0, Number(value.size || 0) || 0),
}
@@ -14,9 +14,7 @@ import {
countWorkCategoryUsages,
countWorkerLevelUsages,
countWorkOrderPendingSharingSubmissions,
countWorkerCancellationsSince,
countWorkerSmsCodesOnDay,
cancelWorkerWorkOrder,
consumeWorkerSmsCode,
createWorkerSmsCode,
createWorkOrder,
@@ -102,7 +100,7 @@ import {
saveWorkerFinanceConfig,
} from './worker-finance-config-service.js'
import { DEFAULT_CATEGORY_KEY, DEFAULT_LEVEL_KEY, DEFAULT_LEVEL_NAME, INVITE_CODE_LENGTH, INVITE_CODE_RETRY_LIMIT, WORKER_CANCEL_LIMIT_PER_WINDOW, WORKER_CANCEL_LIMIT_WINDOW_MS, createWorkerSession, ensureWorkerAuthConfigured, hashWorkerPassword, isIgnorableWorkerAuthError, mapCollectLookupOrder, mapFinanceRequest, mapWalletLedger, mapWorkCategory, mapWorkOrderForWorker, mapWorkOrderPublic, mapWorkOrderShare, mapWorkerUser, normalizeAmountFen, normalizeFinanceRequestStatus, normalizeFinanceRequestType, normalizeInteger, normalizeOptionalId, normalizePassword, normalizePositiveInteger, normalizeProofFiles, normalizeSessionVersion, 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, normalizeStringArray, normalizeSubmittedFields, normalizeUploadedFiles, normalizeUsername, normalizeWalletLedgerType, normalizeWithdrawChannel, resolveFreezeDepositAmount, resolveRequirementFields, resolveWorkerPermissions, safeCompare, signWorkerPayload, throwGrabWorkOrderFailure, validateWorkerPassword, validateWorkerUsername, verifyWorkerPassword } from './mappers.js'
export type WorkerSession = {
sessionId: string
@@ -1086,49 +1084,6 @@ function resolveWorkOrderShareJoinError(
})
}
export async function cancelWorkerOrder(
workOrderId: number | string,
session: WorkerSession,
) {
requireActiveWorkerSession(session)
const worker = await getRequiredWorker(session.workerId)
const now = nowIso()
const since = new Date(Date.now() - WORKER_CANCEL_LIMIT_WINDOW_MS).toISOString()
const cancelCount = await countWorkerCancellationsSince(worker.id, since)
if (cancelCount >= WORKER_CANCEL_LIMIT_PER_WINDOW) {
throw createHttpError(
`30 天内取消接单已达 ${WORKER_CANCEL_LIMIT_PER_WINDOW} 次上限,请谨慎接单`,
{
statusCode: 409,
errorCode: 'worker_cancel_limit_reached',
},
)
}
const result = await cancelWorkerWorkOrder({
workOrderId: Number(workOrderId),
workerId: Number(worker.id),
now,
})
if (result.failureReason === 'work_order_owner_required') {
throw createHttpError('只能取消自己接的订单', {
statusCode: 403,
errorCode: 'work_order_owner_required',
})
}
if (!result.order) {
throw createHttpError('当前订单状态不能取消,仅进行中的订单可取消', {
statusCode: 409,
errorCode: 'work_order_cancel_status_invalid',
})
}
return {
order: mapWorkOrderForWorker(
result.order,
resolveWorkerPermissions(await getRequiredWorker(session.workerId)),
),
}
}
export async function submitWorkerOrderAcceptance(
workOrderId: number | string,
payload: JsonObject = {},