Optimize util structure
This commit is contained in:
262
src/util/auth.tsx
Normal file
262
src/util/auth.tsx
Normal file
@@ -0,0 +1,262 @@
|
||||
import _ from 'lodash'
|
||||
import {
|
||||
STORAGE_TOKEN_KEY,
|
||||
STORAGE_USER_INFO_KEY,
|
||||
DATABASE_SELECT_SUCCESS
|
||||
} from '@/constants/common.constants'
|
||||
import { floorNumber, randomColor, randomFloat, randomInt } from '@/util/common'
|
||||
import { getLocalStorage, removeLocalStorage, setLocalStorage } from '@/util/browser'
|
||||
import { getFullTitle } from '@/util/route'
|
||||
import { r_sys_user_info } from '@/services/system'
|
||||
import { r_auth_login, r_auth_logout } from '@/services/auth'
|
||||
|
||||
let captcha: Captcha
|
||||
|
||||
export const setToken = (token: string) => {
|
||||
setLocalStorage(STORAGE_TOKEN_KEY, token)
|
||||
}
|
||||
|
||||
export const removeToken = () => {
|
||||
removeLocalStorage(STORAGE_USER_INFO_KEY)
|
||||
removeLocalStorage(STORAGE_TOKEN_KEY)
|
||||
}
|
||||
|
||||
export const getToken = () => {
|
||||
return getLocalStorage(STORAGE_TOKEN_KEY)
|
||||
}
|
||||
|
||||
export const getCaptcha = (width: number, high: number, num: number) => {
|
||||
const CHARTS = '23456789ABCDEFGHJKLMNPRSTUVWXYZabcdefghijklmnpqrstuvwxyz'.split('')
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||
|
||||
ctx.rect(0, 0, width, high)
|
||||
ctx.clip()
|
||||
|
||||
ctx.fillStyle = randomColor(200, 250)
|
||||
ctx.fillRect(0, 0, width, high)
|
||||
|
||||
for (let i = 0.05 * width * high; i > 0; i--) {
|
||||
ctx.fillStyle = randomColor(0, 256)
|
||||
ctx.fillRect(randomInt(0, width), randomInt(0, high), 1, 1)
|
||||
}
|
||||
|
||||
ctx.font = `${high - 4}px Consolas`
|
||||
ctx.fillStyle = randomColor(160, 200)
|
||||
let value = ''
|
||||
for (let i = 0; i < num; i++) {
|
||||
const x = ((width - 10) / num) * i + 5
|
||||
const y = high - 12
|
||||
const r = Math.PI * randomFloat(-0.12, 0.12)
|
||||
const ch = CHARTS[randomInt(0, CHARTS.length)]
|
||||
value += ch
|
||||
ctx.translate(x, y)
|
||||
ctx.rotate(r)
|
||||
ctx.fillText(ch, 0, 0)
|
||||
ctx.rotate(-r)
|
||||
ctx.translate(-x, -y)
|
||||
}
|
||||
|
||||
const base64Src = canvas.toDataURL('image/jpg')
|
||||
return {
|
||||
value,
|
||||
base64Src
|
||||
}
|
||||
}
|
||||
|
||||
export const login = async (username: string, password: string) => {
|
||||
return await r_auth_login(username, password)
|
||||
}
|
||||
|
||||
export const logout = async () => {
|
||||
return r_auth_logout().finally(() => {
|
||||
removeToken()
|
||||
})
|
||||
}
|
||||
|
||||
export const getLoginStatus = () => {
|
||||
return getLocalStorage(STORAGE_TOKEN_KEY) !== null
|
||||
}
|
||||
|
||||
export const getUserInfo = async (): Promise<UserWithPowerInfoVo> => {
|
||||
if (getLocalStorage(STORAGE_USER_INFO_KEY) !== null) {
|
||||
return new Promise((resolve) => {
|
||||
resolve(
|
||||
JSON.parse(getLocalStorage(STORAGE_USER_INFO_KEY) as string) as UserWithPowerInfoVo
|
||||
)
|
||||
})
|
||||
}
|
||||
return requestUserInfo()
|
||||
}
|
||||
|
||||
export const requestUserInfo = async () => {
|
||||
let user: UserWithPowerInfoVo | null
|
||||
|
||||
await r_sys_user_info().then((value) => {
|
||||
const response = value.data
|
||||
if (response.code === DATABASE_SELECT_SUCCESS) {
|
||||
user = response.data
|
||||
setLocalStorage(STORAGE_USER_INFO_KEY, JSON.stringify(user))
|
||||
}
|
||||
})
|
||||
|
||||
return new Promise<UserWithPowerInfoVo>((resolve, reject) => {
|
||||
if (user) {
|
||||
resolve(user)
|
||||
}
|
||||
reject(user)
|
||||
})
|
||||
}
|
||||
|
||||
export const getNickname = async () => {
|
||||
const user = await getUserInfo()
|
||||
|
||||
return user.userInfo.nickname
|
||||
}
|
||||
|
||||
export const getUsername = async () => {
|
||||
const user = await getUserInfo()
|
||||
|
||||
return user.username
|
||||
}
|
||||
|
||||
export const getPermissionPath = (): string[] => {
|
||||
const s = getLocalStorage(STORAGE_USER_INFO_KEY)
|
||||
if (s === null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const user = JSON.parse(s) as UserWithPowerInfoVo
|
||||
const paths: string[] = []
|
||||
user.menus.forEach((menu) => {
|
||||
paths.push(menu.url)
|
||||
})
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
export const hasPathPermission = (path: string) => {
|
||||
return getPermissionPath().indexOf(path) !== -1
|
||||
}
|
||||
|
||||
/*
|
||||
export const getAuthRoute = (route: RouteJsonObject[]): RouteJsonObject[] => {
|
||||
return route.map((value) => {
|
||||
if (value.absolutePath) {
|
||||
value.absolutePath
|
||||
}
|
||||
if (value.children) {
|
||||
value.children = getAuthRoute(value.children)
|
||||
}
|
||||
return value
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
export const getCaptchaSrc = () => {
|
||||
captcha = getCaptcha(300, 150, 4)
|
||||
return captcha.base64Src
|
||||
}
|
||||
|
||||
export const verifyCaptcha = (value: string) => {
|
||||
return captcha.value.toLowerCase() === value.replace(/\s*/g, '').toLowerCase()
|
||||
}
|
||||
|
||||
export const powerListToPowerTree = (
|
||||
modules: ModuleVo[],
|
||||
menus: MenuVo[],
|
||||
elements: ElementVo[],
|
||||
operations: OperationVo[]
|
||||
): _DataNode[] => {
|
||||
const moduleChildrenMap = new Map<string, _DataNode[]>()
|
||||
const menuChildrenMap = new Map<string, _DataNode[]>()
|
||||
const elementChildrenMap = new Map<string, _DataNode[]>()
|
||||
|
||||
operations.forEach((operation) => {
|
||||
if (elementChildrenMap.get(String(operation.elementId))) {
|
||||
elementChildrenMap.get(String(operation.elementId))?.push({
|
||||
title: operation.name,
|
||||
key: operation.id,
|
||||
value: operation.id
|
||||
})
|
||||
} else {
|
||||
elementChildrenMap.set(String(operation.elementId), [
|
||||
{
|
||||
title: operation.name,
|
||||
key: operation.id,
|
||||
value: operation.id
|
||||
}
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
const elementTrees = parentToTree(
|
||||
elements.map((element) => ({
|
||||
title: element.name,
|
||||
key: element.id,
|
||||
value: element.id,
|
||||
parentId: element.parentId,
|
||||
children: elementChildrenMap.get(String(element.id))
|
||||
}))
|
||||
)
|
||||
|
||||
elementTrees.forEach((element) => {
|
||||
if (menuChildrenMap.get(String(floorNumber(element.key as number, 5)))) {
|
||||
menuChildrenMap.get(String(floorNumber(element.key as number, 5)))?.push(element)
|
||||
} else {
|
||||
menuChildrenMap.set(String(floorNumber(element.key as number, 5)), [element])
|
||||
}
|
||||
})
|
||||
|
||||
const menuTrees = parentToTree(
|
||||
menus.map((menu) => ({
|
||||
title: menu.name,
|
||||
key: menu.id,
|
||||
value: menu.id,
|
||||
parentId: menu.parentId,
|
||||
children: menuChildrenMap.get(String(menu.id))
|
||||
}))
|
||||
)
|
||||
|
||||
menuTrees.forEach((menu) => {
|
||||
if (moduleChildrenMap.get(String(floorNumber(menu.key as number, 7)))) {
|
||||
moduleChildrenMap.get(String(floorNumber(menu.key as number, 7)))?.push(menu)
|
||||
} else {
|
||||
moduleChildrenMap.set(String(floorNumber(menu.key as number, 7)), [menu])
|
||||
}
|
||||
})
|
||||
|
||||
return modules.map((module) =>
|
||||
getFullTitle({
|
||||
title: module.name,
|
||||
key: module.id,
|
||||
value: module.id,
|
||||
children: moduleChildrenMap.get(String(module.id))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const parentToTree = (data: _DataNode[]): _DataNode[] => {
|
||||
const parents = data.filter((value) => !value.parentId)
|
||||
const children = data.filter((value) => value.parentId)
|
||||
|
||||
const translator = (parents: _DataNode[], children: _DataNode[]) => {
|
||||
parents.forEach((parent) => {
|
||||
children.forEach((current, index) => {
|
||||
if (current.parentId === parent.key) {
|
||||
const temp = _.cloneDeep(children)
|
||||
temp.splice(index, 1)
|
||||
translator([current], temp)
|
||||
typeof parent.children !== 'undefined'
|
||||
? parent.children.push({ ...current })
|
||||
: (parent.children = [current])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
translator(parents, children)
|
||||
|
||||
return parents
|
||||
}
|
||||
63
src/util/browser.tsx
Normal file
63
src/util/browser.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
export const getQueryVariable = (variable: string) => {
|
||||
const query = window.location.search.substring(1)
|
||||
const vars = query.split('&')
|
||||
for (const value of vars) {
|
||||
const pair = value.split('=')
|
||||
if (pair[0] === variable) {
|
||||
return decodeURIComponent(pair[1].replace(/\+/g, ' '))
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const setCookie = (
|
||||
name: string,
|
||||
value: string,
|
||||
daysToLive: number | null,
|
||||
path: string | null
|
||||
) => {
|
||||
let cookie = `${name}=${encodeURIComponent(value)}`
|
||||
|
||||
if (typeof daysToLive === 'number') {
|
||||
cookie = `${cookie}; max-age=${daysToLive * 24 * 60 * 60}`
|
||||
}
|
||||
|
||||
if (typeof path === 'string') {
|
||||
cookie = `${cookie}; path=${path}`
|
||||
}
|
||||
|
||||
document.cookie = cookie
|
||||
}
|
||||
|
||||
export const getCookie = (name: string) => {
|
||||
const cookieArr = document.cookie.split(';')
|
||||
|
||||
for (const cookie of cookieArr) {
|
||||
const cookiePair = cookie.split('=')
|
||||
if (cookiePair[0].trim() === name) {
|
||||
return decodeURIComponent(cookiePair[1])
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export const removeCookie = (name: string) => {
|
||||
document.cookie = `${name}=; max-age=0`
|
||||
}
|
||||
|
||||
export const setLocalStorage = (name: string, value: string) => {
|
||||
localStorage.setItem(name, value)
|
||||
}
|
||||
|
||||
export const getLocalStorage = (name: string) => {
|
||||
return localStorage.getItem(name)
|
||||
}
|
||||
|
||||
export const removeLocalStorage = (name: string) => {
|
||||
localStorage.removeItem(name)
|
||||
}
|
||||
|
||||
export const clearLocalStorage = () => {
|
||||
localStorage.clear()
|
||||
}
|
||||
56
src/util/common.tsx
Normal file
56
src/util/common.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import LoadingMask from '@/components/common/LoadingMask'
|
||||
|
||||
export const randomInt = (start: number, end: number) => {
|
||||
if (start > end) {
|
||||
const t = start
|
||||
start = end
|
||||
end = t
|
||||
}
|
||||
start = Math.ceil(start)
|
||||
end = Math.floor(end)
|
||||
return start + Math.floor(Math.random() * (end - start))
|
||||
}
|
||||
|
||||
export const randomFloat = (start: number, end: number) => {
|
||||
return start + Math.random() * (end - start)
|
||||
}
|
||||
|
||||
export const randomColor = (start: number, end: number) => {
|
||||
return `rgb(${randomInt(start, end)},${randomInt(start, end)},${randomInt(start, end)})`
|
||||
}
|
||||
|
||||
export const floorNumber = (num: number, digits: number) => {
|
||||
if (digits > 0) {
|
||||
return Math.floor(num / Math.pow(10, digits - 1)) * Math.pow(10, digits - 1)
|
||||
} else {
|
||||
const regExpMatchArray = num.toString().match(new RegExp('^\\d\\.\\d{' + -digits + '}'))
|
||||
if (regExpMatchArray !== null) {
|
||||
return parseFloat(regExpMatchArray[0]).toFixed(-digits)
|
||||
} else {
|
||||
return num
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const showLoadingMask = (id: string) => {
|
||||
if (document.querySelector(`#${id}`)) {
|
||||
return
|
||||
}
|
||||
|
||||
const container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
container.id = id
|
||||
container.setAttribute(
|
||||
'style',
|
||||
'position: fixed; width: 100vw; height: 100vh; z-index: 10000; left: 0; top: 0;'
|
||||
)
|
||||
|
||||
return ReactDOM.createRoot(container).render(<LoadingMask />)
|
||||
}
|
||||
|
||||
export const removeLoadingMask = (id: string) => {
|
||||
document.querySelectorAll(`#${id}`).forEach((value) => {
|
||||
value.parentNode?.removeChild(value)
|
||||
})
|
||||
}
|
||||
30
src/util/datetime.tsx
Normal file
30
src/util/datetime.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import moment from 'moment/moment'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export const getNowLocalTime = (format: string = 'yyyy-MM-DD HH:mm:ssZ') => {
|
||||
return moment().local().format(format)
|
||||
}
|
||||
|
||||
export const getNowUtc = () => {
|
||||
return moment().toISOString()
|
||||
}
|
||||
|
||||
export const utcToLocalTime = (utcTime: string, format: string = 'yyyy-MM-DD HH:mm:ssZ') => {
|
||||
return moment.utc(utcTime).local().format(format)
|
||||
}
|
||||
|
||||
export const dayjsToLocalTime = (date: dayjs.Dayjs, format: string = 'YYYY-MM-DD HH:mm:ssZ') => {
|
||||
return date.format(format)
|
||||
}
|
||||
|
||||
export const dayjsToUtc = (date: dayjs.Dayjs) => {
|
||||
return date.toISOString()
|
||||
}
|
||||
|
||||
export const localTimeToUtc = (localTime: string) => {
|
||||
return moment(localTime).toISOString()
|
||||
}
|
||||
|
||||
export const isPastTime = (utcTime: string) => {
|
||||
return moment.utc(utcTime).isBefore(moment.now())
|
||||
}
|
||||
16
src/util/hooks.tsx
Normal file
16
src/util/hooks.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
|
||||
export const useUpdatedEffect = (
|
||||
effect: React.EffectCallback,
|
||||
dependencies: React.DependencyList
|
||||
) => {
|
||||
const isFirstRender = useRef(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (isFirstRender.current) {
|
||||
isFirstRender.current = false
|
||||
} else {
|
||||
effect()
|
||||
}
|
||||
}, dependencies)
|
||||
}
|
||||
13
src/util/route.tsx
Normal file
13
src/util/route.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
export const getRedirectUrl = (path: string, redirectUrl: string): string => {
|
||||
return `${path}?redirect=${encodeURIComponent(redirectUrl)}`
|
||||
}
|
||||
|
||||
export const getFullTitle = (data: _DataNode, preTitle?: string) => {
|
||||
data.fullTitle = `${preTitle ? `${preTitle}-` : ''}${data.title as string}`
|
||||
data.children &&
|
||||
data.children.forEach((value) => {
|
||||
getFullTitle(value, data.fullTitle)
|
||||
})
|
||||
|
||||
return data
|
||||
}
|
||||
Reference in New Issue
Block a user