Add user log item Manage

pull/1471/head
hutanglong 2 years ago
parent 19104a7220
commit 1727caca44

@ -49,5 +49,11 @@ module.exports = {
headers: { headers: {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
}, },
proxy: {
'/hippo4j': {
target: 'http://console.hippo4j.cn',
changeOrigin: true,
},
},
}, },
}; };

@ -3,6 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@ahooksjs/use-url-state": "^3.5.1",
"@ant-design/icons": "^5.2.6", "@ant-design/icons": "^5.2.6",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
@ -12,6 +13,7 @@
"dayjs": "^1.11.9", "dayjs": "^1.11.9",
"i18next": "^23.5.1", "i18next": "^23.5.1",
"i18next-browser-languagedetector": "^7.1.0", "i18next-browser-languagedetector": "^7.1.0",
"lodash": "^4.17.21",
"qs": "^6.11.2", "qs": "^6.11.2",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -49,6 +51,7 @@
"@craco/craco": "^7.1.0", "@craco/craco": "^7.1.0",
"@types/http-errors": "^2.0.1", "@types/http-errors": "^2.0.1",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.2",
"@types/lodash": "^4.14.198",
"@types/node": "^16.18.26", "@types/node": "^16.18.26",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",

@ -1,32 +1,65 @@
import { Suspense } from 'react';
import LayoutCom from './components/layout-com'; import LayoutCom from './components/layout-com';
import { Routes, Route } from 'react-router-dom'; import { Link, Route, Routes } from 'react-router-dom';
import routeList from './route'; import routeList from './route';
import Login from '@/page/login'; import Login from '@/page/login';
import { AppstoreOutlined, MailOutlined } from '@ant-design/icons'; import {
AppstoreOutlined,
MailOutlined,
UsergroupDeleteOutlined,
DiffOutlined,
UserOutlined,
ProjectOutlined,
} from '@ant-design/icons';
import { Spin, ConfigProvider } from 'antd';
const sideMenuList = [ const sideMenuList = [
{ {
label: <a href="/about">about</a>, label: <Link to="/about">about</Link>,
key: 'mail', key: 'mail',
icon: <MailOutlined />, icon: <MailOutlined />,
}, },
{ {
label: <a href="/home"></a>, label: <Link to="/home"></Link>,
key: 'app', key: 'app',
icon: <AppstoreOutlined />, icon: <AppstoreOutlined />,
}, },
{
label: <Link to="/tenant"></Link>,
key: 'tenant',
icon: <UsergroupDeleteOutlined />,
},
{
label: <Link to="/item"></Link>,
key: 'item',
icon: <ProjectOutlined />,
},
{
label: <Link to="/user"></Link>,
key: 'user',
icon: <UserOutlined />,
},
{
label: <Link to="/log"></Link>,
key: 'log',
icon: <DiffOutlined />,
},
]; ];
const App = () => { const App = () => {
return ( return (
<LayoutCom sideMenuList={sideMenuList} isSider={false}> <ConfigProvider>
<Routes> <Suspense fallback={<Spin size="small" />}>
<Route path="/Login" Component={Login}></Route> <LayoutCom sideMenuList={sideMenuList} isSider={true}>
{routeList.map(item => ( <Routes>
<Route key={item.path} path={item.path} Component={item.component} /> <Route path="/Login" Component={Login}></Route>
))} {routeList.map(item => (
</Routes> <Route key={item.path} path={item.path} Component={item.component} />
</LayoutCom> ))}
</Routes>
</LayoutCom>
</Suspense>
</ConfigProvider>
); );
}; };

@ -1,7 +1,7 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import style from './index.module.less'; import style from './index.module.less';
import { UserOutlined } from '@ant-design/icons'; import { UserOutlined } from '@ant-design/icons';
import { Avatar, Button, Col, Dropdown, Row, Switch, Tag } from 'antd'; import { Avatar, Button, Col, Dropdown, Row, Switch } from 'antd';
import useThemeMode from '@/hooks/useThemeMode'; import useThemeMode from '@/hooks/useThemeMode';
import { MyContext } from '@/context'; import { MyContext } from '@/context';
import IconFont from '@/components/icon'; import IconFont from '@/components/icon';

