完善支付宝提现收款码
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
-- 支付宝提现账户保存收款二维码;历史账户保留空值,需补充后才能继续提现。
|
||||||
|
ALTER TABLE worker_withdrawal_accounts
|
||||||
|
ADD COLUMN IF NOT EXISTS alipay_qr_code_json JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN worker_withdrawal_accounts.alipay_qr_code_json IS '支付宝收款二维码文件信息';
|
||||||
@@ -161,6 +161,7 @@ export type WorkerWithdrawalAccountRow = {
|
|||||||
account_channel: string
|
account_channel: string
|
||||||
account_name: string
|
account_name: string
|
||||||
account_no: string
|
account_no: string
|
||||||
|
alipay_qr_code_json: string | Record<string, unknown>
|
||||||
wechat_qr_code_json: string | Record<string, unknown>
|
wechat_qr_code_json: string | Record<string, unknown>
|
||||||
created_at: string
|
created_at: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -654,14 +654,16 @@ export async function createWorkerWithdrawalAccount(input: {
|
|||||||
accountChannel: string
|
accountChannel: string
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNo: string
|
accountNo: string
|
||||||
|
alipayQrCodeJson: string
|
||||||
wechatQrCodeJson: string
|
wechatQrCodeJson: string
|
||||||
now: string
|
now: string
|
||||||
}): Promise<WorkerWithdrawalAccountRow | null> {
|
}): Promise<WorkerWithdrawalAccountRow | null> {
|
||||||
const result = await query<WorkerWithdrawalAccountRow>(
|
const result = await query<WorkerWithdrawalAccountRow>(
|
||||||
`
|
`
|
||||||
INSERT INTO worker_withdrawal_accounts (
|
INSERT INTO worker_withdrawal_accounts (
|
||||||
worker_id, account_channel, account_name, account_no, wechat_qr_code_json, created_at
|
worker_id, account_channel, account_name, account_no,
|
||||||
) VALUES ($1, $2, $3, $4, $5::jsonb, $6)
|
alipay_qr_code_json, wechat_qr_code_json, created_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7)
|
||||||
ON CONFLICT (worker_id, account_channel) DO NOTHING
|
ON CONFLICT (worker_id, account_channel) DO NOTHING
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`,
|
`,
|
||||||
@@ -670,6 +672,7 @@ export async function createWorkerWithdrawalAccount(input: {
|
|||||||
input.accountChannel,
|
input.accountChannel,
|
||||||
input.accountName,
|
input.accountName,
|
||||||
input.accountNo,
|
input.accountNo,
|
||||||
|
input.alipayQrCodeJson,
|
||||||
input.wechatQrCodeJson,
|
input.wechatQrCodeJson,
|
||||||
input.now,
|
input.now,
|
||||||
],
|
],
|
||||||
@@ -682,18 +685,21 @@ export async function upsertWorkerWithdrawalAccount(input: {
|
|||||||
accountChannel: string
|
accountChannel: string
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNo: string
|
accountNo: string
|
||||||
|
alipayQrCodeJson: string
|
||||||
wechatQrCodeJson: string
|
wechatQrCodeJson: string
|
||||||
now: string
|
now: string
|
||||||
}): Promise<WorkerWithdrawalAccountRow | null> {
|
}): Promise<WorkerWithdrawalAccountRow | null> {
|
||||||
const result = await query<WorkerWithdrawalAccountRow>(
|
const result = await query<WorkerWithdrawalAccountRow>(
|
||||||
`
|
`
|
||||||
INSERT INTO worker_withdrawal_accounts (
|
INSERT INTO worker_withdrawal_accounts (
|
||||||
worker_id, account_channel, account_name, account_no, wechat_qr_code_json, created_at
|
worker_id, account_channel, account_name, account_no,
|
||||||
) VALUES ($1, $2, $3, $4, $5::jsonb, $6)
|
alipay_qr_code_json, wechat_qr_code_json, created_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7)
|
||||||
ON CONFLICT (worker_id, account_channel) DO UPDATE
|
ON CONFLICT (worker_id, account_channel) DO UPDATE
|
||||||
SET
|
SET
|
||||||
account_name = EXCLUDED.account_name,
|
account_name = EXCLUDED.account_name,
|
||||||
account_no = EXCLUDED.account_no,
|
account_no = EXCLUDED.account_no,
|
||||||
|
alipay_qr_code_json = EXCLUDED.alipay_qr_code_json,
|
||||||
wechat_qr_code_json = EXCLUDED.wechat_qr_code_json
|
wechat_qr_code_json = EXCLUDED.wechat_qr_code_json
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`,
|
`,
|
||||||
@@ -702,6 +708,7 @@ export async function upsertWorkerWithdrawalAccount(input: {
|
|||||||
input.accountChannel,
|
input.accountChannel,
|
||||||
input.accountName,
|
input.accountName,
|
||||||
input.accountNo,
|
input.accountNo,
|
||||||
|
input.alipayQrCodeJson,
|
||||||
input.wechatQrCodeJson,
|
input.wechatQrCodeJson,
|
||||||
input.now,
|
input.now,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
changeWorkerPassword,
|
changeWorkerPassword,
|
||||||
createWorkerRechargeRequest,
|
createWorkerRechargeRequest,
|
||||||
createWorkerWithdrawalAccount,
|
createWorkerWithdrawalAccount,
|
||||||
|
saveWorkerAlipayWithdrawalQrCode,
|
||||||
createWorkerWithdrawRequest,
|
createWorkerWithdrawRequest,
|
||||||
getWorkerProfile,
|
getWorkerProfile,
|
||||||
getWorkerSessionSummary,
|
getWorkerSessionSummary,
|
||||||
@@ -326,6 +327,19 @@ router.post(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
router.put(
|
||||||
|
'/profile/withdrawal-account/alipay-qr-code',
|
||||||
|
requireActiveWorker,
|
||||||
|
createRouteHandler(
|
||||||
|
(req) => saveWorkerAlipayWithdrawalQrCode(req.body || {}, getRequiredWorkerSession(req)),
|
||||||
|
{
|
||||||
|
successMessage: '支付宝收款二维码已保存',
|
||||||
|
errorMessage: '保存支付宝收款二维码失败',
|
||||||
|
scope: '[worker/profile/withdrawal-account/alipay-qr-code]',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/profile/withdraw-requests',
|
'/profile/withdraw-requests',
|
||||||
requireActiveWorker,
|
requireActiveWorker,
|
||||||
|
|||||||
@@ -1256,7 +1256,16 @@ export async function saveAdminWorkerWithdrawalAccount(
|
|||||||
const current = currentAccounts.find((item) => item.account_channel === accountChannel)
|
const current = currentAccounts.find((item) => item.account_channel === accountChannel)
|
||||||
const accountName = String(payload.accountName || payload.realName || '').trim()
|
const accountName = String(payload.accountName || payload.realName || '').trim()
|
||||||
const accountNo =
|
const accountNo =
|
||||||
accountChannel === 'alipay' ? String(payload.accountNo || payload.account || '').trim() : ''
|
accountChannel === 'alipay'
|
||||||
|
? String(payload.accountNo || payload.account || current?.account_no || '').trim()
|
||||||
|
: ''
|
||||||
|
const uploadedAlipayQrCode = normalizeProofFiles(
|
||||||
|
payload.alipayQrCodeImages || payload.alipayQrCodes,
|
||||||
|
)[0]
|
||||||
|
const alipayQrCodeImage =
|
||||||
|
accountChannel === 'alipay'
|
||||||
|
? uploadedAlipayQrCode || safeParseJson(current?.alipay_qr_code_json)
|
||||||
|
: {}
|
||||||
const uploadedWechatQrCode = normalizeProofFiles(
|
const uploadedWechatQrCode = normalizeProofFiles(
|
||||||
payload.wechatQrCodeImages || payload.wechatQrCodes,
|
payload.wechatQrCodeImages || payload.wechatQrCodes,
|
||||||
)[0]
|
)[0]
|
||||||
@@ -1271,12 +1280,18 @@ export async function saveAdminWorkerWithdrawalAccount(
|
|||||||
errorCode: 'admin_worker_withdraw_account_name_required',
|
errorCode: 'admin_worker_withdraw_account_name_required',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (accountChannel === 'alipay' && !accountNo) {
|
if (accountChannel === 'alipay' && !current && !accountNo) {
|
||||||
throw createHttpError('请填写支付宝账号', {
|
throw createHttpError('请填写支付宝账号', {
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
errorCode: 'admin_worker_withdraw_alipay_account_required',
|
errorCode: 'admin_worker_withdraw_alipay_account_required',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (accountChannel === 'alipay' && !String(alipayQrCodeImage.url || '').trim()) {
|
||||||
|
throw createHttpError('请上传支付宝收款二维码', {
|
||||||
|
statusCode: 400,
|
||||||
|
errorCode: 'admin_worker_withdraw_alipay_qr_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
if (accountChannel === 'wechat' && !String(wechatQrCodeImage.url || '').trim()) {
|
if (accountChannel === 'wechat' && !String(wechatQrCodeImage.url || '').trim()) {
|
||||||
throw createHttpError('请上传微信收款二维码', {
|
throw createHttpError('请上传微信收款二维码', {
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
@@ -1289,6 +1304,7 @@ export async function saveAdminWorkerWithdrawalAccount(
|
|||||||
accountChannel,
|
accountChannel,
|
||||||
accountName,
|
accountName,
|
||||||
accountNo,
|
accountNo,
|
||||||
|
alipayQrCodeJson: JSON.stringify(alipayQrCodeImage),
|
||||||
wechatQrCodeJson: JSON.stringify(wechatQrCodeImage),
|
wechatQrCodeJson: JSON.stringify(wechatQrCodeImage),
|
||||||
now: nowIso(),
|
now: nowIso(),
|
||||||
})
|
})
|
||||||
@@ -1414,11 +1430,13 @@ export async function reviewAdminWorkerFinanceRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapAdminWorkerWithdrawalAccount(account: WorkerWithdrawalAccountRow) {
|
function mapAdminWorkerWithdrawalAccount(account: WorkerWithdrawalAccountRow) {
|
||||||
|
const alipayQrCodeImage = refreshUploadedFileUrls(safeParseJson(account.alipay_qr_code_json))
|
||||||
const wechatQrCodeImage = refreshUploadedFileUrls(safeParseJson(account.wechat_qr_code_json))
|
const wechatQrCodeImage = refreshUploadedFileUrls(safeParseJson(account.wechat_qr_code_json))
|
||||||
return {
|
return {
|
||||||
accountChannel: account.account_channel,
|
accountChannel: account.account_channel,
|
||||||
accountName: account.account_name,
|
accountName: account.account_name,
|
||||||
accountNo: account.account_channel === 'alipay' ? account.account_no : '',
|
accountNo: account.account_channel === 'alipay' ? account.account_no : '',
|
||||||
|
alipayQrCodeImage: String(alipayQrCodeImage.url || '').trim() ? alipayQrCodeImage : null,
|
||||||
wechatQrCodeImage: String(wechatQrCodeImage.url || '').trim() ? wechatQrCodeImage : null,
|
wechatQrCodeImage: String(wechatQrCodeImage.url || '').trim() ? wechatQrCodeImage : null,
|
||||||
createdAt: account.created_at,
|
createdAt: account.created_at,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,10 @@ export function canWorkerAutoAcceptWholeOrder(input: {
|
|||||||
worker: WorkerUserRow
|
worker: WorkerUserRow
|
||||||
hasPersonalSharingShare: boolean
|
hasPersonalSharingShare: boolean
|
||||||
}): boolean {
|
}): boolean {
|
||||||
return !input.hasPersonalSharingShare && resolveWorkerPermissions(input.worker).autoAcceptWithoutEvidence
|
return (
|
||||||
|
!input.hasPersonalSharingShare &&
|
||||||
|
resolveWorkerPermissions(input.worker).autoAcceptWithoutEvidence
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveVisibleDelaySeconds(levelKey: string, configured?: unknown): number {
|
export function resolveVisibleDelaySeconds(levelKey: string, configured?: unknown): number {
|
||||||
@@ -361,6 +364,10 @@ export function mapWalletLedger(ledger: WorkerWalletLedgerRow | null | undefined
|
|||||||
export function mapFinanceRequest(request: WorkerFinanceRequestRow | null | undefined) {
|
export function mapFinanceRequest(request: WorkerFinanceRequestRow | null | undefined) {
|
||||||
if (!request) return null
|
if (!request) return null
|
||||||
const payload = safeParseJson(request.payload_json)
|
const payload = safeParseJson(request.payload_json)
|
||||||
|
const alipayQrCodeImage = refreshUploadedFileUrls(payload.alipayQrCodeImage)
|
||||||
|
if (String(alipayQrCodeImage.url || '').trim()) {
|
||||||
|
payload.alipayQrCodeImage = alipayQrCodeImage
|
||||||
|
}
|
||||||
const wechatQrCodeImage = refreshUploadedFileUrls(payload.wechatQrCodeImage)
|
const wechatQrCodeImage = refreshUploadedFileUrls(payload.wechatQrCodeImage)
|
||||||
if (String(wechatQrCodeImage.url || '').trim()) {
|
if (String(wechatQrCodeImage.url || '').trim()) {
|
||||||
payload.wechatQrCodeImage = wechatQrCodeImage
|
payload.wechatQrCodeImage = wechatQrCodeImage
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
WorkOrderShareRow,
|
WorkOrderShareRow,
|
||||||
WorkProductRuleMappingRow,
|
WorkProductRuleMappingRow,
|
||||||
WorkProductRuleRow,
|
WorkProductRuleRow,
|
||||||
|
WorkerFinanceRequestRow,
|
||||||
WorkerUserRow,
|
WorkerUserRow,
|
||||||
} from '../../repositories/worker-platform/index.js'
|
} from '../../repositories/worker-platform/index.js'
|
||||||
import {
|
import {
|
||||||
@@ -26,6 +27,7 @@ import {
|
|||||||
mapWorkOrderForWorker,
|
mapWorkOrderForWorker,
|
||||||
mapWorkOrderAdmin,
|
mapWorkOrderAdmin,
|
||||||
mapWorkOrderSharingWorkers,
|
mapWorkOrderSharingWorkers,
|
||||||
|
mapFinanceRequest,
|
||||||
maskWorkerLeaderboardDisplayName,
|
maskWorkerLeaderboardDisplayName,
|
||||||
resolveCollectSubmitTargetWorkOrder,
|
resolveCollectSubmitTargetWorkOrder,
|
||||||
resolveAdminMaterialRewardAmount,
|
resolveAdminMaterialRewardAmount,
|
||||||
@@ -505,6 +507,33 @@ test('微信提现金额超过 100 元时被拒绝', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('支付宝提现申请保留收款二维码快照', () => {
|
||||||
|
const request: WorkerFinanceRequestRow = {
|
||||||
|
id: 1,
|
||||||
|
worker_id: 1,
|
||||||
|
request_type: 'withdraw',
|
||||||
|
status: 'pending',
|
||||||
|
amount: 10_000,
|
||||||
|
account_channel: 'alipay',
|
||||||
|
account_name: '测试用户',
|
||||||
|
account_no: 'test@example.com',
|
||||||
|
note: '',
|
||||||
|
reviewed_note: '',
|
||||||
|
payload_json: {
|
||||||
|
alipayQrCodeImage: { url: 'https://example.com/alipay-qr.png' },
|
||||||
|
},
|
||||||
|
created_at: '2026-08-20T00:00:00.000Z',
|
||||||
|
updated_at: '2026-08-20T00:00:00.000Z',
|
||||||
|
reviewed_at: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapped = mapFinanceRequest(request)
|
||||||
|
assert.equal(
|
||||||
|
(mapped?.payload.alipayQrCodeImage as { url?: string }).url,
|
||||||
|
'https://example.com/alipay-qr.png',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test('提现渠道仅支持支付宝和微信', () => {
|
test('提现渠道仅支持支付宝和微信', () => {
|
||||||
assert.equal(normalizeWithdrawChannel('alipay'), 'alipay')
|
assert.equal(normalizeWithdrawChannel('alipay'), 'alipay')
|
||||||
assert.equal(normalizeWithdrawChannel('wechat'), 'wechat')
|
assert.equal(normalizeWithdrawChannel('wechat'), 'wechat')
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import {
|
|||||||
listWorkOrderShares,
|
listWorkOrderShares,
|
||||||
listWorkOrderSharesByOrderIds,
|
listWorkOrderSharesByOrderIds,
|
||||||
listWorkerLevels,
|
listWorkerLevels,
|
||||||
|
upsertWorkerWithdrawalAccount,
|
||||||
getWorkerCancelRequestRisk,
|
getWorkerCancelRequestRisk,
|
||||||
listDueDepositUnfreezes,
|
listDueDepositUnfreezes,
|
||||||
listOverdueWorkOrders,
|
listOverdueWorkOrders,
|
||||||
@@ -1186,7 +1187,14 @@ export async function createWorkerWithdrawRequest(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
assertWithdrawChannelAllowedForAmount(amount, accountChannel)
|
assertWithdrawChannelAllowedForAmount(amount, accountChannel)
|
||||||
|
const alipayQrCodeImage = resolveAlipayWithdrawalQrCode(withdrawalAccount)
|
||||||
const wechatQrCodeImage = resolveWechatWithdrawalQrCode(withdrawalAccount)
|
const wechatQrCodeImage = resolveWechatWithdrawalQrCode(withdrawalAccount)
|
||||||
|
if (accountChannel === 'alipay' && !alipayQrCodeImage) {
|
||||||
|
throw createHttpError('支付宝提现信息缺少收款二维码,请先补充后再提现', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'worker_withdrawal_alipay_qr_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
if (accountChannel === 'wechat' && !wechatQrCodeImage) {
|
if (accountChannel === 'wechat' && !wechatQrCodeImage) {
|
||||||
throw createHttpError('微信提现信息缺少收款二维码,请联系客服处理', {
|
throw createHttpError('微信提现信息缺少收款二维码,请联系客服处理', {
|
||||||
statusCode: 409,
|
statusCode: 409,
|
||||||
@@ -1217,6 +1225,7 @@ export async function createWorkerWithdrawRequest(
|
|||||||
source: 'worker_profile_withdraw',
|
source: 'worker_profile_withdraw',
|
||||||
username: worker.username,
|
username: worker.username,
|
||||||
phone: worker.phone || '',
|
phone: worker.phone || '',
|
||||||
|
alipayQrCodeImage,
|
||||||
wechatQrCodeImage,
|
wechatQrCodeImage,
|
||||||
}),
|
}),
|
||||||
now: nowIso(),
|
now: nowIso(),
|
||||||
@@ -1261,6 +1270,10 @@ export async function createWorkerWithdrawalAccount(
|
|||||||
const accountName = String(payload.accountName || payload.realName || '').trim()
|
const accountName = String(payload.accountName || payload.realName || '').trim()
|
||||||
const accountNo =
|
const accountNo =
|
||||||
accountChannel === 'alipay' ? String(payload.accountNo || payload.account || '').trim() : ''
|
accountChannel === 'alipay' ? String(payload.accountNo || payload.account || '').trim() : ''
|
||||||
|
const alipayQrCodeImage =
|
||||||
|
accountChannel === 'alipay'
|
||||||
|
? normalizeProofFiles(payload.alipayQrCodeImages || payload.alipayQrCodes)[0] || null
|
||||||
|
: null
|
||||||
const wechatQrCodeImage =
|
const wechatQrCodeImage =
|
||||||
accountChannel === 'wechat'
|
accountChannel === 'wechat'
|
||||||
? normalizeProofFiles(payload.wechatQrCodeImages || payload.wechatQrCodes)[0] || null
|
? normalizeProofFiles(payload.wechatQrCodeImages || payload.wechatQrCodes)[0] || null
|
||||||
@@ -1277,6 +1290,12 @@ export async function createWorkerWithdrawalAccount(
|
|||||||
errorCode: 'worker_withdraw_account_no_required',
|
errorCode: 'worker_withdraw_account_no_required',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (accountChannel === 'alipay' && !alipayQrCodeImage) {
|
||||||
|
throw createHttpError('请上传支付宝收款二维码', {
|
||||||
|
statusCode: 400,
|
||||||
|
errorCode: 'worker_withdraw_alipay_qr_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
if (accountChannel === 'wechat' && !wechatQrCodeImage) {
|
if (accountChannel === 'wechat' && !wechatQrCodeImage) {
|
||||||
throw createHttpError('请上传微信收款二维码', {
|
throw createHttpError('请上传微信收款二维码', {
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
@@ -1289,6 +1308,7 @@ export async function createWorkerWithdrawalAccount(
|
|||||||
accountChannel,
|
accountChannel,
|
||||||
accountName,
|
accountName,
|
||||||
accountNo,
|
accountNo,
|
||||||
|
alipayQrCodeJson: JSON.stringify(alipayQrCodeImage || {}),
|
||||||
wechatQrCodeJson: JSON.stringify(wechatQrCodeImage || {}),
|
wechatQrCodeJson: JSON.stringify(wechatQrCodeImage || {}),
|
||||||
now: nowIso(),
|
now: nowIso(),
|
||||||
})
|
})
|
||||||
@@ -1303,24 +1323,81 @@ export async function createWorkerWithdrawalAccount(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 历史支付宝账户只允许补充一次收款二维码,不允许修改账户姓名、账号或二维码。 */
|
||||||
|
export async function saveWorkerAlipayWithdrawalQrCode(
|
||||||
|
payload: JsonObject = {},
|
||||||
|
session: WorkerSession,
|
||||||
|
) {
|
||||||
|
requireActiveWorkerSession(session)
|
||||||
|
const worker = await getRequiredWorker(session.workerId)
|
||||||
|
const current = await getWorkerWithdrawalAccount(worker.id, 'alipay')
|
||||||
|
if (!current) {
|
||||||
|
throw createHttpError('请先添加支付宝提现信息', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'worker_withdrawal_alipay_account_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (resolveAlipayWithdrawalQrCode(current)) {
|
||||||
|
throw createHttpError('支付宝收款二维码已补充,后续修改请联系客服处理', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'worker_withdrawal_alipay_qr_already_set',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const alipayQrCodeImage = normalizeProofFiles(
|
||||||
|
payload.alipayQrCodeImages || payload.alipayQrCodes,
|
||||||
|
)[0]
|
||||||
|
if (!alipayQrCodeImage) {
|
||||||
|
throw createHttpError('请上传支付宝收款二维码', {
|
||||||
|
statusCode: 400,
|
||||||
|
errorCode: 'worker_withdraw_alipay_qr_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const saved = await upsertWorkerWithdrawalAccount({
|
||||||
|
workerId: worker.id,
|
||||||
|
accountChannel: 'alipay',
|
||||||
|
accountName: current.account_name,
|
||||||
|
accountNo: current.account_no,
|
||||||
|
alipayQrCodeJson: JSON.stringify(alipayQrCodeImage),
|
||||||
|
wechatQrCodeJson: JSON.stringify(safeParseJson(current.wechat_qr_code_json)),
|
||||||
|
now: nowIso(),
|
||||||
|
})
|
||||||
|
if (!saved) {
|
||||||
|
throw createHttpError('保存支付宝收款二维码失败', {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: 'worker_withdrawal_alipay_qr_save_failed',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return { withdrawalAccount: mapWithdrawalAccount(saved) }
|
||||||
|
}
|
||||||
|
|
||||||
function mapWithdrawalAccount(account: {
|
function mapWithdrawalAccount(account: {
|
||||||
account_channel: string
|
account_channel: string
|
||||||
account_name: string
|
account_name: string
|
||||||
account_no: string
|
account_no: string
|
||||||
|
alipay_qr_code_json: string | Record<string, unknown>
|
||||||
wechat_qr_code_json: string | Record<string, unknown>
|
wechat_qr_code_json: string | Record<string, unknown>
|
||||||
created_at: string
|
created_at: string
|
||||||
}) {
|
}) {
|
||||||
|
const alipayQrCodeImage = resolveAlipayWithdrawalQrCode(account)
|
||||||
const wechatQrCodeImage = resolveWechatWithdrawalQrCode(account)
|
const wechatQrCodeImage = resolveWechatWithdrawalQrCode(account)
|
||||||
return {
|
return {
|
||||||
accountChannel: account.account_channel,
|
accountChannel: account.account_channel,
|
||||||
accountName: account.account_name,
|
accountName: account.account_name,
|
||||||
accountNoMasked:
|
accountNoMasked:
|
||||||
account.account_channel === 'alipay' ? maskWithdrawalAccountNo(account.account_no) : '',
|
account.account_channel === 'alipay' ? maskWithdrawalAccountNo(account.account_no) : '',
|
||||||
|
alipayQrCodeImage,
|
||||||
wechatQrCodeImage,
|
wechatQrCodeImage,
|
||||||
createdAt: account.created_at,
|
createdAt: account.created_at,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveAlipayWithdrawalQrCode(account: {
|
||||||
|
alipay_qr_code_json: string | Record<string, unknown>
|
||||||
|
}) {
|
||||||
|
const file = refreshUploadedFileUrls(safeParseJson(account.alipay_qr_code_json))
|
||||||
|
return String(file.url || '').trim() ? file : null
|
||||||
|
}
|
||||||
|
|
||||||
function resolveWechatWithdrawalQrCode(account: {
|
function resolveWechatWithdrawalQrCode(account: {
|
||||||
wechat_qr_code_json: string | Record<string, unknown>
|
wechat_qr_code_json: string | Record<string, unknown>
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -235,9 +235,7 @@ export default function FinancePanel() {
|
|||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
render: (_, row) => (
|
render: (_, row) => (
|
||||||
<ImagePreviewList
|
<ImagePreviewList
|
||||||
files={
|
files={row.requestType === 'recharge' ? getRechargeProofs(row) : getWithdrawQrCode(row)}
|
||||||
row.requestType === 'recharge' ? getRechargeProofs(row) : getWechatWithdrawQrCode(row)
|
|
||||||
}
|
|
||||||
size={48}
|
size={48}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -516,6 +514,7 @@ export default function FinancePanel() {
|
|||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
{reviewState.request.requestType === 'withdraw' &&
|
{reviewState.request.requestType === 'withdraw' &&
|
||||||
reviewState.request.accountChannel === 'alipay' ? (
|
reviewState.request.accountChannel === 'alipay' ? (
|
||||||
|
<>
|
||||||
<Descriptions.Item label="支付宝账号">
|
<Descriptions.Item label="支付宝账号">
|
||||||
{reviewState.request.accountNo ? (
|
{reviewState.request.accountNo ? (
|
||||||
<Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
|
<Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
|
||||||
@@ -523,6 +522,13 @@ export default function FinancePanel() {
|
|||||||
'-'
|
'-'
|
||||||
)}
|
)}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="支付宝收款二维码">
|
||||||
|
<ImagePreviewList
|
||||||
|
files={getAlipayWithdrawQrCode(reviewState.request)}
|
||||||
|
size={88}
|
||||||
|
/>
|
||||||
|
</Descriptions.Item>
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{reviewState.request.requestType === 'recharge' ? (
|
{reviewState.request.requestType === 'recharge' ? (
|
||||||
<>
|
<>
|
||||||
@@ -697,6 +703,30 @@ function getWechatWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[]
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[] {
|
||||||
|
if (request.accountChannel === 'alipay') return getAlipayWithdrawQrCode(request)
|
||||||
|
return getWechatWithdrawQrCode(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAlipayWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[] {
|
||||||
|
if (request.requestType !== 'withdraw' || request.accountChannel !== 'alipay') return []
|
||||||
|
const payload = asRecord(request.payload)
|
||||||
|
const file = asRecord(payload.alipayQrCodeImage)
|
||||||
|
const url = String(file.url || '').trim()
|
||||||
|
if (!url) return []
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
mediumUrl: String(file.mediumUrl || '').trim(),
|
||||||
|
thumbnailUrl: String(file.thumbnailUrl || '').trim(),
|
||||||
|
objectKey: String(file.objectKey || '').trim(),
|
||||||
|
filename: String(file.filename || '').trim(),
|
||||||
|
contentType: String(file.contentType || '').trim(),
|
||||||
|
size: Number(file.size || 0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
function getRechargePaidAt(request: WorkerFinanceRequest): string {
|
function getRechargePaidAt(request: WorkerFinanceRequest): string {
|
||||||
const payload = asRecord(request.payload)
|
const payload = asRecord(request.payload)
|
||||||
return String(payload.paidAt || '').trim()
|
return String(payload.paidAt || '').trim()
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ type WithdrawalAccountFormValues = {
|
|||||||
accountChannel?: string
|
accountChannel?: string
|
||||||
accountName?: string
|
accountName?: string
|
||||||
accountNo?: string
|
accountNo?: string
|
||||||
|
alipayQrCodeImages?: UploadedFile[]
|
||||||
wechatQrCodeImages?: UploadedFile[]
|
wechatQrCodeImages?: UploadedFile[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +70,9 @@ export default function WorkersPanel() {
|
|||||||
const [resetPasswordForm] = Form.useForm<{ password: string }>()
|
const [resetPasswordForm] = Form.useForm<{ password: string }>()
|
||||||
const [freezeForm] = Form.useForm<FreezeWorkerFormValues>()
|
const [freezeForm] = Form.useForm<FreezeWorkerFormValues>()
|
||||||
const withdrawalAccountChannel = Form.useWatch('accountChannel', withdrawalAccountForm)
|
const withdrawalAccountChannel = Form.useWatch('accountChannel', withdrawalAccountForm)
|
||||||
|
const editingAlipayAccount = withdrawalAccounts.find(
|
||||||
|
(account) => account.accountChannel === 'alipay',
|
||||||
|
)
|
||||||
|
|
||||||
const workersQuery = useQuery({
|
const workersQuery = useQuery({
|
||||||
queryKey: ['admin-worker-platform-workers', status, keyword, workerType, page, pageSize],
|
queryKey: ['admin-worker-platform-workers', status, keyword, workerType, page, pageSize],
|
||||||
@@ -225,6 +229,7 @@ export default function WorkersPanel() {
|
|||||||
accountChannel,
|
accountChannel,
|
||||||
accountName: account?.accountName || '',
|
accountName: account?.accountName || '',
|
||||||
accountNo: account?.accountNo || '',
|
accountNo: account?.accountNo || '',
|
||||||
|
alipayQrCodeImages: account?.alipayQrCodeImage ? [account.alipayQrCodeImage] : [],
|
||||||
wechatQrCodeImages: account?.wechatQrCodeImage ? [account.wechatQrCodeImage] : [],
|
wechatQrCodeImages: account?.wechatQrCodeImage ? [account.wechatQrCodeImage] : [],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -240,6 +245,7 @@ export default function WorkersPanel() {
|
|||||||
{
|
{
|
||||||
accountName: String(values.accountName || '').trim(),
|
accountName: String(values.accountName || '').trim(),
|
||||||
accountNo: String(values.accountNo || '').trim(),
|
accountNo: String(values.accountNo || '').trim(),
|
||||||
|
alipayQrCodeImages: values.alipayQrCodeImages || [],
|
||||||
wechatQrCodeImages: values.wechatQrCodeImages || [],
|
wechatQrCodeImages: values.wechatQrCodeImages || [],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -559,13 +565,28 @@ export default function WorkersPanel() {
|
|||||||
<ImageUpload scene="admin-worker-withdrawal-wechat-qr" scope="admin" maxCount={1} />
|
<ImageUpload scene="admin-worker-withdrawal-wechat-qr" scope="admin" maxCount={1} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
) : (
|
) : (
|
||||||
|
<>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="支付宝账号"
|
label="支付宝账号"
|
||||||
name="accountNo"
|
name="accountNo"
|
||||||
rules={[{ required: true, message: '请输入支付宝账号' }]}
|
rules={
|
||||||
|
editingAlipayAccount ? [] : [{ required: true, message: '请输入支付宝账号' }]
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入支付宝账号" />
|
<Input
|
||||||
|
placeholder={
|
||||||
|
editingAlipayAccount ? '历史账户未登记账号,可仅补充二维码' : '请输入支付宝账号'
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="支付宝收款二维码"
|
||||||
|
name="alipayQrCodeImages"
|
||||||
|
rules={[{ required: true, message: '请上传支付宝收款二维码' }]}
|
||||||
|
>
|
||||||
|
<ImageUpload scene="admin-worker-withdrawal-alipay-qr" scope="admin" maxCount={1} />
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import {
|
|||||||
deleteWorkerSession,
|
deleteWorkerSession,
|
||||||
fetchWorkerWalletLedgers,
|
fetchWorkerWalletLedgers,
|
||||||
logoutWorker,
|
logoutWorker,
|
||||||
|
saveWorkerAlipayWithdrawalQrCode,
|
||||||
} from '@/services/worker'
|
} from '@/services/worker'
|
||||||
import type {
|
import type {
|
||||||
UploadedFile,
|
UploadedFile,
|
||||||
@@ -80,9 +81,14 @@ type WithdrawalAccountFormValues = {
|
|||||||
accountChannel?: string
|
accountChannel?: string
|
||||||
accountName?: string
|
accountName?: string
|
||||||
accountNo?: string
|
accountNo?: string
|
||||||
|
alipayQrCodeImages?: UploadedFile[]
|
||||||
wechatQrCodeImages?: UploadedFile[]
|
wechatQrCodeImages?: UploadedFile[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlipayQrCodeFormValues = {
|
||||||
|
alipayQrCodeImages?: UploadedFile[]
|
||||||
|
}
|
||||||
|
|
||||||
type PasswordFormValues = {
|
type PasswordFormValues = {
|
||||||
currentPassword?: string
|
currentPassword?: string
|
||||||
newPassword?: string
|
newPassword?: string
|
||||||
@@ -106,6 +112,7 @@ export default function WorkerProfilePage() {
|
|||||||
const [rechargeOpen, setRechargeOpen] = useState(false)
|
const [rechargeOpen, setRechargeOpen] = useState(false)
|
||||||
const [withdrawOpen, setWithdrawOpen] = useState(false)
|
const [withdrawOpen, setWithdrawOpen] = useState(false)
|
||||||
const [withdrawalAccountOpen, setWithdrawalAccountOpen] = useState(false)
|
const [withdrawalAccountOpen, setWithdrawalAccountOpen] = useState(false)
|
||||||
|
const [alipayQrCodeOpen, setAlipayQrCodeOpen] = useState(false)
|
||||||
const [passwordOpen, setPasswordOpen] = useState(false)
|
const [passwordOpen, setPasswordOpen] = useState(false)
|
||||||
const [contactOpen, setContactOpen] = useState(false)
|
const [contactOpen, setContactOpen] = useState(false)
|
||||||
const [devicesOpen, setDevicesOpen] = useState(false)
|
const [devicesOpen, setDevicesOpen] = useState(false)
|
||||||
@@ -116,6 +123,7 @@ export default function WorkerProfilePage() {
|
|||||||
const [rechargeForm] = Form.useForm<RechargeFormValues>()
|
const [rechargeForm] = Form.useForm<RechargeFormValues>()
|
||||||
const [withdrawForm] = Form.useForm<WithdrawFormValues>()
|
const [withdrawForm] = Form.useForm<WithdrawFormValues>()
|
||||||
const [withdrawalAccountForm] = Form.useForm<WithdrawalAccountFormValues>()
|
const [withdrawalAccountForm] = Form.useForm<WithdrawalAccountFormValues>()
|
||||||
|
const [alipayQrCodeForm] = Form.useForm<AlipayQrCodeFormValues>()
|
||||||
const [passwordForm] = Form.useForm<PasswordFormValues>()
|
const [passwordForm] = Form.useForm<PasswordFormValues>()
|
||||||
const selectedWithdrawChannel = Form.useWatch('accountChannel', withdrawForm)
|
const selectedWithdrawChannel = Form.useWatch('accountChannel', withdrawForm)
|
||||||
const selectedWithdrawalAccountChannel = Form.useWatch('accountChannel', withdrawalAccountForm)
|
const selectedWithdrawalAccountChannel = Form.useWatch('accountChannel', withdrawalAccountForm)
|
||||||
@@ -141,6 +149,9 @@ export default function WorkerProfilePage() {
|
|||||||
const selectedWithdrawalAccount = withdrawalAccounts.find(
|
const selectedWithdrawalAccount = withdrawalAccounts.find(
|
||||||
(account) => account.accountChannel === selectedWithdrawChannel,
|
(account) => account.accountChannel === selectedWithdrawChannel,
|
||||||
)
|
)
|
||||||
|
const alipayWithdrawalAccount = withdrawalAccounts.find(
|
||||||
|
(account) => account.accountChannel === 'alipay',
|
||||||
|
)
|
||||||
const canUseFinanceActions = worker?.status === 'active'
|
const canUseFinanceActions = worker?.status === 'active'
|
||||||
|
|
||||||
async function copyInviteCode() {
|
async function copyInviteCode() {
|
||||||
@@ -233,6 +244,11 @@ export default function WorkerProfilePage() {
|
|||||||
openWithdrawalAccountModal()
|
openWithdrawalAccountModal()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (alipayWithdrawalAccount && !alipayWithdrawalAccount.alipayQrCodeImage) {
|
||||||
|
message.warning('请先补充支付宝收款二维码')
|
||||||
|
openAlipayQrCodeModal()
|
||||||
|
return
|
||||||
|
}
|
||||||
withdrawForm.setFieldValue('accountChannel', withdrawalAccounts[0].accountChannel)
|
withdrawForm.setFieldValue('accountChannel', withdrawalAccounts[0].accountChannel)
|
||||||
setWithdrawOpen(true)
|
setWithdrawOpen(true)
|
||||||
}
|
}
|
||||||
@@ -249,6 +265,19 @@ export default function WorkerProfilePage() {
|
|||||||
setWithdrawalAccountOpen(true)
|
setWithdrawalAccountOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openAlipayQrCodeModal() {
|
||||||
|
if (!alipayWithdrawalAccount) {
|
||||||
|
openWithdrawalAccountModal()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
alipayQrCodeForm.setFieldsValue({
|
||||||
|
alipayQrCodeImages: alipayWithdrawalAccount.alipayQrCodeImage
|
||||||
|
? [alipayWithdrawalAccount.alipayQrCodeImage]
|
||||||
|
: [],
|
||||||
|
})
|
||||||
|
setAlipayQrCodeOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
async function submitRecharge(values: RechargeFormValues) {
|
async function submitRecharge(values: RechargeFormValues) {
|
||||||
setSubmittingRecharge(true)
|
setSubmittingRecharge(true)
|
||||||
try {
|
try {
|
||||||
@@ -301,6 +330,7 @@ export default function WorkerProfilePage() {
|
|||||||
accountChannel: String(values.accountChannel || ''),
|
accountChannel: String(values.accountChannel || ''),
|
||||||
accountName: String(values.accountName || '').trim(),
|
accountName: String(values.accountName || '').trim(),
|
||||||
accountNo: String(values.accountNo || '').trim(),
|
accountNo: String(values.accountNo || '').trim(),
|
||||||
|
alipayQrCodeImages: values.alipayQrCodeImages || [],
|
||||||
wechatQrCodeImages: values.wechatQrCodeImages || [],
|
wechatQrCodeImages: values.wechatQrCodeImages || [],
|
||||||
})
|
})
|
||||||
message.success('提现信息已添加,该方式后续修改请联系客服处理')
|
message.success('提现信息已添加,该方式后续修改请联系客服处理')
|
||||||
@@ -316,6 +346,20 @@ export default function WorkerProfilePage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function submitAlipayQrCode(values: AlipayQrCodeFormValues) {
|
||||||
|
try {
|
||||||
|
await saveWorkerAlipayWithdrawalQrCode({
|
||||||
|
alipayQrCodeImages: values.alipayQrCodeImages || [],
|
||||||
|
})
|
||||||
|
message.success('支付宝收款二维码已保存')
|
||||||
|
setAlipayQrCodeOpen(false)
|
||||||
|
alipayQrCodeForm.resetFields()
|
||||||
|
await refreshAll()
|
||||||
|
} catch (error) {
|
||||||
|
message.error(error instanceof Error ? error.message : '保存支付宝收款二维码失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function submitPasswordChange(values: PasswordFormValues) {
|
async function submitPasswordChange(values: PasswordFormValues) {
|
||||||
setSubmittingPassword(true)
|
setSubmittingPassword(true)
|
||||||
try {
|
try {
|
||||||
@@ -673,6 +717,22 @@ export default function WorkerProfilePage() {
|
|||||||
</div>
|
</div>
|
||||||
<span>邀请好友</span>
|
<span>邀请好友</span>
|
||||||
</button>
|
</button>
|
||||||
|
{alipayWithdrawalAccount && !alipayWithdrawalAccount.alipayQrCodeImage ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="worker-profile-mobile-tool-item"
|
||||||
|
disabled={!canUseFinanceActions}
|
||||||
|
onClick={openAlipayQrCodeModal}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="worker-profile-mobile-tool-icon"
|
||||||
|
style={{ background: '#f5f3ff', color: '#7c3aed' }}
|
||||||
|
>
|
||||||
|
<BankOutlined />
|
||||||
|
</div>
|
||||||
|
<span>补充支付宝收款码</span>
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="worker-profile-mobile-tool-item"
|
className="worker-profile-mobile-tool-item"
|
||||||
@@ -1152,6 +1212,15 @@ export default function WorkerProfilePage() {
|
|||||||
添加提现信息
|
添加提现信息
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
|
{alipayWithdrawalAccount && !alipayWithdrawalAccount.alipayQrCodeImage ? (
|
||||||
|
<Button
|
||||||
|
icon={<BankOutlined />}
|
||||||
|
disabled={!canUseFinanceActions}
|
||||||
|
onClick={openAlipayQrCodeModal}
|
||||||
|
>
|
||||||
|
补充支付宝收款码
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
<Button icon={<LockOutlined />} onClick={() => setPasswordOpen(true)}>
|
<Button icon={<LockOutlined />} onClick={() => setPasswordOpen(true)}>
|
||||||
修改密码
|
修改密码
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1234,10 +1303,14 @@ export default function WorkerProfilePage() {
|
|||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
{account.accountChannel === 'wechat'
|
{account.accountChannel === 'wechat'
|
||||||
? '已上传收款二维码'
|
? '已上传收款二维码'
|
||||||
: account.accountNoMasked}
|
: `${account.accountNoMasked} / ${
|
||||||
|
account.alipayQrCodeImage
|
||||||
|
? '已上传收款二维码'
|
||||||
|
: '未上传收款二维码'
|
||||||
|
}`}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
已锁定,修改请联系客服
|
收款人姓名和账号已锁定
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Space>
|
</Space>
|
||||||
))}
|
))}
|
||||||
@@ -1533,7 +1606,7 @@ export default function WorkerProfilePage() {
|
|||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="warning"
|
type="warning"
|
||||||
message="支付宝和微信可分别添加一次;每种方式添加后均无法自行修改,如需修改请联系客服。"
|
message="支付宝和微信可分别添加一次;收款人姓名和账号添加后不可自行修改。历史支付宝账户缺少二维码时,仅可补充一次。"
|
||||||
style={{ marginBottom: 16 }}
|
style={{ marginBottom: 16 }}
|
||||||
/>
|
/>
|
||||||
<Form form={withdrawalAccountForm} layout="vertical" onFinish={submitWithdrawalAccount}>
|
<Form form={withdrawalAccountForm} layout="vertical" onFinish={submitWithdrawalAccount}>
|
||||||
@@ -1570,6 +1643,7 @@ export default function WorkerProfilePage() {
|
|||||||
<ImageUpload scene="worker-withdrawal-wechat-qr" scope="worker" maxCount={1} />
|
<ImageUpload scene="worker-withdrawal-wechat-qr" scope="worker" maxCount={1} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
) : (
|
) : (
|
||||||
|
<>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="支付宝账号"
|
label="支付宝账号"
|
||||||
name="accountNo"
|
name="accountNo"
|
||||||
@@ -1577,10 +1651,46 @@ export default function WorkerProfilePage() {
|
|||||||
>
|
>
|
||||||
<Input placeholder="请输入支付宝账号" />
|
<Input placeholder="请输入支付宝账号" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="支付宝收款二维码"
|
||||||
|
name="alipayQrCodeImages"
|
||||||
|
rules={[{ required: true, message: '请上传支付宝收款二维码' }]}
|
||||||
|
>
|
||||||
|
<ImageUpload scene="worker-withdrawal-alipay-qr" scope="worker" maxCount={1} />
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="补充支付宝收款二维码"
|
||||||
|
open={alipayQrCodeOpen}
|
||||||
|
width={isMobile ? '92%' : 500}
|
||||||
|
destroyOnHidden
|
||||||
|
onCancel={() => {
|
||||||
|
setAlipayQrCodeOpen(false)
|
||||||
|
alipayQrCodeForm.resetFields()
|
||||||
|
}}
|
||||||
|
onOk={() => alipayQrCodeForm.submit()}
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
showIcon
|
||||||
|
type="info"
|
||||||
|
message="历史账户仅可补充一次支付宝收款二维码,保存后不可自行修改;已登记的收款人姓名和账号保持锁定。"
|
||||||
|
style={{ marginBottom: 16 }}
|
||||||
|
/>
|
||||||
|
<Form form={alipayQrCodeForm} layout="vertical" onFinish={submitAlipayQrCode}>
|
||||||
|
<Form.Item
|
||||||
|
label="支付宝收款二维码"
|
||||||
|
name="alipayQrCodeImages"
|
||||||
|
rules={[{ required: true, message: '请上传支付宝收款二维码' }]}
|
||||||
|
>
|
||||||
|
<ImageUpload scene="worker-withdrawal-alipay-qr" scope="worker" maxCount={1} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
title="提现申请"
|
title="提现申请"
|
||||||
open={withdrawOpen}
|
open={withdrawOpen}
|
||||||
|
|||||||
@@ -310,6 +310,7 @@ export function saveAdminWorkerWithdrawalAccount(
|
|||||||
payload: {
|
payload: {
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNo?: string
|
accountNo?: string
|
||||||
|
alipayQrCodeImages?: UploadedFile[]
|
||||||
wechatQrCodeImages?: UploadedFile[]
|
wechatQrCodeImages?: UploadedFile[]
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { apiDelete, apiGet, apiPost } from '@/lib/http'
|
import { apiDelete, apiGet, apiPost, apiPut } from '@/lib/http'
|
||||||
import type {
|
import type {
|
||||||
CollectLookupResponse,
|
CollectLookupResponse,
|
||||||
UploadedFile,
|
UploadedFile,
|
||||||
@@ -176,11 +176,16 @@ export function createWorkerWithdrawalAccount(payload: {
|
|||||||
accountChannel: string
|
accountChannel: string
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNo?: string
|
accountNo?: string
|
||||||
|
alipayQrCodeImages?: UploadedFile[]
|
||||||
wechatQrCodeImages?: UploadedFile[]
|
wechatQrCodeImages?: UploadedFile[]
|
||||||
}) {
|
}) {
|
||||||
return apiPost('/api/v1/worker/profile/withdrawal-account', payload)
|
return apiPost('/api/v1/worker/profile/withdrawal-account', payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function saveWorkerAlipayWithdrawalQrCode(payload: { alipayQrCodeImages: UploadedFile[] }) {
|
||||||
|
return apiPut('/api/v1/worker/profile/withdrawal-account/alipay-qr-code', payload)
|
||||||
|
}
|
||||||
|
|
||||||
export function changeWorkerPassword(payload: { currentPassword: string; newPassword: string }) {
|
export function changeWorkerPassword(payload: { currentPassword: string; newPassword: string }) {
|
||||||
return apiPost<{ worker: WorkerUser; reloginRequired: boolean }>(
|
return apiPost<{ worker: WorkerUser; reloginRequired: boolean }>(
|
||||||
'/api/v1/worker/profile/change-password',
|
'/api/v1/worker/profile/change-password',
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ export type WorkerWithdrawalAccount = {
|
|||||||
accountChannel: string
|
accountChannel: string
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNoMasked: string
|
accountNoMasked: string
|
||||||
|
alipayQrCodeImage: UploadedFile | null
|
||||||
wechatQrCodeImage: UploadedFile | null
|
wechatQrCodeImage: UploadedFile | null
|
||||||
createdAt: string | null
|
createdAt: string | null
|
||||||
}
|
}
|
||||||
@@ -205,6 +206,7 @@ export type AdminWorkerWithdrawalAccount = {
|
|||||||
accountChannel: string
|
accountChannel: string
|
||||||
accountName: string
|
accountName: string
|
||||||
accountNo: string
|
accountNo: string
|
||||||
|
alipayQrCodeImage: UploadedFile | null
|
||||||
wechatQrCodeImage: UploadedFile | null
|
wechatQrCodeImage: UploadedFile | null
|
||||||
createdAt: string
|
createdAt: string
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user