OfficeSystem/utils/url.js

166 lines
4.6 KiB
JavaScript
Raw Normal View History

2025-11-27 10:14:55 +08:00
/**
* URL构建工具
* 统一处理查询参数的构建支持数组对象特殊字符编码等
*/
/**
* 构建带查询参数的URL
* @param {string} basePath - 基础路径 'bst/task/list'
* @param {Object} params - 查询参数对象
* @param {Object} options - 配置选项
* @param {boolean} options.encodeValues - 是否对值进行URL编码默认true
* @param {boolean} options.skipEmpty - 是否跳过空值默认true
* @param {string} options.arrayFormat - 数组格式'repeat'重复参数 'bracket'带索引默认'repeat'
* @returns {string} 完整的URL字符串
*
* @example
* // 基础用法
* buildUrl('bst/task/list', { pageNum: 1, pageSize: 10 })
* // => 'bst/task/list?pageNum=1&pageSize=10'
*
* @example
* // 数组参数(重复格式)
* buildUrl('bst/task/list', { statusList: [1, 2, 3] })
* // => 'bst/task/list?statusList=1&statusList=2&statusList=3'
*
* @example
* // 数组参数(带索引格式)
* buildUrl('bst/project/list', { keys: ['key1', 'key2'] }, { arrayFormat: 'bracket' })
* // => 'bst/project/list?keys[0]=key1&keys[1]=key2'
*
* @example
* // 包含特殊字符
* buildUrl('bst/task/list', { orderByColumn: 'create time', isAsc: 'ascending' })
* // => 'bst/task/list?orderByColumn=create%20time&isAsc=ascending'
*/
export function buildUrl(basePath, params = {}, options = {}) {
const {
encodeValues = true,
skipEmpty = true,
arrayFormat = 'repeat' // 'repeat' | 'bracket'
} = options
// 如果没有参数,直接返回基础路径
if (!params || Object.keys(params).length === 0) {
return basePath
}
const queryParams = []
/**
* 编码值
* @param {any} value - 要编码的值
* @returns {string} 编码后的字符串
*/
const encodeValue = (value) => {
if (encodeValues) {
return encodeURIComponent(String(value))
}
return String(value)
}
/**
* 添加查询参数
* @param {string} key - 参数名
* @param {any} value - 参数值
*/
const addParam = (key, value) => {
// 跳过空值
if (skipEmpty && (value === null || value === undefined || value === '')) {
return
}
const encodedKey = encodeURIComponent(key)
// 处理数组
if (Array.isArray(value)) {
if (value.length === 0) return
value.forEach((item, index) => {
// 跳过数组中的空值
if (skipEmpty && (item === null || item === undefined || item === '')) {
return
}
if (arrayFormat === 'bracket') {
// 带索引格式keys[0]=value1
queryParams.push(`${encodedKey}[${index}]=${encodeValue(item)}`)
} else {
// 重复格式key=value1&key=value2
queryParams.push(`${encodedKey}=${encodeValue(item)}`)
}
})
return
}
// 处理对象转换为JSON字符串
if (typeof value === 'object' && value !== null) {
queryParams.push(`${encodedKey}=${encodeValue(JSON.stringify(value))}`)
return
}
// 处理布尔值
if (typeof value === 'boolean') {
queryParams.push(`${encodedKey}=${value}`)
return
}
// 处理普通值
queryParams.push(`${encodedKey}=${encodeValue(value)}`)
}
// 遍历所有参数
Object.entries(params).forEach(([key, value]) => {
addParam(key, value)
})
// 构建查询字符串
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : ''
return `${basePath}${queryString}`
}
/**
* 合并默认参数和用户参数
* @param {Object} defaultParams - 默认参数
* @param {Object} userParams - 用户传入的参数
* @returns {Object} 合并后的参数对象用户参数优先
*
* @example
* mergeParams({ pageNum: 1, pageSize: 10 }, { pageNum: 2 })
* // => { pageNum: 2, pageSize: 10 }
*/
export function mergeParams(defaultParams = {}, userParams = {}) {
return { ...defaultParams, ...userParams }
}
/**
* 从URL中提取查询参数
* @param {string} url - 完整URL或查询字符串
* @returns {Object} 参数对象
*
* @example
* parseUrl('bst/task/list?pageNum=1&pageSize=10')
* // => { pageNum: '1', pageSize: '10' }
*/
export function parseUrl(url) {
const params = {}
try {
const queryString = url.includes('?') ? url.split('?')[1] : url
if (!queryString) return params
queryString.split('&').forEach(param => {
const [key, value] = param.split('=')
if (key) {
params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : ''
}
})
} catch (error) {
console.error('解析URL参数失败:', error)
}
return params
}