@ -10,13 +10,19 @@
} }
.sider { .sider {
height: calc(100vh - 48px); height: calc(100vh - 48px);
padding-top: 24px; // padding-top: 24px;
}
.menu {
height: 100vh;
}
.breadcrumb {
margin: 16px 0;
} }
.content { .content {
margin: 10px 10px 0px; margin: 0;
border-radius: 12px 12px 0 0; border-radius: 12px 12px 0 0;
min-height: 100%; min-height: 100%;
flex: 1; flex: 1;
padding: 10px 12px; padding: 10px 0;
} }
} }

@ -1,6 +1,6 @@
import { useState, useContext, ReactNode } from 'react'; import { useState, useContext, ReactNode } from 'react';
import { DefaultTheme, ThemeContext } from 'styled-components'; import { DefaultTheme, ThemeContext } from 'styled-components';
import { Layout, Menu } from 'antd'; import { Breadcrumb, Layout, Menu } from 'antd';
import HeaderChild from '../header'; import HeaderChild from '../header';
import { IMenuList } from '@/typings'; import { IMenuList } from '@/typings';
import style from './index.module.less'; import style from './index.module.less';
@ -25,13 +25,26 @@ const LayoutCom = (props: ILayoutCom) => {
<Header className={style.header}> <Header className={style.header}>
<HeaderChild /> <HeaderChild />
</Header> </Header>
<Layout style={{ backgroundColor: myThemes.backgroundColor.bg1, height: 'calc(100vh - 64px)' }}> <Layout style={{ backgroundColor: myThemes.backgroundColor.bg1 }}>
{isSider && ( {isSider && (
<Sider className={style.sider} style={{ backgroundColor: myThemes.backgroundColor.bg1 }}> <Sider className={style.sider} style={{ backgroundColor: myThemes.backgroundColor.bg1 }}>
<Menu onClick={onClick} selectedKeys={[current]} mode="inline" items={sideMenuList} /> <Menu
className={style.menu}
onClick={onClick}
selectedKeys={[current]}
mode="inline"
items={sideMenuList}
/>
</Sider> </Sider>
)} )}
<Content className={style.content}>{children}</Content> <Layout style={{ padding: '0 24px 24px' }}>
<Breadcrumb className={style.breadcrumb}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<Content className={style.content}>{children}</Content>
</Layout>
</Layout> </Layout>
</main> </main>
); );

@ -1,7 +1,7 @@
import { DefaultTheme } from 'styled-components'; import { DefaultTheme } from 'styled-components';
export const lightDefaultTheme: DefaultTheme = { export const lightDefaultTheme: DefaultTheme = {
primary: '#0d68a8', primary: '#1890ff',
baseColor: { baseColor: {
// 前两个是固定的,用于,有颜色按钮 字体颜色等固定不会变的颜色值 // 前两个是固定的,用于,有颜色按钮 字体颜色等固定不会变的颜色值
bc1: '#fff', bc1: '#fff',

@ -0,0 +1,18 @@
import useUrlState from '@ahooksjs/use-url-state';
export const useUrlSet = (options: { form: any }) => {
const { form } = options;
const [state, setState] = useUrlState({});
const setUrl = () => {
const params = form.getFieldsValue();
Object.keys(params).forEach(key => {
if (!params[key]) {
params[key] = undefined;
}
});
setState({ ...params });
};
return { setUrl };
};

@ -0,0 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
}
}

@ -0,0 +1,120 @@
import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import React, { useState } from 'react';
import { fetchTenantList } from './service';
import { useUrlSet } from '@/hooks/useUrlSet';
import style from './index.module.less';
const baseColumns = [
{
title: '序号',
dataIndex: 'id',
},
{
title: '租户',
dataIndex: 'tenantId',
},
{
title: '租户名称',
dataIndex: 'tenantName',
},
{
title: '负责人',
dataIndex: 'owner',
},
{
title: '修改时间',
dataIndex: 'gmtModified',
},
];
const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false);
const [type, setType] = useState('add');
const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const actions = (type: string, item?: any) => {
switch (type) {
case 'add':
setEditVisible(true);
break;
case 'edit':
setEditVisible(true);
break;
case 'delete':
// handleDelete();
break;
default:
break;
}
};
const handleSearch = () => {
setUrl();
search.submit();
};
// const handleDelete = (item: any) => {
// Modal.confirm({
// title: `此操作将删除${item.tenantName}, 是否继续?`,
// onOk: () => {
// search.submit();
// },
// });
// };
return (
<div className={style.tenant_wrapper}>
<Form form={form} wrapperCol={{ span: 23 }}>
<Row>
<Col span={6}>
<Form.Item name="note">
<Input placeholder="租户" />
</Form.Item>
</Col>
<Col span={18}>
<Space>
<Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}>
</Button>
<Button onClick={() => setEditVisible(true)} type="primary" icon={<EditOutlined />}>
</Button>
</Space>
</Col>
</Row>
<Row>
<Col span={6}></Col>
<Col span={18}></Col>
</Row>
</Form>
<Table
{...tableProps}
bordered
rowKey="id"
columns={[
...baseColumns,
{
title: '操作',
key: 'action',
render: (text: string, record: any) => {
return (
<Space>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
</Space>
);
},
},
]}
/>
</div>
);
};
export default Tenant;

