diff --git a/threadpool/console-new/craco.config.js b/threadpool/console-new/craco.config.js index 0d7d72a2..109f8e2c 100644 --- a/threadpool/console-new/craco.config.js +++ b/threadpool/console-new/craco.config.js @@ -49,5 +49,11 @@ module.exports = { headers: { 'Access-Control-Allow-Origin': '*', }, + proxy: { + '/hippo4j': { + target: 'http://console.hippo4j.cn', + changeOrigin: true, + }, + }, }, }; diff --git a/threadpool/console-new/package.json b/threadpool/console-new/package.json index 801cbd51..b72766d7 100644 --- a/threadpool/console-new/package.json +++ b/threadpool/console-new/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@ahooksjs/use-url-state": "^3.5.1", "@ant-design/icons": "^5.2.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", @@ -12,6 +13,7 @@ "dayjs": "^1.11.9", "i18next": "^23.5.1", "i18next-browser-languagedetector": "^7.1.0", + "lodash": "^4.17.21", "qs": "^6.11.2", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -49,6 +51,7 @@ "@craco/craco": "^7.1.0", "@types/http-errors": "^2.0.1", "@types/jest": "^27.5.2", + "@types/lodash": "^4.14.198", "@types/node": "^16.18.26", "@types/react": "^18.2.6", "@types/react-dom": "^18.2.4", diff --git a/threadpool/console-new/src/App.tsx b/threadpool/console-new/src/App.tsx index 709464e4..6bd2bf62 100644 --- a/threadpool/console-new/src/App.tsx +++ b/threadpool/console-new/src/App.tsx @@ -1,32 +1,65 @@ +import { Suspense } from 'react'; 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 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 = [ { - label: about, + label: about, key: 'mail', icon: , }, { - label: 主页, + label: 主页, key: 'app', icon: , }, + { + label: 租户管理, + key: 'tenant', + icon: , + }, + { + label: 项目管理, + key: 'item', + icon: , + }, + { + label: 用户权限, + key: 'user', + icon: , + }, + { + label: 日志管理, + key: 'log', + icon: , + }, ]; const App = () => { return ( - - - - {routeList.map(item => ( - - ))} - - + + }> + + + + {routeList.map(item => ( + + ))} + + + + ); }; diff --git a/threadpool/console-new/src/components/header/index.tsx b/threadpool/console-new/src/components/header/index.tsx index 2619f290..a1858371 100644 --- a/threadpool/console-new/src/components/header/index.tsx +++ b/threadpool/console-new/src/components/header/index.tsx @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import style from './index.module.less'; 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 { MyContext } from '@/context'; import IconFont from '@/components/icon'; diff --git a/threadpool/console-new/src/components/layout-com/index.module.less b/threadpool/console-new/src/components/layout-com/index.module.less index 4d7b07bc..2b52ccf5 100644 --- a/threadpool/console-new/src/components/layout-com/index.module.less +++ b/threadpool/console-new/src/components/layout-com/index.module.less @@ -10,13 +10,19 @@ } .sider { height: calc(100vh - 48px); - padding-top: 24px; + // padding-top: 24px; + } + .menu { + height: 100vh; + } + .breadcrumb { + margin: 16px 0; } .content { - margin: 10px 10px 0px; + margin: 0; border-radius: 12px 12px 0 0; min-height: 100%; flex: 1; - padding: 10px 12px; + padding: 10px 0; } } diff --git a/threadpool/console-new/src/components/layout-com/index.tsx b/threadpool/console-new/src/components/layout-com/index.tsx index 13d25217..bb1f3271 100644 --- a/threadpool/console-new/src/components/layout-com/index.tsx +++ b/threadpool/console-new/src/components/layout-com/index.tsx @@ -1,6 +1,6 @@ import { useState, useContext, ReactNode } from 'react'; import { DefaultTheme, ThemeContext } from 'styled-components'; -import { Layout, Menu } from 'antd'; +import { Breadcrumb, Layout, Menu } from 'antd'; import HeaderChild from '../header'; import { IMenuList } from '@/typings'; import style from './index.module.less'; @@ -25,13 +25,26 @@ const LayoutCom = (props: ILayoutCom) => {
- + {isSider && ( - + )} - {children} + + + Home + List + App + + {children} + ); diff --git a/threadpool/console-new/src/config/theme/index.ts b/threadpool/console-new/src/config/theme/index.ts index c1c656b4..7e40b52d 100644 --- a/threadpool/console-new/src/config/theme/index.ts +++ b/threadpool/console-new/src/config/theme/index.ts @@ -1,7 +1,7 @@ import { DefaultTheme } from 'styled-components'; export const lightDefaultTheme: DefaultTheme = { - primary: '#0d68a8', + primary: '#1890ff', baseColor: { // 前两个是固定的,用于,有颜色按钮 字体颜色等固定不会变的颜色值 bc1: '#fff', diff --git a/threadpool/console-new/src/hooks/useUrlSet.ts b/threadpool/console-new/src/hooks/useUrlSet.ts new file mode 100644 index 00000000..7669d5f3 --- /dev/null +++ b/threadpool/console-new/src/hooks/useUrlSet.ts @@ -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 }; +}; diff --git a/threadpool/console-new/src/page/item/index.module.less b/threadpool/console-new/src/page/item/index.module.less new file mode 100644 index 00000000..5f59dc72 --- /dev/null +++ b/threadpool/console-new/src/page/item/index.module.less @@ -0,0 +1,5 @@ +.tenant_wrapper { + .opreate_btn { + padding: 0px; + } +} \ No newline at end of file diff --git a/threadpool/console-new/src/page/item/index.tsx b/threadpool/console-new/src/page/item/index.tsx new file mode 100644 index 00000000..a7c0b23f --- /dev/null +++ b/threadpool/console-new/src/page/item/index.tsx @@ -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 ( +
+
+ + + + + + + + + + + + + + + + + +
+ { + return ( + + + + + ); + }, + }, + ]} + /> + + ); +}; + +export default Tenant; diff --git a/threadpool/console-new/src/page/item/router.tsx b/threadpool/console-new/src/page/item/router.tsx new file mode 100644 index 00000000..c11cce05 --- /dev/null +++ b/threadpool/console-new/src/page/item/router.tsx @@ -0,0 +1,8 @@ +import { lazy } from 'react'; +import { IRouterList } from '@/typings'; + +const ItemManage = lazy(() => import('./index')); + +const routerList: IRouterList[] = [{ path: '/item', component: () => }]; + +export default routerList; diff --git a/threadpool/console-new/src/page/item/service.ts b/threadpool/console-new/src/page/item/service.ts new file mode 100644 index 00000000..2fab1ef7 --- /dev/null +++ b/threadpool/console-new/src/page/item/service.ts @@ -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 }> => { + 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 }; diff --git a/threadpool/console-new/src/page/log/index.module.less b/threadpool/console-new/src/page/log/index.module.less new file mode 100644 index 00000000..5f59dc72 --- /dev/null +++ b/threadpool/console-new/src/page/log/index.module.less @@ -0,0 +1,5 @@ +.tenant_wrapper { + .opreate_btn { + padding: 0px; + } +} \ No newline at end of file diff --git a/threadpool/console-new/src/page/log/index.tsx b/threadpool/console-new/src/page/log/index.tsx new file mode 100644 index 00000000..a7c0b23f --- /dev/null +++ b/threadpool/console-new/src/page/log/index.tsx @@ -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 ( +
+
+ +
+ + + + + + + + + + + + + + + + +
{ + return ( + + + + + ); + }, + }, + ]} + /> + + ); +}; + +export default Tenant; diff --git a/threadpool/console-new/src/page/log/router.tsx b/threadpool/console-new/src/page/log/router.tsx new file mode 100644 index 00000000..d778e8be --- /dev/null +++ b/threadpool/console-new/src/page/log/router.tsx @@ -0,0 +1,8 @@ +import { lazy } from 'react'; +import { IRouterList } from '@/typings'; + +const LogManage = lazy(() => import('./index')); + +const routerList: IRouterList[] = [{ path: '/log', component: () => }]; + +export default routerList; diff --git a/threadpool/console-new/src/page/log/service.ts b/threadpool/console-new/src/page/log/service.ts new file mode 100644 index 00000000..2fab1ef7 --- /dev/null +++ b/threadpool/console-new/src/page/log/service.ts @@ -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 }> => { + 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 }; diff --git a/threadpool/console-new/src/page/tenant/index.module.less b/threadpool/console-new/src/page/tenant/index.module.less new file mode 100644 index 00000000..5f59dc72 --- /dev/null +++ b/threadpool/console-new/src/page/tenant/index.module.less @@ -0,0 +1,5 @@ +.tenant_wrapper { + .opreate_btn { + padding: 0px; + } +} \ No newline at end of file diff --git a/threadpool/console-new/src/page/tenant/index.tsx b/threadpool/console-new/src/page/tenant/index.tsx index cecb767e..0d80beff 100644 --- a/threadpool/console-new/src/page/tenant/index.tsx +++ b/threadpool/console-new/src/page/tenant/index.tsx @@ -1,16 +1,20 @@ -import { useAntdTable } from 'ahooks'; -import { Button, Form, Input, Row, Space, Table, Col } from 'antd'; 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 style from './index.module.less'; + const baseColumns = [ { title: '序号', - dataIndex: 'num', + dataIndex: 'id', }, { title: '租户', - dataIndex: 'tenant', + dataIndex: 'tenantId', }, { title: '租户名称', @@ -18,53 +22,78 @@ const baseColumns = [ }, { title: '负责人', - dataIndex: 'creator', + dataIndex: 'owner', }, { title: '修改时间', - dataIndex: 'data', + 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 actions = (type: string) => { + // const {run: delete} = useRequest(fetchDeleteTenant, { manual: true }); + const actions = (type: string, item?: any) => { switch (type) { - case 'create': + 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 ( -
-
+
+
- + - - + + + + + +
{ render: (text: string, record: any) => { return ( - - + + ); }, diff --git a/threadpool/console-new/src/page/tenant/service.ts b/threadpool/console-new/src/page/tenant/service.ts index a8b16d3d..2fab1ef7 100644 --- a/threadpool/console-new/src/page/tenant/service.ts +++ b/threadpool/console-new/src/page/tenant/service.ts @@ -3,44 +3,77 @@ import request from '@/utils'; const fetchTenantList = async ( pageProps: { current: number; pageSize: number }, formData: { tencent: string | number } -) => { - // mock request - return { - total: 3, - list: [ - { - num: '1', - tenant: 'admin', - tenantName: 'admin', - creator: 'admin', - data: 'admin', - }, - ], - }; - const res = await request('/tenants', { +): Promise<{ total: number; list: Array }> => { + const res: any = await request('/hippo4j/v1/cs/tenant/query/page', { 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, - pageNum: pageProps.current, - pageSize: pageProps.pageSize, + current: pageProps.current, + size: pageProps.pageSize, + desc: true, }, }); - if (res && res.success) { return { - total: 3, - list: [ - { - num: '1', - tenant: 'admin', - tenantName: 'admin', - creator: 'admin', - data: 'admin', - }, - ], + total: res.data.total, + list: res.data.records, }; } - 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 }; diff --git a/threadpool/console-new/src/page/user/index.module.less b/threadpool/console-new/src/page/user/index.module.less new file mode 100644 index 00000000..5f59dc72 --- /dev/null +++ b/threadpool/console-new/src/page/user/index.module.less @@ -0,0 +1,5 @@ +.tenant_wrapper { + .opreate_btn { + padding: 0px; + } +} \ No newline at end of file diff --git a/threadpool/console-new/src/page/user/index.tsx b/threadpool/console-new/src/page/user/index.tsx new file mode 100644 index 00000000..a7c0b23f --- /dev/null +++ b/threadpool/console-new/src/page/user/index.tsx @@ -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 ( +
+
+ +
+ + + + + + + + + + + + + + + + +
{ + return ( + + + + + ); + }, + }, + ]} + /> + + ); +}; + +export default Tenant; diff --git a/threadpool/console-new/src/page/user/router.tsx b/threadpool/console-new/src/page/user/router.tsx new file mode 100644 index 00000000..a84862be --- /dev/null +++ b/threadpool/console-new/src/page/user/router.tsx @@ -0,0 +1,8 @@ +import { lazy } from 'react'; +import { IRouterList } from '@/typings'; + +const UserManage = lazy(() => import('./index')); + +const routerList: IRouterList[] = [{ path: '/user', component: () => }]; + +export default routerList; diff --git a/threadpool/console-new/src/page/user/service.ts b/threadpool/console-new/src/page/user/service.ts new file mode 100644 index 00000000..2fab1ef7 --- /dev/null +++ b/threadpool/console-new/src/page/user/service.ts @@ -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 }> => { + 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 }; diff --git a/threadpool/console-new/src/route/index.tsx b/threadpool/console-new/src/route/index.tsx index bb3681ca..bb0cfeba 100644 --- a/threadpool/console-new/src/route/index.tsx +++ b/threadpool/console-new/src/route/index.tsx @@ -2,6 +2,16 @@ import { IRouterList } from '@/typings'; import homeRouter from '@/page/home/router'; import aboutRouter from '@/page/about/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; diff --git a/threadpool/console-new/src/utils/common/index.ts b/threadpool/console-new/src/utils/common/index.ts index 8085a28c..2fd348e0 100644 --- a/threadpool/console-new/src/utils/common/index.ts +++ b/threadpool/console-new/src/utils/common/index.ts @@ -1,3 +1,5 @@ +import _ from 'lodash'; + // is plain object const isPlainObject = (obj: { [key: string]: any }): boolean => { 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 {} }; -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 }; diff --git a/threadpool/console-new/src/utils/request/index.ts b/threadpool/console-new/src/utils/request/index.ts index 22a2a2c6..9d9a0f13 100644 --- a/threadpool/console-new/src/utils/request/index.ts +++ b/threadpool/console-new/src/utils/request/index.ts @@ -32,7 +32,7 @@ type Response = { code?: string | number; }; -let baseURL = 'http://127.0.0.1:9999'; +let baseURL = 'http://console.hippo4j.cn'; const inital: RequestOptions = { method: 'GET', @@ -104,6 +104,7 @@ function request(url: string, config: RequestOptions): Promise> { method = method.toUpperCase(); responseType = responseType.toUpperCase(); config = { + ...config, method, credentials, responseType, @@ -113,6 +114,7 @@ function request(url: string, config: RequestOptions): Promise> { } else { config.body = null; } + return fetch(url, config as any).then(function onfulfilled(response) { let { status, statusText } = response; if (status >= 200 && status < 400) {