task-109(任务与重复分析中心): 实现店铺数据任务筛选
新增 shop-data-filter.ts:店铺名/分组/国家/创建时间区间筛选归一与 snake 查询序列化,页大小钳制 [10,100]。 TDD: task-109.test.ts 8 用例先 RED 后 GREEN。
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
/** 店铺数据任务筛选与分页(任务 109):与 Java AdminShopDataCrawlTasksController snake 契约对齐;纯逻辑。 */
|
||||
|
||||
export const SHOP_DATA_DEFAULT_PAGE_SIZE = 20
|
||||
export const SHOP_DATA_MIN_PAGE_SIZE = 10
|
||||
export const SHOP_DATA_MAX_PAGE_SIZE = 100
|
||||
export const SHOP_DATA_PAGE_MIN = 1
|
||||
|
||||
const LOCAL_DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/
|
||||
|
||||
export interface ShopDataFilter {
|
||||
shopName: string
|
||||
groupName: string
|
||||
country: string
|
||||
createdFrom: string
|
||||
createdTo: string
|
||||
}
|
||||
|
||||
export interface ShopDataQuery {
|
||||
page: number
|
||||
page_size: number
|
||||
shop_name?: string
|
||||
group_name?: string
|
||||
country?: string
|
||||
created_from?: string
|
||||
created_to?: string
|
||||
}
|
||||
|
||||
export function createShopDataFilter(): ShopDataFilter {
|
||||
return { shopName: '', groupName: '', country: '', createdFrom: '', createdTo: '' }
|
||||
}
|
||||
|
||||
function textOrUndefined(value: unknown): string | undefined {
|
||||
const text = typeof value === 'string' ? value.trim() : ''
|
||||
return text || undefined
|
||||
}
|
||||
|
||||
function datetimeOrUndefined(value: unknown): string | undefined {
|
||||
if (typeof value !== 'string') return undefined
|
||||
const text = value.trim()
|
||||
return LOCAL_DATETIME.test(text) ? text : undefined
|
||||
}
|
||||
|
||||
export function shopDataFilterActive(filter: ShopDataFilter): boolean {
|
||||
return Boolean(
|
||||
filter.shopName.trim() ||
|
||||
filter.groupName.trim() ||
|
||||
filter.country.trim() ||
|
||||
filter.createdFrom ||
|
||||
filter.createdTo,
|
||||
)
|
||||
}
|
||||
|
||||
function finiteInt(value: unknown): number | null {
|
||||
return typeof value === 'number' && Number.isFinite(value) ? Math.floor(value) : null
|
||||
}
|
||||
|
||||
/** 前端状态 → Java 查询参数(snake_case,仅下发非空)。 */
|
||||
export function toShopDataQuery(filter: ShopDataFilter, page: unknown, pageSize: unknown): ShopDataQuery {
|
||||
const safePage = Math.max(finiteInt(page) ?? SHOP_DATA_PAGE_MIN, SHOP_DATA_PAGE_MIN)
|
||||
const rawSize = finiteInt(pageSize)
|
||||
const pageSizeClamped =
|
||||
rawSize === null || rawSize < 1
|
||||
? SHOP_DATA_DEFAULT_PAGE_SIZE
|
||||
: Math.min(Math.max(rawSize, SHOP_DATA_MIN_PAGE_SIZE), SHOP_DATA_MAX_PAGE_SIZE)
|
||||
const query: ShopDataQuery = { page: safePage, page_size: pageSizeClamped }
|
||||
const shopName = textOrUndefined(filter.shopName)
|
||||
if (shopName) query.shop_name = shopName
|
||||
const groupName = textOrUndefined(filter.groupName)
|
||||
if (groupName) query.group_name = groupName
|
||||
const country = textOrUndefined(filter.country)
|
||||
if (country) query.country = country
|
||||
const createdFrom = datetimeOrUndefined(filter.createdFrom)
|
||||
if (createdFrom) query.created_from = createdFrom
|
||||
const createdTo = datetimeOrUndefined(filter.createdTo)
|
||||
if (createdTo) query.created_to = createdTo
|
||||
return query
|
||||
}
|
||||
Reference in New Issue
Block a user