handle merge

pull/1479/head
yikai 2 years ago
commit 063867d9af

@ -13,6 +13,8 @@
"antd": "^5.4.7", "antd": "^5.4.7",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"dayjs": "^1.11.9", "dayjs": "^1.11.9",
"echarts": "^5.4.3",
"echarts-for-react": "^3.0.2",
"i18next": "^23.5.1", "i18next": "^23.5.1",
"i18next-browser-languagedetector": "^7.1.0", "i18next-browser-languagedetector": "^7.1.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",

@ -1,3 +1,4 @@
// import { Suspense } from 'react';
import LayoutCom from './components/layout-com'; import LayoutCom from './components/layout-com';
import { Routes, Route, Link } from 'react-router-dom'; import { Routes, Route, Link } from 'react-router-dom';
import routeList from './route'; import routeList from './route';
@ -18,6 +19,26 @@ const App = () => {
{ label: <Link to={'/thread-poll/index'}>{useTran(STR_MAP.THREAD_POOL)}</Link>, key: '/thread-poll/index' }, { label: <Link to={'/thread-poll/index'}>{useTran(STR_MAP.THREAD_POOL)}</Link>, key: '/thread-poll/index' },
], ],
}, },
{
label: <Link to={'/tenant'}>{useTran(STR_MAP.TENANT_MANAGE)}</Link>,
key: STR_MAP.TENANT_MANAGE,
icon: <IconFont type="icon-hot-for-ux"></IconFont>,
},
{
label: <Link to={'/item'}>{useTran(STR_MAP.PROJECT_MANAGE)}</Link>,
key: STR_MAP.PROJECT_MANAGE,
icon: <IconFont type="icon-hot-for-ux"></IconFont>,
},
{
label: <Link to={'/user'}>{useTran(STR_MAP.USER_MANAGE)}</Link>,
key: STR_MAP.USER_MANAGE,
icon: <IconFont type="icon-hot-for-ux"></IconFont>,
},
{
label: <Link to={'/log'}>{useTran(STR_MAP.LOG_MANAGE)}</Link>,
key: STR_MAP.LOG_MANAGE,
icon: <IconFont type="icon-hot-for-ux"></IconFont>,
},
]; ];
return ( return (

@ -1,4 +1,5 @@
export enum STR_MAP { export enum STR_MAP {
GLOBAL_TITLE = 'globalTitle',
DYNAMIC_THREAD_POOL = 'dynamicThreadPool', DYNAMIC_THREAD_POOL = 'dynamicThreadPool',
THREAD_POOL_MANAGE = 'threadPoolManage', THREAD_POOL_MANAGE = 'threadPoolManage',
PROJECT = 'project', PROJECT = 'project',
@ -15,6 +16,17 @@ export enum STR_MAP {
EXECUTION_TIMEOUT = 'executionTimeout', EXECUTION_TIMEOUT = 'executionTimeout',
ALARM_OR_NOT = 'alarmOrNot', ALARM_OR_NOT = 'alarmOrNot',
CREATION_TIME = 'creationTime', CREATION_TIME = 'creationTime',
UPDATE_TIME = 'update time', UPDATE_TIME = 'updateTime',
EDIT = 'edit', EDIT = 'edit',
TENANT_MANAGE = 'tenantManage',
LOG_MANAGE = 'logManage',
PROJECT_MANAGE = 'projectManage',
USER_MANAGE = 'userManage',
LOGIN_SUCCESSFUL = 'loginSuccessful',
USER_INPUT_MESSAGE = 'userInputMessage',
USRE_NAME = 'username',
PASSWORD_INPUT_MESSAGE = 'passwordInputMessage',
REMERBER_PASSWORD = 'rememberPassWord',
FORGOT_PASSWORD = 'forgotPassword',
ACCOUNT_PASSWORD_LOGIN = 'accountPasswordLogin',
} }

@ -19,6 +19,18 @@ const enTranslationMap: { [key: string]: string } = {
[STR_MAP.CREATION_TIME]: 'creation time', [STR_MAP.CREATION_TIME]: 'creation time',
[STR_MAP.UPDATE_TIME]: 'update time', [STR_MAP.UPDATE_TIME]: 'update time',
[STR_MAP.EDIT]: 'edit', [STR_MAP.EDIT]: 'edit',
[STR_MAP.TENANT_MANAGE]: 'tenant management',
[STR_MAP.PROJECT_MANAGE]: 'project management',
[STR_MAP.USER_MANAGE]: 'user management',
[STR_MAP.LOG_MANAGE]: 'log management',
[STR_MAP.LOGIN_SUCCESSFUL]: 'login successful',
[STR_MAP.USER_INPUT_MESSAGE]: 'please enter your username',
[STR_MAP.USRE_NAME]: 'username',
[STR_MAP.PASSWORD_INPUT_MESSAGE]: 'please enter password',
[STR_MAP.REMERBER_PASSWORD]: 'remember the password',
[STR_MAP.FORGOT_PASSWORD]: 'forgot password',
[STR_MAP.ACCOUNT_PASSWORD_LOGIN]: 'account password login',
[STR_MAP.GLOBAL_TITLE]: `The world's best thread pool management tool`,
}; };
export default enTranslationMap; export default enTranslationMap;

@ -19,6 +19,18 @@ const zhTranslationMap: { [key: string]: string } = {
[STR_MAP.CREATION_TIME]: '创建时间', [STR_MAP.CREATION_TIME]: '创建时间',
[STR_MAP.UPDATE_TIME]: '更新时间', [STR_MAP.UPDATE_TIME]: '更新时间',
[STR_MAP.EDIT]: '操作', [STR_MAP.EDIT]: '操作',
[STR_MAP.TENANT_MANAGE]: '租户管理',
[STR_MAP.PROJECT_MANAGE]: '项目管理',
[STR_MAP.USER_MANAGE]: '用户管理',
[STR_MAP.LOG_MANAGE]: '日志管理',
[STR_MAP.LOGIN_SUCCESSFUL]: '登录成功',
[STR_MAP.USER_INPUT_MESSAGE]: '请输入用户名',
[STR_MAP.USRE_NAME]: '用户名',
[STR_MAP.PASSWORD_INPUT_MESSAGE]: '请输入密码',
[STR_MAP.REMERBER_PASSWORD]: '记住密码',
[STR_MAP.FORGOT_PASSWORD]: '忘记密码',
[STR_MAP.ACCOUNT_PASSWORD_LOGIN]: '账号密码登录',
[STR_MAP.GLOBAL_TITLE]: `全球最好用的线程池管理工具`,
}; };
export default zhTranslationMap; export default zhTranslationMap;

@ -25,12 +25,12 @@ export const defaultAlgorithm = {
// paddingContentVerticalLG: 4, // paddingContentVerticalLG: 4,
}, },
Modal: { Modal: {
borderRadiusLG: 2, // borderRadiusLG: 2,
borderRadiusSM: 2, // borderRadiusSM: 2,
colorText: lightDefaultTheme.fontColor.fc3, // colorText: lightDefaultTheme.fontColor.fc3,
borderRadius: 2, // borderRadius: 2,
paddingContentHorizontalLG: 0, // paddingContentHorizontalLG: 0,
paddingMD: 0, // paddingMD: 0,
}, },
Menu: { Menu: {
itemBg: lightDefaultTheme.backgroundColor.bg1, itemBg: lightDefaultTheme.backgroundColor.bg1,

@ -1,10 +1,11 @@
import React from 'react'; import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import App from './App'; import App from './App';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import { MyStore } from './context'; import { MyStore } from './context';
import './config/i18n'; import './config/i18n';
import 'antd/dist/reset.css'; import 'antd/dist/reset.css';
import { Spin } from 'antd';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
@ -14,7 +15,9 @@ root.render(
{/* theme context */} {/* theme context */}
<MyStore> <MyStore>
{/* theme config context */} {/* theme config context */}
<Suspense fallback={<Spin />}>
<App /> <App />
</Suspense>
</MyStore> </MyStore>
</BrowserRouter> </BrowserRouter>
</React.StrictMode> </React.StrictMode>

@ -0,0 +1,33 @@
import { useRequest } from 'ahooks';
import { Form, Modal, Input, Select } from 'antd';
import React from 'react';
import { fetchTenantList } from '../tenant/service';
const ItemCreate: React.FC<{
type: string;
data: any;
visible: boolean;
onClose: () => void;
}> = props => {
const { visible, onClose, data, type } = props;
const { data: tenant } = useRequest(fetchTenantList);
console.log('tenant', tenant);
return (
<Modal open={visible} onCancel={onClose} footer={null} width={600} title={type === 'edit' ? '编辑' : '创建'}>
<Form>
<Form.Item label="租户" name="">
{/* <Select options={tenant}></Select> */}
</Form.Item>
<Form.Item label="项目" name="">
<Input />
</Form.Item>
<Form.Item label="负责人" name="">
<Input />
</Form.Item>
</Form>
</Modal>
);
};
export default ItemCreate;

@ -1,27 +1,37 @@
import { useAntdTable } from 'ahooks'; import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col } from 'antd'; import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons'; import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { fetchItemList } from './service'; import { fetchItemList } from './service';
import { useUrlSet } from '@/hooks/useUrlSet'; import { useUrlSet } from '@/hooks/useUrlSet';
import style from './index.module.less'; import style from './index.module.less';
import ItemCreate from './create';
const baseColumns = [ const baseColumns = [
{ {
title: '序号', title: '序号',
dataIndex: 'index', dataIndex: 'index',
with: 200,
}, },
{ {
title: '租户', title: '租户',
dataIndex: 'tenantId', dataIndex: 'tenantId',
with: 200,
},
{
title: '项目',
dataIndex: 'itemId',
with: 200,
}, },
{ {
title: '项目名称', title: '项目名称',
dataIndex: 'itemName', dataIndex: 'itemName',
with: 200,
}, },
{ {
title: '负责人', title: '负责人',
dataIndex: 'owner', dataIndex: 'owner',
with: 200,
}, },
{ {
title: '修改时间', title: '修改时间',
@ -32,37 +42,44 @@ const baseColumns = [
const Tenant: React.FC = () => { const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false); const [editVisible, setEditVisible] = useState(false);
const [type, setType] = useState('add'); const [type, setType] = useState('add');
const [curItem, setCurItem] = useState({});
const [form] = Form.useForm(); const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form }); const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchItemList, { form }); const { tableProps, search } = useAntdTable(fetchItemList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true }); // const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const handleSearch = () => {
setUrl();
search.submit();
};
const handleDelete = (item: any) => {
Modal.confirm({
title: `此操作将删除${item.itemName}, 是否继续?`,
onOk: () => {
search.submit();
},
});
};
const actions = (type: string, item?: any) => { const actions = (type: string, item?: any) => {
switch (type) { switch (type) {
case 'add': case 'add':
setType('add');
setEditVisible(true); setEditVisible(true);
break; break;
case 'edit': case 'edit':
setType('edit');
setCurItem(item);
setEditVisible(true); setEditVisible(true);
break; break;
case 'delete': case 'delete':
// handleDelete(); handleDelete(item);
break; break;
default: default:
break; break;
} }
}; };
const handleSearch = () => { const handleClose = () => {
setUrl(); setEditVisible(false);
search.submit();
}; };
// const handleDelete = (item: any) => {
// Modal.confirm({
// title: `此操作将删除${item.tenantName}, 是否继续?`,
// onOk: () => {
// search.submit();
// },
// });
// };
return ( return (
<div className={style.tenant_wrapper}> <div className={style.tenant_wrapper}>
@ -93,6 +110,7 @@ const Tenant: React.FC = () => {
{...tableProps} {...tableProps}
bordered bordered
rowKey="index" rowKey="index"
scroll={{ x: 1000 }}
columns={[ columns={[
...baseColumns, ...baseColumns,
{ {
@ -104,7 +122,7 @@ const Tenant: React.FC = () => {
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}> <Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button> </Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}> <Button onClick={() => actions('delete', record)} type="link" className={style.opreate_btn}>
</Button> </Button>
</Space> </Space>
@ -113,6 +131,7 @@ const Tenant: React.FC = () => {
}, },
]} ]}
/> />
<ItemCreate data={curItem} onClose={handleClose} visible={editVisible} type={type} />
</div> </div>
); );
}; };

@ -6,12 +6,6 @@ const fetchItemList = async (
): Promise<{ total: number; list: Array<any> }> => { ): Promise<{ total: number; list: Array<any> }> => {
const res: any = await request('/hippo4j/v1/cs/item/query/page', { const res: any = await request('/hippo4j/v1/cs/item/query/page', {
method: 'POST', method: 'POST',
headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: { body: {
...formData, ...formData,
current: pageProps.current, current: pageProps.current,

@ -0,0 +1,33 @@
import { Descriptions, Modal } from 'antd';
import React from 'react';
const LogDetail: React.FC<{
data: any;
visible: boolean;
onClose: () => void;
}> = props => {
const { visible, onClose, data } = props;
return (
<Modal open={visible} onCancel={onClose} footer={null} width={600}>
<Descriptions title={'详情'} column={1}>
<Descriptions.Item span={1} label="业务类型">
{data.category}
</Descriptions.Item>
<Descriptions.Item span={1} label="业务标识">
{data.bizNo}
</Descriptions.Item>
<Descriptions.Item span={1} label="操作人">
{data.operator}
</Descriptions.Item>
<Descriptions.Item span={1} label="创建时间">
{data.createTime}
</Descriptions.Item>
<Descriptions.Item span={1} label="日志内容">
{data.action}
</Descriptions.Item>
</Descriptions>
</Modal>
);
};
export default LogDetail;

@ -1,85 +1,90 @@
import { useAntdTable } from 'ahooks'; import { useAntdTable } from 'ahooks';
import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd'; import { Button, Form, Input, Row, Space, Table, Col } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons'; import { SearchOutlined, RedoOutlined } from '@ant-design/icons';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { fetchTenantList } from './service'; import { fetchLogList } from './service';
import { useUrlSet } from '@/hooks/useUrlSet'; import { useUrlSet } from '@/hooks/useUrlSet';
import style from './index.module.less'; import style from './index.module.less';
import LogDetail from './detail';
const baseColumns = [ const baseColumns = [
{ {
title: '序号', title: '序号',
dataIndex: 'id', dataIndex: 'id',
width: 100,
// fixed: 'left',
}, },
{ {
title: '租户', title: '业务类型',
dataIndex: 'tenantId', dataIndex: 'category',
width: 200,
}, },
{ {
title: '租户名称', title: '业务标识',
dataIndex: 'tenantName', dataIndex: 'bizNo',
width: 380,
}, },
{ {
title: '负责人', title: '日志内容',
dataIndex: 'owner', dataIndex: 'action',
width: 380,
}, },
{ {
title: '修改时间', title: '操作人',
dataIndex: 'gmtModified', dataIndex: 'operator',
width: 100,
},
{
title: '操作时间',
dataIndex: 'createTime',
width: 200,
}, },
]; ];
const Tenant: React.FC = () => { const Tenant: React.FC = () => {
const [editVisible, setEditVisible] = useState(false); const [visible, setVisible] = useState(false);
const [type, setType] = useState('add');
const [form] = Form.useForm(); const [form] = Form.useForm();
const { setUrl } = useUrlSet({ form }); const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form }); const { tableProps, search } = useAntdTable(fetchLogList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true }); const [curItems, setCurItems] = useState({});
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 = () => { const handleSearch = () => {
setUrl(); setUrl();
search.submit(); search.submit();
}; };
// const handleDelete = (item: any) => { const handleDetail = (item: any) => {
// Modal.confirm({ setVisible(!visible);
// title: `此操作将删除${item.tenantName}, 是否继续?`, setCurItems(item);
// onOk: () => { };
// search.submit(); const handleClose = () => {
// }, setVisible(false);
// }); };
// };
return ( return (
<div className={style.tenant_wrapper}> <div className={style.tenant_wrapper}>
<Form form={form} wrapperCol={{ span: 23 }}> <Form form={form} wrapperCol={{ span: 23 }}>
<Row> <Row>
<Col span={6}> <Col span={5}>
<Form.Item name="note"> <Form.Item name="category">
<Input placeholder="租户" /> <Input placeholder="业务类型" allowClear />
</Form.Item>
</Col>
<Col span={5}>
<Form.Item name="bizNo">
<Input placeholder="业务标识" allowClear />
</Form.Item>
</Col>
<Col span={5}>
<Form.Item name="operator">
<Input placeholder="操作人" allowClear />
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={18}> <Col span={6}>
<Space> <Space>
<Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}> <Button onClick={() => handleSearch()} type="primary" icon={<SearchOutlined />}>
</Button> </Button>
<Button onClick={() => setEditVisible(true)} type="primary" icon={<EditOutlined />}> <Button onClick={() => search.reset()} type="primary" icon={<RedoOutlined />}>
</Button> </Button>
</Space> </Space>
</Col> </Col>
@ -93,26 +98,25 @@ const Tenant: React.FC = () => {
{...tableProps} {...tableProps}
bordered bordered
rowKey="id" rowKey="id"
scroll={{ x: 1000 }}
columns={[ columns={[
...baseColumns, ...baseColumns,
{ {
fixed: 'right',
width: 100,
title: '操作', title: '操作',
key: 'action', key: 'action',
render: (text: string, record: any) => { render: (text: string, record: any) => {
return ( return (
<Space> <Button onClick={() => handleDetail(record)} type="link" className={style.opreate_btn}>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button> </Button>
</Space>
); );
}, },
}, },
]} ]}
/> />
<LogDetail visible={visible} onClose={handleClose} data={curItems} />
</div> </div>
); );
}; };

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

@ -93,7 +93,7 @@ const Login = () => {
> >
</Checkbox> </Checkbox>
<Button type="link"></Button> <a></a>
</div> </div>
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>

@ -4,7 +4,6 @@ import { Button, Form, Input, Row, Space, Table, Col, Modal } from 'antd';
import { SearchOutlined, EditOutlined } from '@ant-design/icons'; import { SearchOutlined, EditOutlined } from '@ant-design/icons';
import { useUrlSet } from '@/hooks/useUrlSet'; import { useUrlSet } from '@/hooks/useUrlSet';
import { fetchTenantList } from './service'; import { fetchTenantList } from './service';
import style from './index.module.less'; import style from './index.module.less';
const baseColumns = [ const baseColumns = [
@ -37,6 +36,19 @@ const Tenant: React.FC = () => {
const { setUrl } = useUrlSet({ form }); const { setUrl } = useUrlSet({ form });
const { tableProps, search } = useAntdTable(fetchTenantList, { form }); const { tableProps, search } = useAntdTable(fetchTenantList, { form });
// const {run: delete} = useRequest(fetchDeleteTenant, { manual: true }); // const {run: delete} = useRequest(fetchDeleteTenant, { manual: true });
const handleSearch = () => {
setUrl();
search.submit();
};
const handleDelete = (item: any) => {
Modal.confirm({
title: '提示',
content: `此操作将删除${item.tenantName},是否继续?`,
onOk: () => {
search.submit();
},
});
};
const actions = (type: string, item?: any) => { const actions = (type: string, item?: any) => {
switch (type) { switch (type) {
case 'add': case 'add':
@ -46,24 +58,12 @@ const Tenant: React.FC = () => {
setEditVisible(true); setEditVisible(true);
break; break;
case 'delete': case 'delete':
// handleDelete(); handleDelete(item);
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 className={style.tenant_wrapper}> <div className={style.tenant_wrapper}>
@ -105,7 +105,7 @@ const Tenant: React.FC = () => {
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}> <Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}>
</Button> </Button>
<Button onClick={() => actions('edit', record)} type="link" className={style.opreate_btn}> <Button onClick={() => actions('delete', record)} type="link" className={style.opreate_btn}>
</Button> </Button>
</Space> </Space>

@ -6,12 +6,6 @@ const fetchTenantList = async (
): Promise<{ total: number; list: Array<any> }> => { ): Promise<{ total: number; list: Array<any> }> => {
const res: any = await request('/hippo4j/v1/cs/tenant/query/page', { const res: any = await request('/hippo4j/v1/cs/tenant/query/page', {
method: 'POST', method: 'POST',
headers: {
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
},
body: { body: {
...formData, ...formData,
current: pageProps.current, current: pageProps.current,

@ -0,0 +1,34 @@
import * as echarts from 'echarts/core';
import { GridComponent } from 'echarts/components';
import { LineChart } from 'echarts/charts';
import { UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { useEffect } from 'react';
echarts.use([GridComponent, LineChart, CanvasRenderer, UniversalTransition]);
const ThreadPoolMonitor = () => {
useEffect(() => {
let chartDom = document.getElementById('main');
let myChart = echarts.init(chartDom);
let option;
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
},
],
};
option && myChart.setOption(option);
});
return <div id="main" style={{ width: '400px', height: '400px' }}></div>;
};
export default ThreadPoolMonitor;

@ -0,0 +1,11 @@
import { IRouterList } from '@/typings';
import ThreadPoolMonitor from '.';
const routerList: IRouterList[] = [
{
path: '/echarts',
component: ThreadPoolMonitor,
},
];
export default routerList;

@ -4,7 +4,8 @@ import { STR_MAP } from '@/config/i18n/locales/constants';
import { ColumnProps } from 'antd/es/table'; import { ColumnProps } from 'antd/es/table';
import { SearchButton, AddButton } from '@/components/with-button'; import { SearchButton, AddButton } from '@/components/with-button';
import { useAntdTable } from 'ahooks'; import { useAntdTable } from 'ahooks';
import service, { Result, ThreadPoolTableBody } from './service'; import service from './service';
import { Result } from './type';
const { Title } = Typography; const { Title } = Typography;
const { Item } = Form; const { Item } = Form;
const paramsType = { project: 0, thpool: 0 }; const paramsType = { project: 0, thpool: 0 };
@ -73,7 +74,7 @@ const ThreadPoll = () => {
}); });
}; };
const { tableProps, search } = useAntdTable<Result, ThreadPoolTableBody>(getTableData, { const { tableProps, search } = useAntdTable<Result, any>(getTableData, {
defaultPageSize: 5, defaultPageSize: 5,
form: form, form: form,
}); });

@ -1,4 +1,5 @@
import request from '@/utils'; import request from '@/utils';
import { Result, ThreadPoolTableBody, ThreadPoolTableRes } from './type';
const fetchThreadPoolTable = async (body: ThreadPoolTableBody): Promise<Result> => { const fetchThreadPoolTable = async (body: ThreadPoolTableBody): Promise<Result> => {
const { data } = await request<ThreadPoolTableRes>('/hippo4j/v1/cs/thread/pool/query/page', { const { data } = await request<ThreadPoolTableRes>('/hippo4j/v1/cs/thread/pool/query/page', {

@ -1,7 +1,7 @@
import { Params } from 'ahooks/lib/useAntdTable/types'; import { Params } from 'ahooks/lib/useAntdTable/types';
// body // body
export interface ThreadPoolTableBody extends Params { export interface ThreadPoolTableBody {
/** /**
* current page * current page
*/ */

@ -4,9 +4,20 @@ import aboutRouter from '@/page/about/router';
import ThreadPoolRouter from '@/page/thread-pool/router'; import ThreadPoolRouter from '@/page/thread-pool/router';
import tenantRouter from '@/page/tenant/router'; import tenantRouter from '@/page/tenant/router';
import LoginRouter from '@/page/login/router'; import LoginRouter from '@/page/login/router';
// import itemRouter from '@/page/item/router'; import itemRouter from '@/page/item/router';
// import userRouter from '@/page/user/router'; import userRouter from '@/page/user/router';
// import logRouter from '@/page/log/router'; import logRouter from '@/page/log/router';
import ThreadPoolMonitorRouter from '@/page/thread-pool-monitor/router';
const routerList: IRouterList[] = [...homeRouter, ...aboutRouter, ...tenantRouter, ...ThreadPoolRouter, ...LoginRouter]; const routerList: IRouterList[] = [
...homeRouter,
...aboutRouter,
...tenantRouter,
...ThreadPoolRouter,
...LoginRouter,
...itemRouter,
...userRouter,
...logRouter,
...ThreadPoolMonitorRouter,
];
export default routerList; export default routerList;

@ -49,9 +49,19 @@ const isPlainObject = (obj: { [key: string]: any }): boolean => {
}; };
const setToken = (token: string) => { const setToken = (token: string) => {
localStorage.setItem(TokenKey, token);
Cookie.set(TokenKey, token); Cookie.set(TokenKey, token);
}; };
const removeToken = () => {
localStorage.removeItem(TokenKey);
Cookie.remove(TokenKey);
};
const getToken = () => {
return localStorage.getItem(TokenKey) || Cookie.get(TokenKey);
};
/** /**
* @description object value * @description object value
* @param obj * @param obj
@ -79,4 +89,4 @@ const isEmpty = (value: any) => {
return typeof value === 'object' ? _.isEmpty(value) : isNilValue(value); return typeof value === 'object' ? _.isEmpty(value) : isNilValue(value);
}; };
export { isPlainObject, isEmpty, filterEmptyField, setToken }; export { isPlainObject, isEmpty, filterEmptyField, setToken, removeToken, getToken };

@ -1,4 +1,4 @@
import { isPlainObject } from '../common'; import { getToken, isPlainObject } from '../common';
import { notification, message } from 'antd'; import { notification, message } from 'antd';
import Qs from 'qs'; import Qs from 'qs';
@ -40,10 +40,6 @@ const inital: RequestOptions = {
body: null, body: null,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMCxiYW94aW55aV91c2VyIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTU4MjY1ODQsImlhdCI6MTY5NTIyMTc4NCwicm9sIjoiUk9MRV9VU0VSIn0.HQx33P1hlZK2-0omlUt58kpa77OxiGdW-jLV4GWbbLIFf86y8-0IOdeu8gzMwMWUTRtrwp2_YWMl_05TVlDJbA',
cookie:
'Admin-Token=Bearer%20eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI3LGJhb3hpbnlpX2FkbWluIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTUzOTg4NDksImlhdCI6MTY5NDc5NDA0OSwicm9sIjoiUk9MRV9BRE1JTiJ9.syRDshKpd-xETsSdeMPRtk956f4BJkPt4utVsUl4smgH71Woj8SUq4w2RX1YtGTC4aTZRJYdKOfkTqwK0g_dHQ; userName=baoxinyi_admin',
}, },
// headers, // headers,
credentials: true, credentials: true,
@ -88,8 +84,11 @@ function request<T>(url: string, config: RequestOptions): Promise<Response<T>> {
} }
if (config.headers && isPlainObject(config.headers)) { if (config.headers && isPlainObject(config.headers)) {
config.headers = Object.assign({}, inital.headers, config.headers); config.headers = Object.assign({}, inital.headers, config.headers);
if (!config.headers?.Authorization) {
config.headers.Authorization = getToken();
}
} else { } else {
config.headers = inital.headers; config.headers = { Authorization: getToken(), 'Content-Type': 'application/json' };
} }
let { method, params, body, headers, credentials, responseType } = Object.assign({}, inital, config) as any; let { method, params, body, headers, credentials, responseType } = Object.assign({}, inital, config) as any;

@ -4468,6 +4468,22 @@ eastasianwidth@^0.2.0:
resolved "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" resolved "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
echarts-for-react@^3.0.2:
version "3.0.2"
resolved "https://registry.npmmirror.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz#ac5859157048a1066d4553e34b328abb24f2b7c1"
integrity sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==
dependencies:
fast-deep-equal "^3.1.3"
size-sensor "^1.0.1"
echarts@^5.4.3:
version "5.4.3"
resolved "https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz#f5522ef24419164903eedcfd2b506c6fc91fb20c"
integrity sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==
dependencies:
tslib "2.3.0"
zrender "5.4.4"
ee-first@1.1.1: ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -9647,6 +9663,11 @@ sisteransi@^1.0.5:
resolved "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" resolved "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
size-sensor@^1.0.1:
version "1.0.2"
resolved "https://registry.npmmirror.com/size-sensor/-/size-sensor-1.0.2.tgz#b8f8da029683cf2b4e22f12bf8b8f0a1145e8471"
integrity sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==
slash@^2.0.0: slash@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmmirror.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" resolved "https://registry.npmmirror.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
@ -10318,6 +10339,11 @@ tsconfig-paths@^3.14.2:
minimist "^1.2.6" minimist "^1.2.6"
strip-bom "^3.0.0" strip-bom "^3.0.0"
tslib@2.3.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
tslib@^1.8.1: tslib@^1.8.1:
version "1.14.1" version "1.14.1"
resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
@ -11152,3 +11178,10 @@ yocto-queue@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
zrender@5.4.4:
version "5.4.4"
resolved "https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz#8854f1d95ecc82cf8912f5a11f86657cb8c9e261"
integrity sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==
dependencies:
tslib "2.3.0"

Loading…
Cancel
Save