类型转换
arrayToTree
数组转树结构
typescript
interface IParams {
arr: any[]
idKey?: string
parentKey?: string
childrenKey?: string
rootId?: string | number
}
/**
* 数组转树结构
* @param params
* @returns
*/
export function arrayToTree(params: IParams) {
const { arr, idKey = 'id', parentKey = 'pid', childrenKey = 'children', rootId = null } = params
const result: any[] = []
const itemMap: Record<string, any> = {}
for (const item of arr) {
const id = item[idKey]
const pid = item[parentKey]
if (!itemMap[id]) {
itemMap[id] = {
[childrenKey]: [],
}
}
itemMap[id] = {
...item,
children: itemMap[id][childrenKey],
}
const treeItem = itemMap[id]
if (pid === rootId) {
result.push(treeItem)
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
}
}
itemMap[pid].children.push(treeItem)
}
}
return result
}
/**
* const { arr, idKey = 'id', parentKey = 'pid', childrenKey = 'children', rootId = 0 } = params;
*/
const arr = [
{ id: 1, name: '部门1', pid: 0 },
{ id: 2, name: '部门2', pid: 1 },
{ id: 3, name: '部门3', pid: 1 },
{ id: 4, name: '部门4', pid: 3 },
{ id: 5, name: '部门5', pid: 4 },
]
const tree = arrayToTree({ arr })
/**
* [
{
id: 1,
name: '部门1',
pid: 0,
children: [
{
id: 2,
name: '部门2',
pid: 1,
children: [],
},
{
id: 3,
name: '部门3',
pid: 1,
children: [
// 结果 ,,,
],
},
],
},
];
*/
treeToList
树结构转数组
typescript
export function treeToList(tree) {
let list = []
function traverse(node) {
list.push(node)
if (node.children && node.children.length > 0) {
for (let child of node.children) {
traverse(child)
}
}
}
for (let root of tree) {
traverse(root)
}
return list
}
base64ToBlob
base64 转 Blob 对象
typescript
/**
*
* @param { string } s base64
* @returns Blob
*/
export function base64ToBlob(s: string): Blob {
const arr = s.split(',')
const mime = arr[0]?.match(/:(.*?);/)?.[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) u8arr[n] = bstr.charCodeAt(n)
return new Blob([u8arr], { type: mime })
}
base64ToBlob('base64')
base64ToFile
base64 转 File 对象
typescript
/**
*
* @param { string } s base64
* @param { string } filename 文件名
* @returns
*/
export function base64ToFile(s: string, filename: string): File {
const arr = s.split(',')
const mime = arr[0]?.match(/:(.*?);/)?.[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) u8arr[n] = bstr.charCodeAt(n)
return new File([u8arr], filename, { type: mime })
}
base64ToFile('base64', '文件名')
blobToUrl
Blob 转为 url
typescript
/**
* Blob转为url
* @param { Blob } blob Blob
* @returns url
*/
export function blobToUrl(blob: Blob) {
return window.URL.createObjectURL(blob)
}
blobToUrl(Blob)
fileToArrayBuffer
文件转 buffer
typescript
/**
* 文件转buffer
* @param { File } file 文件
* @returns
*/
export function fileToArrayBuffer(file: File): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = function () {
const arrayBuffer = new Uint8Array(reader.result as any)
resolve(arrayBuffer)
}
reader.onerror = reject
reader.readAsArrayBuffer(file)
})
}
fileToArrayBuffer(File)
fileToBlob
File 文件转为 Blob
typescript
/**
* File文件转为Blob
* @param { File } file 文件
* @returns Blob
*/
export async function fileToBlob(file: File) {
function fileToArrayBuffer(file: File): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = function () {
const arrayBuffer = new Uint8Array(reader.result as any)
resolve(arrayBuffer)
}
reader.onerror = reject
reader.readAsArrayBuffer(file)
})
}
const buffer = await fileToArrayBuffer(file)
const blob = new Blob([buffer], { type: 'application/pdf;chartset=UTF-8' })
return blob
}
fileToBlob(File)
hexToRgb
hex 转 rgba
typescript
/**
* hex 转rgba
* @example console.log(hexToRgb('#ffffff')) // rgb(255,255,255)
* @param hex
* @param opacity
* @returns
*/
export function hexToRgb(hex: string, opacity?: number) {
const l = 7 - hex.length
if (l > 0) hex = hex + hex.slice(-1).repeat(l)
if (l < 0) throw new Error('hex length > 7')
const result = `${parseInt(`0x${hex.slice(1, 3)}`)},${parseInt(`0x${hex.slice(3, 5)}`)},${parseInt(
`0x${hex.slice(5, 7)}`
)}`
return opacity ? `rgba(${result},${opacity})` : `rgb(${result})`
}
hexToRgb('#ffffff') // rgb(255,255,255)
rgbToHex
rgb 转 Hex
typescript
/**
* rgb转Hex
* @example console.log(rgbToHex('rgb(255,255,255)')) // #ffffff
* @param style
* @returns
*/
export function rgbToHex(style: string) {
type TrimType = 'all' | 'pre' | 'around' | 'post'
function trim(s: string, type: TrimType = 'around'): string {
if (type === 'pre') return s.replace(/(^\s*)/g, '')
if (type === 'post') return s.replace(/(\s*$)/g, '')
if (type === 'all') return s.replace(/\s+/g, '')
if (type === 'around') return s.replace(/(^\s*)|(\s*$)/g, '')
return s
}
const reg = /rgb\(([\w\s,]+)\)/
const matcher = style.match(reg)
if (!matcher) return
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, color] = matcher
const [r, g, b] = trim(color, 'all').split(',')
return `#${((1 << 24) + (+r << 16) + (+g << 8) + +b).toString(16).slice(1)}`
}
rgbToHex('rgb(255,255,255)') // #ffffff
toArray
如果是数组直接返回否则封装成数组
typescript
/**
* 如果是数组直接返回否则封装成数组
* @param { any } array
* @returns
*/
export function toArray(array: any) {
return Array.isArray(array) ? array : [array]
}
toArray(1) // [1]
toNumber
转换成数字
typescript
/**
* 转换成数字
* @param { number | string | boolean | undefined | null } val
* @returns 数字
*/
export const toNumber = (val: number | string | boolean | undefined | null): number => {
function isString(o: any): o is string {
return typeof o === 'string'
}
function isBool(value: any): value is boolean {
return typeof value === 'boolean'
}
if (val == null) return 0
if (isString(val)) {
val = parseFloat(val)
val = Number.isNaN(val) ? 0 : val
return val
}
if (isBool(val)) return Number(val)
return val
}
toNumber('111') // 111
byteToFileSize
将字节转换为合理的容量单位
typescript
/**
* 将字节转换为合理的容量单位
* @param bytes
* @returns
*/
export function byteToFileSize(bytes: number) {
let BYTES = bytes
const thresh = 1024
if (Math.abs(BYTES) < thresh) {
return `${BYTES} B`
}
const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
let u = -1
const r = 10 ** 1
do {
BYTES /= thresh
u += 1
} while (Math.round(Math.abs(BYTES) * r) / r >= thresh && u < units.length - 1)
return `${BYTES.toFixed(1)} ${units[u]}`
}
byteToFileSize(1024000000) // 976.6 MB
toAbsolutePath
将相对路径转换为绝对路径
typescript
import process from 'process'
import path from 'path'
/**
*
* @param { string } url 路径
* @returns 绝对路径
*/
export function toAbsolutePath(url: string): string {
function isAbsolute(url: string): boolean {
return /^\/|^\\|^[a-zA-Z]:[/\\]/.test(url)
}
return isAbsolute(url) ? url : path.resolve(process.cwd(), url)
}
toAbsolutePath('/a/b/c') // http://localhost:8080/a/b/c
toObject
将数组转换成对象
typescript
export function toObject(arr: Array<any>, filter?: string[]): object {
function isPlainObject(o: any): o is Record<any, any> {
return Object.prototype.toString.call(o) === '[object Object]'
}
return arr.reduce(
(result, item) =>
!isPlainObject(item)
? result
: Object.keys(item).reduce((result, key) => {
if (filter && !filter.includes(key)) return result
if (!result[key]) result[key] = []
result[key].push(item[key])
return result
}, result),
{} as Record<string, any>
)
}
/**
* @param { Array<any> } arr 数组
* @param { string[] = [] } filter 保留filter中的key
* @return { boolean }
*/
const arr = [
{
a: 1,
},
{
a: 3,
3: 5,
},
]
const data = toObject(arr, ['a']) // { a: [ 1, 3 ] }