Files
boss_font/src/utils/auxiliaryFunction/index.ts
2026-03-05 15:29:53 +08:00

304 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 节流函数 - 限制函数执行频率
* @param func 需要节流的函数
* @param delay 节流延迟时间(毫秒)
* @returns 节流后的函数
*/
export function throttle<T extends (...args: any[]) => any>(
func: T,
delay: number = 300
): (...args: Parameters<T>) => void {
let lastExecTime = 0
return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
const now = Date.now()
// 只有超过延迟时间才执行
if (now - lastExecTime >= delay) {
func.apply(this, args)
lastExecTime = now
}
}
}
/**
* 防抖函数
* @param func 需要防抖的函数
* @param delay 延迟时间(毫秒)
* @returns 防抖后的函数
*/
export function debounce<T extends (...args: any[]) => any>(
func: T,
delay: number = 300
): (...args: Parameters<T>) => void {
let timeoutId: NodeJS.Timeout | null = null
return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(() => {
func.apply(this, args)
timeoutId = null
}, delay)
}
}
/**
* 将文件路径数组转换为对象数组
* @param filePaths 文件路径数组或单个文件路径字符串
* @returns 包含文件信息的对象数组
*/
export function convertFilePathsToObject(filePaths: string | string[]): Array<{
url: string
name: string
domain: string
uuid: string
extension: string // 新增后缀名字段
}> {
// 如果是字符串,先转换为数组
const paths = Array.isArray(filePaths) ? filePaths : [filePaths]
return paths.map((path) => {
// 确保path是字符串类型
if (typeof path !== 'string') {
return {
url: '',
domain: '',
name: '',
uuid: '',
extension: '' // 新增后缀名字段
}
}
// 自动补全协议头
let fullPath = path
if (!path.startsWith('http://') && !path.startsWith('https://')) {
fullPath = `http://${path}`
}
// 分割域名和文件部分
const urlObj = new URL(fullPath)
const domain = urlObj.origin
const filePart = urlObj.pathname.substring(1) // 移除开头的 /
// 优化文件名解析逻辑
// 对于路径 "cd78824383f7新建 文本文档.txt"
// 我们不再强制要求下划线分隔格式,而是提取完整的文件名
let name = ''
let uuid = ''
let extension = '' // 新增后缀名变量
// 尝试从文件名中提取 UUID假设 UUID 是文件名开头的一段字母数字组合)
const uuidMatch = filePart.match(/^([a-f0-9]+)/i)
if (uuidMatch && uuidMatch[1]) {
uuid = uuidMatch[1]
// 文件名是去掉 UUID 后的部分
name = filePart.substring(uuid.length)
// 如果文件名以斜杠开头则去除
if (name.startsWith('/')) {
name = name.substring(1)
}
} else {
// 如果没有匹配到 UUID 格式,整个作为文件名处理
name = filePart
}
// 如果 name 为空,则使用完整文件部分作为文件名
if (!name) {
name = filePart
}
// 提取文件扩展名
const lastDotIndex = name.lastIndexOf('.')
if (lastDotIndex > 0) {
// 确保点号不在开头
extension = name.substring(lastDotIndex + 1).toLowerCase()
name = name.substring(0, lastDotIndex) // 移除扩展名部分,只保留文件名
}
// 解码 URL 编码的文件名
try {
name = decodeURIComponent(name)
} catch (e) {
// 如果解码失败,保持原始文件名
console.warn('文件名解码失败:', name)
}
return {
url: fullPath,
domain,
name,
uuid,
extension // 新增后缀名字段
}
})
}
// 安全的文件信息提取函数
// 更新返回类型定义
export function getFileInfo(fileStr: string): {
url: string
name: string
extension: string // 新增扩展名字段
} | null {
try {
if (!fileStr) return null
// 如果是有效的JSON字符串按原有逻辑处理
if (isValidJson(fileStr)) {
const parsed = JSON.parse(fileStr)
const files = convertFilePathsToObject(parsed)
return files && files.length > 0
? {
url: files[0].url,
name: files[0].name,
extension: files[0].extension // 新增扩展名
}
: null
}
// 如果是URL字符串直接使用 convertFilePathsToObject 处理
else if (typeof fileStr === 'string') {
const files = convertFilePathsToObject(fileStr)
return files && files.length > 0
? {
url: files[0].url,
name: files[0].name,
extension: files[0].extension // 新增扩展名
}
: null
}
return null
} catch (e) {
console.error('解析文件信息失败:', e)
return null
}
}
export function deepCloneByJSON(obj: any) {
try {
return JSON.parse(JSON.stringify(obj))
} catch (error) {
console.error('深拷贝失败:', error)
return obj
}
}
/**
* 将 ISO 8601 时间格式转换为指定格式
* @param isoString ISO 8601 格式的时间字符串,如 "2026-02-28T14:10:51.966269"
* @param format 格式化模板,默认 'YYYY-MM-DD HH:mm:ss'
* @returns 格式化后的时间字符串
*
* @example
* formatISOToDateTime('2026-02-28T14:10:51.966269') // '2026-02-28 14:10:51'
* formatISOToDateTime('2026-02-28T14:10:51.966269', 'YYYY-MM-DD') // '2026-02-28'
* formatISOToDateTime('2026-02-28T14:10:51.966269', 'YYYY/MM/DD HH:mm') // '2026/02/28 14:10'
* formatISOToDateTime('2026-02-28T14:10:51.966269', 'MM-DD HH:mm') // '02-28 14:10'
* formatISOToDateTime('2026-02-28T14:10:51.966269', 'YYYY 年 MM 月 DD 日') // '2026 年 02 月 28 日'
*/
export function formatISOToDateTime(isoString: string, format = 'YYYY-MM-DD HH:mm:ss'): string {
if (!isoString) return ''
try {
const date = new Date(isoString)
// 检查日期是否有效
if (isNaN(date.getTime())) {
console.warn('无效的日期格式:', isoString)
return isoString
}
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
// 替换格式化模板中的占位符
return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds)
} catch (error) {
console.error('日期格式化错误:', error)
return isoString
}
}
export function isString(value: any): boolean {
return typeof value === 'string'
}
export function isFile(obj: any): obj is File {
return obj instanceof File
}
// JSON验证
export function isValidJson(str: string): boolean {
try {
JSON.parse(str)
return true
} catch (e) {
return false
}
}
export function isValidFormat(data: any): boolean {
let parsedData = data
// 如果输入是字符串,尝试解析为 JSON
if (typeof data === 'string') {
try {
parsedData = JSON.parse(data)
} catch (e) {
return false // JSON 解析失败,直接返回 false
}
}
// 检查是否为数组
if (!Array.isArray(parsedData)) {
return false
}
// 检查数组中的每个元素
return parsedData.every((item) => {
// 检查是否为对象且不为 null
if (typeof item !== 'object' || item === null) {
return false
}
// 检查必需的属性是否存在,且类型是否正确
const hasIndex = typeof item.index === 'number'
const hasName = typeof item.name === 'string'
const hasIdNumber = typeof item.idNumber === 'string'
return hasIndex && hasName && hasIdNumber
})
}
/**
* 比较当前时间与指定时间(精确到秒)
* @param timeParam - 要比较的时间参数支持日期字符串、时间戳或Date对象
* @returns 当前时间小于timeParam时返回true否则返回false
*/
export function isCurrentTimeLessThan(timeParam: string | number | Date): boolean {
// 将传入的时间参数转换为Date对象
const paramTime = new Date(timeParam)
// 获取当前时间
const currentTime = new Date()
// 检查时间参数是否有效
if (isNaN(paramTime.getTime())) {
throw new Error('Invalid time parameter provided')
}
// 比较时间(精确到秒):当前时间 < 参数时间 返回true否则返回false
return Math.floor(currentTime.getTime() / 1000) < Math.floor(paramTime.getTime() / 1000)
}