feat(worker-platform): add worker withdrawal blacklist and admin actions
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
revokeAllWorkerSessions,
|
||||
updateWorkerPassword,
|
||||
updateWorkerUser,
|
||||
updateWorkerWithdrawalBlacklist,
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
@@ -31,12 +32,22 @@ export async function listAdminWorkerUsers(query: JsonObject = {}) {
|
||||
const pageSize = normalizePageSize(query.pageSize)
|
||||
const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0
|
||||
const levelId = normalizeOptionalId(query.levelId ?? query.level_id) || 0
|
||||
const rawWithdrawalBlacklisted =
|
||||
query.isWithdrawalBlacklisted ?? query.is_withdrawal_blacklisted ?? query.withdrawalBlacklisted
|
||||
const isWithdrawalBlacklisted =
|
||||
rawWithdrawalBlacklisted !== undefined &&
|
||||
rawWithdrawalBlacklisted !== null &&
|
||||
String(rawWithdrawalBlacklisted).trim() !== ''
|
||||
? normalizeBoolean(rawWithdrawalBlacklisted, false)
|
||||
: undefined
|
||||
|
||||
const filters = {
|
||||
workerId,
|
||||
levelId,
|
||||
status: String(query.status || '').trim(),
|
||||
keyword: String(query.keyword || '').trim(),
|
||||
workerType: String(query.workerType || query.worker_type || '').trim(),
|
||||
isWithdrawalBlacklisted,
|
||||
}
|
||||
const includeStatistics = normalizeBoolean(
|
||||
query.includeStatistics ?? query.include_statistics,
|
||||
@@ -147,3 +158,23 @@ export async function resetAdminWorkerPassword(
|
||||
await revokeAllWorkerSessions(worker.id, now)
|
||||
return { worker: mapWorkerUser(updated || worker), reloginRequired: true }
|
||||
}
|
||||
|
||||
export async function updateAdminWorkerWithdrawalBlacklist(
|
||||
workerId: number | string,
|
||||
payload: JsonObject = {},
|
||||
) {
|
||||
const worker = await getRequiredWorker(workerId)
|
||||
const isWithdrawalBlacklisted = normalizeBoolean(
|
||||
payload.isWithdrawalBlacklisted ?? payload.blacklisted,
|
||||
false,
|
||||
)
|
||||
const reason = String(payload.reason || payload.blacklistReason || '').trim()
|
||||
const now = nowIso()
|
||||
const updated = await updateWorkerWithdrawalBlacklist({
|
||||
workerId: worker.id,
|
||||
isWithdrawalBlacklisted,
|
||||
reason,
|
||||
now,
|
||||
})
|
||||
return { worker: mapWorkerUser(updated || worker) }
|
||||
}
|
||||
|
||||
@@ -102,6 +102,9 @@ export function mapWorkerUser(worker: WorkerUserRow) {
|
||||
createdAt: worker.created_at,
|
||||
updatedAt: worker.updated_at,
|
||||
reviewedAt: worker.reviewed_at,
|
||||
isWithdrawalBlacklisted: Boolean(worker.is_withdrawal_blacklisted),
|
||||
withdrawalBlacklistReason: worker.withdrawal_blacklist_reason || '',
|
||||
withdrawalBlacklistedAt: worker.withdrawal_blacklisted_at || null,
|
||||
renameCards: Number(worker.rename_cards ?? 1),
|
||||
lastRenamedAt: worker.last_renamed_at || null,
|
||||
renameUnlockedAt: worker.last_renamed_at
|
||||
|
||||
@@ -110,6 +110,18 @@ export async function createWorkerWithdrawRequest(
|
||||
) {
|
||||
requireActiveWorkerSession(session)
|
||||
const worker = await getRequiredWorker(session.workerId)
|
||||
if (worker.is_withdrawal_blacklisted) {
|
||||
const reason = worker.withdrawal_blacklist_reason?.trim()
|
||||
throw createHttpError(
|
||||
reason
|
||||
? `您当前已被加入提现黑名单(原因:${reason}),无法发起提现,如有疑问请联系平台客服`
|
||||
: '您当前已被加入提现黑名单,无法发起提现,如有疑问请联系平台客服',
|
||||
{
|
||||
statusCode: 403,
|
||||
errorCode: 'worker_withdrawal_blacklisted',
|
||||
},
|
||||
)
|
||||
}
|
||||
const financeConfig = getWorkerFinanceConfig()
|
||||
if (financeConfig.withdraw.enabled === false) {
|
||||
throw createHttpError('当前提现入口暂未开放,请联系管理员', {
|
||||
|
||||
@@ -12,6 +12,7 @@ import type {
|
||||
} from '../../repositories/worker-platform/index.js'
|
||||
import {
|
||||
buildWorkOrderWhere,
|
||||
buildWorkerUserWhere,
|
||||
resolveWorkOrderShareCancellationStatus,
|
||||
resolveWorkOrderShareDepositAmount,
|
||||
resolveWorkOrderSharingCancellationPlan,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
canWorkerAutoAcceptWholeOrder,
|
||||
isWorkOrderSharingFilled,
|
||||
isWorkerPasswordStrong,
|
||||
mapWorkerUser,
|
||||
normalizeWithdrawChannel,
|
||||
normalizeRequirementFields,
|
||||
normalizeWorkerFreezeReason,
|
||||
@@ -1285,3 +1287,65 @@ test('资金流水映射展示关联的平台订单号', () => {
|
||||
|
||||
assert.equal(mapWalletLedger(ledger)?.relatedPlatformOrderId, '2623301845665410')
|
||||
})
|
||||
|
||||
test('打手提现黑名单信息映射到前端结构', () => {
|
||||
const worker = {
|
||||
id: 99,
|
||||
username: 'blacklisted_worker',
|
||||
password_hash: 'hash',
|
||||
display_name: '违规打手',
|
||||
phone: '13800000000',
|
||||
level_id: null,
|
||||
status: 'active',
|
||||
worker_type: 'external',
|
||||
review_note: '',
|
||||
frozen_reason: '',
|
||||
frozen_at: null,
|
||||
session_version: 1,
|
||||
created_at: '2026-09-01T00:00:00.000Z',
|
||||
updated_at: '2026-09-02T00:00:00.000Z',
|
||||
reviewed_at: null,
|
||||
inviter_id: null,
|
||||
invite_code: 'ABCDEFGH',
|
||||
is_withdrawal_blacklisted: true,
|
||||
withdrawal_blacklist_reason: '账号涉嫌刷单,暂停提现',
|
||||
withdrawal_blacklisted_at: '2026-09-13T00:00:00.000Z',
|
||||
} satisfies WorkerUserRow
|
||||
|
||||
const mapped = mapWorkerUser(worker)
|
||||
assert.equal(mapped.isWithdrawalBlacklisted, true)
|
||||
assert.equal(mapped.withdrawalBlacklistReason, '账号涉嫌刷单,暂停提现')
|
||||
assert.equal(mapped.withdrawalBlacklistedAt, '2026-09-13T00:00:00.000Z')
|
||||
|
||||
const normalWorker = {
|
||||
...worker,
|
||||
is_withdrawal_blacklisted: false,
|
||||
withdrawal_blacklist_reason: null,
|
||||
withdrawal_blacklisted_at: null,
|
||||
} satisfies WorkerUserRow
|
||||
|
||||
const normalMapped = mapWorkerUser(normalWorker)
|
||||
assert.equal(normalMapped.isWithdrawalBlacklisted, false)
|
||||
assert.equal(normalMapped.withdrawalBlacklistReason, '')
|
||||
assert.equal(normalMapped.withdrawalBlacklistedAt, null)
|
||||
})
|
||||
|
||||
test('打手查询条件支持提现黑名单筛选', () => {
|
||||
const blacklistedWhere = buildWorkerUserWhere({
|
||||
isWithdrawalBlacklisted: true,
|
||||
})
|
||||
assert.match(blacklistedWhere.whereClause, /wu\.is_withdrawal_blacklisted = \$1/)
|
||||
assert.deepEqual(blacklistedWhere.params, [true])
|
||||
|
||||
const normalWhere = buildWorkerUserWhere({
|
||||
isWithdrawalBlacklisted: false,
|
||||
})
|
||||
assert.match(normalWhere.whereClause, /wu\.is_withdrawal_blacklisted = \$1/)
|
||||
assert.deepEqual(normalWhere.params, [false])
|
||||
|
||||
const allWhere = buildWorkerUserWhere({
|
||||
isWithdrawalBlacklisted: undefined,
|
||||
})
|
||||
assert.equal(allWhere.whereClause, '')
|
||||
assert.equal(allWhere.params.length, 0)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user