You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
459 lines
11 KiB
459 lines
11 KiB
/* 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<unknown>[]) =>
|
|
arr.reduce(
|
|
(prev: CommonObjectType<unknown>[], item: CommonObjectType<unknown>) => {
|
|
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<string> => {
|
|
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 = /<img.*?(?:>|\/>)/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<string>[], next: CommonObjectType<string>) => [
|
|
...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<any>,
|
|
parentIdField: string = 'parentId'
|
|
): Array<any> => {
|
|
const dataMap: Object = {}
|
|
|
|
data.forEach((item) => {
|
|
dataMap[item.id] = item
|
|
})
|
|
|
|
const dataTree: Array<any> = []
|
|
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<any>,
|
|
treeValueFiled: string = 'value',
|
|
treeTitleFiled: string = 'title'
|
|
): Array<any> => {
|
|
const treeSelect: Array<any> = []
|
|
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<any>,
|
|
treeKeyFiled: string = 'key',
|
|
treeTitleFiled: string = 'title'
|
|
): Array<any> => {
|
|
const treeSelect: Array<any> = []
|
|
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<any>, id: string | number): Array<number | string> => {
|
|
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<number | string>, arr2: Array<number | string>): Array< number | string>=> {
|
|
const diff: Array<number | string> = []
|
|
for (let idx = 0; idx < arr1.length; idx++) {
|
|
if (!arr2.includes(arr1[idx])) {
|
|
diff.push(arr1[idx])
|
|
}
|
|
}
|
|
return diff
|
|
}
|
|
|
|
|