perf: 筛选统计去掉 JSON 兜底,并补上 orders 覆盖索引
去掉 work_orders 堆访问后,JOIN 会把 orders 整表扫进 Hash Right Join。 领取页在快照新鲜时不再打上游;快手出网统一 10 秒超时。倒计时改为自适应间隔。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,30 +1,18 @@
|
||||
import { Tag } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export function DeadlineCountdown({
|
||||
deadlineAt,
|
||||
showExpired: _showExpired = false,
|
||||
}: {
|
||||
deadlineAt: string
|
||||
showExpired?: boolean
|
||||
}) {
|
||||
import { resolveDeadlineCountdown } from '@/utils/deadline-countdown'
|
||||
|
||||
export function DeadlineCountdown({ deadlineAt }: { deadlineAt: string }) {
|
||||
const [now, setNow] = useState(() => Date.now())
|
||||
const view = resolveDeadlineCountdown(deadlineAt, now)
|
||||
|
||||
useEffect(() => {
|
||||
const timer = window.setInterval(() => setNow(Date.now()), 1000)
|
||||
const timer = window.setInterval(() => setNow(Date.now()), view.tickMs)
|
||||
return () => window.clearInterval(timer)
|
||||
}, [])
|
||||
}, [view.tickMs])
|
||||
|
||||
const remainingMs = new Date(deadlineAt).getTime() - now
|
||||
if (remainingMs <= 0) {
|
||||
return <Tag color="red">已超时</Tag>
|
||||
}
|
||||
const totalSeconds = Math.floor(remainingMs / 1000)
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
const seconds = totalSeconds % 60
|
||||
const label = minutes > 0 ? `${minutes} 分 ${seconds} 秒` : `${seconds} 秒`
|
||||
const color = remainingMs < 10 * 60 * 1000 ? 'orange' : 'blue'
|
||||
return <Tag color={color}>剩余 {label}</Tag>
|
||||
return <Tag color={view.color}>{view.label}</Tag>
|
||||
}
|
||||
|
||||
export function formatTimeoutPolicyLabel(policy?: string) {
|
||||
|
||||
@@ -1472,7 +1472,7 @@ export default function WorkOrdersPanel() {
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
{row.status === 'in_progress' && row.deadlineAt ? (
|
||||
<DeadlineCountdown deadlineAt={row.deadlineAt} showExpired />
|
||||
<DeadlineCountdown deadlineAt={row.deadlineAt} />
|
||||
) : null}
|
||||
{row.deadlineAt ? (
|
||||
<Typography.Text type="secondary">
|
||||
@@ -2103,7 +2103,7 @@ export default function WorkOrdersPanel() {
|
||||
<Descriptions.Item label="超时截止">
|
||||
{detailOrder.deadlineAt ? (
|
||||
<Space wrap size={8}>
|
||||
<DeadlineCountdown deadlineAt={detailOrder.deadlineAt} showExpired />
|
||||
<DeadlineCountdown deadlineAt={detailOrder.deadlineAt} />
|
||||
<Typography.Text type="secondary">
|
||||
{formatAdminDateTime(detailOrder.deadlineAt)}
|
||||
</Typography.Text>
|
||||
|
||||
@@ -141,13 +141,12 @@ export default function WorkerHallPage() {
|
||||
})
|
||||
|
||||
const hallSummaryQuery = useQuery({
|
||||
queryKey: ['worker-hall-summary'],
|
||||
queryFn: async () => {
|
||||
const response = await fetchWorkerMyOrderOverview()
|
||||
queryKey: ['worker-my-orders-overview'],
|
||||
queryFn: fetchWorkerMyOrderOverview,
|
||||
select: (response) => {
|
||||
const summaryByStatus = new Map(
|
||||
response.data.items.map((item) => [item.status, item.orderCount]),
|
||||
)
|
||||
|
||||
return {
|
||||
pendingAcceptanceCount: Number(summaryByStatus.get('pending_acceptance') || 0),
|
||||
problemCount: Number(summaryByStatus.get('problem') || 0),
|
||||
@@ -283,7 +282,6 @@ export default function WorkerHallPage() {
|
||||
await Promise.all([
|
||||
ordersQuery.refetch(),
|
||||
queryClient.invalidateQueries({ queryKey: ['worker-hall-categories'] }),
|
||||
queryClient.invalidateQueries({ queryKey: ['worker-hall-summary'] }),
|
||||
queryClient.invalidateQueries({ queryKey: ['worker-profile'] }),
|
||||
queryClient.invalidateQueries({ queryKey: ['worker-my-orders'] }),
|
||||
queryClient.invalidateQueries({ queryKey: ['worker-my-orders-overview'] }),
|
||||
|
||||
@@ -206,11 +206,13 @@ export default function WorkerOrdersPage() {
|
||||
const cancelRequestsQuery = useQuery({
|
||||
queryKey: ['worker-cancel-requests'],
|
||||
queryFn: fetchWorkerCancelRequests,
|
||||
enabled: Boolean(cancelRequestOrder),
|
||||
retry: false,
|
||||
})
|
||||
const feedbacksQuery = useQuery({
|
||||
queryKey: ['worker-order-feedbacks'],
|
||||
queryFn: fetchWorkerOrderFeedbacks,
|
||||
enabled: Boolean(feedbackOrder),
|
||||
retry: false,
|
||||
})
|
||||
const overviewByStatus = new Map(
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
export const DEADLINE_FAST_TICK_MS = 1_000
|
||||
export const DEADLINE_SLOW_TICK_MS = 30_000
|
||||
export const DEADLINE_FAST_WINDOW_MS = 60_000
|
||||
|
||||
export function resolveDeadlineCountdown(deadlineAt: string, now: number) {
|
||||
const remainingMs = new Date(deadlineAt).getTime() - now
|
||||
if (!Number.isFinite(remainingMs) || remainingMs <= 0) {
|
||||
return {
|
||||
label: '已超时',
|
||||
color: 'red' as const,
|
||||
tickMs: DEADLINE_SLOW_TICK_MS,
|
||||
}
|
||||
}
|
||||
|
||||
const totalSeconds = Math.floor(remainingMs / 1000)
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
const seconds = totalSeconds % 60
|
||||
const fast = remainingMs < DEADLINE_FAST_WINDOW_MS
|
||||
const label = fast
|
||||
? minutes > 0
|
||||
? `剩余 ${minutes} 分 ${seconds} 秒`
|
||||
: `剩余 ${seconds} 秒`
|
||||
: `剩余 ${minutes} 分`
|
||||
|
||||
return {
|
||||
label,
|
||||
color: (remainingMs < 10 * 60_000 ? 'orange' : 'blue') as 'orange' | 'blue',
|
||||
tickMs: fast ? DEADLINE_FAST_TICK_MS : DEADLINE_SLOW_TICK_MS,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user