diff --git a/.stylelintrc.js b/.stylelintrc.js index 38d55358192140d41c9d90a1eadc44f58b6ca8a3..9ab1191a4841eaacfdf2b10dcdb71a693a746966 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -9,7 +9,7 @@ module.exports = { ignoreFiles: ['build/**/*', 'public/**/*', 'src/common/style/**/*'], rules: { 'no-empty-source': null, - 'selector-class-pattern': '^[a-z][a-zA-Z0-9]+$', + 'selector-class-pattern': '^[a-z][a-zA-Z0-9-]+$', 'selector-pseudo-class-no-unknown': [ true, { diff --git a/src/components/Layout/LeftRight/index.module.scss b/src/components/Layout/LeftRight/index.module.scss new file mode 100644 index 0000000000000000000000000000000000000000..306a06250b693f3d81cb225af4f3a46d51c6fe9b --- /dev/null +++ b/src/components/Layout/LeftRight/index.module.scss @@ -0,0 +1,30 @@ +.main { + display: flex; + width: 100%; + height: 100%; +} + +.left { + border-right: 1px solid #555; + height: 100%; + + :global { + .ant-menu-inline { + width: 180px; + } + } +} + +.control { + overflow: hidden; +} + +.controlIcon { + float: right; +} + +.right { + overflow-y: auto; + height: 100%; + flex-grow: 1; +} diff --git a/src/components/Layout/LeftRight/index.tsx b/src/components/Layout/LeftRight/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3f4d0e6af33e8bc50bbb820aca1ae69777cf86ef --- /dev/null +++ b/src/components/Layout/LeftRight/index.tsx @@ -0,0 +1,54 @@ +import React from 'react' +import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons' +import { MenuProps, Button, Menu } from 'antd' +import { useNavigate } from 'react-router-dom' +import styles from './index.module.scss' + +interface Props { + left: React.ReactNode | MenuItem[] + right: React.ReactNode + menuKeys?: string[] +} + +type MenuItem = Required['items'][number] + +const LeftRight: React.FC = ({ left, right, menuKeys = [] }) => { + const [collapsed, setCollapsed] = React.useState(false) + const navigate = useNavigate() + const toggleCollapsed = () => { + setCollapsed(!collapsed) + } + let leftNode: React.ReactNode + if (left instanceof Array) { + leftNode = ( + <> +
+ +
+ navigate(item.key)} + items={left.map(row => ({ ...row, key: `${row?.key}?type=menu` }))} + /> + + ) + } else { + leftNode = left + } + return ( +
+
{leftNode}
+
{right}
+
+ ) +} + +export default LeftRight diff --git a/src/pages/apps/Routers.tsx b/src/pages/apps/Routers.tsx new file mode 100644 index 0000000000000000000000000000000000000000..67ca46f3798d86c88e3b009a32c8e6380ca4840e --- /dev/null +++ b/src/pages/apps/Routers.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import { Routes, Route } from 'react-router-dom' +import Management from './management' + +const Routers: React.FC = () => { + return ( + + } /> + + ) +} + +export default Routers diff --git a/src/pages/apps/index.tsx b/src/pages/apps/index.tsx index 37047113eeee59a537c338ebd073f771a104d56f..e989894898e2f694c9d47e094529e12109ea4373 100644 --- a/src/pages/apps/index.tsx +++ b/src/pages/apps/index.tsx @@ -1,14 +1,8 @@ import React from 'react' -import { Routes, Route } from 'react-router-dom' -import Management from './management' +import Routers from './Routers' const Apps: React.FC = () => { - return ( - - asd - } /> - - ) + return } export default Apps diff --git a/src/pages/apps/management/Routers.tsx b/src/pages/apps/management/Routers.tsx new file mode 100644 index 0000000000000000000000000000000000000000..09a46868a177057019ab3f601f407387b0eae12b --- /dev/null +++ b/src/pages/apps/management/Routers.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import { Routes, Route } from 'react-router-dom' +import Userinfo from './user/userinfo' +import Privileges from './system/privileges' +import Role from './system/role' + +const Routers: React.FC = () => { + return ( + + } /> + } /> + } /> + + ) +} + +export default Routers diff --git a/src/pages/apps/management/index.module.scss b/src/pages/apps/management/index.module.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/pages/apps/management/index.tsx b/src/pages/apps/management/index.tsx index dda32313050977d7da1b09080b4d722bdeec4ad1..2f744367e7ce0f72fb9cd38830317ce8573e0933 100644 --- a/src/pages/apps/management/index.tsx +++ b/src/pages/apps/management/index.tsx @@ -1,13 +1,36 @@ import React from 'react' -import { Routes, Route } from 'react-router-dom' -import Userinfo from './user/userinfo' +import Routers from './Routers' +import { AlignLeftOutlined, UserOutlined } from '@ant-design/icons' +import { useSearchParams, useLocation } from 'react-router-dom' +import styles from './index.module.scss' +import LeftRight from '@/components/Layout/LeftRight' const Management: React.FC = () => { - return ( - - } /> - - ) + const [params] = useSearchParams() + const location = useLocation() + const type = params.getAll('type')[0] + if (type === 'menu') { + return ( + + }, + { + label: '角色管理', + key: '/apps/manage/role', + icon: + } + ]} + menuKeys={[`${location.pathname}${location.search}`]} + right={} + /> + ) + } else { + return + } } export default Management diff --git a/src/pages/apps/management/system/privileges/index.module.scss b/src/pages/apps/management/system/privileges/index.module.scss new file mode 100644 index 0000000000000000000000000000000000000000..93319b7a1d047dcb75657305944566fc49fa8289 --- /dev/null +++ b/src/pages/apps/management/system/privileges/index.module.scss @@ -0,0 +1,7 @@ +.icon { + margin-left: 15px; +} + +.control { + margin-bottom: 15px; +} diff --git a/src/pages/apps/management/system/privileges/index.tsx b/src/pages/apps/management/system/privileges/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9e4b8e9273108445f8290ac4f0a6e0fef57f22fd --- /dev/null +++ b/src/pages/apps/management/system/privileges/index.tsx @@ -0,0 +1,216 @@ +import React from 'react' +import { EditOutlined, DeleteOutlined } from '@ant-design/icons' +import { Button, Tree, Popconfirm, Modal, Form, Input, TreeSelect } from 'antd' +import styles from './index.module.scss' +import type { DataNode } from 'antd/es/tree' +import View from '@/components/View' +import useMethods from '@utils/useMethods' + +interface Props {} + +interface Data extends DataNode { + pid: string + children?: Data[] +} + +const initData = [ + { + title: 'parent 1', + key: '0-0', + pid: '0', + children: [ + { + title: 'parent 1-0', + key: '0-0-0', + pid: '0-0', + children: [ + { title: 'leaf', key: '0-0-0-0', pid: '0-0-0' }, + { + title: 'multiple', + pid: '0-0-0', + key: '0-0-0-1' + }, + { title: 'leaf', key: '0-0-0-2', pid: '0-0-0' } + ] + }, + { + title: 'parent 1-1', + key: '0-0-1', + pid: '0-0', + children: [{ title: 'leaf', key: '0-0-1-0', pid: '0-0-1' }] + }, + { + title: 'parent 1-2', + key: '0-0-2', + pid: '0-0', + children: [ + { title: 'leaf', key: '0-0-2-0', pid: '0-0-2' }, + { + title: 'leaf', + pid: '0-0-2', + key: '0-0-2-1' + } + ] + } + ] + }, + { + title: 'parent 2', + key: '0-1', + pid: '0', + children: [ + { + title: 'parent 2-0', + key: '0-1-0', + pid: '0-1', + children: [ + { title: 'leaf', key: '0-1-0-0', pid: '0-1-0' }, + { title: 'leaf', key: '0-1-0-1', pid: '0-1-0' } + ] + } + ] + } +] + +interface PrivilegesData { + name: string + pid: string +} + +const Privileges: React.FC = () => { + const [data, setData] = React.useState(initData) + const [open, setOpen] = React.useState(false) + const [form] = Form.useForm() + const [confirmLoading, setConfirmLoading] = React.useState(false) + const { generalData } = useMethods({ + generalData(data: Data[]) { + return data.map(row => { + const obj: Data = { + ...row, + title: ( + <> + {row.title} + { + form.setFieldsValue({ + name: row.title as string, + pid: row.pid + }) + setOpen(true) + }} + /> + {!row.children && ( + {}} + okText="删除" + cancelText="取消"> + + + )} + + ) + } + if (row.children) { + obj.children = generalData(row.children) + } + return obj + }) + } + }) + const treeData = React.useMemo(() => { + return generalData(data) + }, [data]) // eslint-disable-line + const handleOk = () => { + setConfirmLoading(true) + form + .validateFields() + .then((values: PrivilegesData) => { + console.log(values) + setTimeout(() => { + setOpen(false) + setConfirmLoading(false) + }, 2000) + }) + .catch(() => { + setConfirmLoading(false) + return + }) + } + + const handleCancel = () => { + console.log('Clicked cancel button') + setOpen(false) + } + const onFinish = (values: any) => { + console.log('Success:', values) + } + + const onFinishFailed = (errorInfo: any) => { + console.log('Failed:', errorInfo) + } + return ( +
+ + +
+ +
+ +
+ +
+ + + + + + + +
+
+
+ ) +} + +export default Privileges diff --git a/src/pages/apps/management/system/role/index.module.scss b/src/pages/apps/management/system/role/index.module.scss new file mode 100644 index 0000000000000000000000000000000000000000..93011788da48d23cbeb045b40f3d41a9a57d5f49 --- /dev/null +++ b/src/pages/apps/management/system/role/index.module.scss @@ -0,0 +1,3 @@ +.role { + display: block; +} diff --git a/src/pages/apps/management/system/role/index.tsx b/src/pages/apps/management/system/role/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9d2cfbda496c8f9660940888ff0becc34722c0b4 --- /dev/null +++ b/src/pages/apps/management/system/role/index.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import styles from './index.module.scss' + +interface Props {} + +const Role: React.FC = () => { + return
角色管理
+} + +export default Role