支持待验收工单按VIP等级筛选

This commit is contained in:
yml2213
2026-08-20 18:02:13 +08:00
parent 3587e44261
commit 39aeb0baaa
4 changed files with 66 additions and 1 deletions
@@ -287,6 +287,8 @@ export type ListInput = {
/** 打手类型筛选:internal 内部打手 / external 外部打手 */ /** 打手类型筛选:internal 内部打手 / external 外部打手 */
workerType?: string workerType?: string
workerId?: number workerId?: number
/** 后台待验收筛选:普通单按接单人,拼单按参与打手等级。 */
workerLevelIds?: number[]
categoryId?: number categoryId?: number
workerSharingId?: number workerSharingId?: number
visibleAfterIso?: string visibleAfterIso?: string
@@ -1055,6 +1055,7 @@ export async function listWorkOrders({
workOrderId = 0, workOrderId = 0,
keyword = '', keyword = '',
workerId = 0, workerId = 0,
workerLevelIds = [],
categoryId = 0, categoryId = 0,
workerSharingId = 0, workerSharingId = 0,
visibleAfterIso = '', visibleAfterIso = '',
@@ -1070,6 +1071,7 @@ export async function listWorkOrders({
workOrderId, workOrderId,
keyword, keyword,
workerId, workerId,
workerLevelIds,
categoryId, categoryId,
workerSharingId, workerSharingId,
visibleAfterIso, visibleAfterIso,
@@ -3429,6 +3431,7 @@ function buildWorkOrderWhere({
workOrderId = 0, workOrderId = 0,
keyword = '', keyword = '',
workerId = 0, workerId = 0,
workerLevelIds = [],
categoryId = 0, categoryId = 0,
workerSharingId = 0, workerSharingId = 0,
visibleAfterIso = '', visibleAfterIso = '',
@@ -3491,6 +3494,25 @@ function buildWorkOrderWhere({
) )
)`) )`)
} }
if (workerLevelIds.length > 0) {
params.push(workerLevelIds)
filters.push(`(
EXISTS (
SELECT 1
FROM worker_users wu
WHERE wu.id = wo.assigned_worker_id
AND wu.level_id = ANY($${params.length}::bigint[])
)
OR EXISTS (
SELECT 1
FROM work_order_shares wos
INNER JOIN worker_users wu ON wu.id = wos.worker_id
WHERE wos.work_order_id = wo.id
AND wos.status != 'cancelled'
AND wu.level_id = ANY($${params.length}::bigint[])
)
)`)
}
if (categoryId) { if (categoryId) {
params.push(categoryId) params.push(categoryId)
filters.push(`wo.category_id = $${params.length}`) filters.push(`wo.category_id = $${params.length}`)
@@ -1307,6 +1307,9 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
const pageSize = normalizePageSize(query.pageSize) const pageSize = normalizePageSize(query.pageSize)
const workOrderId = normalizeOptionalId(query.workOrderId ?? query.work_order_id) || 0 const workOrderId = normalizeOptionalId(query.workOrderId ?? query.work_order_id) || 0
const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0 const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0
const workerLevelIds = normalizeStatuses(query.workerLevelIds ?? query.worker_level_ids)
.map(normalizeOptionalId)
.filter((levelId): levelId is number => levelId !== null)
const statuses = normalizeStatuses(query.status) const statuses = normalizeStatuses(query.status)
const vipEvidencePending = normalizeBoolean(query.vipEvidencePending, false) const vipEvidencePending = normalizeBoolean(query.vipEvidencePending, false)
const { items, total } = await listWorkOrders({ const { items, total } = await listWorkOrders({
@@ -1316,6 +1319,7 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
workOrderId, workOrderId,
keyword: String(query.keyword || '').trim(), keyword: String(query.keyword || '').trim(),
workerSharingId: workerId, workerSharingId: workerId,
workerLevelIds,
vipEvidencePending, vipEvidencePending,
useOperationalStatus: true, useOperationalStatus: true,
}) })
@@ -1324,6 +1328,7 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
workOrderId, workOrderId,
keyword: String(query.keyword || '').trim(), keyword: String(query.keyword || '').trim(),
workerSharingId: workerId, workerSharingId: workerId,
workerLevelIds,
vipEvidencePending, vipEvidencePending,
useOperationalStatus: true, useOperationalStatus: true,
}) })
@@ -55,6 +55,7 @@ import {
deleteAdminWorkOrder, deleteAdminWorkOrder,
fetchAdminWorkCategories, fetchAdminWorkCategories,
fetchAdminWorkOrderSharing, fetchAdminWorkOrderSharing,
fetchAdminWorkerLevels,
fetchAdminWorkerUsers, fetchAdminWorkerUsers,
fetchAdminWorkOrders, fetchAdminWorkOrders,
markAdminWorkOrderProblem, markAdminWorkOrderProblem,
@@ -138,6 +139,7 @@ export default function WorkOrdersPanel() {
const [keyword, setKeyword] = useState('') const [keyword, setKeyword] = useState('')
const [keywordInput, setKeywordInput] = useState('') const [keywordInput, setKeywordInput] = useState('')
const [workerId, setWorkerId] = useState<number | undefined>() const [workerId, setWorkerId] = useState<number | undefined>()
const [workerLevelIds, setWorkerLevelIds] = useState<number[]>([])
const [filterWorkerKeyword, setFilterWorkerKeyword] = useState('') const [filterWorkerKeyword, setFilterWorkerKeyword] = useState('')
const [assignWorkerKeyword, setAssignWorkerKeyword] = useState('') const [assignWorkerKeyword, setAssignWorkerKeyword] = useState('')
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
@@ -184,6 +186,7 @@ export default function WorkOrdersPanel() {
(status) => status !== VIP_EVIDENCE_PENDING_STATUS, (status) => status !== VIP_EVIDENCE_PENDING_STATUS,
) )
const vipEvidencePending = statuses.includes(VIP_EVIDENCE_PENDING_STATUS) const vipEvidencePending = statuses.includes(VIP_EVIDENCE_PENDING_STATUS)
const showWorkerLevelFilter = statuses.includes('pending_acceptance')
useEffect(() => { useEffect(() => {
const workOrderId = Number(searchParams.get('workOrderId') || 0) const workOrderId = Number(searchParams.get('workOrderId') || 0)
@@ -193,6 +196,7 @@ export default function WorkOrdersPanel() {
setKeyword('') setKeyword('')
setKeywordInput('') setKeywordInput('')
setWorkerId(undefined) setWorkerId(undefined)
setWorkerLevelIds([])
setPage(1) setPage(1)
setSearchParams( setSearchParams(
(current) => { (current) => {
@@ -209,6 +213,7 @@ export default function WorkOrdersPanel() {
statuses.join(','), statuses.join(','),
keyword, keyword,
workerId, workerId,
workerLevelIds.join(','),
targetWorkOrderId, targetWorkOrderId,
page, page,
pageSize, pageSize,
@@ -221,6 +226,8 @@ export default function WorkOrdersPanel() {
workOrderId: targetWorkOrderId, workOrderId: targetWorkOrderId,
keyword, keyword,
workerId, workerId,
workerLevelIds:
showWorkerLevelFilter && workerLevelIds.length > 0 ? workerLevelIds.join(',') : undefined,
page, page,
pageSize, pageSize,
}), }),
@@ -230,6 +237,11 @@ export default function WorkOrdersPanel() {
queryKey: ['admin-worker-platform-categories'], queryKey: ['admin-worker-platform-categories'],
queryFn: () => fetchAdminWorkCategories(), queryFn: () => fetchAdminWorkCategories(),
}) })
const workerLevelsQuery = useQuery({
queryKey: ['admin-worker-platform-levels'],
queryFn: () => fetchAdminWorkerLevels(),
enabled: showWorkerLevelFilter,
})
const filterWorkersQuery = useQuery({ const filterWorkersQuery = useQuery({
queryKey: ['admin-worker-platform-workers', 'order-filter', filterWorkerKeyword], queryKey: ['admin-worker-platform-workers', 'order-filter', filterWorkerKeyword],
queryFn: () => queryFn: () =>
@@ -258,7 +270,11 @@ export default function WorkOrdersPanel() {
useEffect(() => { useEffect(() => {
setSelectedAcceptanceOrderIds([]) setSelectedAcceptanceOrderIds([])
}, [statuses, keyword, workerId, targetWorkOrderId, page, pageSize]) }, [statuses, keyword, workerId, workerLevelIds, targetWorkOrderId, page, pageSize])
useEffect(() => {
if (!showWorkerLevelFilter) setWorkerLevelIds([])
}, [showWorkerLevelFilter])
function openAssignModal(row: WorkOrder) { function openAssignModal(row: WorkOrder) {
setAssignOrder(row) setAssignOrder(row)
@@ -567,6 +583,7 @@ export default function WorkOrdersPanel() {
setKeyword('') setKeyword('')
setStatuses([]) setStatuses([])
setWorkerId(undefined) setWorkerId(undefined)
setWorkerLevelIds([])
setPage(1) setPage(1)
} }
@@ -1042,6 +1059,25 @@ export default function WorkOrdersPanel() {
setPage(1) setPage(1)
}} }}
/> />
{showWorkerLevelFilter ? (
<Select
mode="multiple"
allowClear
value={workerLevelIds}
placeholder="全部打手 VIP 等级"
style={{ minWidth: 180, maxWidth: 320 }}
maxTagCount="responsive"
loading={workerLevelsQuery.isLoading}
options={(workerLevelsQuery.data?.data.items || []).map((level) => ({
value: level.levelId,
label: level.name,
}))}
onChange={(nextWorkerLevelIds: number[]) => {
setWorkerLevelIds(nextWorkerLevelIds)
setPage(1)
}}
/>
) : null}
<Button type="primary" icon={<SearchOutlined />} onClick={searchOrders}> <Button type="primary" icon={<SearchOutlined />} onClick={searchOrders}>
</Button> </Button>