/* eslint-disable import/no-unused-modules */ import moment from 'moment' import { message } from 'ant-design-vue' import { SysDictionaryDto as Dictionary } from '@/api/swagger' import config from '@/config' import { api } from '@/api' import { getRouter } from '@/route' export interface SelectOption { label: number | string value: number | string } /** * convertArrayToObject函数配置项 * @property arr * @property key * @property whole * @property containsKeys */ interface ConvertArrayToObjectConfig { /** * 待转换对象数组 */ arr: any[] | undefined | null /** * 待搜索的元素key值,可以是数组,若使用数组则使用 || 规则 */ key: string | string[] /** * 是否返回对象所有数据,若为true则containsKeys值被忽略 */ whole?: boolean /** * 返回对象中指定key */ containsKeys?: string | string[] } export function fixedZero(val: number) { return val * 1 < 10 ? `0${val}` : val } export function getTimeDistance(type: string): moment.Moment[] { const now = new Date() const oneDay = 1000 * 60 * 60 * 24 if (type === 'today') { now.setHours(0) now.setMinutes(0) now.setSeconds(0) return [moment(now), moment(now.getTime() + (oneDay - 1000))] } if (type === 'week') { let day = now.getDay() now.setHours(0) now.setMinutes(0) now.setSeconds(0) if (day === 0) { day = 6 } else { day -= 1 } const beginTime = now.getTime() - day * oneDay return [moment(beginTime), moment(beginTime + (7 * oneDay - 1000))] } if (type === 'month') { const year = now.getFullYear() const month = now.getMonth() const nextDate = moment(now).add(1, 'months') const nextYear = nextDate.year() const nextMonth = nextDate.month() return [ moment(`${year}-${fixedZero(month + 1)}-01 00:00:00`), moment(moment(`${nextYear}-${fixedZero(nextMonth + 1)}-01 00:00:00`).valueOf() - 1000), ] } const year1 = now.getFullYear() return [moment(`${year1}-01-01 00:00:00`), moment(`${year1}-12-31 23:59:59`)] } export function flatten(arr: any[]): any[] { return arr.reduce((pre, cur) => { if (!Array.isArray(cur)) { return [...pre, cur] } else { return [...pre, ...flatten(cur)] } }, []) } export function flattenByKey(arr: any[], key: string): any[] { return arr.reduce((pre, cur) => { if (!Array.isArray(cur[key]) || !cur[key].length) { return [...pre, cur] } else { return [...pre, ...flattenByKey(cur[key], key)] } }, []) } export function arrTrans(num: number, arr: any[]) { const iconsArr: any[] = [] arr.forEach((item, index) => { const page = Math.floor(index / num) if (!iconsArr[page]) { iconsArr[page] = [] } iconsArr[page].push(item) }) return iconsArr } export function getPathByTree(tree: any[], fn: (data: any) => any, path: any[] = []) { if (!tree) { return [] } for (const data of tree) { path.push(data) if (fn(data)) { return path } if (data.children) { const findChildren = getPathByTree(data.children, fn, path) if ((findChildren as any[]).length) { return findChildren } } path.pop() } return [] } /** * 根据分割符切割字符串 * * @param str 字符串 * @param separator 分隔符 * @returns string[] */ export function splitStringToArray(str: string | undefined | null, separator = ','): string[] { return str ? String(str).split(separator) : [] } /** * 根据连接符合并数组 * * @param data 要合并的数组 * @param gulp 连接符 * @returns string */ export function joinArrayToString(data: any[] | undefined | null, gulp = ','): string { return Array.isArray(data) ? data.join(gulp) : '' } /** * 级联选择器匹配标签(ant-design cascader) * * @param arr 已选级联数据 * @param data 级联数据 * @param labels 标签组 * @param key 指定标签的key * @returns 匹配到的标签数组 */ export function getLabelsByGroup( arr: string[] | undefined, data: any[] | undefined, labels: Array = [], key = 'label', ): Array { if (typeof data === 'object' && arr) { for (let i = 0; arr[i] !== undefined; i++) { for (let j = 0; data[j] !== undefined; j++) { if (arr[i] === data[j].value || arr[i] === data[j].code) { labels.push(data[j][key]) } } } for (let i = 0; data[i] !== undefined; i++) { getLabelsByGroup(arr, data[i].children, labels, key) } return labels } else { return [] } } /** * 根据key值从待搜索对象中查找值 * * @param key 从待查询对象中提取得key值,若使用数组则使用 || 规则进行赋值 * @param needle 待查询对象 * @returns 搜索到的值,可能为空 */ function searchIndexByKey(key: string | string[], needle: any): any { let index: any = '' if (Array.isArray(key)) { index = key.reduce((res, k) => { return needle[k] || res }, index) } else { index = needle[key] } return index } /** * 根据本地对象查询key value值 * @param target 指向当前的this值 * @param value * @param key */ export function valueToName(target: any, value: string, key: string, split = ',', gulp = '、'): string { const values: Array = String(value || '').split(split) if (target[key]) { const found: Array = values.reduce>((a, b) => { const item: Dictionary = target[key].find((v: any) => v.value === b) // @ts-expect-error ignore a.push(item ? item.label : '') return a }, []) return found.filter((v) => v).join(gulp) } else { return '' } } /** * 根据数组返回由key组成的键值对形式的对象 * * @param config 配置项 * * @example convertArrayToObject({[{a:1, b:2}, {a:2,b:3}], 'a', false, ['b']}) => {'1':{b:2}, '2':{b:3} } * @example convertArrayToObject({[{a:1, b:2}, {a:2,b:3}], 'a', false, 'b'}) => {'1':2, '2':3 } * @example convertArrayToObject({[{a:1, b:2}, {a:2,b:3}], 'a'}) => {'1':{ a:1,b:2 }, '2':{a:2,b:3} } * * @returns 由原对象数组使用传入的key对应的value值作为新对象的key值组成的对象 * */ export function convertArrayToObject(c: ConvertArrayToObjectConfig): R { const { arr, key, whole, containsKeys } = Object.assign({ whole: false, containsKeys: '' }, c) if (Array.isArray(arr) && Object.keys(arr).length > 0) { return arr.reduce((a, needle) => { const kIndex: any = searchIndexByKey(key, needle) if (!!kIndex) { let value: any = {} if (!whole || !!containsKeys) { if (Array.isArray(containsKeys)) { containsKeys.forEach((ckey: any) => { value[ckey] = needle[ckey] }) } else if (containsKeys) { value = needle[containsKeys] } } else { value = needle } a[kIndex] = value } return a }, {}) } return {} as any } export function getFileTypeCAD(foldType) { return foldType == 13 || foldType == 14 || foldType == 12 || foldType == 2 || foldType == 4 ? true : false } /** * 下拉框选项适配器 * @param data 要转换的数据 * @param valueIndex value值的索引 * @param labelIndex label值的索引 支持数组 * @param labelGulp 当labelIndex是数组时的连接符 */ export function antdvSelectOptionAdaptor( data: any[], valueIndex: string, labelIndex: string | string[], labelGulp = '', ): SelectOption[] { let arr: any[] = Array.isArray(data) ? [...data] : [] if (arr.length) { const [item] = arr let hasLabel = false if (typeof labelIndex === 'string') { hasLabel = typeof item[labelIndex] !== 'undefined' } else { labelIndex = labelIndex || [] hasLabel = labelIndex.some((l: string) => typeof item[l] !== 'undefined') } if (typeof item[valueIndex] !== 'undefined' && hasLabel) { arr = arr.map((v: any) => { const value = v[valueIndex] let label: any = '' if (Array.isArray(labelIndex)) { label = labelIndex.map((l: string) => v[l]).join(labelGulp) } else { label = v[labelIndex] } return { value, label } }) } } return arr } /** * 下载文件 * @param url 下载地址 * @param name 文件url */ export function downloadFile(url: string, name?: string): void { const a = window.document.createElement('a') a.href = url a.target = '_blank' a.style.display = 'none' if (name) { a.download = name } document.body.appendChild(a) a.click() document.body.removeChild(a) } /** * 下载excel * @param name 文件名 * @param data 文件Blob数据 */ export function downloadExcel(name: string, data: Blob, type?: string): void { const blob = new Blob([data], { type: // 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.ms-excel;application/x-excel;charset=utf-8' type || 'application/vnd.ms-excel;application/x-excel;charset=utf-8', }) const url = window.URL.createObjectURL(blob) downloadFile(url, name) } /** * 下载附件文件数据 */ export interface FileCodeData { code: string name?: string fileName: string } /** * 获取下载文件地址 * @param code 附件code */ export function getDownloadURL(code: string) { return `${config.apiURL}/api/file/download?code=${code}` } // 判断文件扩展名是否存在 export function checkFileExt(filename, typeList) { let flag = false // 状态 const arr = [...typeList] // 取出上传文件的扩展名 filename = filename.toLowerCase() const index = filename.lastIndexOf('.') const ext = filename.substr(index + 1) // 循环比较 for (const f of arr) { if (ext === f) { flag = true // 一旦找到合适的,立即退出循环 break } } return flag } export function imgTypeList(): string[] { return [ 'jpg', 'jpeg', 'bmp', 'png', 'tif', 'gif', 'pcx', 'tga', 'exif', 'fpx', 'svg', 'psd', 'cdr', 'pcd', 'dxf', 'ufo', 'eps', 'ai', 'raw', 'webp', ] } export function openPdfToHtml(url: string, name?: string, code?: string) { localStorage.setItem('pdfjsFileName', name || '附件') const routeData = getRouter().resolve({ path: `/pdfjs/web/viewer.html?file=${url}`, }) window.open(routeData.href, '_blank') } /** * 通过code打开附件 * @param data */ export function downloadFileByCode(data: FileCodeData, isDownloadPDF = false) { const code = data.code const name = data.fileName || String(data.name || '') const url = getDownloadURL(code) if (!code) { return message.error('打开附件失败,缺少code') } if (checkFileExt(name, imgTypeList())) { // 是图片 window.open(url) } else if (checkFileExt(name, ['pdf']) && !isDownloadPDF) { // pdf跳转pdf预览页面 openPdfToHtml(url, name) } else { api .get( '/api/File/Download', { code }, { responseType: 'arraybuffer', }, ) .then((res: any) => { const blob = new Blob([res]) const downloadURL = window.URL.createObjectURL(blob) const a = document.createElement('a') a.href = downloadURL a.download = name a.click() window.URL.revokeObjectURL(downloadURL) }) .catch((err: any) => { message.warning(err.message) }) } } /** * 生产唯一值 */ export function createUUID(mix = 0): string { const prefix = moment().format('YYYY-MM-DD-HH-mm-ss-SSS') const suffix = parseInt(Math.random() * 100 + mix + '', 20) return `${prefix}-${suffix}` } /** * 将任意数据转换成数字 * @param input 任意数据 * @returns isNaN ? 0 : Number(input) */ export function convertAnyToNumber(input: any): number { const convert = Number(input) return isNaN(convert) ? 0 : convert } /* 获取url传值参数 * * @param {String} name 参数名 * @param {String} thisUrl url地址,若不传则获取当前地址 */ export function getUrlQuery(name, thisUrl = '') { const reg = new RegExp('(^|\\?|&)' + name + '=([^&]*)(\\s|&|$)', 'i') const url = thisUrl || location.href if (reg.test(url)) { return decodeURI(RegExp.$2.replace(/\+/g, ' ')) } else { return false } } /** * 消除正式环境log */ export function log(args: any | any[]) { if (process.env.NODE_ENV === 'development') { // eslint-disable-next-line no-console console.log(args) } } // 是否是图片文件 export function isImageFile(filename: string): boolean { const types = imgTypeList() const arr = filename.split('.') const extName = (arr[arr.length - 1] || '').toLowerCase() return types.includes(extName) } export const imageAccept = imgTypeList() .map((v) => '.' + v) .join(',') export function isVideo(type: string): boolean { return /(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i.test(type) } /* * 获取文件扩展名 * @param fileName 文件名称 */ export function getFileExtension(fileName: string): string { return fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2) } /* eslint-enable import/no-unused-modules */