Complete main UI #37
2
src/ant-design.d.ts
vendored
2
src/ant-design.d.ts
vendored
@@ -3,6 +3,7 @@ import { CustomIconComponentProps } from '@ant-design/icons/es/components/Icon'
|
||||
import { TablePaginationConfig } from 'antd/lib'
|
||||
import { ColumnsType, FilterValue, SorterResult, SortOrder } from 'antd/es/table/interface'
|
||||
import { CheckboxChangeEvent } from 'antd/es/checkbox'
|
||||
import type { DataNode } from 'antd/es/tree'
|
||||
|
||||
declare global {
|
||||
type IconComponent =
|
||||
@@ -16,4 +17,5 @@ declare global {
|
||||
type _SorterResult<T> = SorterResult<T>
|
||||
type _SortOrder = SortOrder
|
||||
type _CheckboxChangeEvent = CheckboxChangeEvent
|
||||
type _DataNode = DataNode
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@ export const URL_API_LOGOUT = '/logout'
|
||||
export const URL_API_SYS_LOG = '/system/log'
|
||||
export const URL_API_USER_INFO = '/system/user/info'
|
||||
export const URL_API_USER_LIST = '/system/user'
|
||||
export const URL_API_SYS_ROLE = '/system/role'
|
||||
|
||||
31
src/global.d.ts
vendored
31
src/global.d.ts
vendored
@@ -111,6 +111,7 @@ interface MenuVo {
|
||||
url: string
|
||||
powerId: number
|
||||
parentId: number
|
||||
moduleId: number
|
||||
}
|
||||
|
||||
interface ElementVo {
|
||||
@@ -161,13 +162,6 @@ interface PageParam {
|
||||
sortOrder?: string
|
||||
}
|
||||
|
||||
interface GetSysLogParams extends PageParam {
|
||||
searchRequestUrl?: string
|
||||
searchRegex?: boolean
|
||||
searchStartTime?: string
|
||||
searchEndTime?: string
|
||||
}
|
||||
|
||||
interface TableParams {
|
||||
pagination?: _TablePaginationConfig
|
||||
sortField?: React.Key | readonly React.Key[]
|
||||
@@ -175,6 +169,13 @@ interface TableParams {
|
||||
filters?: Record<string, _FilterValue | null>
|
||||
}
|
||||
|
||||
interface GetSysLogParams extends PageParam {
|
||||
searchRequestUrl?: string
|
||||
searchRegex?: boolean
|
||||
searchStartTime?: string
|
||||
searchEndTime?: string
|
||||
}
|
||||
|
||||
interface SysLogGetVo {
|
||||
id: string
|
||||
logType: string
|
||||
@@ -193,3 +194,19 @@ interface SysLogGetVo {
|
||||
userAgent: string
|
||||
operateUsername: string
|
||||
}
|
||||
|
||||
interface GetRoleParams extends PageParam {
|
||||
searchName?: string
|
||||
searchRegex?: boolean
|
||||
}
|
||||
|
||||
interface RoleWithPowerGetVo {
|
||||
id: string
|
||||
name: string
|
||||
enable: string
|
||||
modules: ModuleVo[]
|
||||
menus: MenuVo[]
|
||||
elements: ElementVo[]
|
||||
operations: OperationVo[]
|
||||
tree: _DataNode[]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ import { COLOR_MAIN } from '@/constants/common.constants'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<AntdConfigProvider theme={{ token: { colorPrimary: COLOR_MAIN } }} locale={zh_CN}>
|
||||
<AntdConfigProvider
|
||||
theme={{ token: { colorPrimary: COLOR_MAIN, colorBgContainer: 'transparent' } }}
|
||||
locale={zh_CN}
|
||||
>
|
||||
<App />
|
||||
</AntdConfigProvider>
|
||||
</React.StrictMode>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from 'react'
|
||||
import FitFullScreen from '@/components/common/FitFullScreen.tsx'
|
||||
import FitFullScreen from '@/components/common/FitFullScreen'
|
||||
import Card from '@/components/common/Card'
|
||||
import { r_getSysLog } from '@/services/system.tsx'
|
||||
import { r_getSysLog } from '@/services/system'
|
||||
import {
|
||||
COLOR_ERROR_SECONDARY,
|
||||
COLOR_FONT_SECONDARY,
|
||||
DATABASE_SELECT_SUCCESS
|
||||
} from '@/constants/common.constants.ts'
|
||||
import HideScrollbar from '@/components/common/HideScrollbar.tsx'
|
||||
import { getLocalTime } from '@/utils/common.ts'
|
||||
} from '@/constants/common.constants'
|
||||
import HideScrollbar from '@/components/common/HideScrollbar'
|
||||
import { getLocalTime } from '@/utils/common'
|
||||
import FlexBox from '@/components/common/FlexBox'
|
||||
|
||||
const Log: React.FC = () => {
|
||||
|
||||
@@ -1,7 +1,265 @@
|
||||
import React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import FitFullScreen from '@/components/common/FitFullScreen'
|
||||
import HideScrollbar from '@/components/common/HideScrollbar'
|
||||
import FlexBox from '@/components/common/FlexBox'
|
||||
import Card from '@/components/common/Card'
|
||||
import { r_getRole } from '@/services/system.tsx'
|
||||
import { DATABASE_SELECT_SUCCESS } from '@/constants/common.constants.ts'
|
||||
|
||||
const Role: React.FC = () => {
|
||||
return <></>
|
||||
const [roleData, setRoleData] = useState<RoleWithPowerGetVo[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [tableParams, setTableParams] = useState<TableParams>({
|
||||
pagination: {
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
position: ['bottomCenter']
|
||||
}
|
||||
})
|
||||
const [searchName, setSearchName] = useState('')
|
||||
const [useRegex, setUseRegex] = useState(false)
|
||||
const [isRegexLegal, setIsRegexLegal] = useState(true)
|
||||
|
||||
const dataColumns: _ColumnsType<RoleWithPowerGetVo> = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '权限',
|
||||
dataIndex: 'tree',
|
||||
render: (value: _DataNode[]) => <AntdTree treeData={value} />
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'enable',
|
||||
width: '0',
|
||||
align: 'center',
|
||||
render: (value) =>
|
||||
value ? <AntdTag color={'success'}>启用</AntdTag> : <AntdTag>禁用</AntdTag>
|
||||
}
|
||||
]
|
||||
|
||||
const handleOnTableChange = (
|
||||
pagination: _TablePaginationConfig,
|
||||
filters: Record<string, _FilterValue | null>,
|
||||
sorter: _SorterResult<RoleWithPowerGetVo> | _SorterResult<RoleWithPowerGetVo>[]
|
||||
) => {
|
||||
if (Array.isArray(sorter)) {
|
||||
setTableParams({
|
||||
pagination,
|
||||
filters,
|
||||
sortField: sorter.map((value) => value.field).join(',')
|
||||
})
|
||||
} else {
|
||||
setTableParams({
|
||||
pagination,
|
||||
filters,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order
|
||||
})
|
||||
}
|
||||
|
||||
if (pagination.pageSize !== tableParams.pagination?.pageSize) {
|
||||
setRoleData([])
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnSearchNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchName(e.target.value)
|
||||
|
||||
if (useRegex) {
|
||||
try {
|
||||
RegExp(e.target.value)
|
||||
setIsRegexLegal(!(e.target.value.includes('{}') || e.target.value.includes('[]')))
|
||||
} catch (e) {
|
||||
setIsRegexLegal(false)
|
||||
}
|
||||
} else {
|
||||
setIsRegexLegal(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnSearchNameKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
getRole()
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnUseRegexChange = (e: _CheckboxChangeEvent) => {
|
||||
setUseRegex(e.target.checked)
|
||||
if (e.target.checked) {
|
||||
try {
|
||||
RegExp(searchName)
|
||||
setIsRegexLegal(!(searchName.includes('{}') || searchName.includes('[]')))
|
||||
} catch (e) {
|
||||
setIsRegexLegal(false)
|
||||
}
|
||||
} else {
|
||||
setIsRegexLegal(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnQueryBtnClick = () => {
|
||||
getRole()
|
||||
}
|
||||
|
||||
const getRole = () => {
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isRegexLegal) {
|
||||
void message.error({
|
||||
content: '非法正则表达式'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
|
||||
void r_getRole({
|
||||
currentPage: tableParams.pagination?.current,
|
||||
pageSize: tableParams.pagination?.pageSize,
|
||||
sortField:
|
||||
tableParams.sortField && tableParams.sortOrder
|
||||
? (tableParams.sortField as string)
|
||||
: undefined,
|
||||
sortOrder:
|
||||
tableParams.sortField && tableParams.sortOrder ? tableParams.sortOrder : undefined,
|
||||
searchName: searchName.trim().length ? searchName : undefined,
|
||||
searchRegex: useRegex ? useRegex : undefined,
|
||||
...tableParams.filters
|
||||
})
|
||||
.then((res) => {
|
||||
const data = res.data
|
||||
if (data.code === DATABASE_SELECT_SUCCESS) {
|
||||
const records = data.data?.records
|
||||
|
||||
records?.map((value) => {
|
||||
const menuMap = new Map<number, _DataNode[]>()
|
||||
const elementMap = new Map<number, _DataNode[]>()
|
||||
const operationMap = new Map<number, _DataNode[]>()
|
||||
|
||||
value.operations.forEach((operation) => {
|
||||
if (
|
||||
operationMap.has(operation.elementId) &&
|
||||
operationMap.get(operation.elementId) !== null
|
||||
) {
|
||||
operationMap
|
||||
.get(operation.elementId)
|
||||
?.push({ title: operation.name, key: operation.powerId })
|
||||
} else {
|
||||
operationMap.set(operation.elementId, [
|
||||
{ title: operation.name, key: operation.powerId }
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
value.elements.forEach((element) => {
|
||||
if (
|
||||
elementMap.has(element.menuId) &&
|
||||
elementMap.get(element.menuId) !== null
|
||||
) {
|
||||
elementMap.get(element.menuId)?.push({
|
||||
title: element.name,
|
||||
key: element.powerId,
|
||||
children: operationMap.get(element.id)
|
||||
})
|
||||
} else {
|
||||
elementMap.set(element.menuId, [
|
||||
{
|
||||
title: element.name,
|
||||
key: element.powerId,
|
||||
children: operationMap.get(element.id)
|
||||
}
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
value.menus.forEach((menu) => {
|
||||
if (menuMap.has(menu.moduleId) && menuMap.get(menu.moduleId) !== null) {
|
||||
menuMap.get(menu.moduleId)?.push({
|
||||
title: menu.name,
|
||||
key: menu.powerId,
|
||||
children: elementMap.get(menu.id)
|
||||
})
|
||||
} else {
|
||||
menuMap.set(menu.moduleId, [
|
||||
{
|
||||
title: menu.name,
|
||||
key: menu.powerId,
|
||||
children: elementMap.get(menu.id)
|
||||
}
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
value.tree = value.modules.map((module) => ({
|
||||
title: module.name,
|
||||
key: module.powerId,
|
||||
children: menuMap.get(module.id)
|
||||
}))
|
||||
|
||||
return value
|
||||
})
|
||||
|
||||
records && setRoleData(records)
|
||||
data.data &&
|
||||
setTableParams({
|
||||
...tableParams,
|
||||
pagination: {
|
||||
...tableParams.pagination,
|
||||
total: data.data.total
|
||||
}
|
||||
})
|
||||
} else {
|
||||
void message.error({
|
||||
content: '获取失败,请稍后重试'
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getRole()
|
||||
}, [
|
||||
JSON.stringify(tableParams.filters),
|
||||
JSON.stringify(tableParams.sortField),
|
||||
JSON.stringify(tableParams.sortOrder),
|
||||
JSON.stringify(tableParams.pagination?.pageSize),
|
||||
JSON.stringify(tableParams.pagination?.current)
|
||||
])
|
||||
|
||||
return (
|
||||
<>
|
||||
<FitFullScreen>
|
||||
<HideScrollbar
|
||||
style={{ padding: 30 }}
|
||||
isShowVerticalScrollbar
|
||||
autoHideWaitingTime={500}
|
||||
>
|
||||
<FlexBox gap={20}>
|
||||
<FlexBox direction={'horizontal'} gap={10}></FlexBox>
|
||||
<Card>
|
||||
<AntdTable
|
||||
dataSource={roleData}
|
||||
columns={dataColumns}
|
||||
rowKey={(record) => record.id}
|
||||
pagination={tableParams.pagination}
|
||||
loading={loading}
|
||||
onChange={handleOnTableChange}
|
||||
/>
|
||||
</Card>
|
||||
</FlexBox>
|
||||
</HideScrollbar>
|
||||
</FitFullScreen>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Role
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import request from '@/services/index'
|
||||
import { URL_API_SYS_LOG } from '@/constants/urls.constants'
|
||||
import { URL_API_SYS_LOG, URL_API_SYS_ROLE } from '@/constants/urls.constants'
|
||||
|
||||
export const r_getSysLog = (param: GetSysLogParams) =>
|
||||
request.get<PageVo<SysLogGetVo>>(URL_API_SYS_LOG, { ...param })
|
||||
|
||||
export const r_getRole = (parm: GetRoleParams) =>
|
||||
request.get<PageVo<RoleWithPowerGetVo>>(URL_API_SYS_ROLE, { ...parm })
|
||||
|
||||
@@ -144,3 +144,16 @@ export const getRedirectUrl = (path: string, redirectUrl: string): string => {
|
||||
export const getLocalTime = (utcTime: string, format: string = 'yyyy-MM-DD HH:mm:ssZ') => {
|
||||
return moment.utc(utcTime).local().format(format)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user