From 941dd4fd65c00537f5fb64c44aac7136d7ab1b7a Mon Sep 17 00:00:00 2001 From: GraceWalk Date: Fri, 28 Oct 2022 17:36:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20Zookeeper=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config-manager-fe/package-lock.json | 6 +- .../packages/config-manager-fe/package.json | 2 +- .../layout-clusters-fe/package-lock.json | 6 +- .../packages/layout-clusters-fe/package.json | 2 +- .../src/assets/beta-tag.png | Bin 0 -> 6395 bytes .../components/ChartOperateBar/NodeScope.tsx | 129 ++++++------ .../src/components/ChartOperateBar/index.tsx | 2 - .../src/components/DraggableCharts/config.tsx | 2 +- .../src/components/DraggableCharts/index.tsx | 4 +- .../src/constants/{menu.ts => menu.tsx} | 45 ++++- .../layout-clusters-fe/src/index.less | 15 ++ .../layout-clusters-fe/src/locales/zh.tsx | 4 + .../src/pages/Zookeeper/Data.tsx | 60 ++++++ .../src/pages/Zookeeper/Detail.tsx | 188 ++++++++++++++++++ .../src/pages/Zookeeper/Info.tsx | 61 ++++++ .../src/pages/Zookeeper/Sider.tsx | 179 +++++++++++++++++ .../src/pages/Zookeeper/config.tsx | 133 +++++++++++++ .../src/pages/Zookeeper/index.less | 131 ++++++++++++ .../src/pages/Zookeeper/index.tsx | 128 ++++++++++++ .../src/pages/ZookeeperDashboard/index.tsx | 27 +++ .../layout-clusters-fe/src/pages/index.tsx | 16 +- .../src/pages/pageRoutes.ts | 15 ++ 22 files changed, 1064 insertions(+), 91 deletions(-) create mode 100644 km-console/packages/layout-clusters-fe/src/assets/beta-tag.png rename km-console/packages/layout-clusters-fe/src/constants/{menu.ts => menu.tsx} (70%) create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Data.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Detail.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Info.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Sider.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/config.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.less create mode 100644 km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.tsx create mode 100644 km-console/packages/layout-clusters-fe/src/pages/ZookeeperDashboard/index.tsx diff --git a/km-console/packages/config-manager-fe/package-lock.json b/km-console/packages/config-manager-fe/package-lock.json index 08574fb2..8db0ed4a 100644 --- a/km-console/packages/config-manager-fe/package-lock.json +++ b/km-console/packages/config-manager-fe/package-lock.json @@ -1345,9 +1345,9 @@ } }, "@knowdesign/icons": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/@knowdesign/icons/-/icons-1.0.0.tgz", - "integrity": "sha512-7c+h2TSbh2ihTkXIivuO+DddNC5wG7hVv9SS4ccmkvTKls2ZTLitPu+U0wpufDxPhkPMaKEQfsECsVJ+7jLMiw==", + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@knowdesign/icons/-/icons-1.0.2.tgz", + "integrity": "sha512-eQuUQZbPRvC1xU4ouzgrk8j6UE39Cui+eEkYkLbfGLpVbGPFKJ7yEmUyKhIjG9zhf1qS7/h08yzq0hAHajBi8g==", "requires": { "@ant-design/colors": "^6.0.0", "@ant-design/icons": "^4.7.0", diff --git a/km-console/packages/config-manager-fe/package.json b/km-console/packages/config-manager-fe/package.json index 013ffec0..42f8c3c8 100644 --- a/km-console/packages/config-manager-fe/package.json +++ b/km-console/packages/config-manager-fe/package.json @@ -21,7 +21,7 @@ "build": "cross-env NODE_ENV=production webpack --max_old_space_size=8000" }, "dependencies": { - "@knowdesign/icons": "^1.0.0", + "@knowdesign/icons": "^1.0.2", "babel-preset-react-app": "^10.0.0", "classnames": "^2.2.6", "dotenv": "^16.0.1", diff --git a/km-console/packages/layout-clusters-fe/package-lock.json b/km-console/packages/layout-clusters-fe/package-lock.json index dfb11c4b..7a98639a 100644 --- a/km-console/packages/layout-clusters-fe/package-lock.json +++ b/km-console/packages/layout-clusters-fe/package-lock.json @@ -1388,9 +1388,9 @@ } }, "@knowdesign/icons": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@knowdesign/icons/-/icons-1.0.1.tgz", - "integrity": "sha512-EI3s25BJt+Slv7/t6B3K3zv7I6TKkk2Wf1y68zuxK80MMkWf8lqqUtyAZbFDoPUfXAjw6vHktMBH44gbMHMRFA==", + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@knowdesign/icons/-/icons-1.0.2.tgz", + "integrity": "sha512-eQuUQZbPRvC1xU4ouzgrk8j6UE39Cui+eEkYkLbfGLpVbGPFKJ7yEmUyKhIjG9zhf1qS7/h08yzq0hAHajBi8g==", "requires": { "@ant-design/colors": "^6.0.0", "@ant-design/icons": "^4.7.0", diff --git a/km-console/packages/layout-clusters-fe/package.json b/km-console/packages/layout-clusters-fe/package.json index cee05daa..af1faf35 100644 --- a/km-console/packages/layout-clusters-fe/package.json +++ b/km-console/packages/layout-clusters-fe/package.json @@ -35,7 +35,7 @@ "dependencies": { "@ant-design/compatible": "^1.0.8", "@ant-design/icons": "^4.6.2", - "@knowdesign/icons": "^1.0.1", + "@knowdesign/icons": "^1.0.2", "@types/react": "^17.0.39", "@types/react-copy-to-clipboard": "^5.0.2", "@types/react-dom": "^17.0.11", diff --git a/km-console/packages/layout-clusters-fe/src/assets/beta-tag.png b/km-console/packages/layout-clusters-fe/src/assets/beta-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..f93fb77f4a003e8472618db5f4e29929d93e05bc GIT binary patch literal 6395 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 JPDHLkV1oT^0NDTl literal 0 HcmV?d00001 diff --git a/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/NodeScope.tsx b/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/NodeScope.tsx index b41cd748..80f160c3 100644 --- a/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/NodeScope.tsx +++ b/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/NodeScope.tsx @@ -26,7 +26,6 @@ const OptionsDefault = [ const NodeScope = ({ nodeScopeModule, change }: propsType) => { const { - hasCustomScope, customScopeList: customList, scopeName = '', scopeLabel = '自定义范围', @@ -129,79 +128,75 @@ const NodeScope = ({ nodeScopeModule, change }: propsType) => { - {hasCustomScope && ( -
-
{scopeLabel}
-
-
- - 全选 - - } - size="small" - placeholder={searchPlaceholder} - onChange={(e) => setScopeSearchValue(e.target.value)} - /> -
-
- - - {customList - .filter((item) => item.label.includes(scopeSearchValue)) - .map((item) => ( - - {item.label} - - ))} - - -
+
+
{scopeLabel}
+
+
+ + 全选 + + } + size="small" + placeholder={searchPlaceholder} + onChange={(e) => setScopeSearchValue(e.target.value)} + /> +
+
+ + + {customList + .filter((item) => item.label.includes(scopeSearchValue)) + .map((item) => ( + + {item.label} + + ))} + + +
-
- - -
+
+ +
- )} +
); return ( - <> -
-
{scopeName}筛选:
- - - } - /> - - -
- +
+
{scopeName}筛选:
+ + + } + /> + + +
); }; diff --git a/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/index.tsx b/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/index.tsx index 42d66366..af8cdd61 100644 --- a/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/components/ChartOperateBar/index.tsx @@ -47,7 +47,6 @@ export interface IcustomScope { } export interface InodeScopeModule { - hasCustomScope: boolean; customScopeList: IcustomScope[]; scopeName?: string; scopeLabel?: string; @@ -87,7 +86,6 @@ const GRID_SIZE_OPTIONS = [ const MetricOperateBar = ({ metricSelect, nodeScopeModule = { - hasCustomScope: false, customScopeList: [], }, hideNodeScope = false, diff --git a/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/config.tsx b/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/config.tsx index 8fb015e5..3a60eca4 100644 --- a/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/config.tsx @@ -4,7 +4,7 @@ import { getBasicChartConfig, CHART_COLOR_LIST } from '@src/constants/chartConfi const METRIC_DASHBOARD_REQ_MAP = { [MetricType.Broker]: (clusterId: string) => api.getDashboardMetricChartData(clusterId, MetricType.Broker), [MetricType.Topic]: (clusterId: string) => api.getDashboardMetricChartData(clusterId, MetricType.Topic), - [MetricType.Zookeeper]: (clusterId: string) => '', + [MetricType.Zookeeper]: (clusterId: string) => api.getZookeeperMetrics(clusterId), }; export const getMetricDashboardReq = (clusterId: string, type: MetricType.Broker | MetricType.Topic | MetricType.Zookeeper) => diff --git a/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/index.tsx b/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/index.tsx index ab2ce555..c4aa8b97 100644 --- a/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/components/DraggableCharts/index.tsx @@ -108,10 +108,10 @@ const DraggableCharts = (props: PropsType): JSX.Element => { startTime, endTime, metricsNames: selectedMetricNames, - topNu: curHeaderOptions?.scopeData?.isTop ? curHeaderOptions.scopeData.data : null, }, dashboardType === MetricType.Broker || dashboardType === MetricType.Topic ? { + topNu: curHeaderOptions?.scopeData?.isTop ? curHeaderOptions.scopeData.data : null, [dashboardType === MetricType.Broker ? 'brokerIds' : 'topics']: curHeaderOptions?.scopeData?.isTop ? null : curHeaderOptions.scopeData.data, @@ -233,8 +233,8 @@ const DraggableCharts = (props: PropsType): JSX.Element => {
({ +export const leftMenus = (clusterId?: string, clusterRunState?: number) => ({ name: `${systemKey}`, icon: 'icon-jiqun', path: `cluster/${clusterId}`, @@ -11,12 +12,12 @@ export const leftMenus = (clusterId?: string) => ({ { name: 'cluster', path: 'cluster', - icon: 'icon-Cluster', + icon: 'icon-Cluster1', }, { name: 'broker', path: 'broker', - icon: 'icon-Brokers', + icon: 'icon-Brokers1', children: [ { name: 'dashbord', @@ -38,7 +39,7 @@ export const leftMenus = (clusterId?: string) => ({ { name: 'topic', path: 'topic', - icon: 'icon-Topics', + icon: 'icon-Topics1', children: [ { name: 'dashbord', @@ -52,10 +53,36 @@ export const leftMenus = (clusterId?: string) => ({ }, ], }, + clusterRunState && clusterRunState !== ClusterRunState.Raft + ? { + name: (intl: any) => { + return ( +
+ {intl.formatMessage({ id: 'menu.cluster.zookeeper' })} +
+
+ ); + }, + path: 'zookeeper', + icon: 'icon-Zookeeper', + children: [ + { + name: (intl: any) => {intl.formatMessage({ id: 'menu.cluster.zookeeper.dashboard' })}, + path: '', + icon: '#icon-luoji', + }, + { + name: (intl: any) => {intl.formatMessage({ id: 'menu.cluster.zookeeper.servers' })}, + path: 'servers', + icon: 'icon-Jobs', + }, + ], + } + : undefined, { name: 'consumer-group', path: 'consumers', - icon: 'icon-ConsumerGroups', + icon: 'icon-Consumer', // children: [ // { // name: 'operating-state', @@ -72,7 +99,7 @@ export const leftMenus = (clusterId?: string) => ({ { name: 'operation', path: 'operation', - icon: 'icon-Jobs', + icon: 'icon-Operation', children: [ process.env.BUSINESS_VERSION ? { @@ -92,7 +119,7 @@ export const leftMenus = (clusterId?: string) => ({ ? { name: 'produce-consume', path: 'testing', - icon: 'icon-a-ProduceConsume', + icon: 'icon-Message', permissionPoint: [ClustersPermissionMap.TEST_CONSUMER, ClustersPermissionMap.TEST_PRODUCER], children: [ { @@ -113,7 +140,7 @@ export const leftMenus = (clusterId?: string) => ({ { name: 'security', path: 'security', - icon: 'icon-ACLs', + icon: 'icon-Security', children: [ { name: 'acls', diff --git a/km-console/packages/layout-clusters-fe/src/index.less b/km-console/packages/layout-clusters-fe/src/index.less index c219a44f..f7da736e 100644 --- a/km-console/packages/layout-clusters-fe/src/index.less +++ b/km-console/packages/layout-clusters-fe/src/index.less @@ -259,6 +259,21 @@ li { } } +.menu-item-with-beta-tag { + display: flex; + .beta-tag { + width: 26px; + margin-left: 4px; + background: no-repeat center/26px 15px url('./assets/beta-tag.png'); + } +} + +.dcloud-menu-item-selected .menu-item-with-beta-tag .beta-tag { + width: 0; +} + + + .empty-panel { display: flex; flex-direction: column; diff --git a/km-console/packages/layout-clusters-fe/src/locales/zh.tsx b/km-console/packages/layout-clusters-fe/src/locales/zh.tsx index 85c9014b..99c6682d 100755 --- a/km-console/packages/layout-clusters-fe/src/locales/zh.tsx +++ b/km-console/packages/layout-clusters-fe/src/locales/zh.tsx @@ -51,6 +51,10 @@ export default { [`menu.${systemKey}.jobs`]: 'Job', + [`menu.${systemKey}.zookeeper`]: 'Zookeeper', + [`menu.${systemKey}.zookeeper.dashboard`]: 'Overview', + [`menu.${systemKey}.zookeeper.servers`]: 'Servers', + 'access.cluster': '接入集群', 'access.cluster.low.version.tip': '监测到当前Version较低,建议维护Zookeeper信息以便得到更好的产品体验', 'edit.cluster': '编辑集群', diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Data.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Data.tsx new file mode 100644 index 00000000..3c26da24 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Data.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import { Controlled as CodeMirror } from 'react-codemirror2'; +import SwitchTab from '@src/components/SwitchTab'; + +const isJSON = (str: string) => { + if (typeof str == 'string') { + try { + JSON.parse(str); + return true; + } catch (e) { + return false; + } + } else { + return false; + } +}; + +const ZKData = ({ nodeData }: { nodeData: string }) => { + const [showMode, setShowMode] = useState('default'); + return ( + <> +
+ setShowMode(key)}> + +
原始格式
+
+ +
JSON格式
+
+
+
+ {showMode === 'default' && ( +
+ {isJSON(nodeData) ? JSON.stringify(JSON.parse(nodeData), null, 2) : nodeData} +
+ )} + {showMode === 'JSON' && ( +
+ { + return; + }} + /> +
+ )} + + ); +}; + +export default ZKData; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Detail.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Detail.tsx new file mode 100644 index 00000000..ac54ad88 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Detail.tsx @@ -0,0 +1,188 @@ +import React, { useState, useEffect } from 'react'; +import { Drawer, Utils, AppContainer, Spin, Empty } from 'knowdesign'; +import ZKDetailMenu from './Sider'; +import Api from '@src/api'; +import ZKInfo from './Info'; +import ZKData from './Data'; +const { request } = Utils; +import './index.less'; +import { DataNode } from './config'; + +const ZookeeperDetail = ({ visible, setVisible }: { visible: boolean; setVisible: (visible: boolean) => void }) => { + const [global] = AppContainer.useGlobalValue(); + // const { visible, setVisible } = props; + const [detailLoading, setDetailLoading] = useState(true); + const [isDetail, setIsDetail] = useState(true); + const [detailInfoLoading, setDetailInfoLoading] = useState(false); + const [pathList, setPathList] = useState([]); + const [node, setNode] = useState({}); + const [idenKey, setIdenKey] = useState([]); + const [siderWidth, setSiderWidth] = useState(200); + const [startPageX, setStartPageX] = useState(0); + const [dragging, setDragging] = useState(false); + const [detailTreeData, setDetailTreeData] = useState([]); + + const onClose = () => { + setVisible(false); + setPathList([]); + setNode({}); + setIdenKey([]); + }; + + const siderMouseDown = (e: { pageX: number }) => { + setStartPageX(e.pageX); + setDragging(true); + }; + + const siderMouseMove = (e: { pageX: number }) => { + const currentSiderWidth = siderWidth + e.pageX - startPageX; + + if (currentSiderWidth < 200) { + setSiderWidth(200); + } else if (currentSiderWidth > 320) { + setSiderWidth(320); + } else { + setSiderWidth(currentSiderWidth); + } + + setStartPageX(e.pageX); + }; + + const siderMouseUp = () => { + setDragging(false); + }; + + const rootClick = () => { + setPathList([]); + setIdenKey([]); + }; + + useEffect(() => { + // 第一次加载不触发详情信息的loading + !detailLoading && setDetailInfoLoading(true); + visible && + request(Api.getZookeeperNodeData(+global?.clusterInfo?.id), { + params: { path: '/' + pathList.map((item: DataNode) => item.title).join('/') }, + }) + .then((res) => { + setNode(res || {}); + }) + .catch(() => { + setNode({}); + }) + .finally(() => { + setDetailInfoLoading(false); + }); + }, [pathList]); + + useEffect(() => { + setDetailLoading(true); + visible && + request(Api.getZookeeperNodeChildren(+global?.clusterInfo?.id), { params: { path: '/', keyword: '' } }) + // zkDetailInfo() + .then((res: string[]) => { + const newData = + res && res.length > 0 + ? res.map((item: string, index: number) => { + return { + title: item, + key: `${index}`, + }; + }) + : []; + if (newData.length > 0) { + setIsDetail(false); + setDetailTreeData(newData); + } + }) + .finally(() => { + setDetailLoading(false); + }); + }, [visible]); + + return ( + + + {isDetail ? ( +
+ +
+ ) : ( +
+
+
目录结构
+
+ {visible && ( + + )} +
+
+
+ {dragging &&
} +
+
+
详细信息
+
+ {visible && ( + +
+
+ {node.namespace} + {pathList.length > 0 && + pathList.map((item, index) => { + if (item.key === idenKey[0]) { + return ( + + {' '} + / + setIdenKey([item.key])}> + {item.title} + + + ); + } + return ( + + {' '} + / + setIdenKey([item.key])}> + {item.title} + + + ); + })} +
+ {/*
{'/' + pathList.map((item: any) => item.title).join(' / ') || '/'}
*/} +
+ +
+ +
+
+ )} +
+
+
+ )} + + + ); +}; + +export default ZookeeperDetail; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Info.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Info.tsx new file mode 100644 index 00000000..d327c552 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Info.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Descriptions } from 'knowdesign'; +import moment from 'moment'; +const ZKInfo = ({ nodeInfo, siderWidth }: any) => { + const smallStyle = { + width: 82, + }; + return ( + = 270 ? 2 : 3} + labelStyle={{ + display: 'flex', + textAlign: 'right', + justifyContent: 'end', + color: '#74788D', + fontSize: '13px', + width: siderWidth >= 270 ? 144 : 100, + }} + contentStyle={{ fontSize: '13px' }} + > + + {nodeInfo.aversion || nodeInfo.aversion === 0 ? nodeInfo.aversion : '-'} + + {nodeInfo.ctime || nodeInfo.ctime === 0 ? nodeInfo.ctime : '-'} + + {nodeInfo.ctime ? moment(nodeInfo.ctime).format('YYYY-MM-DD HH:mm:ss') : '-'} + + + {nodeInfo.cversion || nodeInfo.cversion === 0 ? nodeInfo.cversion : '-'} + + {nodeInfo.czxid || nodeInfo.czxid === 0 ? nodeInfo.czxid : '-'} + + {nodeInfo.dataLength || nodeInfo.dataLength === 0 ? nodeInfo.dataLength : '-'} + + + {nodeInfo.mtime || nodeInfo.mtime === 0 ? nodeInfo.mtime : '-'} + + + {nodeInfo.mtime ? moment(nodeInfo.mtime).format('YYYY-MM-DD HH:mm:ss') : '-'} + + + {nodeInfo.numChildren || nodeInfo.numChildren === 0 ? nodeInfo.numChildren : '-'} + + + {nodeInfo.mzxid || nodeInfo.mzxid === 0 ? nodeInfo.mzxid : '-'} + + + {nodeInfo.ephemeralOwner || nodeInfo.ephemeralOwner === 0 ? nodeInfo.ephemeralOwner : '-'} + + + {nodeInfo.pzxid || nodeInfo.pzxid === 0 ? nodeInfo.pzxid : '-'} + + + {nodeInfo.version || nodeInfo.version === 0 ? nodeInfo.version : '-'} + + + ); +}; + +export default ZKInfo; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Sider.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Sider.tsx new file mode 100644 index 00000000..40f4bbc5 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/Sider.tsx @@ -0,0 +1,179 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { Tree, SearchInput, AppContainer, Utils } from 'knowdesign'; +import { DataNode, DetailMenuType, getPathByKey, updateTreeData } from './config'; +import Api from '@src/api'; + +const { request } = Utils; + +const ZKDetailMenu = (props: DetailMenuType) => { + const { detailTreeData, setDetailInfoLoading, setPathList, setIdenKey, idenKey } = props; + const [global] = AppContainer.useGlobalValue(); + const [treeData, setTreeData] = useState(detailTreeData); + const [autoExpandParent, setAutoExpandParent] = useState(true); + const [expandedKeys, setExpandedKeys] = useState([]); + const [loadedKeys, setLoadedKeys] = useState([]); + const [childrenClose, setChildrenClose] = useState(false); + // const [searchValue, setSearchValue] = useState(''); + + // const treeRef = useRef(); + + // 处理参数 + const getParams = (key: string, searchValue?: string) => { + const path = + '/' + + getPathByKey(key, treeData) + .map((item: any) => item.title) + .join('/'); + return { + path, + keyword: searchValue ? searchValue : '', + }; + }; + + const onSelect = (selectedKeys: string[]) => { + // 控制右侧详情内容的Loading + setDetailInfoLoading(true); + setIdenKey(selectedKeys); + }; + + const onLoadData = ({ key, children = null }: any) => { + return new Promise((resolve, reject) => { + // 节点关闭,在展开要重新发送请求,以保证节点的准确性 + if (children && !childrenClose) { + resolve(); + return; + } + request(Api.getZookeeperNodeChildren(+global?.clusterInfo?.id), { params: getParams(key) }) + .then((res: string[]) => { + const newData = + res && res.length > 0 + ? res.map((item: string, index: number) => { + return { + title: item, + key: `${key}-${index}`, + }; + }) + : [ + { + title: '暂无子节点', + key: `${key}-${1}`, + disabled: true, + selectable: false, + isLeaf: true, + }, + ]; + setAutoExpandParent(true); + setTreeData((origin: DataNode[]) => updateTreeData(origin, key, newData)); + }) + .finally(() => { + return resolve(); + }); + }); + }; + + const searchChange = (e: string) => { + if (idenKey[0] && idenKey[0].length > 0) { + request(Api.getZookeeperNodeChildren(+global?.clusterInfo?.id), { params: getParams(idenKey[0], e) }).then((res: string[]) => { + const newData = + res && res.length > 0 + ? res.map((item: string, index: number) => { + return { + title: item, + key: `${idenKey[0]}-${index}`, + }; + }) + : [ + // 如果查询不到节点或者所查询的父节点下没有子节点人为插入一个节点 + { + title: e ? '未搜索到相关节点' : '暂无子节点', + key: `${idenKey[0]}-${0}`, + disabled: true, + selectable: false, + isLeaf: true, + }, + ]; + + setTreeData((origin: DataNode[]) => { + return updateTreeData(origin, idenKey[0], newData); + }); + // 筛选打开的节点中非选中节点的其他节点(排除选中节点以及选中节点的叶子节点) + const filterExpandedKeys = expandedKeys.filter((item) => item.slice(0, idenKey[0].length) !== idenKey[0]); + // 将当前选中的节点再次合并 + const newExpandedKeys = [...filterExpandedKeys, ...idenKey]; + setExpandedKeys(newExpandedKeys); + setLoadedKeys(newExpandedKeys); + setAutoExpandParent(true); + }); + } + }; + + // 展开收起 + const onExpand = (keys: any, arg: any) => { + const { node, expanded } = arg; + let filterExpandedKeys = keys; + let newLoadKeys = loadedKeys; + setChildrenClose(false); + if (!expanded) { + idenKey[0] !== node.key && (idenKey[0] as string)?.slice(0, node.key.length) === node.key && setIdenKey([]); + filterExpandedKeys = keys.filter((item: string) => { + return item !== node.key && item.slice(0, node.key.length) !== node.key; + }); + newLoadKeys = loadedKeys.filter((i: string) => i.slice(0, node.key.length) !== node.key); + setChildrenClose(true); + } + setAutoExpandParent(false); + setExpandedKeys(filterExpandedKeys); + setLoadedKeys(newLoadKeys); + }; + + const onLoad = (loadedKeys: string[]) => { + setLoadedKeys(loadedKeys); + }; + + useEffect(() => { + // treeRef?.current?.scrollTo({ key: idenKey[0] }); + const pathKey = getPathByKey(idenKey[0], treeData); + setPathList(pathKey); + }, [idenKey]); + + useEffect(() => { + if (detailTreeData.length > 0) { + setTreeData(detailTreeData); + } + }, [detailTreeData]); + + return ( + <> + setSearchValue(value), + }} + /> +
+ +
+ + ); +}; + +export default ZKDetailMenu; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/config.tsx new file mode 100644 index 00000000..29f4b78d --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/config.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import { Tag } from 'knowdesign'; +export interface DetailMenuType { + detailTreeData: any; + setDetailInfoLoading: (loading: boolean) => void; + setPathList: (pathList: DataNode[]) => void; + setIdenKey: (idenKey: string[]) => void; + idenKey: string[]; +} +export interface DataNode { + title: string; + key: string; + isLeaf?: boolean; + children?: DataNode[]; +} + +// 角色 +const roleType: any = { + leader: 'Leader', + follower: 'Follower', + ovsever: 'Obsever', +}; + +export const updateTreeData = (list: DataNode[], key: React.Key, children: DataNode[]): DataNode[] => { + return list.map((node) => { + if (node.key === key) { + return { + ...node, + children, + }; + } + if (node.children) { + return { + ...node, + children: updateTreeData(node.children, key, children), + }; + } + return node; + }); +}; + +export const getZookeeperColumns = (arg?: any) => { + const columns = [ + { + title: 'Host', + dataIndex: 'host', + key: 'host', + width: 200, + render: (t: string, r: any) => { + return ( + + {t} + {r?.status ? Live : Down} + + ); + }, + }, + { + title: 'Port', + dataIndex: 'port', + key: 'port', + width: 200, + }, + { + title: 'Version', + dataIndex: 'version', + key: 'version', + width: 200, + }, + { + title: 'Role', + dataIndex: 'role', + key: 'role', + width: 200, + render(t: string, r: any) { + return ( + + {roleType[t]} + + ); + }, + }, + ]; + return columns; +}; + +export const defaultPagination = { + current: 1, + pageSize: 10, + position: 'bottomRight', + showSizeChanger: true, + pageSizeOptions: ['10', '20', '50', '100', '200', '500'], +}; + +export const getPathByKey = (curKey: string, data: DataNode[]) => { + /** 存放搜索到的树节点到顶部节点的路径节点 */ + let result: any[] = []; + + const traverse = (curKey: string, path: any[], data: DataNode[]) => { + // 树为空时,不执行函数 + if (data.length === 0) { + return; + } + + // 遍历存放树的数组 + for (const item of data) { + // 遍历的数组元素存入path参数数组中 + path.push(item); + // 如果目的节点的id值等于当前遍历元素的节点id值 + if (item.key === curKey) { + // 把获取到的节点路径数组path赋值到result数组 + result = JSON.parse(JSON.stringify(path)); + return; + } + + // 当前元素的children是数组 + const children = Array.isArray(item.children) ? item.children : []; + // 递归遍历子数组内容 + traverse(curKey, path, children); + // 利用回溯思想,当没有在当前叶树找到目的节点,依次删除存入到的path数组路径 + path.pop(); + } + }; + traverse(curKey, [], data); + // 返回找到的树节点路径 + return result; +}; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.less b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.less new file mode 100644 index 00000000..1d0a3c34 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.less @@ -0,0 +1,131 @@ +.zookeeper-detail-drawer { + .zk-detail-empty { + display: flex; + align-items: center; + justify-content: center; + border-radius: 8px; + border: 2px solid #eff2f7; + height: calc(100vh - 90px); + } + .zk-detail-layout { + display: flex; + border-radius: 8px; + border: 2px solid #eff2f7; + height: 100%; + position: relative; + &-left, + &-right { + &-title { + background-color: rgba(116, 120, 141, 0.04); + font-size: 14px; + font-weight: 500; + font-family: @font-family-bold; + padding: 12px 20px; + border-bottom: 2px solid #eff2f7; + } + &-content { + height: calc(100vh - 128px); + } + } + &-left { + min-width: 200px; + max-width: 320px; + &-content { + padding: 10px; + &-text { + height: calc(100vh - 190px); + overflow: auto; + } + } + .dcloud-tree-title { + white-space: nowrap !important; + } + .dcloud-tree-treenode { + font-size: 13px; + padding: 6px 0; + } + .dcloud-tree-node-content-wrapper { + &:hover:not(.dcloud-tree-node-content-wrapper-normal) { + background: #f1f3ff !important; + color: #556ee6; + } + } + .dcloud-tree .dcloud-tree-node-content-wrapper.dcloud-tree-node-selected { + background-color: transparent; + color: #556ee6; + } + } + &-resizer { + .resize-mask { + background: rgba(0, 0, 0, 0); + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: 1; + cursor: col-resize; + } + border: 1px solid #eff2f7; + position: absolute; + left: 200px; + top: 0; + bottom: 0; + cursor: col-resize; + &:hover { + border: 1px solid #556ee6; + } + } + &-right { + flex: 1; + &-content { + padding: 12px 20px 16px; + overflow: auto; + &-info { + background: rgba(116, 120, 141, 0.04); + border-radius: 8px; + padding: 12px 0 0; + } + &-countheight { + display: flex; + flex-direction: column; + height: calc(100vh - 156px); + } + &-path { + margin-bottom: 16px; + + & > *:hover { + color: #556ee6; + cursor: pointer; + } + } + &-format { + margin: 12px 0 6px; + display: flex; + justify-content: right; + } + &-data { + flex: 1; + overflow: auto; + background: rgba(116, 120, 141, 0.04); + border-radius: 8px; + padding: 12px 20px 0; + } + &-code { + flex: 1; + overflow: auto; + border-radius: 8px; + &-data { + height: 100% !important; + } + .cm-s-default { + height: 100% !important; + // border-radius: 8px !important; + overflow: hidden; + background: rgba(116, 120, 141, 0.04); + } + } + } + } + } +} diff --git a/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.tsx new file mode 100644 index 00000000..c7b56f53 --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/Zookeeper/index.tsx @@ -0,0 +1,128 @@ +import React, { useState, useEffect, memo } from 'react'; +import { useParams, useHistory, useLocation } from 'react-router-dom'; +import { ProTable, Button, Utils, AppContainer, SearchInput } from 'knowdesign'; +import { IconFont } from '@knowdesign/icons'; +import API from '../../api'; +import { getZookeeperColumns, defaultPagination } from './config'; +import { tableHeaderPrefix } from '@src/constants/common'; +import ZookeeperDetail from './Detail'; +import ZookeeperCard from '@src/components/CardBar/ZookeeperCard'; +import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb'; +import './index.less'; +const { request } = Utils; + +const ZookeeperList: React.FC = () => { + const [global] = AppContainer.useGlobalValue(); + const [loading, setLoading] = useState(false); + const [detailVisible, setDetailVisible] = useState(false); + const [data, setData] = useState([]); + const [searchKeywords, setSearchKeywords] = useState(''); + const [pagination, setPagination] = useState(defaultPagination); + + // 请求接口获取数据 + const genData = async ({ pageNo, pageSize, filters, sorter }: any) => { + if (global?.clusterInfo?.id === undefined) return; + + setLoading(true); + const params = { + searchKeywords: searchKeywords.slice(0, 128), + pageNo, + pageSize, + }; + + request(API.getZookeeperList(global?.clusterInfo?.id), { method: 'POST', data: params }) + .then((res: any) => { + setPagination({ + current: res.pagination?.pageNo, + pageSize: res.pagination?.pageSize, + total: res.pagination?.total, + }); + const newData = + res?.bizData.map((item: any) => { + return { + ...item, + ...item?.latestMetrics?.metrics, + }; + }) || []; + setData(newData); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + + const onTableChange = (pagination: any, filters: any, sorter: any) => { + genData({ pageNo: pagination.current, pageSize: pagination.pageSize, filters, sorter }); + }; + + useEffect(() => { + genData({ + pageNo: 1, + pageSize: pagination.pageSize, + }); + }, [searchKeywords]); + + return ( +
+
+ +
+
+ +
+
+
+
+
genData({ pageNo: pagination.current, pageSize: pagination.pageSize })} + > + +
+
+
+ + +
+
+ +
+ {} +
+ ); +}; + +export default ZookeeperList; diff --git a/km-console/packages/layout-clusters-fe/src/pages/ZookeeperDashboard/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/ZookeeperDashboard/index.tsx new file mode 100644 index 00000000..4f92604b --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/ZookeeperDashboard/index.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { MetricType } from '@src/api'; +import DraggableCharts from '@src/components/DraggableCharts'; +import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb'; +import { AppContainer } from 'knowdesign'; +import ZookeeperCard from '@src/components/CardBar/ZookeeperCard'; + +const ZookeeperDashboard = (): JSX.Element => { + const [global] = AppContainer.useGlobalValue(); + return ( + <> +
+ +
+ + + + ); +}; + +export default ZookeeperDashboard; diff --git a/km-console/packages/layout-clusters-fe/src/pages/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/index.tsx index 16d73de9..063e2db0 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/index.tsx @@ -7,6 +7,7 @@ import { leftMenus, systemKey } from '@src/constants/menu'; import { ClustersPermissionMap } from './CommonConfig'; import { getLicenseInfo } from '@src/constants/common'; import { licenseEventBus } from '@src/constants/axiosConfig'; +import { ClusterRunState } from './MutliClusterPage/List'; export const NoMatch = ; @@ -35,6 +36,13 @@ const LayoutContainer = () => { const [showSider, setShowSider] = useState(!(notCurrentSystemKey || hasNoSiderPage)); const [handledLeftMenus, setHandledLeftMenus] = useState(leftMenus()); + const forbidenPaths = (path: string) => { + // Raft 模式运行的集群没有 ZK 页面 + if (path.includes('zookeeper') && global.clusterInfo?.runState === ClusterRunState.Raft) { + history.replace('/404'); + } + }; + const isShowMenu = useCallback( (nodes: ClustersPermissionMap | ClustersPermissionMap[]) => { let isAllow = false; @@ -67,6 +75,7 @@ const LayoutContainer = () => { if (permissionNode) { // 判断用户是否有当前页面的权限 if (global.hasPermission(permissionNode)) { + forbidenPaths(path); return Promise.resolve(true); } else { // 用户没有当前页面权限,跳转到多集群首页 @@ -77,6 +86,7 @@ const LayoutContainer = () => { return Promise.reject(false); } } + forbidenPaths(path); return Promise.resolve(true); }, [global.clusterInfo, global.hasPermission, global.getMetricDefine] @@ -86,12 +96,14 @@ const LayoutContainer = () => { const notCurrentSystemKey = window.location.pathname.split('/')?.[1] !== systemKey; const hasNoSiderPage = noSiderPages.findIndex((item) => item.path === getCurrentPathname(pathname)) > -1; setShowSider(notCurrentSystemKey || hasNoSiderPage ? false : true); + if (pathname.startsWith('/cluster') || pathname === '/') { const items = pathname.split('/'); const clusterId = items[2]; - setHandledLeftMenus(leftMenus(clusterId)); + clusterId !== global.clusterInfo?.id && + setHandledLeftMenus(leftMenus(clusterId, pathname === '/' ? undefined : global.clusterInfo?.runState)); } - }, [pathname]); + }, [pathname, global.clusterInfo]); return (
diff --git a/km-console/packages/layout-clusters-fe/src/pages/pageRoutes.ts b/km-console/packages/layout-clusters-fe/src/pages/pageRoutes.ts index 50e6ac71..4ed321aa 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/pageRoutes.ts +++ b/km-console/packages/layout-clusters-fe/src/pages/pageRoutes.ts @@ -22,6 +22,9 @@ import SecurityACLs from './SecurityACLs'; import SecurityUsers from './SecurityUsers'; import LoadRebalance from './LoadRebalance'; +import Zookeeper from './Zookeeper'; +import ZookeeperDashboard from './ZookeeperDashboard'; + const pageRoutes = [ { path: '/', @@ -115,6 +118,18 @@ const pageRoutes = [ component: Jobs, noSider: false, }, + { + path: 'zookeeper', + exact: true, + component: ZookeeperDashboard, + noSider: false, + }, + { + path: 'zookeeper/servers', + exact: true, + component: Zookeeper, + noSider: false, + }, { path: 'security/acls', exact: true,