2025-06-26 17:04:17 +08:00

336 lines
9.2 KiB
JavaScript

import { isMatch, snakeCase, toUpper, cloneDeep, keys, pick } from 'lodash-es'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
/**
* 数据映射
* @param {array} data 数据源
* @param {object} fieldNames 自定义节点
* @param {object} expand 拓展数据
* @param {string} treeFieldName 子节点,如果是树型结构,传入树型结构的子节点对应的字典名
* @param {boolean} keepOtherFields 保留其他字段
* @returns {array}
*/
export const mapping = ({ data, fieldNames = {}, expand = {}, treeFieldName, keepOtherFields = false }) => {
let result = []
if (!Array.isArray(data)) return []
if (!fieldNames) return data
data.forEach((item, index, array) => {
let temp = keepOtherFields ? { ...item } : {},
record,
filedValue
if (treeFieldName) {
delete temp[treeFieldName]
}
for (let filedKey in fieldNames) {
filedValue = fieldNames[filedKey]
record = item[filedValue]
if (filedValue === treeFieldName) {
// 树结构
if (record && record.length) {
const child = mapping({
data: item[treeFieldName],
fieldNames,
expand,
treeFieldName,
keepOtherFields,
})
if (child && child.length) {
temp[filedKey] = child
}
}
} else if (filedValue instanceof Function) {
// 函数
temp[filedKey] = filedValue(item, index, array)
} else {
temp[filedKey] = typeof record !== 'undefined' && record !== '' ? record : ''
}
}
temp = expand ? { ...temp, ...expand } : temp
result.push(temp)
})
return result
}
/**
* 从树型结构中查找对应数据
* @param {array } data
* @param {string | object} value
* @param {function} callback
* @param {object} fieldNames
* @param {array} path
*/
export const findTree = (data, value, callback, fieldNames = { key: 'id', children: 'children' }, path = []) => {
data.forEach((item, index, array) => {
if (isObject(value) ? isMatch(item, value) : item[fieldNames.key] === value) {
return callback(item, index, array, [...path, item])
}
if (item[fieldNames.children]) {
return findTree(item[fieldNames.children], value, callback, fieldNames, [...path, item])
}
})
}
/**
* 数组最深层级
* 查找一个树型结构最多有几级
* @param data
* @param fieldNames
* @return {number}
*/
export const deep = (data, fieldNames = { children: 'children' }) => {
let result = 1
data.forEach((item) => {
const child = item[fieldNames.children] || []
if (child.length) {
let temp = deep(child, fieldNames) + 1
result = temp > result ? temp : result
}
})
return result
}
/**
* 深度合并
* @param object
* @param sources
* @return {*}
*/
export const deepMerge = (object, sources) => {
let key
for (key in sources) {
object[key] =
object[key] && object[key].toString() === '[object Object]'
? deepMerge(object[key], sources[key])
: (object[key] = sources[key])
}
return object
}
/**
* 时间段前缀
* @returns
*/
export const timeFix = () => {
const time = new Date()
const hour = time.getHours()
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}
/**
* 数组合并为对象
* @param {array} keys
* @param {array} values
* @param {function | array} funcs
* @return {{}}
*/
export const zipObjectPlus = (keys = [], values = [], funcs) => {
const result = {}
if (Array.isArray(keys) && Array.isArray(values)) {
keys.forEach((key, index) => {
const func = Array.isArray(funcs) ? funcs[index] : funcs
result[key] =
Object.prototype.toString.call(func) === '[object Function]' ? func(values[index]) : values[index]
})
}
return result
}
/**
* 获取环境变量
* @param {string} key
* @returns
*/
export const env = (key, def = null) => {
const value = import.meta.env[`VITE_${toUpper(snakeCase(key))}`] || def
if (['true', 'false'].includes(value)) {
return Boolean(value)
}
return value
}
/**
* 树形结构转线形结构
* @param {array} data
* @param {object} fieldNames
* @return {*[]}
*/
export const toList = (data = [], fieldNames = { children: 'children' }) => {
let result = []
if (!Array.isArray(data)) return result
data.forEach((item) => {
let temp = []
result.push(item)
if (item[fieldNames.children] && item[fieldNames.children].length) {
let children = toList(item[fieldNames.children], fieldNames)
if (children.length) {
temp = children
}
}
result.push(...temp)
})
return result
}
/**
* 线形数据转树形数据
* @param {array} data
* @param {string | number} parentValue
* @param {object} fieldNames
* @return {*[]}
*/
export const toTree = (
data = [],
parentValue = '0',
fieldNames = {
key: 'id',
children: 'children',
parentKey: 'parentId',
}
) => {
const result = []
data.forEach((item) => {
if (item[fieldNames.parentKey] === parentValue) {
let temp = item
let children = toTree(data, item[fieldNames.key])
if (children.length) {
temp[fieldNames.children] = children
}
result.push(temp)
}
})
return result
}
/**
* 线形数据转 菜单树形数据
* @param {array} data
* @param {string | number} parentValue
* @param {object} fieldNames
* @return {*[]}
*/
export const toMenuTree = (data = []) => {
const result = []
data.forEach((item) => {
let temp = {
title: item.code,
key: item.id,
}
if (item.children && item.children.length) {
let children = toMenuTree(item.children)
temp['children'] = children || []
}
result.push(temp)
})
return result
}
/**
* 格式化日期
* @param dateTime {Date} 日期
* @param def {*} 默认值
* @return {string}
*/
export const formatDateTime = (dateTime, def = null) => (dateTime ? dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss') : def)
/**
* 格式化utc日期
* @param dateTime {Date} 日期
* @return {string}
*/
export const formatUtcDateTime = (dateTime, type = 'local') => {
dayjs.extend(utc)
if (type === 'local') {
// 传入local则将UTC时间转换为本地时间
return dayjs.utc(dateTime).local().format('YYYY-MM-DD HH:mm:ss')
} else if (type === 'UTC') {
// 传入UTC则将时间转换为UTC时间
return dayjs(dateTime).utc().format()
}
}
/**
* 格式化一天的开始时间
* @param dateTime
* @param def
* @return {string}
*/
export const formatStartTimeOfDay = (dateTime, def = null) =>
dateTime ? dayjs(dateTime).startOf('day').format('YYYY-MM-DD HH:mm:ss') : def
/**
* 格式化一天的结束时间
* @param dateTime
* @param def
* @return {string}
*/
export const formatEndTimeOfDay = (dateTime, def = null) =>
dateTime ? dayjs(dateTime).endOf('day').format('YYYY-MM-DD HH:mm:ss') : def
/**
* 格式化字段,无数据是返回自定义空值
* @param data
* @param def
* @returns {string}
*/
export const formatField = (data, def = '-') => data ?? def
/**
* 格式化时间区间
* @param {array} keys
* @param {array} values
* @return {{}}
*/
export const formatRangeTime = (keys, values) => zipObjectPlus(keys, values, [formatStartTimeOfDay, formatEndTimeOfDay])
/**
* 文件后缀
*/
export const suffix = (filename) => filename.split('.').pop().toLowerCase()
/**
* 获取表单数据
* 根据表单字段从行数据中获取对应的数据,用于回填表单
* @param {object} record
* @param {object} formData
*/
export const getformData = (record = {}, formData = {}) => pick(cloneDeep(record), keys(formData) || []) || {}
/**
* 获取静态文件 url
* @param {string} url
* @returns
*/
export const assets = (url) => {
return new URL(`../assets/${url}`, import.meta.url).href
}
/**
* 是否 url
* @param {string} value
*/
export const isUrl = (value) => new RegExp('^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s]+', 'g').test(value)
/**
* 是否 object
*/
export const isObject = (value) => '[object Object]' === Object.prototype.toString.call(value)
export const myTrim = (str, char, type = 'right') => {
if (char) {
if (type === 'left') {
return str.replace(new RegExp('^\\' + char + '+', 'g'), '')
} else if (type === 'right') {
return str.replace(new RegExp('\\' + char + '+$', 'g'), '')
}
return str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '')
}
return str.replace(/^\s+|\s+$/g, '')
}
/**截取图片路径域名部分 */
export const spliceUrl=(fullUrl)=>{
if(!fullUrl) return null
const pathOnly = fullUrl.replace(/^https?:\/\/[^\/]+/, '');
return pathOnly
}