增加打手列表筛选汇总
This commit is contained in:
@@ -44,6 +44,18 @@ export type WorkerUserRow = {
|
||||
last_renamed_at?: string | null
|
||||
}
|
||||
|
||||
export type WorkerUserStatistics = {
|
||||
totalCount: number
|
||||
statusCounts: Record<string, number>
|
||||
workerTypeCounts: Record<string, number>
|
||||
availableAmount: number
|
||||
frozenDepositAmount: number
|
||||
pendingUnfreezeAmount: number
|
||||
totalCreditedAmount: number
|
||||
totalSettledAmount: number
|
||||
timeoutOrderCount: number
|
||||
}
|
||||
|
||||
export type WorkerSessionRow = {
|
||||
id: number
|
||||
session_id: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { query, withTransaction } from '../../db/client.js'
|
||||
import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js'
|
||||
import type { CreateWorkerInput, ListInput, WorkerUserRow } from './types.js'
|
||||
import type { CreateWorkerInput, ListInput, WorkerUserRow, WorkerUserStatistics } from './types.js'
|
||||
import type { PoolClient } from 'pg'
|
||||
|
||||
const WORKER_USER_SELECT = `
|
||||
@@ -265,6 +265,75 @@ export async function listWorkerUsers({
|
||||
return { items: itemsResult.rows, total: Number(totalResult.rows[0]?.total || 0) }
|
||||
}
|
||||
|
||||
/** 按筛选条件汇总打手,统计范围不受当前分页影响。 */
|
||||
export async function getWorkerUserStatistics(
|
||||
input: Pick<ListInput, 'status' | 'keyword' | 'workerType' | 'workerId' | 'levelId'> = {},
|
||||
): Promise<WorkerUserStatistics> {
|
||||
const { whereClause, params } = buildWorkerUserWhere(input)
|
||||
const statisticsResult = await query<{
|
||||
status: string
|
||||
worker_type: string
|
||||
total_count: number
|
||||
available_amount: number
|
||||
frozen_deposit_amount: number
|
||||
pending_unfreeze_amount: number
|
||||
total_credited_amount: number
|
||||
total_settled_amount: number
|
||||
}>(
|
||||
`
|
||||
SELECT
|
||||
wu.status,
|
||||
wu.worker_type,
|
||||
COUNT(*)::int AS total_count,
|
||||
COALESCE(SUM(COALESCE(ww.available_amount, 0)), 0)::bigint AS available_amount,
|
||||
COALESCE(SUM(COALESCE(ww.frozen_deposit_amount, 0)), 0)::bigint AS frozen_deposit_amount,
|
||||
COALESCE(SUM(COALESCE(ww.pending_unfreeze_amount, 0)), 0)::bigint AS pending_unfreeze_amount,
|
||||
COALESCE(SUM(COALESCE(ww.total_credited_amount, 0)), 0)::bigint AS total_credited_amount,
|
||||
COALESCE(SUM(COALESCE(ww.total_settled_amount, 0)), 0)::bigint AS total_settled_amount
|
||||
FROM worker_users wu
|
||||
LEFT JOIN worker_wallets ww ON ww.worker_id = wu.id
|
||||
${whereClause}
|
||||
GROUP BY wu.status, wu.worker_type
|
||||
`,
|
||||
params,
|
||||
)
|
||||
|
||||
const timeoutResult = await query<{ total: number }>(
|
||||
`
|
||||
SELECT COUNT(*)::int AS total
|
||||
FROM work_order_events e
|
||||
INNER JOIN worker_users wu ON e.payload_json->>'workerId' = wu.id::text
|
||||
${whereClause ? `${whereClause} AND` : 'WHERE'} e.event_type LIKE 'timeout_%'
|
||||
`,
|
||||
params,
|
||||
)
|
||||
|
||||
const statistics: WorkerUserStatistics = {
|
||||
totalCount: 0,
|
||||
statusCounts: {},
|
||||
workerTypeCounts: {},
|
||||
availableAmount: 0,
|
||||
frozenDepositAmount: 0,
|
||||
pendingUnfreezeAmount: 0,
|
||||
totalCreditedAmount: 0,
|
||||
totalSettledAmount: 0,
|
||||
timeoutOrderCount: Number(timeoutResult.rows[0]?.total || 0),
|
||||
}
|
||||
for (const row of statisticsResult.rows) {
|
||||
const count = Number(row.total_count || 0)
|
||||
statistics.totalCount += count
|
||||
statistics.statusCounts[row.status] = (statistics.statusCounts[row.status] || 0) + count
|
||||
statistics.workerTypeCounts[row.worker_type] =
|
||||
(statistics.workerTypeCounts[row.worker_type] || 0) + count
|
||||
statistics.availableAmount += Number(row.available_amount || 0)
|
||||
statistics.frozenDepositAmount += Number(row.frozen_deposit_amount || 0)
|
||||
statistics.pendingUnfreezeAmount += Number(row.pending_unfreeze_amount || 0)
|
||||
statistics.totalCreditedAmount += Number(row.total_credited_amount || 0)
|
||||
statistics.totalSettledAmount += Number(row.total_settled_amount || 0)
|
||||
}
|
||||
return statistics
|
||||
}
|
||||
|
||||
export {
|
||||
addWorkerWalletCredit,
|
||||
ensureWorkerWallet,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
countTimeoutEventsByWorkerIds,
|
||||
getWorkerUserStatistics,
|
||||
getWorkerLevelById,
|
||||
listWorkerUsers,
|
||||
revokeAllWorkerSessions,
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
hashWorkerPassword,
|
||||
mapWorkerUser,
|
||||
normalizeAmountFen,
|
||||
normalizeBoolean,
|
||||
normalizeOptionalId,
|
||||
normalizeReviewStatus,
|
||||
normalizeSessionVersion,
|
||||
@@ -29,15 +31,21 @@ export async function listAdminWorkerUsers(query: JsonObject = {}) {
|
||||
const pageSize = normalizePageSize(query.pageSize)
|
||||
const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0
|
||||
const levelId = normalizeOptionalId(query.levelId ?? query.level_id) || 0
|
||||
const { items, total } = await listWorkerUsers({
|
||||
page,
|
||||
pageSize,
|
||||
const filters = {
|
||||
workerId,
|
||||
levelId,
|
||||
status: String(query.status || '').trim(),
|
||||
keyword: String(query.keyword || '').trim(),
|
||||
workerType: String(query.workerType || query.worker_type || '').trim(),
|
||||
})
|
||||
}
|
||||
const includeStatistics = normalizeBoolean(
|
||||
query.includeStatistics ?? query.include_statistics,
|
||||
false,
|
||||
)
|
||||
const [{ items, total }, statistics] = await Promise.all([
|
||||
listWorkerUsers({ page, pageSize, ...filters }),
|
||||
includeStatistics ? getWorkerUserStatistics(filters) : Promise.resolve(undefined),
|
||||
])
|
||||
const timeoutCounts = await countTimeoutEventsByWorkerIds(items.map((item) => Number(item.id)))
|
||||
return {
|
||||
items: items.map((item) => ({
|
||||
@@ -45,6 +53,7 @@ export async function listAdminWorkerUsers(query: JsonObject = {}) {
|
||||
timeoutOrderCount: timeoutCounts.get(Number(item.id)) || 0,
|
||||
})),
|
||||
pagination: { page, pageSize, total },
|
||||
...(statistics ? { statistics } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user