Skip to content

Commit 48b064c

Browse files
TianWuwtchris-sun-star
authored andcommitted
fix:修复部分缺陷问题 || fix: Fix some defects (#839)
1 parent e998012 commit 48b064c

7 files changed

Lines changed: 160 additions & 78 deletions

File tree

ui/src/app.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ export const request: RequestConfig = {
2626
},
2727
errorHandler: (err) => {
2828
console.log('errorHandler', err);
29+
30+
const url = err?.config?.url || err?.request?.responseURL || '';
31+
2932
if (err?.response?.status === 401) {
3033
location.href = '/#/login';
34+
} else if (url.includes('/api/web/oceanbase/report')) {
35+
console.log('Report data error, not showing message:', err);
3136
} else {
3237
message.error(err?.response?.data?.message || err.message);
3338
}

ui/src/components/MonitorComp/LineGraph.tsx

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Line } from '@antv/g2plot';
66
import { useInViewport, useUpdateEffect } from 'ahooks';
77
import { Empty, Spin } from 'antd';
88
import dayjs from 'dayjs';
9-
import { useRef, useState } from 'react';
9+
import { useEffect, useRef, useState } from 'react';
1010

1111
type MetricType = {
1212
description: string;
@@ -104,13 +104,16 @@ export default function LineGraph({
104104
},
105105
interactions: [{ type: 'marker-active' }, { type: 'brush' }],
106106
};
107+
108+
// 如果图表实例存在,先销毁它
107109
if (lineInstanceRef.current) {
108-
// lineInstanceRef.current.update({ ...config });
109-
lineInstanceRef.current.changeData(metricsData);
110-
} else {
111-
lineInstanceRef.current = new Line(id, { ...config });
112-
lineInstanceRef.current.render();
110+
lineInstanceRef.current.destroy();
111+
lineInstanceRef.current = null;
113112
}
113+
114+
// 创建新的图表实例
115+
lineInstanceRef.current = new Line(id, { ...config });
116+
lineInstanceRef.current.render();
114117
};
115118

116119
const lineInstanceDestroy = () => {
@@ -135,14 +138,12 @@ export default function LineGraph({
135138
}
136139

137140
if (metricsData && metricsData.length > 0) {
138-
if (isEmpty) {
139-
setIsEmpty(false);
140-
setIsloading(false);
141-
return;
142-
}
141+
setIsEmpty(false);
142+
setIsloading(false);
143143
lineInstanceRender(metricsData);
144+
} else {
145+
lineInstanceDestroy();
144146
}
145-
setIsloading(false);
146147
},
147148
onError: () => {
148149
lineInstanceDestroy();
@@ -161,6 +162,13 @@ export default function LineGraph({
161162
}
162163
}, [inViewport]);
163164

165+
// 当ID变化时,重新检查视口状态
166+
useUpdateEffect(() => {
167+
if (inViewport && inViewportCount === 0) {
168+
setInViewportCount(1);
169+
}
170+
}, [id, inViewport]);
171+
164172
useUpdateEffect(() => {
165173
if (inViewportCount === 1 && !isRefresh) {
166174
queryMetrics(getQueryParms());
@@ -183,6 +191,32 @@ export default function LineGraph({
183191
}
184192
}, [labels, queryRange]);
185193

194+
// 监听ID变化,当tab切换导致ID变化时,重新初始化图表
195+
useUpdateEffect(() => {
196+
if (lineInstanceRef.current) {
197+
lineInstanceDestroy();
198+
}
199+
// 重置inViewportCount,确保新tab能触发数据查询
200+
setInViewportCount(0);
201+
// 立即触发数据查询,不等待视口检测
202+
if (!isRefresh) {
203+
queryMetrics(getQueryParms());
204+
}
205+
}, [id]);
206+
207+
// 组件卸载时清理图表实例
208+
useEffect(() => {
209+
return () => {
210+
if (lineInstanceRef.current) {
211+
lineInstanceDestroy();
212+
}
213+
// 重置状态
214+
setInViewportCount(0);
215+
setIsEmpty(true);
216+
setIsloading(true);
217+
};
218+
}, []);
219+
186220
return (
187221
<div style={{ height: `${height}px` }}>
188222
<Spin spinning={isloading}>

ui/src/components/MonitorComp/index.tsx

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -46,65 +46,70 @@ export default function MonitorComp({
4646
defaultParams: [queryScope],
4747
});
4848

49-
// 生成tab列表和内容
50-
const { tabList, contentList } = useMemo(() => {
51-
const tabs =
49+
// 生成tab列表
50+
const tabList = useMemo(() => {
51+
return (
5252
allMetrics?.map((container: any, index: number) => ({
5353
key: index.toString(),
5454
label: container?.name,
55-
})) || [];
55+
})) || []
56+
);
57+
}, [allMetrics]);
5658

57-
const contents: Record<string, React.ReactNode> = {};
59+
// 生成当前激活tab的内容
60+
const currentTabContent = useMemo(() => {
61+
const currentContainer = allMetrics?.[parseInt(activeTabKey)];
62+
if (!currentContainer) return null;
5863

59-
allMetrics?.forEach((container: any, index: number) => {
60-
contents[index.toString()] = (
61-
<div className={styles.monitorContainer}>
62-
{container?.metricGroups?.map(
63-
(graphContainer: any, graphIdx: number) => (
64-
<Card className={styles.monitorItem} key={graphIdx}>
65-
<div className={styles.graphHeader}>
66-
<IconTip
67-
tip={graphContainer.description}
68-
style={{ fontSize: 16 }}
69-
content={
70-
<span className={styles.graphHeaderText}>
71-
{graphContainer.name}
72-
{graphContainer.metrics[0]?.unit &&
73-
`(${graphContainer.metrics[0].unit}${
74-
(graphContainer.metrics[0].unit && type) ===
75-
'OVERVIEW'
76-
? ','
77-
: ''
78-
}${
79-
type === 'OVERVIEW'
80-
? graphContainer.metrics[0].key
81-
: ''
82-
})`}
83-
</span>
84-
}
85-
/>
86-
</div>
87-
<LineGraph
88-
id={`monitor-${graphContainer.name.replace(/\s+/g, '')}`}
89-
isRefresh={isRefresh}
90-
queryRange={queryRange}
91-
metrics={graphContainer.metrics}
92-
labels={filterLabel}
93-
groupLabels={groupLabels}
94-
type={type}
95-
useFor={useFor}
96-
filterData={filterData}
97-
filterQueryMetric={filterQueryMetric}
64+
return (
65+
<div className={styles.monitorContainer}>
66+
{currentContainer?.metricGroups?.map(
67+
(graphContainer: any, graphIdx: number) => (
68+
<Card className={styles.monitorItem} key={graphIdx}>
69+
<div className={styles.graphHeader}>
70+
<IconTip
71+
tip={graphContainer.description}
72+
style={{ fontSize: 16 }}
73+
content={
74+
<span className={styles.graphHeaderText}>
75+
{graphContainer.name}
76+
{graphContainer.metrics[0]?.unit &&
77+
`(${graphContainer.metrics[0].unit}${
78+
(graphContainer.metrics[0].unit && type) ===
79+
'OVERVIEW'
80+
? ','
81+
: ''
82+
}${
83+
type === 'OVERVIEW'
84+
? graphContainer.metrics[0].key
85+
: ''
86+
})`}
87+
</span>
88+
}
9889
/>
99-
</Card>
100-
),
101-
)}
102-
</div>
103-
);
104-
});
105-
106-
return { tabList: tabs, contentList: contents };
90+
</div>
91+
<LineGraph
92+
id={`monitor-${activeTabKey}-${graphContainer.name.replace(
93+
/\s+/g,
94+
'',
95+
)}`}
96+
isRefresh={isRefresh}
97+
queryRange={queryRange}
98+
metrics={graphContainer.metrics}
99+
labels={filterLabel}
100+
groupLabels={groupLabels}
101+
type={type}
102+
useFor={useFor}
103+
filterData={filterData}
104+
filterQueryMetric={filterQueryMetric}
105+
/>
106+
</Card>
107+
),
108+
)}
109+
</div>
110+
);
107111
}, [
112+
activeTabKey,
108113
allMetrics,
109114
isRefresh,
110115
queryRange,
@@ -125,7 +130,7 @@ export default function MonitorComp({
125130
activeTabKey={activeTabKey}
126131
onTabChange={(key) => setActiveTabKey(key)}
127132
>
128-
{contentList[activeTabKey] || (
133+
{currentTabContent || (
129134
<div style={{ padding: 20, textAlign: 'center', color: '#999' }}>
130135
暂无数据
131136
</div>

ui/src/hook/usePublicKey.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ export const usePublicKey = () => {
77
const { publicKey, setPublicKey } = useModel('global');
88

99
useEffect(() => {
10-
if (!publicKey) {
11-
getAppInfo()
12-
.then(({ data }) => {
13-
setPublicKey(data.publicKey);
14-
})
15-
.catch((err) => {
16-
console.log(err);
17-
});
18-
}
10+
getAppInfo()
11+
.then(({ data }) => {
12+
setPublicKey(data.publicKey);
13+
})
14+
.catch((err) => {
15+
console.log(err);
16+
});
1917
}, []);
2018

2119
return publicKey;

ui/src/pages/Cluster/Detail/Connection/index.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { PageContainer } from '@ant-design/pro-components';
77
import { useAccess, useParams } from '@umijs/max';
88
import { useRequest } from 'ahooks';
99
import { Button, Col, Row, Space, message } from 'antd';
10-
import React, { useState } from 'react';
10+
import React, { useEffect, useState } from 'react';
1111
import BasicInfo from '../Overview/BasicInfo';
1212

1313
const ClusterConnection: React.FC = () => {
@@ -33,6 +33,33 @@ const ClusterConnection: React.FC = () => {
3333
});
3434

3535
const [terminalId, setTerminalId] = useState<string>();
36+
37+
// 组件卸载时关闭连接
38+
useEffect(() => {
39+
return () => {
40+
if (terminalId) {
41+
// 这里可以调用关闭连接的API 通过设置terminalId为undefined来触发关闭
42+
setTerminalId(undefined);
43+
}
44+
};
45+
}, [terminalId, ns, name]);
46+
47+
// 监听路由变化,关闭连接
48+
useEffect(() => {
49+
const handleRouteChange = () => {
50+
if (terminalId) {
51+
setTerminalId(undefined);
52+
}
53+
};
54+
55+
// 监听 popstate 事件(浏览器前进后退)
56+
window.addEventListener('popstate', handleRouteChange);
57+
58+
return () => {
59+
window.removeEventListener('popstate', handleRouteChange);
60+
};
61+
}, [terminalId]);
62+
3663
return (
3764
<PageContainer header={header()}>
3865
<link

ui/src/pages/Cluster/Detail/Tenant/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,18 @@ export default function Tenant() {
5050
</Col>
5151
) : null}
5252

53-
{tenantsList && (
53+
{tenantsList && tenantsList.length > 0 && clusterDetail && (
5454
<Col span={24}>
5555
<MonitorComp
56+
key={`monitor-${clusterName}-${tenantsList.length}`}
5657
queryRange={DEFAULT_QUERY_RANGE}
5758
queryScope="OBTENANT"
5859
groupLabels={['tenant_name']}
5960
useFor="tenant"
60-
filterLabel={[{ key: 'ob_cluster_name', value: clusterName }]}
61+
type="DETAIL"
62+
filterLabel={[
63+
{ key: 'ob_cluster_name', value: clusterName || '' },
64+
]}
6165
filterQueryMetric={[
6266
...tenantsList.map((tenant) => ({
6367
key: 'tenant_name' as API.LableKeys,

ui/src/services/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,16 @@ export async function queryMetricsReq({
455455
).value || '';
456456
}
457457
} else {
458-
item.name = metric.metric.name;
458+
// 对于租户详情页面,需要区分不同租户的指标名称
459+
if (useFor === 'tenant' && type === 'DETAIL') {
460+
const tenantLabel = metric.metric.labels.find(
461+
(label) => label.key === 'tenant_name',
462+
);
463+
const tenantName = tenantLabel?.value || '';
464+
item.name = `${metric.metric.name} (${tenantName})`;
465+
} else {
466+
item.name = metric.metric.name;
467+
}
459468
}
460469
});
461470
});

0 commit comments

Comments
 (0)