From c9195c623d0c1253c5b13a0caf1bd7ce27c73556 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sun, 2 Aug 2026 10:32:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=93=E6=89=8B=E7=AB=AF?= =?UTF-8?q?=E6=88=91=E7=9A=84=E8=AE=A2=E5=8D=95=E4=B8=8E=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E7=95=8C=E9=9D=A2=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/worker/WorkerOrdersPage.tsx | 255 +++++++----------- .../src/pages/worker/WorkerProfilePage.tsx | 149 +++------- apps/frontend/src/styles/main.css | 85 ++++++ 3 files changed, 225 insertions(+), 264 deletions(-) diff --git a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx index 527d7fcd..9b797bc6 100644 --- a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx +++ b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx @@ -9,18 +9,15 @@ import { App, Button, Card, - Col, Descriptions, Drawer, Empty, Form, Input, Modal, - Row, - Segmented, Space, - Statistic, Table, + Tabs, Tag, Typography, } from 'antd' @@ -40,24 +37,14 @@ import { formatDateTime } from '@/utils/date-time' const STATUS_OPTIONS = [ { value: '', label: '全部订单' }, - { value: 'open', label: '已超时' }, { value: 'in_progress', label: '代练中' }, { value: 'pending_acceptance', label: '待验收' }, { value: 'problem', label: '问题单' }, + { value: 'open', label: '已超时' }, { value: 'accepted', label: '已验收' }, { value: 'cancelled', label: '已取消' }, ] as const -const STATUS_SUMMARY_ITEMS = [ - { key: 'all', label: '全部订单', note: '当前账号历史接单总数' }, - { key: 'in_progress', label: '代练中', note: '正在执行中的订单' }, - { key: 'pending_acceptance', label: '待验收', note: '已提交,等待审核' }, - { key: 'problem', label: '问题单', note: '需要补充或重新处理' }, - { key: 'open', label: '已超时', note: '超时被系统退回的订单数' }, - { key: 'accepted', label: '已验收', note: '已完成并结算的订单' }, - { key: 'cancelled', label: '已取消', note: '已结束且不再继续' }, -] as const - type AcceptanceFormValues = { note?: string } @@ -171,7 +158,7 @@ export default function WorkerOrdersPage() { const columns: TableColumnsType = [ { title: '订单信息', - minWidth: 320, + minWidth: 280, render: (_, row) => (
setDetailOrder(row)}> @@ -179,12 +166,10 @@ export default function WorkerOrdersPage() { {row.categoryName ? {row.categoryName} : null} - - 工单号:{row.workOrderNo} - + {row.myShare ? 拼单 : null} - 订单号:{row.platformOrderId || '-'} + {row.workOrderNo} · {row.platformOrderId || '-'} 接单时间:{formatDateTime(row.assignedAt)} @@ -192,6 +177,25 @@ export default function WorkerOrdersPage() {
), }, + { + title: '状态', + width: 170, + render: (_, row) => ( +
+ + {formatStatus(row.status)} + {row.status === 'in_progress' && row.deadlineAt ? ( + + ) : null} + + {row.status === 'problem' && String(row.problemNote || '').trim() ? ( + + {row.problemNote} + + ) : null} +
+ ), + }, { title: '奖励 / 押金', width: 150, @@ -201,77 +205,46 @@ export default function WorkerOrdersPage() { 冻结押金:{formatMoney(row.freezeDepositAmount)} - - ), - }, - { - title: '我的拼单', - width: 170, - render: (_, row) => - row.myShare ? ( -
- - {formatSharingShareStatus(row.myShare.status)} - - - {row.myShare.quantity} 份 × {formatMoney(row.myShare.unitReward)} - + {row.myShare ? ( - 份额报酬:{formatMoney(row.myShare.shareReward)} + {row.myShare.quantity} 份 · 份额 {formatMoney(row.myShare.shareReward)} -
- ) : ( - - - ), - }, - { - title: '当前状态', - width: 180, - render: (_, row) => ( -
- {formatStatus(row.status)} - {row.status === 'in_progress' && row.deadlineAt ? ( - ) : null} - - {getStatusHint(row.status)} -
), }, { title: '验收信息', - minWidth: 210, - render: (_, row) => ( -
- - - 提交时间:{formatDateTime(getAcceptanceSubmittedAt(row))} - - {row.acceptance?.note ? ( - {row.acceptance.note} - ) : ( - 暂无验收说明 - )} -
- ), - }, - { - title: '问题备注', - minWidth: 180, - render: (_, row) => ( - - {String(row.problemNote || '').trim() || '-'} - - ), + minWidth: 200, + render: (_, row) => { + const submittedAt = getAcceptanceSubmittedAt(row) + const hasAcceptance = + getAcceptanceFiles(row).length > 0 || getAcceptanceImageUrls(row).length > 0 + if (!hasAcceptance && !submittedAt) { + return 未提交 + } + return ( +
+ + + 提交时间:{formatDateTime(submittedAt)} + + {row.acceptance?.note ? ( + + {row.acceptance.note} + + ) : null} +
+ ) + }, }, { title: '操作', - width: 280, + width: 260, render: (_, row) => ( ) : null} {canCancelOrder(row) ? ( - ) : null} @@ -312,73 +282,56 @@ export default function WorkerOrdersPage() { - - {STATUS_SUMMARY_ITEMS.map((item) => ( - - - - {item.note} - - - ))} - - - - - - } - onChange={(event) => { - const nextValue = event.target.value - setKeywordInput(nextValue) - if (!nextValue.trim()) { - setKeyword('') - setPage(1) - } - }} - onPressEnter={applyKeywordSearch} - /> - - - - 当前筛选: - {STATUS_OPTIONS.find((item) => item.value === status)?.label || '全部订单'} - - + { + const countKey = item.value || 'all' + const count = Number(overviewQuery.data?.[countKey] || 0) + return { + key: item.value || 'all', + label: ( + + {item.label} + {count > 0 ? ( + {count} + ) : null} + + ), + } + })} + onChange={(nextKey) => { + const nextStatus = nextKey === 'all' ? '' : nextKey + setStatus(nextStatus) + setPage(1) + }} + /> - { - const countKey = item.value || 'all' - return { - value: item.value || 'all', - label: `${item.label} (${Number(overviewQuery.data?.[countKey] || 0)})`, + + } + onChange={(event) => { + const nextValue = event.target.value + setKeywordInput(nextValue) + if (!nextValue.trim()) { + setKeyword('') + setPage(1) } - })} - onChange={(value) => { - const nextStatus = String(value) === 'all' ? '' : String(value) - setStatus(nextStatus) - setPage(1) }} + onPressEnter={applyKeywordSearch} /> - + + rowKey="workOrderId" @@ -417,7 +370,7 @@ export default function WorkerOrdersPage() { setPageSize(nextPageSize) }, }} - scroll={{ x: 1160 }} + scroll={{ x: 1060 }} /> @@ -762,13 +715,3 @@ function resolveStatusColor(status: string) { if (status === 'open') return 'red' return 'blue' } - -function formatSharingShareStatus(status: string) { - const labels: Record = { - joined: '已参与', - submitted: '已提交验收', - accepted: '已验收', - cancelled: '已取消', - } - return labels[status] || status -} diff --git a/apps/frontend/src/pages/worker/WorkerProfilePage.tsx b/apps/frontend/src/pages/worker/WorkerProfilePage.tsx index ad67baf8..f39a414c 100644 --- a/apps/frontend/src/pages/worker/WorkerProfilePage.tsx +++ b/apps/frontend/src/pages/worker/WorkerProfilePage.tsx @@ -2,11 +2,9 @@ import { BankOutlined, CopyOutlined, CustomerServiceOutlined, - HistoryOutlined, LockOutlined, LogoutOutlined, ReloadOutlined, - SafetyCertificateOutlined, WalletOutlined, } from '@ant-design/icons' import { useQuery, useQueryClient } from '@tanstack/react-query' @@ -16,7 +14,6 @@ import { Avatar, Button, Card, - Col, DatePicker, Descriptions, Empty, @@ -26,10 +23,8 @@ import { InputNumber, Modal, Progress, - Row, Select, Space, - Statistic, Table, Tabs, Tag, @@ -80,16 +75,6 @@ type PasswordFormValues = { confirmPassword?: string } -type MetricCardItem = { - label: string - value: number - note: string - prefix?: string - suffix?: string - precision?: number - danger?: boolean -} - export default function WorkerProfilePage() { const { message } = App.useApp() const navigate = useNavigate() @@ -510,23 +495,38 @@ export default function WorkerProfilePage() { - - {buildMetricCards(worker, summary).map((item) => ( - - - - {item.note} - - - ))} - + +
+
+ 可用余额 + + {formatMoney(worker.wallet.availableAmount)} + + 可用于抢单冻结或提现申请 +
+
+ 冻结押金 + + {formatMoney(worker.wallet.frozenDepositAmount)} + + 抢单后冻结,验收后进入待解冻 +
+
+ 待解冻押金 + + {formatMoney(worker.wallet.pendingUnfreezeAmount)} + + 验收后按配置天数解冻到账 +
+
+ 累计结算 + + {formatMoney(worker.wallet.totalSettledAmount)} + + 已结算入账的报酬合计 +
+
+
@@ -546,18 +546,6 @@ export default function WorkerProfilePage() { > 提现申请 - - @@ -617,6 +605,15 @@ export default function WorkerProfilePage() { {summary?.acceptedOrderCount || 0} 单 + + {summary?.timeoutOrderCount || 0} 单 + + + {formatMoney(worker.wallet.totalCreditedAmount)} + + + {formatMoney(summary?.pendingWithdrawAmount)} + {formatMoney(worker.level?.permissions.depositFreeAmount || 0)} @@ -1055,66 +1052,6 @@ export default function WorkerProfilePage() { ) } -function buildMetricCards(worker: WorkerUser, summary?: WorkerProfileSummary): MetricCardItem[] { - return [ - { - label: '账户余额', - value: toYuan(worker.wallet.availableAmount), - note: '可用于抢单冻结或提现申请', - prefix: '¥', - precision: 2, - }, - { - label: '冻结押金', - value: toYuan(worker.wallet.frozenDepositAmount), - note: '抢单后冻结,验收通过后 3 天自动解冻', - prefix: '¥', - precision: 2, - }, - { - label: '待解冻押金', - value: toYuan(worker.wallet.pendingUnfreezeAmount), - note: '验收通过后待 3 天解冻到账的押金', - prefix: '¥', - precision: 2, - }, - { - label: '累计充值', - value: toYuan(worker.wallet.totalCreditedAmount), - note: '管理员已处理的累计充值金额', - prefix: '¥', - precision: 2, - }, - { - label: '累计结算', - value: toYuan(worker.wallet.totalSettledAmount), - note: '已经结算入账的报酬金额', - prefix: '¥', - precision: 2, - }, - { - label: '提现中金额', - value: toYuan(summary?.pendingWithdrawAmount), - note: '待管理员处理的提现申请金额', - prefix: '¥', - precision: 2, - }, - { - label: '累计成单', - value: Number(summary?.acceptedOrderCount || 0), - note: '已完成并验收通过的工单数量', - suffix: '单', - }, - { - label: '超时订单', - value: Number(summary?.timeoutOrderCount || 0), - note: '因任务超时被系统判定失败的工单数量', - suffix: '单', - danger: Number(summary?.timeoutOrderCount || 0) > 0, - }, - ] -} - function resolveAvailableForWithdraw( worker: WorkerUser | undefined, summary: WorkerProfileSummary | undefined, @@ -1137,10 +1074,6 @@ function formatMoney(value: number | undefined) { return `¥${((Number(value || 0) || 0) / 100).toFixed(2)}` } -function toYuan(value: number | undefined) { - return Number(((Number(value || 0) || 0) / 100).toFixed(2)) -} - function formatWorkerStatus(status: string) { if (status === 'active') return '已审核' if (status === 'pending_review') return '待审核' diff --git a/apps/frontend/src/styles/main.css b/apps/frontend/src/styles/main.css index baf67194..ddb237dd 100644 --- a/apps/frontend/src/styles/main.css +++ b/apps/frontend/src/styles/main.css @@ -1685,6 +1685,91 @@ select { margin: 0; } +.worker-order-summary-card { + cursor: pointer; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.worker-order-summary-card.active { + border-color: #1677ff; + box-shadow: 0 0 0 1px #1677ff inset; +} + +.worker-order-summary-card .ant-statistic-title { + font-size: 12px; +} + +.worker-order-tab-count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + padding: 0 5px; + margin-left: 6px; + border-radius: 9px; + background: #f0f0f0; + color: #595959; + font-size: 12px; + line-height: 18px; +} + +.worker-order-tabs .ant-tabs-nav { + margin-bottom: 12px; +} + +.worker-profile-wallet-card .ant-card-body { + padding: 0; +} + +.worker-profile-wallet-strip { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 0; + overflow: hidden; +} + +.worker-profile-wallet-item { + min-width: 0; + padding: 14px 16px; + display: grid; + gap: 4px; +} + +.worker-profile-wallet-item + .worker-profile-wallet-item { + border-left: 1px solid #f0f0f0; +} + +.worker-profile-wallet-label { + color: #64748b; + font-size: 12px; +} + +.worker-profile-wallet-value { + color: #0f172a; + font-size: 20px; + line-height: 1.2; +} + +.worker-profile-wallet-note { + color: #94a3b8; + font-size: 12px; + line-height: 1.5; +} + +@media (max-width: 768px) { + .worker-profile-wallet-strip { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .worker-profile-wallet-item:nth-child(3) { + border-left: 0; + border-top: 1px solid #f0f0f0; + } + .worker-profile-wallet-item:nth-child(4) { + border-top: 1px solid #f0f0f0; + } +} + .worker-hall-head-copy { display: grid; gap: 4px;