chore: create cluster ux

This commit is contained in:
jialin
2025-09-16 11:26:17 +08:00
parent 55b0a20a4a
commit 62dbd18ef8
26 changed files with 690 additions and 392 deletions
+6 -4
View File
@@ -24,6 +24,8 @@ export default function useChartConfig() {
splitLineColor: token.colorBorder,
tickLineColor: token.colorSplit,
axislabelColor: token.colorTextTertiary,
colorSecondary: token.colorTextSecondary,
colorTertiary: token.colorTextTertiary,
gaugeBgColor: token.colorFillSecondary,
gaugeSplitLineColor: isDarkTheme
? 'rgba(255,255,255,.3)'
@@ -172,8 +174,8 @@ export default function useChartConfig() {
}
},
axisTick: {
distance: -11,
length: 6,
distance: -10,
length: 5,
splitNumber: 5,
lineStyle: {
width: 1.5,
@@ -206,13 +208,13 @@ export default function useChartConfig() {
rich: {
value: {
fontSize: 16,
fontWeight: '500',
fontWeight: '600',
color: chartColorMap.titleColor
},
unit: {
fontSize: 14,
color: chartColorMap.titleColor,
fontWeight: '500',
fontWeight: '600',
padding: [0, 0, 0, 2]
}
}
+12 -3
View File
@@ -1,7 +1,7 @@
import Chart from '@/components/echarts/chart';
import useChartConfig from '@/components/echarts/config';
import EmptyData from '@/components/empty-data';
import React, { memo } from 'react';
import React from 'react';
import { ChartProps } from './types';
const strokeColorFunc = (percent: number) => {
@@ -34,10 +34,19 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
...gaugeItemConfig,
...gaugeConfig
};
combineGaugeConfig.detail.rich.value.color = colorValue;
combineGaugeConfig.detail.rich.unit.color = colorValue;
return {
title: {
...titleConfig,
text: title,
textStyle: {
fontSize: 12,
color: chartColorMap.colorSecondary,
fontWeight: 400
},
top: '0',
left: 'center'
},
@@ -58,7 +67,7 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
color: 'transparent'
},
detail: {
...gaugeItemConfig.detail,
...combineGaugeConfig.detail,
formatter: labelFormatter || gaugeItemConfig.detail.formatter
},
data: [{ value }]
@@ -78,4 +87,4 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
);
};
export default memo(GaugeChart);
export default GaugeChart;
+37 -5
View File
@@ -1,10 +1,20 @@
import OverlayScroller from '@/components/overlay-scroller';
import useBodyScroll from '@/hooks/use-body-scroll';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { Modal, type ModalProps } from 'antd';
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.div<{ $maxHeight?: number }>`
max-height: ${({ $maxHeight }) =>
typeof $maxHeight === 'number' ? `${$maxHeight}px` : $maxHeight};
overflow-y: auto;
width: 100%;
`;
const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
const scroller = React.useRef<any>(null);
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
const { initialize, destroyInstance } = useOverlayScroller();
React.useEffect(() => {
if (props.open) {
@@ -14,6 +24,24 @@ const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
}
}, [props.open]);
// init scroller, delay to ensure modal is fully open
React.useEffect(() => {
let timeout = null;
if (props.open) {
timeout = setTimeout(() => {
if (scroller.current) {
initialize(scroller.current);
}
}, 100);
}
return () => {
if (timeout) {
clearTimeout(timeout);
}
destroyInstance();
};
}, [props.open, initialize]);
return (
<Modal
{...props}
@@ -34,12 +62,16 @@ const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
}
}}
>
<OverlayScroller
style={{ paddingInline: 24, paddingBlockEnd: props.footer ? 0 : 32 }}
maxHeight={props.maxContentHeight || 500}
<Wrapper
ref={scroller}
data-overlayscrollbars-initialize
className="overlay-scroller-wrapper"
$maxHeight={props.maxContentHeight || 500}
hidden={false}
style={{ paddingInline: 24, paddingBlockEnd: props.footer ? 0 : 24 }}
>
{props.children}
</OverlayScroller>
</Wrapper>
</Modal>
);
};
+14 -2
View File
@@ -1,6 +1,18 @@
import useUserSettings from '@/hooks/use-user-settings';
import { Tag, TagProps } from 'antd';
import React from 'react';
import styled from 'styled-components';
const TagWrapper = styled(Tag)`
display: flex;
align-items: center;
justify-content: center;
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
height: 22px;
opacity: 0.7;
`;
const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
opacity,
@@ -11,7 +23,7 @@ const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
const { userSettings } = useUserSettings();
const { isDarkTheme } = userSettings;
return (
<Tag
<TagWrapper
{...restProps}
style={{
...style,
@@ -19,7 +31,7 @@ const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
}}
>
{children}
</Tag>
</TagWrapper>
);
};
+13 -2
View File
@@ -8,13 +8,14 @@ interface CardProps {
children?: React.ReactNode;
clickable?: boolean;
ghost?: boolean;
header?: React.ReactNode;
footer?: React.ReactNode;
onClick?: () => void;
}
const CardWrapper = styled.div`
overflow: hidden;
display: flex;
padding: 16px 20px;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
@@ -39,6 +40,12 @@ const CardWrapper = styled.div`
}
`;
const CardContent = styled.div`
padding: 16px 20px;
width: 100%;
flex: 1;
`;
const Card: React.FC<CardProps> = (props) => {
const {
className,
@@ -46,6 +53,8 @@ const Card: React.FC<CardProps> = (props) => {
children,
clickable = true,
ghost = false,
header,
footer,
onClick
} = props;
@@ -58,7 +67,9 @@ const Card: React.FC<CardProps> = (props) => {
style={{ height: height || '180px' }}
onClick={onClick}
>
{children}
{header}
<CardContent>{children}</CardContent>
{footer}
</CardWrapper>
);
};