/* eslint-disable no-param-reassign */ import { Modal } from 'antd' import routes from '@/route/routes' import ErrorPage from '@/pages/public/errorPage' import { store } from '@/store' // 通用confirm方法 export const commonConfirm = (title: string, cb: () => void) => { const { confirm } = Modal confirm({ okText: '确定', cancelText: '取消', title, onOk() { cb() }, onCancel() {} }) } /** * 隐藏手机号码 * @param {string} phone 手机号 */ export const hidePhone = (phone: string) => phone && phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') /** * 以递归的方式展平react router数组 * @param {object[]} arr 路由数组 * @param {string} child 需要递归的字段名 */ export const flattenRoutes = (arr: CommonObjectType[]) => arr.reduce( (prev: CommonObjectType[], item: CommonObjectType) => { if (Array.isArray(item.routes)) { prev.push(item) } return prev.concat( Array.isArray(item.routes) ? flattenRoutes(item.routes) : item ) }, [] ) /** * 根据路径获取路由的name和key * @param {string} path 路由 */ export const getKeyName = (path: string = '/403') => { const truePath = path.split('?')[0]; const curRoute = flattenRoutes(routes).filter( (item: { path: string | string[] }) => item.path.includes(truePath) ) if (!curRoute[0]) return { title: '暂无权限', tabKey: '403', component: ErrorPage } const { name, key, component } = curRoute[0] return { title: name, tabKey: key, component } } /** * 同步执行操作,Currying * @param {*} action 要执行的操作 * @param {function} cb 下一步操作回调 */ export const asyncAction = (action: unknown) => { const wait = new Promise((resolve) => { resolve(action) }) return (cb: () => void) => { wait.then(() => setTimeout(() => cb())) } } /** * 页签关闭操作回调 * @param {object} history 路由history对象。不能new新实例,不然参数无法传递 * @param {string} returnUrl 返回地址 * @param {function} cb 回调操作,可选 */ export const closeTabAction = ( history: CommonObjectType, returnUrl: string = '/', cb?: () => void ) => { const { curTab } = store.getState().storeData const { href } = window.location const pathname = href.split('#')[1] // 删除tab const tabArr = JSON.parse(JSON.stringify(curTab)) const delIndex = tabArr.findIndex((item: string) => item === pathname) tabArr.splice(delIndex, 1) // 如果要返回的页面被关闭了,再加进去 if (!tabArr.includes(returnUrl)) { tabArr.push(returnUrl) } // 储存新的tabs数组 const setTab = store.dispatch({ type: 'SET_CURTAB', payload: tabArr }) // 刷新tab const reloadTab = store.dispatch({ type: 'SET_RELOADPATH', payload: returnUrl }) // 停止刷新tab const stopReload = setTimeout(() => { store.dispatch({ type: 'SET_RELOADPATH', payload: 'null' }) }, 500) const action = () => setTab && reloadTab && stopReload // 刷新回调 const callback = () => { if (cb && typeof cb === 'function') { return cb } return history.push({ pathname: returnUrl }) } asyncAction(action)(callback) } /** * 获取地址栏 ?参数,返回键值对对象 */ export const getQuery = (): CommonObjectType => { const { href } = window.location const query = href.split('?') if (!query[1]) return {} const queryArr = decodeURI(query[1]).split('&') const queryObj = queryArr.reduce((prev, next) => { const item = next.split('=') return { ...prev, [item[0]]: item[1] } }, {}) return queryObj } /** * 深拷贝操作,简单类型的对象的可以直接用 JSON.parse(JSON.stringify())或 [...]/{...} * @param {object} obj 需要拷贝的对象 */ export const deepClone = (obj: CommonObjectType) => { if ( obj === null || typeof obj !== 'object' || obj instanceof Date || obj instanceof Function ) { return obj } const cloneObj = Array.isArray(obj) ? [] : {} Object.keys(obj).map((key) => { cloneObj[key] = deepClone(obj[key]) return cloneObj }) return cloneObj } /** * 获取图片地址 * @param {*} html 富文本字符串 */ export const getImgsUrl = (html?: string) => { // 匹配图片(g表示匹配所有结果i表示区分大小写) const imgReg = /|\/>)/gi // 匹配src属性 const srcReg = /src=['"]?([^'"]*)['"]?/i const arr = html.match(imgReg) if (!arr) return null // 获取图片地址 const urlArr = arr.reduce((prev, next) => { const src = next.match(srcReg) return src[1] ? [...prev, src[1]] : prev }, []) return urlArr } /** * 获取视频地址 * @param {*} html 富文本字符串 */ export const getVideoUrl = (html?: string) => { // 匹配图片(g表示匹配所有结果i表示区分大小写) const imgReg = /<(video|iframe).*?(?:>|\/>)/gi // 匹配src属性 const srcReg = /src=['"]?([^'"]*)['"]?/i const arr = html.match(imgReg) if (!arr) return null // 获取图片地址 const urlArr = arr.reduce((prev, next) => { const src = next.match(srcReg) return src[1] ? [...prev, src[1]] : prev }, []) return urlArr } /** * 获取本地存储中的权限 */ export const getPermission = () => localStorage.getItem('permissions') || [] /** * 根据权限判断是否有权限 */ export const isAuthorized = (val: string): boolean => { const permissions = getPermission(); return permissions.includes(val) } /** * 用requestAnimationFrame替代setTimeout、setInterval,解决内存溢出 * @export * @param {*} cb 定时回调 * @param {*} interval 定时时间 */ export const customizeTimer = { intervalTimer: null, timeoutTimer: null, setTimeout(cb: () => void, interval: number) { // 实现setTimeout功能 const { now } = Date const stime = now() let etime = stime const loop = () => { this.timeoutTimer = requestAnimationFrame(loop) etime = now() if (etime - stime >= interval) { cb() cancelAnimationFrame(this.timeoutTimer) } } this.timeoutTimer = requestAnimationFrame(loop) return this.timeoutTimer }, clearTimeout() { cancelAnimationFrame(this.timeoutTimer) }, setInterval(cb: () => void, interval: number) { // 实现setInterval功能 const { now } = Date let stime = now() let etime = stime const loop = () => { this.intervalTimer = requestAnimationFrame(loop) etime = now() if (etime - stime >= interval) { stime = now() etime = stime cb() } } this.intervalTimer = requestAnimationFrame(loop) return this.intervalTimer }, clearInterval() { cancelAnimationFrame(this.intervalTimer) } } /** * 预览图片 */ export const previewImg = (children: string | React.ReactNode) => { Modal.info({ title: '预览', icon: false, okText: '关闭', maskClosable: true, content: children }) } /** * 限制两位小数,可 ± * @param {string} val 要格式化的数字 */ export const limitDecimal = (val: string) => val.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') /** * 处理用户信息并储存起来 */ export const setUserInfo = ( userInfo: CommonObjectType, action: (arg0: string, arg1: unknown) => unknown, oldToken?: string ) => { const { permission, userName, token } = userInfo console.log(permission); const permissionArray = permission.reduce( (prev: CommonObjectType[], next: CommonObjectType) => [ ...prev, next.code ], [] ); localStorage.setItem('permissions', permissionArray) const result = { userName, permission, token: token || oldToken } action('SET_USERINFO', result) } /** * 生成tree结构数据 * @param data * @param parentIdField */ export const makeTree = ( data: Array, parentIdField: string = 'parentId' ): Array => { const dataMap: Object = {} data.forEach((item) => { dataMap[item.id] = item }) const dataTree: Array = [] data.forEach((item) => { const parent = dataMap[item[parentIdField]] if (parent) { if (parent.children) { parent.children.push(item) } else { parent.children = [] parent.children.push(item) } } else { dataTree.push(item) } }) return dataTree } /** * 生成TreeSelect组件结构数据 * @param dataTree * @param treeValueFiled * @param treeTitleFiled */ export const makeTreeSelectData = ( dataTree: Array, treeValueFiled: string = 'value', treeTitleFiled: string = 'title' ): Array => { const treeSelect: Array = [] dataTree.forEach((item) => { const temp = { value: item[treeValueFiled], title: item[treeTitleFiled], children: item.children || undefined } if (temp.children) { temp.children = makeTreeSelectData( temp.children, treeValueFiled, treeTitleFiled ) } treeSelect.push(temp) }) return treeSelect } /** * 生成Tree组件结构数据 * @param dataTree * @param treeKeyFiled * @param treeTitleFiled */ export const makeTreeData = ( dataTree: Array, treeKeyFiled: string = 'key', treeTitleFiled: string = 'title' ): Array => { const treeSelect: Array = [] dataTree.forEach((item) => { const temp = { key: item[treeKeyFiled], title: item[treeTitleFiled], children: item.children || undefined } if (temp.children) { temp.children = makeTreeData( temp.children, treeKeyFiled, treeTitleFiled ) } treeSelect.push(temp) }) return treeSelect } /** * 根据节点获取所有父节点id数组 * @param tree * @param id */ export const treeFindParentById = (tree: Array, id: string | number): Array => { const path = [] if (tree.length === 0) return [] const forFn = function (tree, id) { for (let i = 0; i < tree.length; i++) { const data = tree[i] if (data.id === id) { return path } path.push(data.id) if (data.children) { const findChildren = forFn(data.children, id); if (findChildren && findChildren.length > 0) return findChildren } path.pop() } } forFn(tree, id) return path } /** * 获取数据差集 * @param arr1 * @param arr2 */ export const diffArray = (arr1: Array, arr2: Array): Array< number | string>=> { const diff: Array = [] for (let idx = 0; idx < arr1.length; idx++) { if (!arr2.includes(arr1[idx])) { diff.push(arr1[idx]) } } return diff }