完善账号冻结与VIP免审核
This commit is contained in:
@@ -42,6 +42,10 @@ type WithdrawalAccountFormValues = {
|
||||
wechatQrCodeImages?: UploadedFile[]
|
||||
}
|
||||
|
||||
type FreezeWorkerFormValues = {
|
||||
freezeReason: string
|
||||
}
|
||||
|
||||
export default function WorkersPanel() {
|
||||
const { message, modal } = App.useApp()
|
||||
const queryClient = useQueryClient()
|
||||
@@ -55,6 +59,7 @@ export default function WorkersPanel() {
|
||||
const [levelWorker, setLevelWorker] = useState<WorkerUser | null>(null)
|
||||
const [withdrawalAccountWorker, setWithdrawalAccountWorker] = useState<WorkerUser | null>(null)
|
||||
const [resetPasswordWorker, setResetPasswordWorker] = useState<WorkerUser | null>(null)
|
||||
const [freezeWorker, setFreezeWorker] = useState<WorkerUser | null>(null)
|
||||
const [withdrawalAccounts, setWithdrawalAccounts] = useState<AdminWorkerWithdrawalAccount[]>([])
|
||||
const [loadingWithdrawalAccounts, setLoadingWithdrawalAccounts] = useState(false)
|
||||
const [savingWithdrawalAccount, setSavingWithdrawalAccount] = useState(false)
|
||||
@@ -62,6 +67,7 @@ export default function WorkersPanel() {
|
||||
const [levelForm] = Form.useForm<{ levelId?: number }>()
|
||||
const [withdrawalAccountForm] = Form.useForm<WithdrawalAccountFormValues>()
|
||||
const [resetPasswordForm] = Form.useForm<{ password: string }>()
|
||||
const [freezeForm] = Form.useForm<FreezeWorkerFormValues>()
|
||||
const withdrawalAccountChannel = Form.useWatch('accountChannel', withdrawalAccountForm)
|
||||
|
||||
const workersQuery = useQuery({
|
||||
@@ -108,6 +114,22 @@ export default function WorkersPanel() {
|
||||
}
|
||||
}
|
||||
|
||||
async function submitFreezeWorker(values: FreezeWorkerFormValues) {
|
||||
if (!freezeWorker) return
|
||||
try {
|
||||
await reviewAdminWorkerUser(freezeWorker.workerId, {
|
||||
status: 'rejected',
|
||||
freezeReason: values.freezeReason.trim(),
|
||||
})
|
||||
message.success('打手账号已冻结,原登录设备已退出')
|
||||
setFreezeWorker(null)
|
||||
freezeForm.resetFields()
|
||||
await refreshWorkers()
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '冻结账号失败')
|
||||
}
|
||||
}
|
||||
|
||||
function toggleWorkerType(worker: WorkerUser, workerType: 'internal' | 'external') {
|
||||
const isInternal = workerType === 'internal'
|
||||
modal.confirm({
|
||||
@@ -297,6 +319,18 @@ export default function WorkersPanel() {
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '冻结原因',
|
||||
width: 220,
|
||||
render: (_, row) =>
|
||||
row.status === 'rejected' && row.freezeReason ? (
|
||||
<Typography.Text ellipsis={{ tooltip: row.freezeReason }}>
|
||||
{row.freezeReason}
|
||||
</Typography.Text>
|
||||
) : (
|
||||
'-'
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 340,
|
||||
@@ -306,7 +340,9 @@ export default function WorkersPanel() {
|
||||
<Button onClick={() => review(row, 'active')}>启用</Button>
|
||||
) : null}
|
||||
{row.status !== 'rejected' ? (
|
||||
<Button onClick={() => review(row, 'rejected')}>拒绝</Button>
|
||||
<Button danger onClick={() => setFreezeWorker(row)}>
|
||||
冻结
|
||||
</Button>
|
||||
) : null}
|
||||
{row.workerType !== 'internal' ? (
|
||||
<Button onClick={() => toggleWorkerType(row, 'internal')}>设为内部</Button>
|
||||
@@ -406,6 +442,40 @@ export default function WorkersPanel() {
|
||||
scroll={{ x: 1000 }}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
title="冻结打手账号"
|
||||
open={Boolean(freezeWorker)}
|
||||
onCancel={() => {
|
||||
setFreezeWorker(null)
|
||||
freezeForm.resetFields()
|
||||
}}
|
||||
onOk={() => freezeForm.submit()}
|
||||
destroyOnHidden
|
||||
>
|
||||
<Form form={freezeForm} layout="vertical" onFinish={submitFreezeWorker}>
|
||||
<Form.Item label="打手">
|
||||
<Typography.Text>
|
||||
{freezeWorker?.displayName || freezeWorker?.username || '-'}
|
||||
</Typography.Text>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="冻结原因"
|
||||
name="freezeReason"
|
||||
rules={[
|
||||
{ required: true, whitespace: true, message: '请填写冻结原因或备注' },
|
||||
{ max: 500, message: '冻结原因不能超过 500 个字符' },
|
||||
]}
|
||||
>
|
||||
<Input.TextArea
|
||||
autoSize={{ minRows: 3, maxRows: 6 }}
|
||||
maxLength={500}
|
||||
placeholder="例如:多次超时未完成订单,经核实后冻结账号"
|
||||
showCount
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title="重置打手密码"
|
||||
open={Boolean(resetPasswordWorker)}
|
||||
|
||||
@@ -277,7 +277,13 @@ export function reprocessAdminKuaishouWorkOrderMatches(limit = 100) {
|
||||
|
||||
export function reviewAdminWorkerUser(
|
||||
workerId: number,
|
||||
payload: { status: string; reviewNote?: string; levelId?: number; workerType?: string },
|
||||
payload: {
|
||||
status: string
|
||||
reviewNote?: string
|
||||
freezeReason?: string
|
||||
levelId?: number
|
||||
workerType?: string
|
||||
},
|
||||
) {
|
||||
return apiPost<{ worker: WorkerUser }>(
|
||||
`/api/v1/admin/worker-platform/workers/${workerId}/review`,
|
||||
|
||||
@@ -6,6 +6,8 @@ export type WorkerUser = {
|
||||
status: string
|
||||
workerType: string
|
||||
reviewNote: string
|
||||
freezeReason: string
|
||||
frozenAt: string | null
|
||||
inviteCode: string
|
||||
inviter: null | {
|
||||
workerId: number
|
||||
|
||||
Reference in New Issue
Block a user