first commit
This commit is contained in:
295
src/utils/index.js
Normal file
295
src/utils/index.js
Normal file
@@ -0,0 +1,295 @@
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
// 设置dayjs语言
|
||||
dayjs.locale('zh-cn')
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
* @param {Date|string} date 日期
|
||||
* @param {string} format 格式
|
||||
* @returns {string} 格式化后的日期字符串
|
||||
*/
|
||||
export const formatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
|
||||
if (!date) return ''
|
||||
return dayjs(date).format(format)
|
||||
}
|
||||
|
||||
/**
|
||||
* 相对时间
|
||||
* @param {Date|string} date 日期
|
||||
* @returns {string} 相对时间字符串
|
||||
*/
|
||||
export const fromNow = (date) => {
|
||||
if (!date) return ''
|
||||
return dayjs(date).fromNow()
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号格式化
|
||||
* @param {string} phone 手机号
|
||||
* @returns {string} 格式化后的手机号
|
||||
*/
|
||||
export const formatPhone = (phone) => {
|
||||
if (!phone) return ''
|
||||
return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额格式化
|
||||
* @param {number} amount 金额
|
||||
* @param {number} decimals 小数位数
|
||||
* @returns {string} 格式化后的金额
|
||||
*/
|
||||
export const formatMoney = (amount, decimals = 2) => {
|
||||
if (amount === null || amount === undefined) return '0.00'
|
||||
return Number(amount).toFixed(decimals)
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件大小格式化
|
||||
* @param {number} bytes 字节数
|
||||
* @returns {string} 格式化后的文件大小
|
||||
*/
|
||||
export const formatFileSize = (bytes) => {
|
||||
if (bytes === 0) return '0 B'
|
||||
const k = 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param {Function} func 要防抖的函数
|
||||
* @param {number} wait 等待时间
|
||||
* @returns {Function} 防抖后的函数
|
||||
*/
|
||||
export const debounce = (func, wait) => {
|
||||
let timeout
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout)
|
||||
func(...args)
|
||||
}
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(later, wait)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* @param {Function} func 要节流的函数
|
||||
* @param {number} limit 限制时间
|
||||
* @returns {Function} 节流后的函数
|
||||
*/
|
||||
export const throttle = (func, limit) => {
|
||||
let inThrottle
|
||||
return function() {
|
||||
const args = arguments
|
||||
const context = this
|
||||
if (!inThrottle) {
|
||||
func.apply(context, args)
|
||||
inThrottle = true
|
||||
setTimeout(() => inThrottle = false, limit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝
|
||||
* @param {any} obj 要拷贝的对象
|
||||
* @returns {any} 拷贝后的对象
|
||||
*/
|
||||
export const deepClone = (obj) => {
|
||||
if (obj === null || typeof obj !== 'object') return obj
|
||||
if (obj instanceof Date) return new Date(obj.getTime())
|
||||
if (obj instanceof Array) return obj.map(item => deepClone(item))
|
||||
if (typeof obj === 'object') {
|
||||
const clonedObj = {}
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
clonedObj[key] = deepClone(obj[key])
|
||||
}
|
||||
}
|
||||
return clonedObj
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成UUID
|
||||
* @returns {string} UUID字符串
|
||||
*/
|
||||
export const generateUUID = () => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0
|
||||
const v = c == 'x' ? r : (r & 0x3 | 0x8)
|
||||
return v.toString(16)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机号
|
||||
* @param {string} phone 手机号
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
export const validatePhone = (phone) => {
|
||||
const phoneRegex = /^1[3-9]\d{9}$/
|
||||
return phoneRegex.test(phone)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邮箱
|
||||
* @param {string} email 邮箱
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
export const validateEmail = (email) => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return emailRegex.test(email)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证身份证号
|
||||
* @param {string} idCard 身份证号
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
export const validateIdCard = (idCard) => {
|
||||
const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
|
||||
return idCardRegex.test(idCard)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取URL参数
|
||||
* @param {string} name 参数名
|
||||
* @returns {string|null} 参数值
|
||||
*/
|
||||
export const getUrlParam = (name) => {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
return urlParams.get(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置URL参数
|
||||
* @param {string} name 参数名
|
||||
* @param {string} value 参数值
|
||||
*/
|
||||
export const setUrlParam = (name, value) => {
|
||||
const url = new URL(window.location)
|
||||
url.searchParams.set(name, value)
|
||||
window.history.replaceState({}, '', url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除URL参数
|
||||
* @param {string} name 参数名
|
||||
*/
|
||||
export const removeUrlParam = (name) => {
|
||||
const url = new URL(window.location)
|
||||
url.searchParams.delete(name)
|
||||
window.history.replaceState({}, '', url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文本到剪贴板
|
||||
* @param {string} text 要复制的文本
|
||||
* @returns {Promise<boolean>} 是否复制成功
|
||||
*/
|
||||
export const copyToClipboard = async (text) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
return true
|
||||
} catch (err) {
|
||||
// 降级方案
|
||||
const textArea = document.createElement('textarea')
|
||||
textArea.value = text
|
||||
document.body.appendChild(textArea)
|
||||
textArea.select()
|
||||
try {
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(textArea)
|
||||
return true
|
||||
} catch (err) {
|
||||
document.body.removeChild(textArea)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param {string} url 文件URL
|
||||
* @param {string} filename 文件名
|
||||
*/
|
||||
export const downloadFile = (url, filename) => {
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = filename
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器信息
|
||||
* @returns {object} 浏览器信息
|
||||
*/
|
||||
export const getBrowserInfo = () => {
|
||||
const ua = navigator.userAgent
|
||||
const browser = {
|
||||
name: '',
|
||||
version: '',
|
||||
os: ''
|
||||
}
|
||||
|
||||
// 检测浏览器
|
||||
if (ua.includes('Chrome')) {
|
||||
browser.name = 'Chrome'
|
||||
} else if (ua.includes('Firefox')) {
|
||||
browser.name = 'Firefox'
|
||||
} else if (ua.includes('Safari')) {
|
||||
browser.name = 'Safari'
|
||||
} else if (ua.includes('Edge')) {
|
||||
browser.name = 'Edge'
|
||||
} else if (ua.includes('MSIE') || ua.includes('Trident')) {
|
||||
browser.name = 'IE'
|
||||
}
|
||||
|
||||
// 检测操作系统
|
||||
if (ua.includes('Windows')) {
|
||||
browser.os = 'Windows'
|
||||
} else if (ua.includes('Mac')) {
|
||||
browser.os = 'Mac'
|
||||
} else if (ua.includes('Linux')) {
|
||||
browser.os = 'Linux'
|
||||
} else if (ua.includes('Android')) {
|
||||
browser.os = 'Android'
|
||||
} else if (ua.includes('iOS')) {
|
||||
browser.os = 'iOS'
|
||||
}
|
||||
|
||||
return browser
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为移动设备
|
||||
* @returns {boolean} 是否为移动设备
|
||||
*/
|
||||
export const isMobile = () => {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为微信浏览器
|
||||
* @returns {boolean} 是否为微信浏览器
|
||||
*/
|
||||
export const isWeChat = () => {
|
||||
return /MicroMessenger/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为支付宝浏览器
|
||||
* @returns {boolean} 是否为支付宝浏览器
|
||||
*/
|
||||
export const isAlipay = () => {
|
||||
return /AlipayClient/i.test(navigator.userAgent)
|
||||
}
|
||||
Reference in New Issue
Block a user