完善账号冻结与VIP免审核

This commit is contained in:
yml2213
2026-08-20 20:42:03 +08:00
parent e05a6797a3
commit 942cbcab68
10 changed files with 178 additions and 10 deletions
@@ -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