diff --git a/src/ant-design.d.ts b/src/ant-design.d.ts index f9b7f55..cc5ddae 100644 --- a/src/ant-design.d.ts +++ b/src/ant-design.d.ts @@ -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 = SorterResult type _SortOrder = SortOrder type _CheckboxChangeEvent = CheckboxChangeEvent + type _DataNode = DataNode } diff --git a/src/constants/urls.constants.ts b/src/constants/urls.constants.ts index d494efe..f0aa8fa 100644 --- a/src/constants/urls.constants.ts +++ b/src/constants/urls.constants.ts @@ -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' diff --git a/src/global.d.ts b/src/global.d.ts index 91657ea..aeeaa9e 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -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 } +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[] +} diff --git a/src/main.tsx b/src/main.tsx index 1d2932f..53aeaaa 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -8,7 +8,10 @@ import { COLOR_MAIN } from '@/constants/common.constants' ReactDOM.createRoot(document.getElementById('root')!).render( - + diff --git a/src/pages/system/Log.tsx b/src/pages/system/Log.tsx index caebc92..71a722f 100644 --- a/src/pages/system/Log.tsx +++ b/src/pages/system/Log.tsx @@ -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 = () => { diff --git a/src/pages/system/Role.tsx b/src/pages/system/Role.tsx index eecd05b..05c1804 100644 --- a/src/pages/system/Role.tsx +++ b/src/pages/system/Role.tsx @@ -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([]) + const [loading, setLoading] = useState(false) + const [tableParams, setTableParams] = useState({ + pagination: { + current: 1, + pageSize: 20, + position: ['bottomCenter'] + } + }) + const [searchName, setSearchName] = useState('') + const [useRegex, setUseRegex] = useState(false) + const [isRegexLegal, setIsRegexLegal] = useState(true) + + const dataColumns: _ColumnsType = [ + { + title: '名称', + dataIndex: 'name', + width: '20%' + }, + { + title: '权限', + dataIndex: 'tree', + render: (value: _DataNode[]) => + }, + { + title: '状态', + dataIndex: 'enable', + width: '0', + align: 'center', + render: (value) => + value ? 启用 : 禁用 + } + ] + + const handleOnTableChange = ( + pagination: _TablePaginationConfig, + filters: Record, + sorter: _SorterResult | _SorterResult[] + ) => { + 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) => { + 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() + const elementMap = new Map() + const operationMap = new Map() + + 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 ( + <> + + + + + + record.id} + pagination={tableParams.pagination} + loading={loading} + onChange={handleOnTableChange} + /> + + + + + + ) } export default Role diff --git a/src/services/system.tsx b/src/services/system.tsx index c5ff320..ae3fa72 100644 --- a/src/services/system.tsx +++ b/src/services/system.tsx @@ -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>(URL_API_SYS_LOG, { ...param }) + +export const r_getRole = (parm: GetRoleParams) => + request.get>(URL_API_SYS_ROLE, { ...parm }) diff --git a/src/utils/common.ts b/src/utils/common.ts index ffe9f7e..84f4e30 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -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 + } + } +}