import { MenuProps, message } from "antd"; import { RcFile } from "antd/lib/upload"; import dayjs from 'dayjs'; // 排序这是比较函数 export const compare = (field: string, order: 'descend' | 'ascend') => { // descend 降序 大到小 ascend 升序 小到大 if (order === 'ascend') { return function (m: any, n: any) { var a = m[field]; var b = n[field]; return a - b; //升序 } } else { return function (m: any, n: any) { var a = m[field]; var b = n[field]; return b - a; //降序 } } } // 返回别名 export const getChannelName = (name: string) => { let newName = name let abridgeServer: string[] = ['知定', '巨网', '广联', '太古', '云广', '傲星', '弘捷', '开域'] let asName = abridgeServer.find((item: string) => name?.indexOf(item) !== -1) if (asName) { newName = asName } else if (newName?.length > 5) { newName = newName?.slice(2, 5) + '...' } return newName } // 输入文案时判断 export const txtLength = (value?: string) => { if (value) { let length = value?.length let text = value?.replace(/[\x00-\xff]/g, '') return text?.length * 3 + Number(((length - text?.length) / 2).toFixed()) + 3 } else { return 0 } } /** 获取base64 */ export const getBase64 = (file: RcFile, callback: (url: string) => void) => { const reader = new FileReader(); reader.addEventListener('load', () => callback(reader.result as string)); reader.readAsDataURL(file); }; /** 获取图片上传宽高 */ export const getImgSizeProper = (file: RcFile): Promise => { return new Promise((resolve: (value: any | PromiseLike) => void) => { let img: any = new Image(); let _URL = window.URL || window.webkitURL; img.onload = function (e: any) { resolve({ width: this.width, height: this.height }) } img.src = _URL.createObjectURL(file); }) } export const getImgSizeProperUrl = (url: string): Promise => { return new Promise((resolve: (value: any | PromiseLike) => void) => { let img: any = new Image(); let _URL = window.URL || window.webkitURL; img.onload = function (e: any) { resolve({ width: this.width, height: this.height }) } img.onerror = function () { resolve({ width: 100, height: 100 }) } img.src = url; }) } // 设置导航 type MenuItem = Required['items'][number]; export function getItem( label: React.ReactNode, key?: React.Key | null, icon?: React.ReactNode, children?: MenuItem[], ): MenuItem { let newChildren: MenuItem[] = [] if (children && children?.length > 0) { newChildren = children?.map((item: any, i: number) => { if (item.children?.length > 0) { return getItem(item?.title, item?.path, item?.icon, item.children) } return getItem(item?.title, item?.path, item?.icon) }) } return { key, icon, children: newChildren?.length > 0 ? newChildren : undefined, label } as MenuItem; } // 处理路由 export function getRouter(data: any): any { if (data) { let arr = Object.keys(data)?.filter(key => data[key]?.length > 0) let obj: any = {} arr.forEach(a => { obj[a] = data[a] }) let menus: any = Object.values(obj).sort((a: any, b: any) => { return a[0]?.orderNum - b[0]?.orderNum }) let menu: any = {} menus[0]?.forEach((item: { path: string, children: any[] }) => { let belongPlatform = item?.path?.replace('/', '') let newChildren: any[] = [] if (item?.children?.length > 0) { newChildren = getRouterItem(item?.children, belongPlatform) } menu[belongPlatform] = [{ ...item, belongPlatform, children: newChildren }] }); return menu } else { return {} } } // 处理子路由 export function getRouterItem(children: any[], belongPlatform: string): any[] { if (children?.length > 0) { return children.map((item: { children: any[] }) => { let newChildren: any[] = [] if (item?.children?.length > 0) { newChildren = getRouterItem(item?.children, belongPlatform) } return { ...item, belongPlatform, children: newChildren } }) } return [] } /** * 点击复制 *@param str 要复制的文字 *@param cb 将message 方法传进来可避免警告 * */ export const copy = (str: string, cb?: any) => { let element = document.createElement("textarea"); element.id = 'myTextarea' element.textContent = str document.body.append(element); (document.getElementById('myTextarea') as any).select(); document.execCommand("Copy") document.body.removeChild(element); cb?.success(`复制成功:${str}`, 1) ?? message.success(`复制成功:${str}`, 1) } /** * 格式化文件大小, 输出成带单位的字符串 * @method formatSize * @grammar Base.formatSize( size ) => String * @grammar Base.formatSize( size, pointLength ) => String * @grammar Base.formatSize( size, pointLength, units ) => String * @param {Number} size 文件大小 * @param {Number} [pointLength=2] 精确到的小数点数。 * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节,到千字节,一直往上指定。如果单位数组里面只指定了到了K(千字节),同时文件大小大于M, 此方法的输出将还是显示成多少K. * @example * console.log( Base.formatSize( 100 ) ); // => 100B * console.log( Base.formatSize( 1024 ) ); // => 1.00K * console.log( Base.formatSize( 1024, 0 ) ); // => 1K * console.log( Base.formatSize( 1024 * 1024 ) ); // => 1.00M * console.log( Base.formatSize( 1024 * 1024 * 1024 ) ); // => 1.00G * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) ); // => 1024MB */ export const formatSize = (size: number | undefined, pointLength?: number, units?: string[]) => { if (!size) return '0B' let unit; units = units || ['B', 'K', 'M', 'G', 'TB']; while ((unit = units.shift()) && size > 1024) { size = size / 1024; } return (unit === 'B' ? size : size.toFixed(pointLength || 2)) + (unit || 'B'); } /** * 拼接oss参数获取视频首针图 * @param videoUrl */ export const getVideoImgUrl = (videoUrl: string) => { return videoUrl + "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto" } /** * 获取音频时长 * @param file * @returns */ export const getAudioTime = (file: RcFile) => { return new Promise((resolve) => { let url = URL.createObjectURL(file);//获取录音时长 let audioElement = new Audio(url);//audio也可获取视频的时长 let duration; function callback() { duration = audioElement.duration; resolve(duration.toFixed(1)) audioElement.removeEventListener("loadedmetadata", callback) } audioElement.addEventListener("loadedmetadata", callback) }) } /** * 随机生成字符串 * @param flag * @param min * @param max * @returns string */ export const randomString = (flag: boolean, min: number, max: number) => { let str = "", range = min let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; if (flag) { range = Math.round(Math.random() * (max - min)) + min; } for (let i = 0; i < range; i++) { let pos = Math.round(Math.random() * (arr.length - 1)); str += arr[pos]; } return str; } // 数组分组 export const groupBy = (array: any[], f: (item: any) => any[], isObject?: boolean) => { const groups: any = {}; array.forEach(function (o) { //注意这里必须是forEach 大写 const group = JSON.stringify(f(o)); groups[group] = groups[group] || []; groups[group].push(o); }); if (isObject) { return groups } return Object.keys(groups).map(function (group) { return groups[group]; }); } /** * 日期处理 * @param timestamp 时间戳1703635630000 * @returns */ export const formatTimeDifference = (timestamp: string): string => { const currentTime = dayjs(); const targetTime = dayjs(timestamp); const minuteDifference = currentTime.diff(targetTime, 'minute'); if (minuteDifference < 3) { return '刚刚'; } else if (minuteDifference <= 5) { return '5分钟前'; } else if (minuteDifference <= 10) { return '10分钟前'; } else if (minuteDifference <= 30) { return '30分钟前'; } else if (minuteDifference <= 24 * 60 && currentTime.isSame(targetTime, 'day')) { return `今天 ${targetTime.format('HH:mm')}`; } else if (minuteDifference <= 48 * 60 && currentTime.subtract(1, 'day').isSame(targetTime, 'day')) { return `昨天 ${targetTime.format('HH:mm')}`; } else { if (targetTime.isSame(currentTime, 'week')) { return '周' + { 1: '一', 2: '二', 3: '三', 4: '四', 5: '五', 6: '六', 7: '天' }[targetTime.day()] + " " + targetTime.format('HH:mm'); } else { return targetTime.format('YYYY-MM-DD HH:mm:ss'); } } }; /** * 判断2个时间戳是否相差2分钟之内 * @param timestamp * @param lastTimestamp * @returns */ export const isTimeDiffTwo = (timestamp: number, lastTimestamp: number): boolean => { const currentTime = dayjs(timestamp); const targetTime = dayjs(lastTimestamp); const minuteDifference = currentTime.diff(targetTime, 'minute'); if (minuteDifference < 2) return true else return false } /** * 给定最小宽度最大宽度 按比例处理图片 [width, height] = adjustSize(widthO, heightO, 100, 400); * @param width * @param height * @param minSize 最小尺寸 * @param maxSize 最大尺寸 * @returns */ export const adjustSize = (width: number, height: number, minSize: number, maxSize: number): [number, number] => { if (width === height) { if (width <= minSize) { return [minSize, minSize]; } else if (width > maxSize) { return [maxSize, maxSize]; } } else { if (width <= minSize) { return [minSize, minSize / width * height]; } else if (width > maxSize) { let newW = maxSize let newH = maxSize / width * height if (newH > (maxSize * 1.4) && newW > minSize) { newH = minSize / newW * newH newW = minSize } return [newW, newH]; } } return [width, height]; }; /** * 下载文件 * @param url 文件地址 * @param back 返回下载进度 */ export const downloadFile = (url: string, name: string, back?: (vale: number) => void) => { const fileName = name; // 可以自定义下载的文件名 let link = url; let x = new XMLHttpRequest(); x.open('GET', link, true); x.responseType = 'blob'; // 监听下载进度 x.onprogress = (e) => { if (e.lengthComputable) { const percentComplete = (e.loaded / e.total) * 100; // 这里可以根据需要更新 UI,显示下载进度 back?.(Number(percentComplete.toFixed(1))) } }; x.onload = (e) => { let url = window.URL.createObjectURL(x.response); let a = document.createElement('a'); a.href = url; a.download = fileName; a.click(); }; x.send(); } /** * 找2个数组不同元素 * @param arr1 * @param arr2 * @returns */ export const getArrDifference = (arr1: any[], arr2: any[]) => { return arr1.concat(arr2).filter((v, i, arr) => { return arr.indexOf(v) === arr.lastIndexOf(v); }); } /** * file转buffer * @param file * @returns */ export const readFileAsBuffer = (file) => { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target.result); reader.readAsArrayBuffer(file); }); }; /** * 字符串截取 * @param str * @param bytes * @returns */ export const cutByBytes = (str: string, bytes: number) => { let result = ''; let byteCount = 0; for (let char of str) { const charSize = char.charCodeAt(0) > 255 ? 3 : 1; if (byteCount + charSize > bytes) break; result += char; byteCount += charSize; } return result !== str ? result + '...' : str; } /** * 对象去空 * @param obj * @returns */ export const removeEmptyValues = (obj: { [x: string]: any }) => { for (const key in obj) { if (obj[key] === null || obj[key] === undefined || obj[key] === '') { delete obj[key]; } } return obj; }