@ -0,0 +1,8 @@
import { lazy } from 'react';
import { IRouterList } from '@/typings';
const ItemManage = lazy(() => import('./index'));
const routerList: IRouterList[] = [{ path: '/item', component: () => <ItemManage /> }];
export default routerList;

@ -0,0 +1,79 @@
import request from '@/utils';
const fetchTenantList = async (
pageProps: { current: number; pageSize: number },
formData: { tencent: string | number }
): Promise<{ total: number; list: Array<any> }> => {
const res: any = await request('/hippo4j/v1/cs/tenant/query/page', {
method: 'POST',
headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: {
...formData,
current: pageProps.current,
size: pageProps.pageSize,
desc: true,
},
});
if (res && res.success) {
return {
total: res.data.total,
list: res.data.records,
};
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchAddTenant = async (id: string) => {
const res = await request('/hippo4j/v1/cs/tenant/save', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchDeleteTenant = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchUpdateTenant = async (id: string) => {
const res = await request('hippo4j/v1/cs/tenant/update', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchTenantDetail = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
export { fetchTenantList, fetchAddTenant, fetchDeleteTenant, fetchUpdateTenant, fetchTenantDetail };

@ -0,0 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
}
}

@ -0,0 +1,120 @@
import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import React, { useState } from 'react';
import { fetchTenantList } from './service';
import { useUrlSet } from '@/hooks/useUrlSet';
import style from './index.module.less';
const baseColumns = [
{
title: '序号',
dataIndex: 'id',
},
{
title: '租户',
dataIndex: 'tenantId',
},
{
title: '租户名称',
dataIndex: 'tenantName',
},
{
title: '负责人',
dataIndex: 'owner',
},
{
title: '修改时间',
dataIndex: 'gmtModified',
},
];
const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false);
const [type, setType] = useState('add');
const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const actions = (type: string, item?: any) => {
switch (type) {
case 'add':
setEditVisible(true);
break;
case 'edit':
setEditVisible(true);
break;
case 'delete':
// handleDelete();
break;
default:
break;
}
};
const handleSearch = () => {
setUrl();
search.submit();
};
// const handleDelete = (item: any) => {
// Modal.confirm({
// title: `此操作将删除${item.tenantName}, 是否继续?`,
// onOk: () => {
// search.submit();
// },
// });
// };
return (
<div className={style.tenant_wrapper}>
<Form form={form} wrapperCol={{ span: 23 }}>
<Row>
<Col span={6}>
<Form.Item name="note">
<Input placeholder="租户" />
</Form.Item>
</Col>
<Col span={18}>
<Space>
<Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}>
</Button>
<Button onClick={() => setEditVisible(true)} type="primary" icon={<EditOutlined />}>
</Button>
</Space>
</Col>
</Row>
<Row>
<Col span={6}></Col>
<Col span={18}></Col>
</Row>
</Form>
<Table
{...tableProps}
bordered
rowKey="id"
columns={[
...baseColumns,
{
title: '操作',
key: 'action',
render: (text: string, record: any) => {
return (
<Space>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
</Space>
);
},
},
]}
/>
</div>
);
};
export default Tenant;

@ -0,0 +1,8 @@
import { lazy } from 'react';
import { IRouterList } from '@/typings';
const LogManage = lazy(() => import('./index'));
const routerList: IRouterList[] = [{ path: '/log', component: () => <LogManage /> }];
export default routerList;

@ -0,0 +1,79 @@
import request from '@/utils';
const fetchTenantList = async (
pageProps: { current: number; pageSize: number },
formData: { tencent: string | number }
): Promise<{ total: number; list: Array<any> }> => {
const res: any = await request('/hippo4j/v1/cs/tenant/query/page', {
method: 'POST',
headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: {
...formData,
current: pageProps.current,
size: pageProps.pageSize,
desc: true,
},
});
if (res && res.success) {
return {
total: res.data.total,
list: res.data.records,
};
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchAddTenant = async (id: string) => {
const res = await request('/hippo4j/v1/cs/tenant/save', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchDeleteTenant = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchUpdateTenant = async (id: string) => {
const res = await request('hippo4j/v1/cs/tenant/update', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchTenantDetail = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
export { fetchTenantList, fetchAddTenant, fetchDeleteTenant, fetchUpdateTenant, fetchTenantDetail };

@ -0,0 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
}
}

@ -1,16 +1,20 @@
import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col } from 'antd';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import { useUrlSet } from '@/hooks/useUrlSet';
import { fetchTenantList } from './service'; import { fetchTenantList } from './service';
import style from './index.module.less';
const baseColumns = [ const baseColumns = [
{ {
title: '序号', title: '序号',
dataIndex: 'num', dataIndex: 'id',
}, },
{ {
title: '租户', title: '租户',
dataIndex: 'tenant', dataIndex: 'tenantId',
}, },
{ {
title: '租户名称', title: '租户名称',
@ -18,53 +22,78 @@ const baseColumns = [
}, },
{ {
title: '负责人', title: '负责人',
dataIndex: 'creator', dataIndex: 'owner',
}, },
{ {
title: '修改时间', title: '修改时间',
dataIndex: 'data', dataIndex: 'gmtModified',
}, },
]; ];
const Tenant: React.FC = () => { const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false); const [editVisible, setEditVisible] = useState(false);
const [type, setType] = useState('add');
const [form] = Form.useForm(); const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form }); const { tableProps, search } = useAntdTable(fetchTenantList, { form });
const actions = (type: string) => { // const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const actions = (type: string, item?: any) => {
switch (type) { switch (type) {
case 'create': case 'add':
setEditVisible(true); setEditVisible(true);
break; break;
case 'edit': case 'edit':
setEditVisible(true); setEditVisible(true);
break; break;
case 'delete': case 'delete':
// handleDelete();
break; break;
default: default:
break; break;
} }
}; };
const handleSearch = () => {
setUrl();
search.submit();
};
// const handleDelete = (item: any) => {
// Modal.confirm({
// title: `此操作将删除${item.tenantName}, 是否继续?`,
// onOk: () => {
// search.submit();
// },
// });
// };
return ( return (
<div> <div className={style.tenant_wrapper}>
<Form> <Form form={form} wrapperCol={{ span: 23 }}>
<Row> <Row>
<Col span={6}> <Col span={6}>
<Form.Item name="note" rules={[{ required: true }]}> <Form.Item name="note">
<Input placeholder="租户" /> <Input placeholder="租户" />
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={18}> <Col span={18}>
<Space> <Space>
<Button onClick={() => search.submit()}></Button> <Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}>
<Button onClick={() => setEditVisible(true)}></Button>
</Button>
<Button onClick={() => setEditVisible(true)} type="primary" icon={<EditOutlined />}>
</Button>
</Space> </Space>
</Col> </Col>
</Row> </Row>
<Row>
<Col span={6}></Col>
<Col span={18}></Col>
</Row>
</Form> </Form>
<Table <Table
{...tableProps} {...tableProps}
rowKey="num" bordered
rowKey="id"
columns={[ columns={[
...baseColumns, ...baseColumns,
{ {
@ -73,8 +102,12 @@ const Tenant: React.FC = () => {
render: (text: string, record: any) => { render: (text: string, record: any) => {
return ( return (
<Space> <Space>
<Button onClick={() => actions('edit')}></Button> <Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
<Button onClick={() => actions('edit')}></Button>
</Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
</Space> </Space>
); );
}, },

@ -3,44 +3,77 @@ import request from '@/utils';
const fetchTenantList = async ( const fetchTenantList = async (
pageProps: { current: number; pageSize: number }, pageProps: { current: number; pageSize: number },
formData: { tencent: string | number } formData: { tencent: string | number }
) => { ): Promise<{ total: number; list: Array<any> }> => {
// mock request const res: any = await request('/hippo4j/v1/cs/tenant/query/page', {
return {
total: 3,
list: [
{
num: '1',
tenant: 'admin',
tenantName: 'admin',
creator: 'admin',
data: 'admin',
},
],
};
const res = await request('/tenants', {
method: 'POST', method: 'POST',
params: { headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: {
...formData, ...formData,
pageNum: pageProps.current, current: pageProps.current,
pageSize: pageProps.pageSize, size: pageProps.pageSize,
desc: true,
}, },
}); });
if (res && res.success) { if (res && res.success) {
return { return {
total: 3, total: res.data.total,
list: [ list: res.data.records,
{
num: '1',
tenant: 'admin',
tenantName: 'admin',
creator: 'admin',
data: 'admin',
},
],
}; };
} }
throw new Error(res.msg || '接口异常'); throw new Error(res.msg || '服务器开小差啦~');
};
const fetchAddTenant = async (id: string) => {
const res = await request('/hippo4j/v1/cs/tenant/save', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchDeleteTenant = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchUpdateTenant = async (id: string) => {
const res = await request('hippo4j/v1/cs/tenant/update', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchTenantDetail = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
}; };
export { fetchTenantList }; export { fetchTenantList, fetchAddTenant, fetchDeleteTenant, fetchUpdateTenant, fetchTenantDetail };

@ -0,0 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
}
}

@ -0,0 +1,120 @@
import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import React, { useState } from 'react';
import { fetchTenantList } from './service';
import { useUrlSet } from '@/hooks/useUrlSet';
import style from './index.module.less';
const baseColumns = [
{
title: '序号',
dataIndex: 'id',
},
{
title: '租户',
dataIndex: 'tenantId',
},
{
title: '租户名称',
dataIndex: 'tenantName',
},
{
title: '负责人',
dataIndex: 'owner',
},
{
title: '修改时间',
dataIndex: 'gmtModified',
},
];
const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false);
const [type, setType] = useState('add');
const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const actions = (type: string, item?: any) => {
switch (type) {
case 'add':
setEditVisible(true);
break;
case 'edit':
setEditVisible(true);
break;
case 'delete':
// handleDelete();
break;
default:
break;
}
};
const handleSearch = () => {
setUrl();
search.submit();
};
// const handleDelete = (item: any) => {
// Modal.confirm({
// title: `此操作将删除${item.tenantName}, 是否继续?`,
// onOk: () => {
// search.submit();
// },
// });
// };
return (
<div className={style.tenant_wrapper}>
<Form form={form} wrapperCol={{ span: 23 }}>
<Row>
<Col span={6}>
<Form.Item name="note">
<Input placeholder="租户" />
</Form.Item>
</Col>
<Col span={18}>
<Space>
<Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}>
</Button>
<Button onClick={() => setEditVisible(true)} type="primary" icon={<EditOutlined />}>
</Button>
</Space>
</Col>
</Row>
<Row>
<Col span={6}></Col>
<Col span={18}></Col>
</Row>
</Form>
<Table
{...tableProps}
bordered
rowKey="id"
columns={[
...baseColumns,
{
title: '操作',
key: 'action',
render: (text: string, record: any) => {
return (
<Space>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
</Space>
);
},
},
]}
/>
</div>
);
};
export default Tenant;

@ -0,0 +1,8 @@
import { lazy } from 'react';
import { IRouterList } from '@/typings';
const UserManage = lazy(() => import('./index'));
const routerList: IRouterList[] = [{ path: '/user', component: () => <UserManage /> }];
export default routerList;

@ -0,0 +1,79 @@
import request from '@/utils';
const fetchTenantList = async (
pageProps: { current: number; pageSize: number },
formData: { tencent: string | number }
): Promise<{ total: number; list: Array<any> }> => {
const res: any = await request('/hippo4j/v1/cs/tenant/query/page', {
method: 'POST',
headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: {
...formData,
current: pageProps.current,
size: pageProps.pageSize,
desc: true,
},
});
if (res && res.success) {
return {
total: res.data.total,
list: res.data.records,
};
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchAddTenant = async (id: string) => {
const res = await request('/hippo4j/v1/cs/tenant/save', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchDeleteTenant = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchUpdateTenant = async (id: string) => {
const res = await request('hippo4j/v1/cs/tenant/update', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
const fetchTenantDetail = async (id: string) => {
const res = await request('/tenants', {
method: 'POST',
params: { id },
});
if (res && res.success) {
return res;
}
throw new Error(res.msg || '服务器开小差啦~');
};
export { fetchTenantList, fetchAddTenant, fetchDeleteTenant, fetchUpdateTenant, fetchTenantDetail };

@ -2,6 +2,16 @@ import { IRouterList } from '@/typings';
import homeRouter from '@/page/home/router'; import homeRouter from '@/page/home/router';
import aboutRouter from '@/page/about/router'; import aboutRouter from '@/page/about/router';
import tenantRouter from '@/page/tenant/router'; import tenantRouter from '@/page/tenant/router';
import itemRouter from '@/page/item/router';
import userRouter from '@/page/user/router';
import logRouter from '@/page/log/router';
const routerList: IRouterList[] = [...homeRouter, ...aboutRouter, ...tenantRouter]; const routerList: IRouterList[] = [
...homeRouter,
...aboutRouter,
...tenantRouter,
...itemRouter,
...userRouter,
...logRouter,
];
export default routerList; export default routerList;

@ -1,3 +1,5 @@
import _ from 'lodash';
// is plain object // is plain object
const isPlainObject = (obj: { [key: string]: any }): boolean => { const isPlainObject = (obj: { [key: string]: any }): boolean => {
let proto, Ctor; let proto, Ctor;
@ -8,4 +10,31 @@ const isPlainObject = (obj: { [key: string]: any }): boolean => {
return typeof Ctor === 'function' && Ctor === Object; // insure is new by Object or {} return typeof Ctor === 'function' && Ctor === Object; // insure is new by Object or {}
}; };
export { isPlainObject }; /**
* @description object value
* @param obj
* @returns
*/
const filterEmptyField = (obj: { [key: string]: any }) => {
return _.omitBy(obj, isEmpty);
};
/**
* @description
* @param value
* @returns
*/
const isNilValue = (value: any) => {
return value === undefined || value === '' || value === null || Number.isNaN(value);
};
/**
* @description /
* @param value
* @returns
*/
const isEmpty = (value: any) => {
return typeof value === 'object' ? _.isEmpty(value) : isNilValue(value);
};
export { isPlainObject, isEmpty, filterEmptyField };

@ -32,7 +32,7 @@ type Response<T = any> = {
code?: string | number; code?: string | number;
}; };
let baseURL = 'http://127.0.0.1:9999'; let baseURL = 'http://console.hippo4j.cn';
const inital: RequestOptions = { const inital: RequestOptions = {
method: 'GET', method: 'GET',
@ -104,6 +104,7 @@ function request<T>(url: string, config: RequestOptions): Promise<Response<T>> {
method = method.toUpperCase(); method = method.toUpperCase();
responseType = responseType.toUpperCase(); responseType = responseType.toUpperCase();
config = { config = {
...config,
method, method,
credentials, credentials,
responseType, responseType,
@ -113,6 +114,7 @@ function request<T>(url: string, config: RequestOptions): Promise<Response<T>> {
} else { } else {
config.body = null; config.body = null;
} }
return fetch(url, config as any).then(function onfulfilled(response) { return fetch(url, config as any).then(function onfulfilled(response) {
let { status, statusText } = response; let { status, statusText } = response;
if (status >= 200 && status < 400) { if (status >= 200 && status < 400) {

Loading…
Cancel
Save