/** * filekorolheader: URL参数处理工具函数 - 通用URL参数解析和优先级管理 * 功能:从浏览器URL读取参数、参数优先级处理、类型安全的参数转换 * 路径:/utils/urlParams * 规范:遵循crop-x/docs/开发项目规范.md,TypeScript类型安全,泛型支持 */ // URL参数解析配置接口 export interface UrlParamsConfig> { // 搜索字段配置,定义哪些字段需要从URL中读取 searchFields: { [K in keyof T]?: { type: 'string' | 'number' | 'boolean'; // URL参数名映射,如果不配置则使用字段名 urlKey?: string; // 默认值 default?: T[K]; // 是否必需字段 required?: boolean; }; }; // 分页字段配置 paginationFields?: { page?: { urlKey?: string; default?: number; }; size?: { urlKey?: string; default?: number; }; }; } // URL参数解析结果接口 export interface UrlParamsResult> { // 搜索参数 searchParams: Partial; // 分页参数 paginationParams: { page: number; size: number; }; // 是否包含任何URL参数 hasUrlParams: boolean; // 原始URL参数字符串 rawUrlParams: string; } /** * 通用URL参数解析函数 * * @param config URL参数配置 * @returns 解析后的URL参数结果 * * @example * interface MyParams { * search: string; * status: string; * category: string; * } * * const config: UrlParamsConfig = { * searchFields: { * search: { type: 'string', urlKey: 'search', default: '' }, * status: { type: 'string', urlKey: 'audit_status', default: 'all' }, * category: { type: 'string', default: 'all' } * }, * paginationFields: { * page: { urlKey: 'page', default: 1 }, * size: { urlKey: 'size', default: 10 } * } * }; * * const result = parseUrlParams(config); * console.log(result.searchParams); // { search: 'keyword', status: 'pending', category: 'all' } * console.log(result.paginationParams); // { page: 2, size: 20 } */ export function parseUrlParams>( config: UrlParamsConfig ): UrlParamsResult { // 检查是否在浏览器环境 if (typeof window === 'undefined') { return { searchParams: {} as Partial, paginationParams: { page: config.paginationFields?.page?.default ?? 1, size: config.paginationFields?.size?.default ?? 10 }, hasUrlParams: false, rawUrlParams: '' }; } try { const urlParams = new URLSearchParams(window.location.search); const rawUrlParams = urlParams.toString(); const searchParams: Partial = {}; let hasUrlParams = rawUrlParams !== ''; // 解析搜索字段 Object.entries(config.searchFields).forEach(([fieldKey, fieldConfig]) => { if (!fieldConfig) return; const urlKey = fieldConfig.urlKey || fieldKey; const rawValue = urlParams.get(urlKey); if (rawValue !== null) { let parsedValue: any = rawValue; // 类型转换 switch (fieldConfig.type) { case 'number': parsedValue = parseInt(rawValue, 10); if (isNaN(parsedValue)) { parsedValue = fieldConfig.default; } break; case 'boolean': parsedValue = rawValue === 'true' || rawValue === '1'; break; case 'string': default: parsedValue = rawValue; break; } (searchParams as any)[fieldKey] = parsedValue; } else if (fieldConfig.default !== undefined) { (searchParams as any)[fieldKey] = fieldConfig.default; } else if (fieldConfig.required) { console.warn(`Required URL parameter '${urlKey}' is missing`); } }); // 解析分页字段 const pageValue = urlParams.get(config.paginationFields?.page?.urlKey || 'page'); const sizeValue = urlParams.get(config.paginationFields?.size?.urlKey || 'size'); const page = pageValue ? Math.max(1, parseInt(pageValue, 10) || 1) : (config.paginationFields?.page?.default ?? 1); const size = sizeValue ? Math.max(1, parseInt(sizeValue, 10) || 10) : (config.paginationFields?.size?.default ?? 10); const paginationParams = { page, size }; return { searchParams, paginationParams, hasUrlParams, rawUrlParams }; } catch (error) { console.error('Failed to parse URL parameters:', error); return { searchParams: {} as Partial, paginationParams: { page: config.paginationFields?.page?.default ?? 1, size: config.paginationFields?.size?.default ?? 10 }, hasUrlParams: false, rawUrlParams: '' }; } } /** * 参数优先级合并函数 * 优先级:URL参数 > 函数传入参数 > 默认状态 * * @param urlParams 从URL解析的参数 * @param functionParams 函数传入的参数 * @param defaultState 默认状态 * @returns 合并后的参数 */ export function mergeParamsWithPriority>( urlParams: Partial, functionParams: Partial = {}, defaultState: T ): T { const result = { ...defaultState }; // 先合并函数参数(第二优先级) Object.keys(result).forEach(key => { if (functionParams[key as keyof T] !== undefined) { (result as any)[key] = functionParams[key as keyof T]; } }); // 再合并URL参数(第一优先级) Object.keys(urlParams).forEach(key => { if (urlParams[key as keyof T] !== undefined && urlParams[key as keyof T] !== '') { (result as any)[key] = urlParams[key as keyof T]; } }); return result; } /** * 分页参数优先级合并函数 * * @param urlPagination 从URL解析的分页参数 * @param functionPagination 函数传入的分页参数 * @param defaultPagination 默认分页状态 * @param resetPage 是否重置到第一页 * @returns 合并后的分页参数 */ export function mergePaginationWithPriority( urlPagination: { page: number; size: number }, functionPagination: { page?: number; size?: number } = {}, defaultPagination: { page: number; size: number }, resetPage: boolean = false ): { page: number; size: number } { const page = resetPage ? 1 : (urlPagination.page || functionPagination.page || defaultPagination.page); const size = urlPagination.size || functionPagination.size || defaultPagination.size; return { page: Math.max(1, page), size: Math.max(1, size) }; } /** * 审核历史页面专用的URL参数配置 */ export const AUDIT_HISTORY_URL_CONFIG: UrlParamsConfig<{ search: string; action: string; audit_status: string; date_range: string; }> = { searchFields: { search: { type: 'string', default: '' }, action: { type: 'string', urlKey: 'action', default: 'all' }, audit_status: { type: 'string', urlKey: 'audit_status', default: 'all' }, date_range: { type: 'string', urlKey: 'date_range', default: 'all' } }, paginationFields: { page: { urlKey: 'page', default: 1 }, size: { urlKey: 'size', default: 10 } } }; /** * 企业审核页面专用的URL参数配置 */ export const ENTERPRISE_AUDIT_URL_CONFIG: UrlParamsConfig<{ search: string; audit_status: string; }> = { searchFields: { search: { type: 'string', default: '' }, audit_status: { type: 'string', urlKey: 'audit_status', default: 'all' } }, paginationFields: { page: { urlKey: 'page', default: 1 }, size: { urlKey: 'size', default: 10 } } }; /** * 默认URL参数配置(通用) */ export const DEFAULT_URL_CONFIG: UrlParamsConfig> = { searchFields: {}, paginationFields: { page: { urlKey: 'page', default: 1 }, size: { urlKey: 'size', default: 10 } } };