From 4e8fb433efd9aa3c69a2e96472a8ca7771ca04cb Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 21 Aug 2026 16:18:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E6=89=93=E6=89=8B=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/worker/WorkerOrderDesktopList.tsx | 12 +- .../pages/worker/WorkerOrderMobileList.tsx | 438 +++++++++++ .../pages/worker/WorkerOrderTableColumns.tsx | 349 +++++++++ .../src/pages/worker/WorkerOrdersPage.tsx | 689 ++---------------- 4 files changed, 860 insertions(+), 628 deletions(-) create mode 100644 apps/frontend/src/pages/worker/WorkerOrderMobileList.tsx create mode 100644 apps/frontend/src/pages/worker/WorkerOrderTableColumns.tsx diff --git a/apps/frontend/src/pages/worker/WorkerOrderDesktopList.tsx b/apps/frontend/src/pages/worker/WorkerOrderDesktopList.tsx index d99086e2..a3269f28 100644 --- a/apps/frontend/src/pages/worker/WorkerOrderDesktopList.tsx +++ b/apps/frontend/src/pages/worker/WorkerOrderDesktopList.tsx @@ -19,8 +19,11 @@ export function WorkerOrderDesktopList({ keyword, orders, pagination, + page, + pageSize, columns, loading, + searching, refreshing, error, onRefresh, @@ -36,8 +39,11 @@ export function WorkerOrderDesktopList({ keyword: string orders: WorkOrder[] pagination: Pagination | undefined + page: number + pageSize: number columns: TableColumnsType loading: boolean + searching: boolean refreshing: boolean error: unknown onRefresh: () => void @@ -91,7 +97,7 @@ export function WorkerOrderDesktopList({ onChange={(event) => onKeywordInputChange(event.target.value)} onPressEnter={onKeywordSearch} /> - @@ -114,8 +120,8 @@ export function WorkerOrderDesktopList({ ), }} pagination={{ - current: pagination?.page || 1, - pageSize: pagination?.pageSize || 20, + current: pagination?.page || page, + pageSize: pagination?.pageSize || pageSize, total: pagination?.total || 0, showSizeChanger: true, pageSizeOptions: [10, 20, 50, 100], diff --git a/apps/frontend/src/pages/worker/WorkerOrderMobileList.tsx b/apps/frontend/src/pages/worker/WorkerOrderMobileList.tsx new file mode 100644 index 00000000..bcc9fbf7 --- /dev/null +++ b/apps/frontend/src/pages/worker/WorkerOrderMobileList.tsx @@ -0,0 +1,438 @@ +import { + CopyOutlined, + EditOutlined, + EyeOutlined, + MessageOutlined, + PictureOutlined, + ReloadOutlined, + SearchOutlined, +} from '@ant-design/icons' +import { Button, Empty, Input, Pagination, Spin, Tag } from 'antd' + +import { DeadlineCountdown } from '@/components/DeadlineCountdown' +import ImagePreviewList from '@/components/files/ImagePreviewList' +import type { + Pagination as PaginationData, + WorkerOrderOverviewItem, + WorkOrder, +} from '@/types/worker-platform' +import { formatDateTime } from '@/utils/date-time' + +import type { WorkerOrderStatusOption } from './WorkerOrderDesktopList' +import { + canEditAcceptanceImages, + canRemindAcceptance, + canRequestCancel, + canSubmitAcceptance, + canSubmitFeedback, + formatMoney, + formatStatus, + getCopyOrderInfoItems, + getDisplayOrderNo, + getMaterialDetailItems, + getMaterialScreenshots, + getSettlementLabel, + getUniqueAcceptanceFiles, + getWorkerAcceptance, + getWorkerDraft, + hasSubmittedAcceptance, + isVipEvidencePending, + resolveStatusColor, +} from './worker-order-utils' + +export function WorkerOrderMobileList({ + statusOptions, + status, + overviewByStatus, + keywordInput, + keyword, + orders, + pagination, + page, + pageSize, + loading, + searching, + refreshing, + error, + onStatusChange, + onKeywordInputChange, + onKeywordSearch, + onRefresh, + onPageChange, + onOpenDetail, + onOpenAcceptance, + onRemindAcceptance, + onOpenCancelRequest, + onOpenFeedback, + onOpenNote, + onCopyOrderInfo, + onCopyMaterialImages, +}: { + statusOptions: readonly WorkerOrderStatusOption[] + status: string + overviewByStatus: Map + keywordInput: string + keyword: string + orders: WorkOrder[] + pagination: PaginationData | undefined + page: number + pageSize: number + loading: boolean + searching: boolean + refreshing: boolean + error: unknown + onStatusChange: (status: string) => void + onKeywordInputChange: (keyword: string) => void + onKeywordSearch: () => void + onRefresh: () => void + onPageChange: (page: number, pageSize: number) => void + onOpenDetail: (order: WorkOrder) => void + onOpenAcceptance: (order: WorkOrder) => void + onRemindAcceptance: (order: WorkOrder) => void + onOpenCancelRequest: (order: WorkOrder) => void + onOpenFeedback: (order: WorkOrder) => void + onOpenNote: (order: WorkOrder) => void + onCopyOrderInfo: (order: WorkOrder) => void + onCopyMaterialImages: (order: WorkOrder) => void +}) { + return ( +
+
+ {statusOptions.map((item) => { + const overview = overviewByStatus.get(item.value || 'all') + const count = Number(overview?.orderCount || 0) + return ( + + ) + })} +
+ +
+ } + className="worker-orders-mobile-search-input" + onChange={(event) => onKeywordInputChange(event.target.value)} + onPressEnter={onKeywordSearch} + /> +
+ +
+ {loading ? ( +
+ +
+ ) : error ? ( + + ) : orders.length === 0 ? ( + + ) : ( + orders.map((order) => ( + + )) + )} + {(pagination?.total || 0) > 0 ? ( +
+ +
+ ) : null} +
+
+ ) +} + +function WorkerOrderMobileCard({ + order, + onOpenDetail, + onOpenAcceptance, + onRemindAcceptance, + onOpenCancelRequest, + onOpenFeedback, + onOpenNote, + onCopyOrderInfo, + onCopyMaterialImages, +}: Omit< + Parameters[0], + | 'statusOptions' + | 'status' + | 'overviewByStatus' + | 'keywordInput' + | 'keyword' + | 'orders' + | 'pagination' + | 'page' + | 'pageSize' + | 'loading' + | 'searching' + | 'refreshing' + | 'error' + | 'onStatusChange' + | 'onKeywordInputChange' + | 'onKeywordSearch' + | 'onRefresh' + | 'onPageChange' +> & { order: WorkOrder }) { + const items = getMaterialDetailItems(order).filter((item) => String(item.value || '').trim()) + const screenshots = getMaterialScreenshots(order) + const acceptanceFiles = getUniqueAcceptanceFiles(getWorkerAcceptance(order)) + const draftFiles = getUniqueAcceptanceFiles(getWorkerDraft(order)) + const noteText = getWorkerAcceptance(order)?.note + const workerNote = String(order.workerNote || '').trim() + + return ( +
+
+
+ {order.isUnread ? ( + + 新 + + ) : null} + {order.categoryName ? ( + + {order.categoryName} + + ) : null} + {order.myShare ? ( + + 拼单 + + ) : null} + {getDisplayOrderNo(order)} +
+
+ {formatStatus(order.status)} + {order.status === 'in_progress' && order.deadlineAt ? ( + + ) : null} +
+
+ +
+
{order.productName || '未命名商品'}
+
+ 报酬 + + {formatMoney(order.rewardAmount)} + +
+
+
+ + 押金: {formatMoney(order.freezeDepositAmount)} + + {order.myShare ? ( + + 已拼 {order.myShare.quantity} 份 ({formatMoney(order.myShare.shareReward)}) + + ) : null} + {formatDateTime(order.assignedAt)} +
+ + {order.status === 'problem' && String(order.problemNote || '').trim() ? ( +
+ 问题: + {order.problemNote} +
+ ) : null} + {items.length > 0 || screenshots.length > 0 ? ( +
+ {items.length > 0 ? ( +
+ {items.map((item) => ( +
+ {item.label}: + {item.value} +
+ ))} +
+ ) : null} + {screenshots.length > 0 ? ( +
+ 截图: + +
+ ) : null} +
+ + {screenshots.length > 0 ? ( + + ) : null} +
+
+ ) : null} + + {acceptanceFiles.length > 0 || + (draftFiles.length > 0 && !hasSubmittedAcceptance(order)) || + noteText ? ( +
+ {acceptanceFiles.length > 0 ? ( +
+ + 已提交凭据 ({acceptanceFiles.length}张) + + +
+ ) : null} + {isVipEvidencePending(order) ? VIP 免审核,待补图 : null} + {draftFiles.length > 0 && !hasSubmittedAcceptance(order) ? ( +
+ }> + 已暂存 {draftFiles.length} 张图片 + + +
+ ) : null} + {noteText ? ( +
说明:{noteText}
+ ) : null} +
+ ) : null} + +
+
+ {workerNote ? ( +
onOpenNote(order)} + > + + {workerNote} + + +
+ ) : ( + + )} +
+
+ + {canEditAcceptanceImages(order) ? ( + + ) : null} + {canRemindAcceptance(order) ? ( + + ) : null} + {canRequestCancel(order) ? ( + + ) : null} + {canSubmitFeedback(order) ? ( + + ) : null} +
+
+
+ ) +} + +function resolveNoteTheme(note?: string) { + const text = String(note || '') + .trim() + .toLowerCase() + if (!text) return 'default' + if ( + ['问题', '异常', '密码', '封号', '错误', '无法', '投诉', '退', '失败', '被挤'].some((item) => + text.includes(item), + ) + ) + return 'danger' + if ( + ['未安排', '未', '暂缓', '暂停', '稍后', '延后', '挂起', '待定'].some((item) => + text.includes(item), + ) + ) + return 'warning' + if (['排队', '等待', '等买家', '等扫码', '等验证', '待扫'].some((item) => text.includes(item))) + return 'purple' + if ( + ['打单', '做单', '进行', '处理', '上号', '练级', '正在', '开打', '肝'].some((item) => + text.includes(item), + ) + ) + return 'processing' + if ( + ['已安排', '安排', '已就绪', '就绪', '已联系', '完成', '已好', '搞定', '正常', 'ok'].some( + (item) => text.includes(item), + ) + ) + return 'success' + return 'default' +} diff --git a/apps/frontend/src/pages/worker/WorkerOrderTableColumns.tsx b/apps/frontend/src/pages/worker/WorkerOrderTableColumns.tsx new file mode 100644 index 00000000..773e7538 --- /dev/null +++ b/apps/frontend/src/pages/worker/WorkerOrderTableColumns.tsx @@ -0,0 +1,349 @@ +import { + CopyOutlined, + EditOutlined, + EyeOutlined, + MessageOutlined, + PictureOutlined, +} from '@ant-design/icons' +import { Button, Space, Tag, Tooltip, Typography } from 'antd' +import type { TableColumnsType } from 'antd' + +import { DeadlineCountdown } from '@/components/DeadlineCountdown' +import ImagePreviewList from '@/components/files/ImagePreviewList' +import type { WorkOrder } from '@/types/worker-platform' +import { formatDateTime } from '@/utils/date-time' + +import { + canEditAcceptanceImages, + canRemindAcceptance, + canRequestCancel, + canSubmitAcceptance, + canSubmitFeedback, + formatMoney, + formatStatus, + getAcceptanceSubmittedAt, + getCopyOrderInfoItems, + getDisplayOrderNo, + getMaterialDetailItems, + getMaterialScreenshots, + getUniqueAcceptanceFiles, + getWorkerAcceptance, + getWorkerDraft, + hasSubmittedAcceptance, + isVipEvidencePending, + resolveStatusColor, +} from './worker-order-utils' + +type NoteTheme = 'success' | 'processing' | 'danger' | 'warning' | 'purple' | 'default' + +export function buildWorkerOrderTableColumns({ + onOpenDetail, + onOpenAcceptance, + onRemindAcceptance, + onOpenCancelRequest, + onOpenFeedback, + onOpenNote, + onCopyOrderInfo, + onCopyMaterialImages, +}: { + onOpenDetail: (order: WorkOrder) => void + onOpenAcceptance: (order: WorkOrder) => void + onRemindAcceptance: (order: WorkOrder) => void + onOpenCancelRequest: (order: WorkOrder) => void + onOpenFeedback: (order: WorkOrder) => void + onOpenNote: (order: WorkOrder) => void + onCopyOrderInfo: (order: WorkOrder) => void + onCopyMaterialImages: (order: WorkOrder) => void +}): TableColumnsType { + return [ + { + title: '订单信息', + width: 270, + render: (_, row) => ( +
+ + {row.isUnread ? ( + + 新 + + ) : null} + onOpenDetail(row)} + title={row.productName || '未命名商品'} + ellipsis + > + {row.productName || '未命名商品'} + + + + {row.categoryName ? {row.categoryName} : null} + {row.myShare ? 拼单 : null} + + + {getDisplayOrderNo(row)} + + + 接单:{formatDateTime(row.assignedAt)} + +
+ ), + }, + { + title: '状态', + width: 130, + render: (_, row) => ( +
+ + {formatStatus(row.status)} + {row.status === 'in_progress' && row.deadlineAt ? ( + + ) : null} + + {row.status === 'problem' && String(row.problemNote || '').trim() ? ( + + {row.problemNote} + + ) : null} +
+ ), + }, + { + title: '奖励 / 押金', + width: 140, + render: (_, row) => ( +
+ + {formatMoney(row.rewardAmount)} + + + 押金:{formatMoney(row.freezeDepositAmount)} + + {row.myShare ? ( + + {row.myShare.quantity} 份 · {formatMoney(row.myShare.shareReward)} + + ) : null} +
+ ), + }, + { + title: '验收信息', + width: 220, + render: (_, row) => , + }, + { + title: '快捷复制', + width: 250, + render: (_, row) => { + const items = getMaterialDetailItems(row).filter((item) => String(item.value || '').trim()) + const screenshots = getMaterialScreenshots(row) + return ( +
+ {items.length > 0 ? ( + items.map((item) => ( + + {item.label}: {item.value} + + )) + ) : ( + + 暂无资料信息 + + )} + {screenshots.length > 0 ? : null} + + + {screenshots.length > 0 ? ( + + ) : null} + +
+ ) + }, + }, + { + title: '备注', + width: 180, + render: (_, row) => , + }, + { + title: '操作', + width: 150, + render: (_, row) => ( +
+ + + + ) : null} + {canRemindAcceptance(row) ? ( + + ) : null} + {canRequestCancel(row) ? ( + + ) : null} + {canSubmitFeedback(row) ? ( + + + + ) : null} + +
+ ), + }, + ] +} + +function AcceptanceCell({ order }: { order: WorkOrder }) { + const submittedAt = getAcceptanceSubmittedAt(order) + const acceptanceFiles = getUniqueAcceptanceFiles(getWorkerAcceptance(order)) + const draftFiles = getUniqueAcceptanceFiles(getWorkerDraft(order)) + if (acceptanceFiles.length === 0 && !submittedAt && draftFiles.length === 0) { + return ( + + 未提交 + + ) + } + return ( +
+ {acceptanceFiles.length > 0 ? ( + + ) : null} + {submittedAt ? ( + + 提交:{formatDateTime(submittedAt)} + + ) : null} + {isVipEvidencePending(order) ? VIP 免审核,待补图 : null} + {draftFiles.length > 0 && !hasSubmittedAcceptance(order) ? ( +
+ }> + 已暂存 {draftFiles.length} 张图片 + + +
+ ) : null} + {getWorkerAcceptance(order)?.note ? ( + + {getWorkerAcceptance(order)?.note} + + ) : null} +
+ ) +} + +function NoteCell({ + order, + onOpenNote, +}: { + order: WorkOrder + onOpenNote: (order: WorkOrder) => void +}) { + const note = String(order.workerNote || '').trim() + return ( +
+ {note ? ( +
onOpenNote(order)} + > + + {note} + + +
+ ) : ( + + )} +
+ ) +} + +function resolveNoteTheme(note?: string): NoteTheme { + const text = String(note || '') + .trim() + .toLowerCase() + if (!text) return 'default' + if ( + ['问题', '异常', '密码', '封号', '错误', '无法', '投诉', '退', '失败', '被挤'].some((item) => + text.includes(item), + ) + ) + return 'danger' + if ( + ['未安排', '未', '暂缓', '暂停', '稍后', '延后', '挂起', '待定'].some((item) => + text.includes(item), + ) + ) + return 'warning' + if (['排队', '等待', '等买家', '等扫码', '等验证', '待扫'].some((item) => text.includes(item))) + return 'purple' + if ( + ['打单', '做单', '进行', '处理', '上号', '练级', '正在', '开打', '肝'].some((item) => + text.includes(item), + ) + ) + return 'processing' + if ( + ['已安排', '安排', '已就绪', '就绪', '已联系', '完成', '已好', '搞定', '正常', 'ok'].some( + (item) => text.includes(item), + ) + ) + return 'success' + return 'default' +} diff --git a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx index bedae9f7..f7371291 100644 --- a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx +++ b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx @@ -1,31 +1,7 @@ -import { - CopyOutlined, - EditOutlined, - EyeOutlined, - MessageOutlined, - PictureOutlined, - ReloadOutlined, - SearchOutlined, -} from '@ant-design/icons' import { useQuery, useQueryClient } from '@tanstack/react-query' -import { - App, - Button, - Empty, - Form, - Input, - Pagination, - Space, - Spin, - Tag, - Tooltip, - Typography, -} from 'antd' -import type { TableColumnsType } from 'antd' +import { App, Form } from 'antd' import { useState } from 'react' -import { DeadlineCountdown } from '@/components/DeadlineCountdown' -import ImagePreviewList from '@/components/files/ImagePreviewList' import { fetchWorkerCancelRequests, fetchWorkerOrderFeedbacks, @@ -42,12 +18,12 @@ import { submitWorkerOrderFeedback, } from '@/services/worker' import type { UploadedFile, WorkOrder } from '@/types/worker-platform' -import { formatDateTime } from '@/utils/date-time' import { useIsMobile } from '@/utils/use-is-mobile' import { buildWorkerOrderQuery } from '@/utils/worker-order-query' import WorkerAfterSalesSection from './WorkerAfterSalesSection' import { WorkerOrderDesktopList } from './WorkerOrderDesktopList' import { WorkerOrderDetailDrawer } from './WorkerOrderDetailDrawer' +import { WorkerOrderMobileList } from './WorkerOrderMobileList' import { type AcceptanceFormValues, type CancelRequestFormValues, @@ -55,30 +31,17 @@ import { type WorkerNoteFormValues, WorkerOrderModals, } from './WorkerOrderModals' +import { buildWorkerOrderTableColumns } from './WorkerOrderTableColumns' import { - asRecord, canAutoAcceptOrder, - canEditAcceptanceImages, - canRemindAcceptance, - canRequestCancel, - canSubmitAcceptance, - canSubmitFeedback, canSupplementAcceptedEvidence, - formatMoney, - formatStatus, - getAcceptanceSubmittedAt, getCopyOrderInfoItems, - getDisplayOrderNo, - getMaterialDetailItems, getMaterialScreenshots, - getSettlementLabel, getUniqueAcceptanceFiles, getWorkerAcceptance, getWorkerDraft, hasSubmittedAcceptance, - isVipEvidencePending, patchWorkOrderReadState, - resolveStatusColor, toPngBlob, } from './worker-order-utils' @@ -461,598 +424,71 @@ export default function WorkerOrdersPage() { setPage(1) } - const columns: TableColumnsType = [ - { - title: '订单信息', - width: 270, - render: (_, row) => ( -
- - {row.isUnread ? ( - - 新 - - ) : null} - openOrderDetail(row)} - title={row.productName || '未命名商品'} - ellipsis - > - {row.productName || '未命名商品'} - - - - {row.categoryName ? {row.categoryName} : null} - {row.myShare ? 拼单 : null} - - - {getDisplayOrderNo(row)} - - - 接单:{formatDateTime(row.assignedAt)} - -
- ), + const columns = buildWorkerOrderTableColumns({ + onOpenDetail: openOrderDetail, + onOpenAcceptance: openAcceptanceModal, + onRemindAcceptance: (order) => { + void submitAcceptanceReminder(order) }, - { - title: '状态', - width: 130, - render: (_, row) => ( -
- - {formatStatus(row.status)} - {row.status === 'in_progress' && row.deadlineAt ? ( - - ) : null} - - {row.status === 'problem' && String(row.problemNote || '').trim() ? ( - - {row.problemNote} - - ) : null} -
- ), + onOpenCancelRequest: openCancelRequestModal, + onOpenFeedback: openFeedbackModal, + onOpenNote: openNoteModal, + onCopyOrderInfo: copyOrderInfo, + onCopyMaterialImages: (order) => { + void copyMaterialImages(order) }, - { - title: '奖励 / 押金', - width: 140, - render: (_, row) => ( -
- - {formatMoney(row.rewardAmount)} - - - 押金:{formatMoney(row.freezeDepositAmount)} - - {row.myShare ? ( - - {row.myShare.quantity} 份 · {formatMoney(row.myShare.shareReward)} - - ) : null} -
- ), - }, - { - title: '验收信息', - width: 220, - render: (_, row) => { - const submittedAt = getAcceptanceSubmittedAt(row) - const acceptanceFiles = getUniqueAcceptanceFiles(getWorkerAcceptance(row)) - const hasAcceptance = acceptanceFiles.length > 0 - const draftFiles = getUniqueAcceptanceFiles(getWorkerDraft(row)) - const draftCount = draftFiles.length - const vipEvidencePending = isVipEvidencePending(row) - - if (!hasAcceptance && !submittedAt && draftCount === 0) { - return ( - - 未提交 - - ) - } - return ( -
- {hasAcceptance ? ( - - ) : null} - {submittedAt ? ( - - 提交:{formatDateTime(submittedAt)} - - ) : null} - {vipEvidencePending ? VIP 免审核,待补图 : null} - {draftCount > 0 && !hasSubmittedAcceptance(row) ? ( -
- }> - 已暂存 {draftCount} 张图片 - - -
- ) : null} - {getWorkerAcceptance(row)?.note ? ( - - {getWorkerAcceptance(row)?.note} - - ) : null} -
- ) - }, - }, - { - title: '快捷复制', - width: 250, - render: (_, row) => { - const items = getMaterialDetailItems(row).filter((item) => String(item.value || '').trim()) - const canCopyInfo = getCopyOrderInfoItems(row).length > 0 - const screenshots = getMaterialScreenshots(row) - return ( -
- {items.length > 0 ? ( - items.map((item) => ( - - {item.label}: {item.value} - - )) - ) : ( - - 暂无资料信息 - - )} - {screenshots.length > 0 ? : null} - - - {screenshots.length > 0 ? ( - - ) : null} - -
- ) - }, - }, - { - title: '备注', - width: 180, - render: (_, row) => { - const note = String(row.workerNote || '').trim() - const theme = resolveNoteTheme(note) - return ( -
- {note ? ( -
openNoteModal(row)} - > - - {note} - - -
- ) : ( - - )} -
- ) - }, - }, - { - title: '操作', - width: 150, - render: (_, row) => ( -
- - - - ) : null} - {canRemindAcceptance(row) ? ( - - ) : null} - {canRequestCancel(row) ? ( - - ) : null} - {canSubmitFeedback(row) ? ( - - - - ) : null} - -
- ), - }, - ] + }) return ( <> {isMobile ? ( -
- {/* 顶部水平滑动状态切换胶囊条 */} -
- {STATUS_OPTIONS.map((item) => { - const countKey = item.value || 'all' - const overview = overviewByStatus.get(countKey) - const count = Number(overview?.orderCount || 0) - const settlementAmount = Number(overview?.settlementAmount || 0) - const isActive = (status || '') === item.value - const settlementLabel = getSettlementLabel(item.value) - return ( - - ) - })} -
- - {/* 搜索与刷新栏 */} -
- } - className="worker-orders-mobile-search-input" - onChange={(event) => { - const nextValue = event.target.value - setKeywordInput(nextValue) - if (!nextValue.trim()) { - setKeyword('') - setPage(1) - } - }} - onPressEnter={applyKeywordSearch} - /> -
- - {/* 移动端紧凑卡片列表 */} -
- {ordersQuery.isLoading ? ( -
- -
- ) : ordersQuery.error ? ( - - ) : orders.length === 0 ? ( - - ) : ( - orders.map((order) => { - const items = getMaterialDetailItems(order).filter((item) => - String(item.value || '').trim(), - ) - const screenshots = getMaterialScreenshots(order) - const canCopyInfo = getCopyOrderInfoItems(order).length > 0 - const _submittedAt = getAcceptanceSubmittedAt(order) - const acceptanceFiles = getUniqueAcceptanceFiles(getWorkerAcceptance(order)) - const hasAcceptance = acceptanceFiles.length > 0 - const draftFiles = getUniqueAcceptanceFiles(getWorkerDraft(order)) - const draftCount = draftFiles.length - const noteText = getWorkerAcceptance(order)?.note - const workerNote = String(order.workerNote || '').trim() - - return ( -
- {/* 卡片顶栏:分类 + 订单号 + 状态/倒计时 */} -
-
- {order.isUnread ? ( - - 新 - - ) : null} - {order.categoryName ? ( - - {order.categoryName} - - ) : null} - {order.myShare ? ( - - 拼单 - - ) : null} - - {getDisplayOrderNo(order)} - -
-
- - {formatStatus(order.status)} - - {order.status === 'in_progress' && order.deadlineAt ? ( - - ) : null} -
-
- - {/* 商品标题与金额 */} -
-
- {order.productName || '未命名商品'} -
-
- 报酬 - - {formatMoney(order.rewardAmount)} - -
-
- - {/* 辅助金额与接单时间 */} -
- - 押金: {formatMoney(order.freezeDepositAmount)} - - {order.myShare ? ( - - 已拼 {order.myShare.quantity} 份 ({formatMoney(order.myShare.shareReward)} - ) - - ) : null} - - {formatDateTime(order.assignedAt)} - -
- - {/* 问题单提示 */} - {order.status === 'problem' && String(order.problemNote || '').trim() ? ( -
- 问题: - {order.problemNote} -
- ) : null} - - {/* 买家资料与截图 */} - {(items.length > 0 || screenshots.length > 0) && ( -
- {items.length > 0 ? ( -
- {items.map((item) => ( -
- - {item.label}: - - - {item.value} - -
- ))} -
- ) : null} - - {screenshots.length > 0 ? ( -
- 截图: - -
- ) : null} - -
- - {screenshots.length > 0 ? ( - - ) : null} -
-
- )} - - {/* 验收凭据与暂存状态 */} - {(hasAcceptance || - (draftCount > 0 && !hasSubmittedAcceptance(order)) || - noteText) && ( -
- {hasAcceptance ? ( -
- - 已提交凭据 ({acceptanceFiles.length}张) - - -
- ) : null} - {isVipEvidencePending(order) ? ( - VIP 免审核,待补图 - ) : null} - {draftCount > 0 && !hasSubmittedAcceptance(order) ? ( -
- }> - 已暂存 {draftCount} 张图片 - - -
- ) : null} - {noteText ? ( -
- 说明:{noteText} -
- ) : null} -
- )} - - {/* 底部备注与操作 */} -
-
- {workerNote ? ( -
openNoteModal(order)} - > - - {workerNote} - - -
- ) : ( - - )} -
- -
- - {canEditAcceptanceImages(order) ? ( - - ) : null} - {canRemindAcceptance(order) ? ( - - ) : null} - {canRequestCancel(order) ? ( - - ) : null} - {canSubmitFeedback(order) ? ( - - ) : null} -
-
-
- ) - }) - )} - - {(pagination?.total || 0) > 0 ? ( -
- { - setPage(nextPage) - setPageSize(nextPageSize) - }} - /> -
- ) : null} -
-
+ { + setStatus(nextStatus) + setPage(1) + }} + onKeywordInputChange={(nextValue) => { + setKeywordInput(nextValue) + if (!nextValue.trim()) { + setKeyword('') + setPage(1) + } + }} + onKeywordSearch={applyKeywordSearch} + onRefresh={() => { + void refreshAll() + }} + onPageChange={(nextPage, nextPageSize) => { + setPage(nextPage) + setPageSize(nextPageSize) + }} + onOpenDetail={openOrderDetail} + onOpenAcceptance={openAcceptanceModal} + onRemindAcceptance={(order) => { + void submitAcceptanceReminder(order) + }} + onOpenCancelRequest={openCancelRequestModal} + onOpenFeedback={openFeedbackModal} + onOpenNote={openNoteModal} + onCopyOrderInfo={copyOrderInfo} + onCopyMaterialImages={(order) => { + void copyMaterialImages(order) + }} + /> ) : ( {