123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- import lodashCloneDeep from 'lodash-es/cloneDeep'
- /**
- * @function 深拷贝
- * @param value {*}
- * @return {*}
- */
- export const cloneDeep = (value) => {
- return lodashCloneDeep(value)
- }
- /**
- * @function 2个对象值进行比较
- * @param objectA
- * @param objectB
- * @return {boolean}
- */
- export const objectEqual = (objectA = {}, objectB = {}) => {
- if (objectA === objectB) return true
- const keysA = Object.keys(objectA)
- const keysB = Object.keys(objectB)
- if (keysA.length !== keysB.length) return false
- const keysLength = keysA.length
- for (let i = 0; i < keysLength; i++) {
- const keyA = keysA[i]
- if (!keysB.includes(keyA)) return false
- const valueA = objectA[keyA]
- const valueB = objectB[keyA]
- if (typeof valueA === 'object' && typeof valueB === 'object') {
- if (!objectEqual(valueA, valueB)) return false
- } else {
- if (valueA !== valueB) return false
- }
- }
- // 排除所有不想等的情况
- return true
- }
- /**
- * 节流
- * @param fn {Function} 方法
- * @param delay {Number} 延迟执行时间
- * @return {function(): void}
- */
- export function throttle (fn, delay) {
- let pre = 0
- return function () {
- const args = arguments
- const now = Date.now()
- if (now - pre > delay) {
- pre = now
- fn.apply(this, args)
- }
- }
- }
- /**
- *
- * @param fn
- * @param wait
- * @param immediate
- * @return {function(): *}
- */
- export const debounce = (fn, wait, immediate) => {
- let timeout, result
- const debounced = function () {
- const context = this
- const args = arguments
- if (timeout) clearTimeout(timeout)
- if (immediate) {
- // 如果已经执行过,不再执行
- const callNow = !timeout
- timeout = setTimeout(() => {
- timeout = null
- }, wait)
- if (callNow) result = fn.apply(context, args)
- } else {
- timeout = setTimeout(() => {
- fn.apply(context, args)
- }, wait)
- }
- return result
- }
- debounced.cancel = () => {
- clearTimeout(timeout)
- timeout = null
- }
- return debounced
- }
- /**
- * 大写第一位字符串
- * @param str {String} 字符串
- * @return {string}
- */
- export const toUpperFirstCase = (str) => {
- const first = str.charAt(0)
- const upperFirst = first.toUpperCase()
- return upperFirst + str.slice(1)
- }
- /**
- * 平铺数组转换为树状结构
- * @param list {Array} 数组列表
- * @param parentKey {String} 父节点名称
- * @param root {Number} 根节点值
- * @return {boolean}
- */
- export const toTreeData = (list, parentKey = 'parentId', root = 0) => {
- const cloneData = cloneDeep(list)
- const tree = cloneData.filter((father) => {
- const branchArr = cloneData.filter((child) => {
- return father.id === child[parentKey]
- })
- if (branchArr.length > 0) {
- father.children = branchArr
- }
- return father[parentKey] === root
- })
- tree.forEach(row => {
- row[parentKey] = ''
- })
- return tree
- }
- /**
- * 判断值是否为undefined或null
- * @param value {*} 待判断值
- * @return {boolean}
- */
- export const isEmpty = (value) => {
- return value === undefined || value === null
- }
- /**
- * 判断值是否为undefined或null或空字符串
- * @param value {*} 待判断值
- * @return {boolean}
- */
- export const isInputEmpty = (value) => {
- return value === undefined || value === null || value === ''
- }
- /**
- * 判断值是否不为undefined或null
- * @param value {*} 待判断值
- * @return {boolean}
- */
- export const isNotEmpty = (value) => {
- return !isEmpty(value)
- }
- /**
- * 是否为没有空对象
- * @param value {Object} 待判断对象
- * @return {boolean}
- */
- export const isEmptyObject = (value) => {
- return Object.keys(value).length === 0
- }
- /**
- * 判断值是否为数组
- * @param value {*}
- * @return {boolean}
- */
- export const isArray = (value) => {
- return Object.prototype.toString.call(value) === '[object Array]'
- }
- /**
- * 判断是否对象
- * @param value
- * @return {boolean}
- */
- export const isObject = (value) => {
- return Object.prototype.toString.call(value) === '[object Object]'
- }
- /**
- * 判断是否为字符串
- * @param value
- * @return {boolean}
- */
- export const isString = (value) => {
- return Object.prototype.toString.call(value) === '[object String]'
- }
- /**
- * 判断是否为数字
- * @param value
- * @return {boolean}
- */
- export const isNumber = (value) => {
- return Object.prototype.toString.call(value) === '[object Number]'
- }
- /**
- * 判断值是否为JSON String
- * @param value
- * @return {boolean}
- */
- export const isJson = (value) => {
- try {
- const obj = JSON.parse(value)
- return !!(typeof obj === 'object' && obj)
- } catch (e) {
- return false
- }
- }
- /**
- * 下载文件
- * @param href {String} base64地址或远程地址
- * @param filename {String} 文件名
- */
- export const downloadFile = (href, filename) => {
- if (href && filename) {
- const a = document.createElement('a')
- a.download = filename // 指定下载的文件名
- a.href = href // URL对象
- a.click() // 模拟点击
- URL.revokeObjectURL(a.href) // 释放URL 对象
- }
- }
- /**
- * 删除一条数据后返回下一条数据
- * @param itemList 列表
- * @param index 待删除数据
- * @return {{}}
- */
- export const getNextItem = (itemList, index) => {
- let result = {}
- if (index === itemList.length - 1) {
- if (index !== 0) {
- result = itemList[index - 1]
- }
- } else {
- result = itemList[index + 1]
- }
- return result
- }
- /**
- * @description: 耗时格式化
- * @param {*} time 毫秒
- * @return {*} timeStr eg: 22时22分22秒
- */
- export const durationTimeFormat = (time) => {
- if (!time && typeof time !== 'number') return ''
- const result = []
- const seconds = Math.ceil(time / 1000)
- const minutes = Math.floor(seconds / 60)
- const hours = Math.floor(minutes / 60)
- const days = Math.floor(hours / 24)
- const months = Math.floor(days / 30)
- const years = Math.floor(months / 12)
- if (years) {
- result.push(years + '年')
- }
- if (months % 12) {
- result.push(months % 12 + '月')
- }
- if (days % 365 % 30) {
- result.push(days % 365 % 30 + '天')
- }
- if (hours % 24) {
- result.push(hours % 24 + '小时')
- }
- if (minutes % 60) {
- result.push(minutes % 60 + '分')
- }
- if (seconds % 60) {
- result.push(seconds % 60 + '秒')
- }
- return result.join('')
- }
- /**
- * 根据url获取query中key对应的值
- * @param key
- * @param url
- * @return {string|null}
- */
- export const getQueryString = (key, url) => {
- if (isEmpty(url)) url = window.location.href
- const reg = new RegExp('(^|&|\\?)' + key + '=([^&]*)(&|$|#)', 'i')
- const r = url.match(reg)
- if (r != null) return decodeURIComponent(r[2])
- return null
- }
- /**
- * 拼接url和query的值
- * @param url String
- * @param query Object
- * @return {string}
- */
- export const setUrlQuery = (url, query) => {
- if (!url) return ''
- if (query) {
- const queryArray = []
- // eslint-disable-next-line
- for (const key in query) {
- if (Object.prototype.hasOwnProperty.call(query, key)) {
- queryArray.push(`${key}=${query[key]}`)
- }
- }
- if (url.includes('?')) {
- url = `${url}&${queryArray.join('&')}`
- } else {
- url = `${url}?${queryArray.join('&')}`
- }
- }
- return url
- }
- export const getLabelByValue = (value, options, optionProps) => {
- return options.find(option => option[optionProps.value] === value)?.[optionProps.label]
- }
- export const getFieldValue = (target, propertyName) => {
- if (isNotEmpty(propertyName)) {
- const keys = propertyName.split('.')
- for (let i = 0; i < keys.length; i++) {
- if (i === keys.length - 1 && isNotEmpty(target[keys[i]])) {
- return target[keys[i]]
- } else if (isObject(target[keys[i]])) {
- target = target[keys[i]]
- } else if (isArray(target[keys[i]])) {
- if (isNaN(Number(keys[i]))) target = target[keys[i]]
- } else {
- return undefined
- }
- }
- } else {
- return undefined
- }
- }
- /**
- * 向对象添加一个property
- * @param target {Object} 目标对象
- * @param propertyName {String} 属性名
- * @param value
- */
- export const setFieldValue = (target, propertyName, value, hasArray = false) => {
- if (isNotEmpty(propertyName)) {
- const keys = propertyName.split('.')
- const len = keys.length - 1
- keys.reduce((cur, key, index) => {
- if (index < len) {
- if (!cur[key]) {
- // 判断下一个key是否为数字
- if (hasArray && !isNaN(Number(keys[index + 1]))) {
- cur[key] = []
- } else {
- cur[key] = {}
- }
- }
- }
- if (index === len) {
- cur[key] = value
- }
- return cur[key]
- }, target)
- }
- }
- /**
- * 判断值是否为Map类型
- * @param value
- * @return {boolean}
- */
- const isMap = (value) => {
- return value instanceof Map
- }
- /**
- * 根据key获取mapping中的value
- * @param key
- * @param mapping
- * @return {*}
- */
- export const getValueByKey = (key, mapping) => {
- if (isMap(mapping)) {
- return mapping.get(key)
- } else {
- return mapping[key]
- }
- }
- /**
- * 根据value获取mapping中的key
- * @param value
- * @param mapping
- * @return {string|*}
- */
- export const getKeyByValue = (value, mapping) => {
- if (isMap(mapping)) {
- // eslint-disable-next-line no-unused-vars
- for (const [key, mapValue] of mapping) {
- if (mapValue === value) {
- return key
- }
- }
- } else {
- // eslint-disable-next-line no-unused-vars
- for (const key in mapping) {
- if (mapping[key] === value) {
- return key
- }
- }
- }
- }
- /**
- * 值根据映射关系和方向进行转换
- * @param value {*} 待转换值
- * @param mapping {Object} 映射关系
- * @param type {String} 转换方向 form-转为值 to-转为键
- */
- export const getValueMapping = (value, mapping = {}, valueType) => {
- let result
- if (valueType === 'value') {
- // form 此时 value 为 value
- Object.keys(mapping).forEach(key => {
- const mapValue = mapping[key]
- if (mapValue === value) {
- result = key
- }
- })
- // 未找到映射关系返回原值
- } else {
- // form 此时 value 为 key
- const mapValue = mapping[value]
- if (isNotEmpty(mapValue)) {
- result = mapValue
- }
- }
- return result
- }
- export const depthFirstSearchTree = (tree, value, key, children = 'children', depth = 0) => {
- depth++
- if (!tree) return
- if (getFieldValue(tree, key) === value) {
- const { children, ...useObject } = tree
- return [useObject]
- }
- // 最深至搜索10层
- if (depth > 9) return
- if (!tree[children]) return
- const loop = tree[children].length
- for (let i = 0; i < loop; i++) {
- const result = depthFirstSearchTree(tree[children][i], value, key, children, depth)
- if (result) {
- const { children, ...useObject } = tree
- result.unshift(useObject)
- return result
- }
- }
- }
- export const getUsingConfig = (...args) => {
- for (let i = 0; i < args.length; i++) {
- const value = args[i]
- if (isNotEmpty(value)) {
- return value
- }
- }
- }
- export const getEquipmentType = () => {
- if ((navigator.userAgent.match(/(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i))) {
- return 'mobile'
- } else {
- return 'pc'
- }
- }
- /**
- * 数字添加千分位分隔符
- * @param {Number} number 数字
- * @param {String} separator 分隔符
- * @return {string}
- */
- export const addThousandSeparator = (number, separator = '') => {
- const arr = (number + '').split('.')
- arr[0] = arr[0].replace(/(\d)(?=(?:\d{3})+$)/g, `$1${separator}`)
- return arr.join('.')
- }
- export const getValueByTemplate = (template, object) => {
- // 不能完全匹配template的数据 直接返回原始值
- if (typeof template !== 'string') {
- return template
- }
- return template?.replace(/\${([^}]+)}/g, (_, key) => {
- const val = getFieldValue(object, key)
- return isNotEmpty(val) ? val : `\${${key}}`
- })
- }
|