增加待补图订单筛选

This commit is contained in:
yml2213
2026-08-17 12:43:22 +08:00
parent baf09dc533
commit 1d9e102527
7 changed files with 50 additions and 9 deletions
@@ -226,6 +226,8 @@ export type ListInput = {
categoryId?: number categoryId?: number
workerSharingId?: number workerSharingId?: number
visibleAfterIso?: string visibleAfterIso?: string
/** VIP 免审核后仍在补图期限内的订单;与状态筛选取并集 */
vipEvidencePending?: boolean
/** 置顶订单优先展示(抢单大厅使用) */ /** 置顶订单优先展示(抢单大厅使用) */
pinnedFirst?: boolean pinnedFirst?: boolean
sort?: 'id_desc' | 'worker_claimed_at_desc' sort?: 'id_desc' | 'worker_claimed_at_desc'
@@ -764,6 +764,7 @@ export async function listWorkOrders({
categoryId = 0, categoryId = 0,
workerSharingId = 0, workerSharingId = 0,
visibleAfterIso = '', visibleAfterIso = '',
vipEvidencePending = false,
pinnedFirst = false, pinnedFirst = false,
sort = 'id_desc', sort = 'id_desc',
}: ListInput = {}): Promise<{ items: WorkOrderRow[]; total: number }> { }: ListInput = {}): Promise<{ items: WorkOrderRow[]; total: number }> {
@@ -775,6 +776,7 @@ export async function listWorkOrders({
categoryId, categoryId,
workerSharingId, workerSharingId,
visibleAfterIso, visibleAfterIso,
vipEvidencePending,
}) })
const totalResult = await query<{ total: number }>( const totalResult = await query<{ total: number }>(
` `
@@ -2585,13 +2587,27 @@ function buildWorkOrderWhere({
categoryId = 0, categoryId = 0,
workerSharingId = 0, workerSharingId = 0,
visibleAfterIso = '', visibleAfterIso = '',
vipEvidencePending = false,
}: ListInput) { }: ListInput) {
const filters: string[] = [] const filters: string[] = []
const params: unknown[] = [] const params: unknown[] = []
const normalizedStatuses = [ const normalizedStatuses = [
...new Set(statuses.map((item) => String(item || '').trim()).filter(Boolean)), ...new Set(statuses.map((item) => String(item || '').trim()).filter(Boolean)),
] ]
if (vipEvidencePending) {
const vipEvidencePendingWhere = `
wo.status = 'accepted'
AND wo.acceptance_json->>'reviewMode' = 'vip_auto'
AND wo.acceptance_json->>'evidenceStatus' = 'pending'
AND NULLIF(wo.acceptance_json->>'evidenceDueAt', '')::timestamptz > NOW()
`
if (normalizedStatuses.length > 0) { if (normalizedStatuses.length > 0) {
params.push(normalizedStatuses)
filters.push(`(wo.status = ANY($${params.length}::text[]) OR (${vipEvidencePendingWhere}))`)
} else {
filters.push(`(${vipEvidencePendingWhere})`)
}
} else if (normalizedStatuses.length > 0) {
params.push(normalizedStatuses) params.push(normalizedStatuses)
filters.push(`wo.status = ANY($${params.length}::text[])`) filters.push(`wo.status = ANY($${params.length}::text[])`)
} }
@@ -696,12 +696,15 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
const page = normalizePage(query.page) const page = normalizePage(query.page)
const pageSize = normalizePageSize(query.pageSize) const pageSize = normalizePageSize(query.pageSize)
const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0 const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0
const statuses = normalizeStatuses(query.status)
const vipEvidencePending = normalizeBoolean(query.vipEvidencePending, false)
const { items, total } = await listWorkOrders({ const { items, total } = await listWorkOrders({
page, page,
pageSize, pageSize,
statuses: normalizeStatuses(query.status), statuses,
keyword: String(query.keyword || '').trim(), keyword: String(query.keyword || '').trim(),
workerSharingId: workerId, workerSharingId: workerId,
vipEvidencePending,
}) })
const shares = await listWorkOrderSharesByOrderIds(items.map((item) => Number(item.id))) const shares = await listWorkOrderSharesByOrderIds(items.map((item) => Number(item.id)))
const sharesByOrderId = new Map<number, WorkOrderShareRow[]>() const sharesByOrderId = new Map<number, WorkOrderShareRow[]>()
@@ -89,6 +89,7 @@ import {
mapWorkerUser, mapWorkerUser,
normalizeAmountFen, normalizeAmountFen,
assertWithdrawChannelAllowedForAmount, assertWithdrawChannelAllowedForAmount,
normalizeBoolean,
normalizeFinanceRequestStatus, normalizeFinanceRequestStatus,
normalizeFinanceRequestType, normalizeFinanceRequestType,
normalizeInteger, normalizeInteger,
@@ -1114,12 +1115,14 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker
await settleOverdueWorkOrders({ workerId: worker.id, limit: 50 }) await settleOverdueWorkOrders({ workerId: worker.id, limit: 50 })
const page = normalizePage(query.page) const page = normalizePage(query.page)
const pageSize = normalizePageSize(query.pageSize) const pageSize = normalizePageSize(query.pageSize)
const vipEvidencePending = normalizeBoolean(query.vipEvidencePending, false)
const { items, total } = await listWorkOrders({ const { items, total } = await listWorkOrders({
page, page,
pageSize, pageSize,
statuses: normalizeStatuses(query.status), statuses: normalizeStatuses(query.status),
keyword: String(query.keyword || '').trim(), keyword: String(query.keyword || '').trim(),
workerSharingId: worker.id, workerSharingId: worker.id,
vipEvidencePending,
sort: 'worker_claimed_at_desc', sort: 'worker_claimed_at_desc',
}) })
const permissions = resolveWorkerPermissions(worker) const permissions = resolveWorkerPermissions(worker)
@@ -95,10 +95,12 @@ const FILTERABLE_WORK_ORDER_STATUSES = [
'in_progress', 'in_progress',
'pending_acceptance', 'pending_acceptance',
'problem', 'problem',
'vip_evidence_pending',
'accepted', 'accepted',
'cancelled', 'cancelled',
] as const ] as const
const VIP_EVIDENCE_PENDING_STATUS = 'vip_evidence_pending'
const SKIP_PUBLISH_CONFIRM_KEY = 'admin-work-order-skip-publish-confirm' const SKIP_PUBLISH_CONFIRM_KEY = 'admin-work-order-skip-publish-confirm'
type MaterialFormValues = { type MaterialFormValues = {
@@ -158,6 +160,10 @@ export default function WorkOrdersPanel() {
}>() }>()
// 仅单独筛选「待验收」时提供批量验收入口(多选状态下不启用勾选,避免误操作) // 仅单独筛选「待验收」时提供批量验收入口(多选状态下不启用勾选,避免误操作)
const isPendingAcceptanceOnly = statuses.length === 1 && statuses[0] === 'pending_acceptance' const isPendingAcceptanceOnly = statuses.length === 1 && statuses[0] === 'pending_acceptance'
const selectedWorkOrderStatuses = statuses.filter(
(status) => status !== VIP_EVIDENCE_PENDING_STATUS,
)
const vipEvidencePending = statuses.includes(VIP_EVIDENCE_PENDING_STATUS)
const ordersQuery = useQuery({ const ordersQuery = useQuery({
queryKey: [ queryKey: [
@@ -170,7 +176,9 @@ export default function WorkOrdersPanel() {
], ],
queryFn: () => queryFn: () =>
fetchAdminWorkOrders({ fetchAdminWorkOrders({
status: statuses.length > 0 ? statuses.join(',') : undefined, status:
selectedWorkOrderStatuses.length > 0 ? selectedWorkOrderStatuses.join(',') : undefined,
vipEvidencePending: vipEvidencePending || undefined,
keyword, keyword,
workerId, workerId,
page, page,
@@ -875,6 +883,7 @@ export default function WorkOrdersPanel() {
placeholder="全部状态(可多选)" placeholder="全部状态(可多选)"
style={{ minWidth: 220, maxWidth: 420 }} style={{ minWidth: 220, maxWidth: 420 }}
maxTagCount="responsive" maxTagCount="responsive"
listHeight={320}
options={FILTERABLE_WORK_ORDER_STATUSES.map((item) => ({ options={FILTERABLE_WORK_ORDER_STATUSES.map((item) => ({
value: item, value: item,
label: <Tag color={resolveStatusColor(item)}>{formatStatus(item)}</Tag>, label: <Tag color={resolveStatusColor(item)}>{formatStatus(item)}</Tag>,
@@ -202,6 +202,7 @@ export function formatStatus(status: string) {
in_progress: '代练中', in_progress: '代练中',
pending_acceptance: '待验收', pending_acceptance: '待验收',
problem: '问题单', problem: '问题单',
vip_evidence_pending: '待补图',
accepted: '已验收', accepted: '已验收',
cancelled: '已取消', cancelled: '已取消',
} }
@@ -216,6 +217,7 @@ export function resolveStatusColor(status: string) {
in_progress: 'geekblue', in_progress: 'geekblue',
pending_acceptance: 'purple', pending_acceptance: 'purple',
problem: 'red', problem: 'red',
vip_evidence_pending: 'gold',
accepted: 'green', accepted: 'green',
cancelled: 'default', cancelled: 'default',
} }
@@ -56,6 +56,7 @@ const STATUS_OPTIONS = [
{ value: 'pending_acceptance', label: '待验收' }, { value: 'pending_acceptance', label: '待验收' },
{ value: 'problem', label: '问题单' }, { value: 'problem', label: '问题单' },
{ value: 'open', label: '已超时' }, { value: 'open', label: '已超时' },
{ value: 'vip_evidence_pending', label: '待补图' },
{ value: 'accepted', label: '已验收' }, { value: 'accepted', label: '已验收' },
{ value: 'cancelled', label: '已取消' }, { value: 'cancelled', label: '已取消' },
{ value: '', label: '全部订单' }, { value: '', label: '全部订单' },
@@ -69,6 +70,15 @@ type WorkerNoteFormValues = {
note?: string note?: string
} }
function buildWorkerOrderQuery(status: string, keyword: string, page: number, pageSize: number) {
return {
keyword,
page,
pageSize,
...(status === 'vip_evidence_pending' ? { vipEvidencePending: true } : { status }),
}
}
type NoteTheme = 'success' | 'processing' | 'danger' | 'warning' | 'purple' | 'default' type NoteTheme = 'success' | 'processing' | 'danger' | 'warning' | 'purple' | 'default'
const PRESET_NOTE_TAGS: Array<{ label: string; theme: NoteTheme }> = [ const PRESET_NOTE_TAGS: Array<{ label: string; theme: NoteTheme }> = [
@@ -187,7 +197,7 @@ export default function WorkerOrdersPage() {
const ordersQuery = useQuery({ const ordersQuery = useQuery({
queryKey: ['worker-my-orders', status, keyword, page, pageSize], queryKey: ['worker-my-orders', status, keyword, page, pageSize],
queryFn: () => fetchWorkerMyOrders({ status, keyword, page, pageSize }), queryFn: () => fetchWorkerMyOrders(buildWorkerOrderQuery(status, keyword, page, pageSize)),
retry: false, retry: false,
}) })
const pagination = ordersQuery.data?.data.pagination const pagination = ordersQuery.data?.data.pagination
@@ -208,11 +218,7 @@ export default function WorkerOrdersPage() {
queryFn: async () => { queryFn: async () => {
const results = await Promise.all( const results = await Promise.all(
STATUS_OPTIONS.map(async (item) => { STATUS_OPTIONS.map(async (item) => {
const response = await fetchWorkerMyOrders({ const response = await fetchWorkerMyOrders(buildWorkerOrderQuery(item.value, '', 1, 1))
status: item.value,
page: 1,
pageSize: 1,
})
return [item.value || 'all', response.data.pagination.total] as const return [item.value || 'all', response.data.pagination.total] as const
}), }),
) )