import { ElMessageBox, ElTag } from 'element-plus' import { __getItem } from './storage' export function isValidKey ( key: string, object: object ): // typeof object 的值决定于 object 是什么类型 // keyof 代表循环 // is 属于 接口 object 的类型 key is keyof typeof object { return key in object } export function paramsInterfaceValidKey (obj: any, params: object) { for (const key in params) { if (isValidKey(key, params)) { obj[key] = params[key] } } } interface CallbackValue { _get: () => unknown _set: (newValue: unknown) => void } export interface ObjectInterface { [key: string]: any } type FormValue = (obj: ObjectInterface, filed: string, index?: undefined | number) => CallbackValue /** * 查找目标字符第n次出现的位置 * @param {*} str 目标字符 * @param {*} source 源字符串 * @param {*} n 次数 * @returns 索引 */ const findN = (str: string, source: string[], n: number) => { let index = source.indexOf(str) for (let i = 1; i < n; i++) { index = source.indexOf(str, index + 1) } return index } export const globalFormValue: FormValue = (obj, filed, index) => { const keyList: string[] = [] if (index === 0) { // 就是在第一层 // key += `['${filed}']` keyList.push(filed) } else if (index && index > 0) { const list = filed.split('.', index) // 前面截取的数组 for (const item of list) { keyList.push(item) } // @ts-ignore const start = findN('.', filed, index) keyList.push(filed.substring(start + 1)) } else { // 无限层 for (const item of filed.split('.')) { keyList.push(item) } } return { _get: () => { const key = `['${keyList.join('\'][\'')}']` // eslint-disable-next-line return new Function('arg', `return arg${key}`)(obj) }, _set: (newValue) => { const length = keyList.length switch (length) { case 1: obj[keyList[0]] = newValue break case 2: obj[keyList[0]][keyList[1]] = newValue break case 3: obj[keyList[0]][keyList[1]][keyList[2]] = newValue break case 4: obj[keyList[0]][keyList[1]][keyList[2]][keyList[3]] = newValue break default: throw new Error('set 层级太深,添加层级') } // obj[a][c][aa] = newValue } } } export const isPromise = (val: ObjectInterface): boolean => { // 是否是promise return ( val && typeof val.then === 'function' && typeof val.catch === 'function' ) } export const getTreeObjById = (data: ObjectInterface[], id: string, key = 'children'): ObjectInterface | undefined => { // 遍历tree找到id for (let item of data) { if (item.id === id) { return item } else { if (item[key] && item[key].length > 0) { let res = getTreeObjById(item[key], id, key) if (res) { return res } } } } } export const confirm = (text: string, cb: () => void) => { const messageBox = (ElMessageBox as any) const confirmHandler = typeof messageBox === 'function' ? messageBox.confirm : messageBox?.confirm confirmHandler(window.$t(text), window.$t('confirmTips')).then(() => { cb() }).catch((err: any) => { throw err }) } interface tagInterface { isBorder?: string type?: string size?: string effect?: string text?: string color?: string } export const createTag = (h: Function, params: tagInterface): Element => { return h(ElTag, { type: params?.type, hit: false, size: params?.size || 'medium', effect: params?.effect || 'light', color: params?.color, style: { borderWidth: params?.isBorder ? '1px' : '0px' } }, params?.text || '标签') } function checkField (filed: string, array: any[]) { if (filed === undefined) { throw new Error(`参数一 输入的值是${filed}, 不能是 undefined`) } if (array === undefined) { throw new Error(`参数二 输入的值是${array}, 需要的是数组`) } return true } /*** * Example * let array =[ * { name: 'zhangSan', age: '20'} * { name: 'lisi', age: '23'} * ] * 根据 filed = zhangSan, array = array, attr = name , 能把array[0] 的数据返回 * @param filed * @param array * @param attr */ export const checkFiledExistInArray = (filed: string, array: any[], attr: string) => { checkField(filed, array) return array.find(item => { if (item[attr] === undefined) { throw new Error(`对象中不存在${attr}属性 ${JSON.stringify(array)}`) } return item[attr] === filed }) } export const getImageUrl = (name: string, url = 'src/assets/images/') => { // 获取图片名称记得带后缀 .png .svg return `/${url}${name}` } export function buildURL (url: string, inputQuery?: ObjectInterface) { if (!url) return '' let baseUrl = JSON.parse((window as any)?.sessionStorage?.getItem('serveConfig'))?.baseURL || '/api' let tokenKey = __getItem('serveConfig').token let query = { [tokenKey]: __getItem('x-auth-token') } Object.assign(query, inputQuery) let queryArr: string[] = [] for (const key in query) { if (query.hasOwnProperty(key) && !isEmptyStr(query[key])) { queryArr.push(`${key}=${query[key]}`) } } if (url.indexOf('?') !== -1) { baseUrl = `${baseUrl}${url}&${queryArr.join('&')}` } else { baseUrl = `${baseUrl}${url}?${queryArr.join('&')}` } return baseUrl } // eslint-disable-next-line complexity export function deepAssign (obj1: ObjectInterface, obj2: ObjectInterface) { // 1有key 从2拿 // 1有key为obj 重复 for (let key in obj1) { if (Object.prototype.toString.call(obj1[key]) === '[object Object]') { deepAssign(obj1[key], obj2[key]) } else if (Array.isArray(obj1[key]) && obj2[key]) { obj1[key].length = 0 obj1[key].push(...obj2[key]) } else if (obj2 && obj2[key] !== undefined && obj2[key] !== null) { obj1[key] = obj2[key] } else { // 如果 obj1 比 obj2 属性多 就删除 多的属性 delete obj1[key] } } // 1无key 从2拿 for (let key in obj2) { if (!obj1.hasOwnProperty(key)) { obj1[key] = obj2[key] } } return obj1 } const getRoutePath = (route) => { let tempPath = window.location.pathname const paramsValue = route.path.substring(route.path.lastIndexOf('/') + 1) if (JSON.stringify(route.params).indexOf(paramsValue) > 0) { tempPath = tempPath.substring(0, tempPath.lastIndexOf('/')) } if ((window as any).info.secDir) { tempPath = tempPath.split((window as any).info.secDir)[1] // 如果有二级目录去掉 } return tempPath } // 按钮权限过滤 export const filterButtonHandler = (code?: string) => { if (!code || !(window as any).loadButtons) return true let path = window.location.pathname if ((window as any).info.secDir) { path = path.split((window as any).info.secDir)[1] // 如果有二级目录去掉 } let buttonArr = ((window as any).loadButtons && (window as any).loadButtons[path]) || [] if (buttonArr.length === 0) { // 未匹配到 截取参数再匹配 const path = getRoutePath((window as any).route) buttonArr = ((window as any).loadButtons && (window as any) .loadButtons[path]) || [] } if (!(window as any).loadButtons[path]) { // 路由不是菜单的按钮就都显示 return true } return buttonArr.includes(code) } // 按钮权限过滤 export const someButtonHandler = (arr: any) => { // return arr.length let index = 0 if (!(window as any).loadButtons) return arr.length let path = window.location.pathname if ((window as any).info.secDir) { path = path.split((window as any).info.secDir)[1] // 如果有二级目录去掉 } let buttonArr = ((window as any).loadButtons && (window as any).loadButtons[path]) || [] if (buttonArr.length === 0) { // 未匹配到 截取参数再匹配 const path = getRoutePath((window as any).route) buttonArr = ((window as any).loadButtons && (window as any).loadButtons[path]) || [] } if (!(window as any).loadButtons[path]) return arr.length arr.forEach(item => { if (!item.code || buttonArr.includes(item.code)) { index += 1 } }) return index } export function deepCopy (obj: ObjectInterface) { return JSON.parse(JSON.stringify(obj)) } export const getFieldValue = (obj: ObjectInterface, filed: string) => { // eslint-disable-next-line return new Function('arg', `return arg.${filed}`)(obj) } // 删除数组对象的一行 export const deleteObject = (value: string, array: ObjectInterface[], attr: string) => { const key: number[] = [] let i = 0 array.forEach((item: ObjectInterface, index: number) => { if (!getFieldValue(item, attr)) { throw new Error('attr 不存在 object 中') } if (getFieldValue(item, attr) === value) { key.push(index) } }) key.forEach((j) => { array.splice(j - i, 1) i++ }) } // 判断是否为空值 export const isEmptyStr = (v) => { return v === '' || v === null || v === undefined } // eslint-disable-next-line max-params export const duplicateRemoval = (arr: ObjectInterface[], _key: string, _key2 = '', _key3 = '') => { let map = new Map() arr.forEach((item: ObjectInterface, index: number) => { // 根据两个值 判断是否重复 if ( !map.has(item[_key]) && !map.has(item[_key2]) && !map.has(item[_key3]) ) { map.set(item[_key] + item[_key2] + item[_key3], item) } }) arr.length = 0 arr.push(...map.values()) return [...map.values()] } export const formatterCurrentTime = (date: any, format?: string) => { const currentDate = new Date(date) const year = currentDate.getFullYear() let month = String(currentDate.getMonth() + 1).padStart(2, '0') let day = String(currentDate.getDate()).padStart(2, '0') let hours = String(currentDate.getHours()).padStart(2, '0') let minutes = String(currentDate.getMinutes()).padStart(2, '0') let seconds = String(currentDate.getSeconds()).padStart(2, '0') let formattedDate = '' switch (format) { case 'yyyy-MM-DD': formattedDate = `${year}-${month}-${day}` break case 'yyyy-MM-DD-hh': formattedDate = `${year}-${month}-${day}-${hours}` break case 'yyyy-MM-DD-hh-mm-ss': formattedDate = `${year}-${month}-${day}-${hours}-${minutes}-${seconds}` break default: formattedDate = `${year}-${month}-${day}` break } return formattedDate } // 两个对象数组的差集 export const getArrDifDifferentValue = (arr1: any[], arr2: any[], typeName: string, key = 'difference') => { // key 区分 intersection交集还是difference差集 默认差集 let arr: any[] = [] let differArr = Object.values( arr1.concat(arr2).reduce((acc: any, cur: any) => { if ( acc[cur[typeName]] && acc[cur[typeName]][typeName] === cur[typeName] ) { if (key === 'difference') { delete acc[cur[typeName]] } else { arr.push(acc[cur[typeName]]) } } else { acc[cur[typeName]] = cur } return acc }, {}) ) if (key === 'difference') { return differArr } return arr } export const getNameByCode = (list: any[], val: string | number, code: string = 'value', name: string = 'label') => { const item = list.find(item => item[code] === val) return item?.[name] || '' } export const downloadBlobFile = (data, fileName) => { // 下载(文件流) let url = window.URL.createObjectURL(new Blob([data])) let link = document.createElement('a') link.style.display = 'none' link.href = url link.download = fileName document.body.appendChild(link) // 将 a 标签添加到页面中 link.click() setTimeout(() => { document.body.removeChild(link) // 下载完成移除元素 window.URL.revokeObjectURL(url) // 释放掉blob对象 }, 0) }