新增打手撤单审核

This commit is contained in:
yml2213
2026-08-20 19:43:03 +08:00
parent d76d1e8d90
commit e504b3a207
20 changed files with 1331 additions and 8 deletions
@@ -34,6 +34,7 @@ import WorkOrderEventTimeline from '@/components/WorkOrderEventTimeline'
import ImagePreviewList from '@/components/files/ImagePreviewList'
import ImageUpload from '@/components/files/ImageUpload'
import {
fetchWorkerCancelRequests,
fetchWorkerMyOrderOverview,
fetchWorkerMyOrders,
fetchWorkerProfile,
@@ -43,6 +44,7 @@ import {
saveWorkerOrderNote,
supplementWorkerAcceptedOrderEvidence,
submitWorkerAcceptance,
submitWorkerCancelRequest,
} from '@/services/worker'
import type {
CollectField,
@@ -73,6 +75,10 @@ type WorkerNoteFormValues = {
note?: string
}
type CancelRequestFormValues = {
reason?: string
}
function buildWorkerOrderQuery(status: string, keyword: string, page: number, pageSize: number) {
return {
keyword,
@@ -194,9 +200,11 @@ export default function WorkerOrdersPage() {
const [detailOrder, setDetailOrder] = useState<WorkOrder | null>(null)
const [editingOrder, setEditingOrder] = useState<WorkOrder | null>(null)
const [noteOrder, setNoteOrder] = useState<WorkOrder | null>(null)
const [cancelRequestOrder, setCancelRequestOrder] = useState<WorkOrder | null>(null)
const [acceptanceFiles, setAcceptanceFiles] = useState<UploadedFile[]>([])
const [form] = Form.useForm<AcceptanceFormValues>()
const [noteForm] = Form.useForm<WorkerNoteFormValues>()
const [cancelRequestForm] = Form.useForm<CancelRequestFormValues>()
const ordersQuery = useQuery({
queryKey: ['worker-my-orders', status, keyword, page, pageSize],
@@ -221,6 +229,11 @@ export default function WorkerOrdersPage() {
queryFn: fetchWorkerMyOrderOverview,
retry: false,
})
const cancelRequestsQuery = useQuery({
queryKey: ['worker-cancel-requests'],
queryFn: fetchWorkerCancelRequests,
retry: false,
})
const overviewByStatus = new Map(
(overviewQuery.data?.data.items || []).map((item) => [item.status, item]),
)
@@ -229,6 +242,7 @@ export default function WorkerOrdersPage() {
await Promise.all([
queryClient.invalidateQueries({ queryKey: ['worker-my-orders'] }),
queryClient.invalidateQueries({ queryKey: ['worker-my-orders-overview'] }),
queryClient.invalidateQueries({ queryKey: ['worker-cancel-requests'] }),
])
}
@@ -314,6 +328,27 @@ export default function WorkerOrdersPage() {
noteForm.setFieldsValue({ note: String(order.workerNote || '') })
}
function openCancelRequestModal(order: WorkOrder) {
markOrderAsRead(order)
setCancelRequestOrder(order)
cancelRequestForm.resetFields()
}
async function submitCancelRequest(values: CancelRequestFormValues) {
if (!cancelRequestOrder) return
try {
await submitWorkerCancelRequest(cancelRequestOrder.workOrderId, {
reason: String(values.reason || '').trim(),
})
message.success('取消申请已提交,等待客服审核')
setCancelRequestOrder(null)
cancelRequestForm.resetFields()
await refreshAll()
} catch (error) {
message.error(error instanceof Error ? error.message : '提交取消申请失败')
}
}
async function saveOrderNote(values: WorkerNoteFormValues) {
if (!noteOrder) return
try {
@@ -644,6 +679,11 @@ export default function WorkerOrdersPage() {
{canRemindAcceptance(row) ? (
<Button onClick={() => submitAcceptanceReminder(row)}></Button>
) : null}
{canRequestCancel(row) ? (
<Button danger onClick={() => openCancelRequestModal(row)}>
</Button>
) : null}
</Space>
</div>
),
@@ -950,6 +990,11 @@ export default function WorkerOrdersPage() {
</Button>
) : null}
{canRequestCancel(order) ? (
<Button size="small" danger onClick={() => openCancelRequestModal(order)}>
</Button>
) : null}
</div>
</div>
</article>
@@ -1113,6 +1158,11 @@ export default function WorkerOrdersPage() {
{hasSubmittedAcceptance(detailOrder) ? '补充图片' : '上传图片 / 提交验收'}
</Button>
) : null}
{canRequestCancel(detailOrder) ? (
<Button danger onClick={() => openCancelRequestModal(detailOrder)}>
</Button>
) : null}
</Space>
) : null
}
@@ -1229,6 +1279,46 @@ export default function WorkerOrdersPage() {
</div>
) : null}
</Drawer>
<Modal
title={`申请取消 · ${getDisplayOrderNo(cancelRequestOrder)}`}
open={Boolean(cancelRequestOrder)}
width={isMobile ? '92%' : 520}
onCancel={() => {
setCancelRequestOrder(null)
cancelRequestForm.resetFields()
}}
onOk={() => cancelRequestForm.submit()}
okText="提交申请"
destroyOnHidden
>
<Space direction="vertical" size={8} style={{ width: '100%', marginBottom: 16 }}>
<Typography.Text type="secondary">
退
</Typography.Text>
<Typography.Text type="secondary">
{cancelRequestsQuery.data?.data.risk.dailyUsed || 0}/
{cancelRequestsQuery.data?.data.risk.dailyLimit || 5}
{cancelRequestsQuery.data?.data.risk.approvedTotal || 0}
</Typography.Text>
<Typography.Text type="warning">
10 VIP1 5
</Typography.Text>
</Space>
<Form form={cancelRequestForm} layout="vertical" onFinish={submitCancelRequest}>
<Form.Item
label="申请原因"
name="reason"
rules={[{ required: true, whitespace: true, message: '请填写申请取消原因' }]}
>
<Input.TextArea
rows={4}
maxLength={300}
showCount
placeholder="请说明无法继续处理的原因"
/>
</Form.Item>
</Form>
</Modal>
<Modal
title={`订单备注 · ${getDisplayOrderNo(noteOrder)}`}
open={Boolean(noteOrder)}
@@ -1382,6 +1472,16 @@ function canRemindAcceptance(order: WorkOrder) {
return !order.myShare && order.status === 'pending_acceptance'
}
function canRequestCancel(order: WorkOrder) {
if (order.myShare) {
return (
['joined', 'submitted'].includes(order.myShare.status) &&
['open', 'pending_acceptance'].includes(order.status)
)
}
return order.status === 'in_progress'
}
function canAutoAcceptOrder(order: WorkOrder, workerCanAutoAcceptWithoutEvidence: boolean) {
if (!workerCanAutoAcceptWithoutEvidence) return false
if (order.myShare) return order.myShare.status === 'joined' && order.status !== 'accepted'