Commit f52e72ff by 周志凯

feat: add modal

1 parent 88c50f9d
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
"conventional-changelog": "^3.1.21", "conventional-changelog": "^3.1.21",
"customize-cra": "^1.0.0", "customize-cra": "^1.0.0",
"cz-customizable": "^6.2.0", "cz-customizable": "^6.2.0",
"dayjs": "^1.8.28",
"http-proxy-middleware": "^1.0.4", "http-proxy-middleware": "^1.0.4",
"husky": "^4.2.5", "husky": "^4.2.5",
"less": "^3.11.2", "less": "^3.11.2",
......
...@@ -3,12 +3,12 @@ import { message as $message } from 'antd'; ...@@ -3,12 +3,12 @@ import { message as $message } from 'antd';
const Service = axios.create({ const Service = axios.create({
baseURL: '/api', baseURL: '/api',
timeout: 6000, timeout: 20000,
}); });
Service.interceptors.request.use( Service.interceptors.request.use(
config => { config => {
const aToken = sessionStorage.getItem('aToken') || 'bearer 07a2814e-edc2-4ced-b675-469ec3e08242'; const aToken = sessionStorage.getItem('aToken') || 'bearer fff06119-e69f-4527-a4bc-d4ca613e09be';
aToken && (config.headers.Authorization = aToken); aToken && (config.headers.Authorization = aToken);
return config; return config;
}, },
......
import request from './request'; import request from './request';
const SystemApiUrl = '/oauthSystems/'; const ServiceApiUrl = '/oauthServices/';
interface queryParameter { // interface queryParameter {
page?: number // page?: number
pageSize?: number // pageSize?: number
} // }
interface createData { interface createData {
name: string name: string
...@@ -15,19 +15,18 @@ interface createData { ...@@ -15,19 +15,18 @@ interface createData {
/** /**
* 获取系统列表 * 获取系统列表
*/ */
export const getSystemList = (query?: queryParameter) => { export const getServiceList = () => {
return request({ return request({
url: SystemApiUrl, url: ServiceApiUrl,
method: 'get', method: 'get'
params: query
}) })
} }
/** /**
* 添加系统列表 * 添加系统列表
*/ */
export const createSystem = (data: createData) => { export const createService = (data: createData) => {
return request({ return request({
url: SystemApiUrl, url: ServiceApiUrl,
method: 'post', method: 'post',
data data
}) })
...@@ -35,9 +34,9 @@ export const createSystem = (data: createData) => { ...@@ -35,9 +34,9 @@ export const createSystem = (data: createData) => {
/** /**
* 删除系统 * 删除系统
*/ */
export const deleteSystem = (id: string) => { export const deleteService = (id: string) => {
return request({ return request({
url: SystemApiUrl, url: ServiceApiUrl,
method: 'delete' method: 'delete'
}) })
} }
......
import React, { FC } from 'react'; import React, { FC, useEffect, useState } from 'react';
import { Layout, Menu } from 'antd'; import { Layout, Menu } from 'antd';
import { import {
Link, Link,
...@@ -6,6 +6,8 @@ import { ...@@ -6,6 +6,8 @@ import {
withRouter, withRouter,
RouteComponentProps, RouteComponentProps,
Route, Route,
useLocation,
useHistory,
} from 'react-router-dom'; } from 'react-router-dom';
import routes from '../router'; import routes from '../router';
...@@ -14,55 +16,87 @@ import './PageLayout.less'; ...@@ -14,55 +16,87 @@ import './PageLayout.less';
const { Item } = Menu; const { Item } = Menu;
const { Header, Content, Sider } = Layout; const { Header, Content, Sider } = Layout;
interface MenuItem {
name: string
key: string
path: string
}
interface PageLayoutProp {} interface PageLayoutProp {}
const PageLayout:FC<PageLayoutProp & RouteComponentProps> = () => (
<Layout> const PageLayout:FC<PageLayoutProp & RouteComponentProps> = () => {
<Header className="header"> const history = useHistory()
<div className="logo" /> const { pathname } = useLocation()
</Header> const [selectedKeys, setSelectedKeys] = useState<string[]>([])
const onMenuClick = (menu: MenuItem) => {
console.log(menu)
if (menu.path === pathname) return
const { key, path } = menu
setSelectedKeys([key])
history.replace(path)
}
useEffect(() => {
const findKey = (path: string): any => routes.find(item => item.children ? findKey(path) : path === item.path)
const filterRouteKey = findKey(pathname);
if (filterRouteKey) {
setSelectedKeys(filterRouteKey.key)
history.replace(filterRouteKey.path)
} else {
setSelectedKeys(['SystemSetting'])
history.replace('/system-setting')
}
}, [history, pathname])
return (
<Layout> <Layout>
<Sider width={200} className="site-layout-background"> <Header className="header">
<Menu <div className="logo" />
mode="inline" </Header>
defaultSelectedKeys={['SystemSetting']} <Layout>
style={{ height: '100%', borderRight: 0 }} <Sider width={200} className="site-layout-background">
> <Menu
{routes.map(route => ( mode="inline"
<Item key={route.key}> selectedKeys={selectedKeys}
<Link to={route.path}> style={{ height: '100%', borderRight: 0 }}
<span>{route.name}</span> >
</Link>
</Item>
))}
</Menu>
</Sider>
<Layout style={{ padding: '24px 24px' }}>
{/* <Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb> */}
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 280,
}}
>
<Switch>
{routes.map(route => ( {routes.map(route => (
<Route <Item key={route.key} onClick={ () => onMenuClick(route) }>
key={route.key} <Link to={route.path}>
path={route.path} <span>{route.name}</span>
component={route.component} </Link>
/> </Item>
))} ))}
</Switch> </Menu>
</Content> </Sider>
<Layout style={{ padding: '24px 24px' }}>
{/* <Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb> */}
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 280,
}}
>
<Switch>
{routes.map(route => (
<Route
key={route.key}
path={route.path}
component={route.component}
/>
))}
</Switch>
</Content>
</Layout>
</Layout> </Layout>
</Layout> </Layout>
</Layout> )
) }
export default withRouter(PageLayout); export default withRouter(PageLayout);
import React, { FC } from 'react';
interface AppSettingProp {}
const AppSetting: FC<AppSettingProp> = () => (<div>AppSetting</div>)
export default AppSetting;
import React, { FC } from 'react'; import React, { FC, useState } from 'react';
import { Select, Tree } from 'antd';
const { Option } = Select;
const treeData = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
];
interface MenuManageProp {} interface MenuManageProp {}
const MenuManage: FC<MenuManageProp> = () => (<div>MenuManage</div>) const MenuManage: FC<MenuManageProp> = () => {
const [expandedKeys, setExpandedKeys] = useState<string[]>(['0-0-0', '0-0-1']);
const [checkedKeys, setCheckedKeys] = useState<string[]>(['0-0-0']);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
const onExpand = (expandedKeys: any) => {
console.log('onExpand', expandedKeys);
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
const onCheck = (checkedKeys: any) => {
console.log('onCheck', checkedKeys);
setCheckedKeys(checkedKeys);
};
const onSelect = (selectedKeys: any, info: any) => {
console.log('onSelect', info);
setSelectedKeys(selectedKeys);
};
const onChange = (value: string) => console.log(`selected ${value}`)
const onBlur = () => console.log(`onBlur`)
const onFocus = () => console.log(`onFocus`)
const onSearch = (value: string) => console.log(`search ${value}`)
return (
<>
<Select
showSearch
style={{ width: 200, marginBottom: '10px' }}
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option: any) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="tom">Tom</Option>
</Select>
<Tree
checkable
showLine
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={treeData}
/>
</>
)
}
export default MenuManage; export default MenuManage;
import React, { FC, useState } from 'react';
import { Modal, Form, Select, Tree, Input, Button } from 'antd';
const { Item } = Form;
const { Option } = Select;
const treeData = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
];
interface ServiceProp {
modalVisible: boolean
onCreate: (values: any) => void
onCancel: () => void
}
const ServiceModal: FC<ServiceProp> = ({ modalVisible, onCreate, onCancel }) => {
const [expandedKeys, setExpandedKeys] = useState<string[]>(['0-0-0', '0-0-1']);
const [checkedKeys, setCheckedKeys] = useState<string[]>(['0-0-0']);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
const onExpand = (expandedKeys: any) => {
console.log('onExpand', expandedKeys);
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
const onCheck = (checkedKeys: any) => {
console.log('onCheck', checkedKeys);
setCheckedKeys(checkedKeys);
};
const onSelect = (selectedKeys: any, info: any) => {
console.log('onSelect', info);
setSelectedKeys(selectedKeys);
};
const onChange = (value: string) => console.log(`selected ${value}`)
const onBlur = () => console.log(`onBlur`)
const onFocus = () => console.log(`onFocus`)
const onSearch = (value: string) => console.log(`search ${value}`)
const [form] = Form.useForm()
const onFinish = async () => {
try {
const validateRes = await form.validateFields()
console.log('onFinish::', validateRes)
if (validateRes.errorFields) return
onCreate(validateRes)
form.resetFields()
} catch (error) {
console.log(error)
}
}
const onClose = () => {
form.resetFields()
onCancel()
}
return (
<Modal
title="创建应用"
visible={modalVisible}
destroyOnClose={true}
onOk={onFinish}
onCancel={onClose}
footer={[
<Button type="primary" key="submit" onClick={ onFinish }>
确定
</Button>,
]}
>
<Form
name="systemForm"
form={form}
initialValues={{
name: '',
description: ''
}}
>
<Item
label="系统名称"
name="name"
rules={[{ required: true, message: 'Please select system' }]}
>
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option: any) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="tom">Tom</Option>
</Select>
</Item>
<Item
label="应用名称"
name="name"
rules={[{ required: true, message: 'Please input app name' }]}
>
<Input />
</Item>
<Item
label="应用菜单"
name="appMenu"
rules={[{ required: true, message: 'Please check menu' }]}
>
<Tree
checkable
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={treeData}
/>
</Item>
</Form>
</Modal>
)
}
export default ServiceModal;
import React, { FC, useState, useEffect, useCallback } from 'react';
import { Table, Button, Space } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { ColumnProps } from "antd/es/table";
import dayjs from 'dayjs';
import ServiceModal from './ServiceModal';
import { getServiceList } from "../../api/service.api";
const { Column } = Table;
interface ServiceProp {
createTime: string
description: string
id: number
modifyTime: null
name: string
status: number
}
interface ServiceSettingProp {}
const ServiceSetting: FC<ServiceSettingProp> = () => {
const [modalShow, setModalShow] = useState(false)
const [tableData, setTableData] = useState<ServiceProp[]>()
const initData = useCallback(async () => {
try {
const result = await getServiceList()
console.log('initData', result.data)
if (result.data) {
setTableData(result.data)
}
} catch (error) {
console.log(error)
}
}, [])
useEffect(() => {
initData()
}, [initData])
return (
<div>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={ () => setModalShow(true) }
style={{ marginBottom: '10px' }}
>添加应用</Button>
<Table dataSource={tableData} rowKey="id">
<Column<ColumnProps<ServiceProp>> title="应用ID" dataIndex="id" align="center" />
<Column<ColumnProps<ServiceProp>> title="系统名称" dataIndex="systemName" align="center" />
<Column<ColumnProps<ServiceProp>> title="应用名称" dataIndex="name" align="center" />
<Column<ColumnProps<ServiceProp>>
title="创建时间"
dataIndex="createTime"
align="center"
render={(text) => <span>{text ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '--'}</span>}
/>
<Column<ColumnProps<ServiceProp>>
title="操作"
align="center"
render={() => (
<Space>
<Button
type="link"
size="small"
>编辑</Button>
<Button
type="link"
size="small"
>删除</Button>
</Space>
)}
/>
</Table>
<ServiceModal
modalVisible={modalShow}
onCreate={ (value) => {
console.log(value)
setModalShow(false)
} }
onCancel={ () => setModalShow(false) }
/>
</div>
)
}
export default ServiceSetting;
import React, { FC } from 'react';
import { Modal, Form, Input, Button } from 'antd';
const { Item } = Form
interface systemProp {
modalVisible: boolean
onCreate: (values: any) => void
onCancel: () => void
}
const SystemModal: FC<systemProp> = ({ modalVisible, onCreate, onCancel }) => {
const [form] = Form.useForm()
const onFinish = async () => {
try {
const validateRes = await form.validateFields()
console.log('onFinish::', validateRes)
if (validateRes.errorFields) return
onCreate(validateRes)
form.resetFields()
} catch (error) {
console.log(error)
}
}
const onClose = () => {
form.resetFields()
onCancel()
}
return (
<Modal
title="创建系统"
visible={modalVisible}
destroyOnClose={true}
onOk={onFinish}
onCancel={onClose}
footer={[
<Button type="primary" key="submit" onClick={ onFinish }>
确定
</Button>,
]}
>
<Form
name="systemForm"
form={form}
initialValues={{
name: '',
description: ''
}}
>
<Item
label="系统名称"
name="name"
rules={[{ required: true, message: 'Please input system name' }]}
>
<Input />
</Item>
<Item
label="系统描述"
name="description"
rules={[{ required: true, message: 'Please input description' }]}
>
<Input />
</Item>
</Form>
</Modal>
)
}
export default SystemModal;
import React, { FC, useState, useEffect, useCallback } from 'react'; import React, { FC, useState, useEffect, useCallback } from 'react';
import { Button, Table } from "antd"; import { Table, Button } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { ColumnProps } from "antd/es/table"; import { ColumnProps } from "antd/es/table";
import dayjs from 'dayjs';
import SystemModal from './SystemModal';
import { getSystemList } from "../../api/system.api"; import { getSystemList } from "../../api/system.api";
interface SystemTableProp { // const utc = require('dayjs/plugin/utc');
key: string // dayjs.extend(utc);
systemName: string
systemId: number
createTime: string | Date
}
const columns:ColumnProps<SystemTableProp>[] = [
{
title: '系统ID',
dataIndex: 'systemId',
key: 'systemId',
align: 'center',
},
{
title: '系统名称',
dataIndex: 'systemName',
key: 'systemName',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
},
];
const data: SystemTableProp[] = [ const { Column } = Table;
{
key: '1',
systemName: 'John Brown',
systemId: 32,
createTime: '2020-05-27 12:47:33',
},
{
key: '2',
systemName: 'Jim Green',
systemId: 32,
createTime: '2020-05-27 12:47:33',
},
{
key: '3',
systemName: 'Joe Black',
systemId: 32,
createTime: '2020-05-27 12:47:33',
},
];
interface System {
createTime: string
description: string
id: number
modifyTime: null
name: string
status: number
}
interface SystemSettingProp {} interface SystemSettingProp {}
const SystemSetting: FC<SystemSettingProp> = () => { const SystemSetting: FC<SystemSettingProp> = () => {
const [modalShow, setModalShow] = useState(false)
const [tableData, setTableData] = useState<System[]>()
const initData = useCallback(async () => { const initData = useCallback(async () => {
try { try {
const result = await getSystemList() const result = await getSystemList()
console.log('initData', result) console.log('initData', result.data)
if (result.data) {
setTableData(result.data)
}
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }
...@@ -69,8 +41,30 @@ const SystemSetting: FC<SystemSettingProp> = () => { ...@@ -69,8 +41,30 @@ const SystemSetting: FC<SystemSettingProp> = () => {
}, [initData]) }, [initData])
return ( return (
<div> <div>
<Button type="primary">添加系统</Button> <Button
<Table columns={columns} dataSource={data} /> type="primary"
icon={<PlusOutlined />}
onClick={ () => setModalShow(true) }
style={{ marginBottom: '10px' }}
>添加系统</Button>
<Table dataSource={tableData} rowKey="id">
<Column<ColumnProps<System>> title="系统ID" dataIndex="id" align="center" />
<Column<ColumnProps<System>> title="系统名称" dataIndex="name" align="center" />
<Column<ColumnProps<System>>
title="创建时间"
dataIndex="createTime"
align="center"
render={(text) => <span>{text ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '--'}</span>}
/>
</Table>
<SystemModal
modalVisible={modalShow}
onCreate={ (value) => {
console.log(value)
setModalShow(false)
} }
onCancel={ () => setModalShow(false) }
/>
</div> </div>
) )
} }
......
...@@ -2,7 +2,7 @@ import { RouteComponentProps } from 'react-router-dom'; ...@@ -2,7 +2,7 @@ import { RouteComponentProps } from 'react-router-dom';
import SystemSetting from '../pages/SystemSetting'; import SystemSetting from '../pages/SystemSetting';
import MenuManage from '../pages/MenuManage'; import MenuManage from '../pages/MenuManage';
import AppSetting from '../pages/AppSetting'; import ServiceSetting from '../pages/ServiceSetting';
export interface RouteListProp { export interface RouteListProp {
name: string name: string
...@@ -34,9 +34,9 @@ const routes: RouteListProp[] = [ ...@@ -34,9 +34,9 @@ const routes: RouteListProp[] = [
}, },
{ {
name: '应用设置', name: '应用设置',
key: 'AppSetting', key: 'ServiceSetting',
path: '/app-setting', path: '/service-setting',
component: AppSetting component: ServiceSetting
} }
] ]
......
...@@ -3677,6 +3677,10 @@ dateformat@^3.0.0: ...@@ -3677,6 +3677,10 @@ dateformat@^3.0.0:
version "3.0.3" version "3.0.3"
resolved "https://registry.npm.taobao.org/dateformat/download/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" resolved "https://registry.npm.taobao.org/dateformat/download/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
dayjs@^1.8.28:
version "1.8.28"
resolved "https://registry.npm.taobao.org/dayjs/download/dayjs-1.8.28.tgz#37aa6201df483d089645cb6c8f6cef6f0c4dbc07"
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9" version "2.6.9"
resolved "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" resolved "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!