feat(worker-hall): 抢单大厅支持分类与全部按钮图标自定义及PNG透明通道修复

This commit is contained in:
yml2213
2026-09-12 20:16:27 +08:00
parent 694d7fff40
commit 1cf790d6ab
11 changed files with 187 additions and 41 deletions
@@ -1,5 +1,6 @@
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import { countWorkOrders, listWorkerUsers } from '../../repositories/worker-platform/index.js'
import { refreshStoredFileUrl } from '../file-storage/file-storage-service.js'
import { publishWorkerHallRealtimeRefresh } from '../realtime/realtime-event-service.js'
import { getWorkerHallConfig, saveWorkerHallConfig } from './worker-hall-config-service.js'
@@ -55,6 +56,7 @@ export async function getAdminWorkerHallConfig() {
])
return {
...config,
allIconUrl: config.allIconUrl ? refreshStoredFileUrl(config.allIconUrl) : null,
visibleOrderCount: visibleOpenOrderCount,
queuedOrderCount: Math.max(0, openOrderCount - visibleOpenOrderCount),
}
@@ -17,7 +17,10 @@ import {
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { safeParseJson } from '../admin/admin-query-utils.js'
import { refreshUploadedFileUrls } from '../file-storage/file-storage-service.js'
import {
refreshStoredFileUrl,
refreshUploadedFileUrls,
} from '../file-storage/file-storage-service.js'
import { DEFAULT_DEPOSIT_THRESHOLD_AMOUNT } from './worker-finance-mappers.js'
import { normalizeUploadedFiles } from './worker-input-normalizers.js'
import { resolveFreezeDepositAmount } from './worker-permission-utils.js'
@@ -34,7 +37,7 @@ export function mapWorkCategory(category: WorkCategoryRow | null | undefined) {
categoryKey: category.category_key,
name: category.name,
parentId: category.parent_id ? Number(category.parent_id) : null,
iconUrl: category.icon_url || null,
iconUrl: category.icon_url ? refreshStoredFileUrl(category.icon_url) : null,
sortOrder: Number(category.sort_order || 100),
status: category.status,
createdAt: category.created_at,
@@ -10,35 +10,45 @@ test('大厅配置默认展示 50 个订单', () => {
assert.deepEqual(createDefaultWorkerHallConfig(), {
maxVisibleOrders: 50,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.deepEqual(normalizeWorkerHallConfig({}), {
maxVisibleOrders: 50,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.equal(normalizeWorkerHallConfig({ showSubcategories: false }).showSubcategories, false)
assert.equal(
normalizeWorkerHallConfig({ allIconUrl: ' https://example.com/icon.png ' }).allIconUrl,
'https://example.com/icon.png',
)
})
test('大厅配置只接受 1 到 500 的整数', () => {
assert.deepEqual(normalizeWorkerHallConfig({ maxVisibleOrders: 88 }), {
maxVisibleOrders: 88,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.deepEqual(normalizeWorkerHallConfig({ max_visible_orders: 999 }), {
maxVisibleOrders: 500,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.deepEqual(normalizeWorkerHallConfig({ maxVisibleOrders: 0 }), {
maxVisibleOrders: 1,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.deepEqual(normalizeWorkerHallConfig({ maxVisibleOrders: 1.5 }), {
maxVisibleOrders: 50,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
})
assert.deepEqual(
@@ -5,6 +5,7 @@ import { readAppConfigEntry, saveAppConfigEntry } from '../config/app-config-sto
export type WorkerHallConfig = {
maxVisibleOrders: number
showSubcategories: boolean
allIconUrl: string | null
categoryMaxVisibleOrders: Record<string, number>
}
@@ -25,7 +26,12 @@ export async function saveWorkerHallConfig(rawValue: unknown): Promise<WorkerHal
}
export function createDefaultWorkerHallConfig(): WorkerHallConfig {
return { maxVisibleOrders: 50, showSubcategories: true, categoryMaxVisibleOrders: {} }
return {
maxVisibleOrders: 50,
showSubcategories: true,
allIconUrl: null,
categoryMaxVisibleOrders: {},
}
}
export function normalizeWorkerHallConfig(rawValue: unknown): WorkerHallConfig {
@@ -37,9 +43,20 @@ export function normalizeWorkerHallConfig(rawValue: unknown): WorkerHallConfig {
: source.show_subcategories !== undefined
? Boolean(source.show_subcategories)
: true
const allIconUrl =
source.allIconUrl !== undefined
? typeof source.allIconUrl === 'string' && source.allIconUrl.trim()
? source.allIconUrl.trim()
: null
: source.all_icon_url !== undefined
? typeof source.all_icon_url === 'string' && source.all_icon_url.trim()
? source.all_icon_url.trim()
: null
: null
return {
maxVisibleOrders: Number.isInteger(value) ? Math.min(500, Math.max(1, value)) : 50,
showSubcategories,
allIconUrl,
categoryMaxVisibleOrders: normalizeCategoryMaxVisibleOrders(
source.categoryMaxVisibleOrders ?? source.category_max_visible_orders,
),
@@ -7,6 +7,7 @@ import {
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { normalizePage, normalizePageSize } from '../admin/admin-query-utils.js'
import { refreshStoredFileUrl } from '../file-storage/file-storage-service.js'
import {
mapWorkCategory,
mapWorkOrderForWorker,
@@ -91,6 +92,7 @@ export async function listWorkerHallOrders(query: JsonObject = {}, session: Work
pagination: { page, pageSize, total },
categories,
showSubcategories: hallConfig.showSubcategories,
allIconUrl: hallConfig.allIconUrl ? refreshStoredFileUrl(hallConfig.allIconUrl) : null,
visibleDelaySeconds,
}
})