feat(data-vi): optimize style settings for chart blocks (#4940)

* feat(data-vi): adapt styles to mobile client

* fix: style

* chore: update

* fix: bug

* fix: bug
This commit is contained in:
YANG QIA 2024-07-24 21:34:52 +08:00 committed by GitHub
parent fe2a679132
commit de1994521a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 196 additions and 18 deletions

View File

@ -14,6 +14,7 @@ import { ChartDataProvider } from './ChartDataProvider';
import { ChartRenderer, ChartRendererProvider } from '../renderer'; import { ChartRenderer, ChartRendererProvider } from '../renderer';
import { ChartFilterBlockProvider, ChartFilterBlockDesigner } from '../filter'; import { ChartFilterBlockProvider, ChartFilterBlockDesigner } from '../filter';
import { ChartFilterProvider } from '../filter/FilterProvider'; import { ChartFilterProvider } from '../filter/FilterProvider';
import { css } from '@emotion/css';
export const ChartV2Block: React.FC = (props) => { export const ChartV2Block: React.FC = (props) => {
const [initialVisible, setInitialVisible] = useState(false); const [initialVisible, setInitialVisible] = useState(false);
@ -25,11 +26,24 @@ export const ChartV2Block: React.FC = (props) => {
<SchemaComponentOptions <SchemaComponentOptions
components={{ ChartRenderer, ChartRendererProvider, ChartFilterBlockProvider, ChartFilterBlockDesigner }} components={{ ChartRenderer, ChartRendererProvider, ChartFilterBlockProvider, ChartFilterBlockDesigner }}
> >
<ChartDataProvider> <div
<ChartFilterProvider> className={css`
<ChartConfigProvider>{props.children}</ChartConfigProvider> .ant-nb-card-item {
</ChartFilterProvider> .ant-card {
</ChartDataProvider> box-shadow: none;
}
}
.nb-grid-warp > button:last-child {
margin-bottom: 24px !important;
}
`}
>
<ChartDataProvider>
<ChartFilterProvider>
<ChartConfigProvider>{props.children}</ChartConfigProvider>
</ChartFilterProvider>
</ChartDataProvider>
</div>
</SchemaComponentOptions> </SchemaComponentOptions>
</SchemaInitializerContext.Provider> </SchemaInitializerContext.Provider>
); );

View File

@ -12,15 +12,65 @@ import {
SchemaSettingsBlockTitleItem, SchemaSettingsBlockTitleItem,
SchemaSettingsDivider, SchemaSettingsDivider,
SchemaSettingsRemove, SchemaSettingsRemove,
SchemaSettingsSelectItem,
SchemaSettingsSwitchItem,
useDesignable,
useToken,
} from '@nocobase/client'; } from '@nocobase/client';
import React from 'react'; import React from 'react';
import { useChartsTranslation } from '../locale'; import { useChartsTranslation } from '../locale';
import { useField, useFieldSchema } from '@formily/react';
export const ChartV2BlockDesigner: React.FC = () => { export const ChartV2BlockDesigner: React.FC = () => {
const { t } = useChartsTranslation(); const { t } = useChartsTranslation();
const field = useField();
const fieldSchema = useFieldSchema();
const { dn } = useDesignable();
const { token } = useToken();
return ( return (
<GeneralSchemaDesigner title={t('Charts')} showDataSource={false}> <GeneralSchemaDesigner title={t('Charts')} showDataSource={false}>
<SchemaSettingsBlockTitleItem /> <SchemaSettingsBlockTitleItem />
<SchemaSettingsSwitchItem
title={t('Show background')}
checked={field.componentProps.style?.background !== 'none'}
onChange={(v) => {
const style = {
...field.componentProps.style,
background: v ? token.colorBgContainer : 'none',
boxShadow: v ? token.boxShadowTertiary : 'none',
};
field.componentProps.style = style;
field.componentProps.bordered = v;
fieldSchema['x-component-props'] = field.componentProps;
dn.emit('patch', {
schema: {
['x-uid']: fieldSchema['x-uid'],
'x-component-props': field.componentProps,
},
});
dn.refresh();
}}
/>
<SchemaSettingsSwitchItem
title={t('Show padding')}
checked={field.componentProps.bodyStyle?.padding !== '5px 0 0'}
onChange={(v) => {
const style = {
...field.componentProps.bodyStyle,
padding: v ? `${token.paddingLG}px ${token.paddingLG}px 0` : '5px 0 0',
};
field.componentProps.bodyStyle = style;
fieldSchema['x-component-props'] = field.componentProps;
dn.emit('patch', {
schema: {
['x-uid']: fieldSchema['x-uid'],
'x-component-props': field.componentProps,
},
});
dn.refresh();
}}
/>
<SchemaSettingsDivider /> <SchemaSettingsDivider />
<SchemaSettingsRemove <SchemaSettingsRemove
removeParentsIfNoChildren removeParentsIfNoChildren

View File

@ -17,6 +17,7 @@ import {
useACLRoleContext, useACLRoleContext,
useSchemaInitializer, useSchemaInitializer,
useSchemaInitializerItem, useSchemaInitializerItem,
useToken,
} from '@nocobase/client'; } from '@nocobase/client';
import React, { useCallback, useContext } from 'react'; import React, { useCallback, useContext } from 'react';
import { ChartConfigContext } from '../configure'; import { ChartConfigContext } from '../configure';
@ -103,6 +104,7 @@ export const chartInitializers = new CompatibleSchemaInitializer(
export const ChartV2BlockInitializer: React.FC = () => { export const ChartV2BlockInitializer: React.FC = () => {
const itemConfig = useSchemaInitializerItem(); const itemConfig = useSchemaInitializerItem();
const { insert } = useSchemaInitializer(); const { insert } = useSchemaInitializer();
const { token } = useToken();
return ( return (
<SchemaInitializerItem <SchemaInitializerItem
{...itemConfig} {...itemConfig}
@ -113,6 +115,9 @@ export const ChartV2BlockInitializer: React.FC = () => {
'x-component': 'CardItem', 'x-component': 'CardItem',
'x-component-props': { 'x-component-props': {
name: 'charts', name: 'charts',
bodyStyle: {
padding: `${token.paddingLG}px ${token.paddingLG}px 0`,
},
}, },
'x-designer': 'ChartV2BlockDesigner', 'x-designer': 'ChartV2BlockDesigner',
properties: { properties: {

View File

@ -11,25 +11,38 @@ import React, { useContext, useEffect, useRef } from 'react';
import { ChartRendererContext } from '../../renderer'; import { ChartRendererContext } from '../../renderer';
export const getAntChart = (Component: React.FC<any>) => (props: any) => { export const getAntChart = (Component: React.FC<any>) => (props: any) => {
const { size = {} } = props;
let { height: fixedHeight } = props;
if (!fixedHeight && size.type === 'fixed') {
fixedHeight = size.fixed;
}
const { service } = useContext(ChartRendererContext); const { service } = useContext(ChartRendererContext);
const chartRef = useRef(null); const chartRef = useRef(null);
const [height, setHeight] = React.useState<number>(0); const [height, setHeight] = React.useState<number>(0);
useEffect(() => { useEffect(() => {
const el = chartRef.current; const el = chartRef.current;
if (!el || service.loading === true || props.height) { if (!el || service.loading === true || fixedHeight) {
return; return;
} }
let ratio = 0;
if (size.type === 'ratio' && size.ratio?.width && size.ratio?.height) {
ratio = size.ratio.height / size.ratio.width;
}
const observer = new ResizeObserver((entries) => { const observer = new ResizeObserver((entries) => {
entries.forEach((entry) => { entries.forEach((entry) => {
if (ratio) {
setHeight(entry.contentRect.width * ratio);
return;
}
setHeight(entry.contentRect.height); setHeight(entry.contentRect.height);
}); });
}); });
observer.observe(el); observer.observe(el);
return () => observer.disconnect(); return () => observer.disconnect();
}, [service.loading, props.height]); }, [service.loading, fixedHeight, size.type, size.ratio?.width, size.ratio?.height]);
return ( return (
<div ref={chartRef} style={height ? { height: `${props.height || height}px` } : {}}> <div ref={chartRef} style={height ? { height: `${fixedHeight || height}px` } : {}}>
<Component {...props} {...(height ? { height: props.height || height } : {})} /> <Component {...props} {...(height ? { height: fixedHeight || height } : {})} />
</div> </div>
); );
}; };

View File

@ -9,10 +9,95 @@
import config, { FieldConfigProps } from '../configs'; import config, { FieldConfigProps } from '../configs';
const { booleanField } = config; const { booleanField } = config;
import { lang } from '../../locale';
export default { export default {
isStack: (props: FieldConfigProps) => booleanField({ name: 'isStack', title: 'isStack', ...props }), isStack: (props: FieldConfigProps) => booleanField({ name: 'isStack', title: 'isStack', ...props }),
smooth: (props: FieldConfigProps) => booleanField({ name: 'smooth', title: 'smooth', ...props }), smooth: (props: FieldConfigProps) => booleanField({ name: 'smooth', title: 'smooth', ...props }),
isPercent: (props: FieldConfigProps) => booleanField({ name: 'isPercent', title: 'isPercent', ...props }), isPercent: (props: FieldConfigProps) => booleanField({ name: 'isPercent', title: 'isPercent', ...props }),
isGroup: (props: FieldConfigProps) => booleanField({ name: 'isGroup', title: 'isGroup', ...props }), isGroup: (props: FieldConfigProps) => booleanField({ name: 'isGroup', title: 'isGroup', ...props }),
size: () => ({
size: {
title: lang('Size'),
type: 'object',
'x-decorator': 'FormItem',
'x-component': 'Space',
properties: {
type: {
'x-component': 'Select',
'x-component-props': {
allowClear: false,
},
default: 'ratio',
enum: [
{
label: lang('Aspect ratio'),
value: 'ratio',
},
{
label: lang('Fixed height'),
value: 'fixed',
},
],
},
fixed: {
type: 'number',
'x-component': 'InputNumber',
'x-component-props': {
min: 0,
addonAfter: 'px',
},
'x-reactions': [
{
dependencies: ['.type'],
fulfill: {
state: {
visible: "{{$deps[0] === 'fixed'}}",
},
},
},
],
},
ratio: {
type: 'object',
'x-component': 'Space',
'x-reactions': [
{
dependencies: ['.type'],
fulfill: {
state: {
visible: "{{$deps[0] === 'ratio'}}",
},
},
},
],
properties: {
width: {
type: 'number',
'x-component': 'InputNumber',
'x-component-props': {
placeholder: lang('Width'),
min: 1,
},
},
colon: {
type: 'void',
'x-component': 'Text',
'x-component-props': {
children: ':',
},
},
height: {
type: 'number',
'x-component': 'InputNumber',
'x-component-props': {
placeholder: lang('Height'),
min: 1,
},
},
},
},
},
},
}),
}; };

View File

@ -17,7 +17,7 @@ export class G2PlotChart extends Chart {
name, name,
title, title,
Component: getAntChart(Component), Component: getAntChart(Component),
config: ['xField', 'yField', 'seriesField', ...(config || [])], config: ['xField', 'yField', 'seriesField', 'size', ...(config || [])],
}); });
this.addConfigs(configs); this.addConfigs(configs);
} }

View File

@ -147,11 +147,9 @@ export const ChartRendererProvider: React.FC<ChartRendererProps> = (props) => {
return ( return (
<CollectionManagerProvider dataSource={dataSource}> <CollectionManagerProvider dataSource={dataSource}>
<MaybeCollectionProvider collection={collection}> <MaybeCollectionProvider collection={collection}>
<ConfigProvider card={{ style: { boxShadow: 'none' } }}> <ChartRendererContext.Provider value={{ dataSource, collection, config, transform, service, query }}>
<ChartRendererContext.Provider value={{ dataSource, collection, config, transform, service, query }}> {props.children}
{props.children} </ChartRendererContext.Provider>
</ChartRendererContext.Provider>
</ConfigProvider>
</MaybeCollectionProvider> </MaybeCollectionProvider>
</CollectionManagerProvider> </CollectionManagerProvider>
); );

View File

@ -87,5 +87,12 @@
"Show border": "Show border", "Show border": "Show border",
"Transformation tip": "Fields allow multiple transformations, applied sequentially. Pay attention to data type changes after each transformation. Drag-and-drop functionality enables adjustment of transformation order.", "Transformation tip": "Fields allow multiple transformations, applied sequentially. Pay attention to data type changes after each transformation. Drag-and-drop functionality enables adjustment of transformation order.",
"Type conversion": "Type conversion", "Type conversion": "Type conversion",
"Transformer": "Transformer" "Transformer": "Transformer",
"Size": "Size",
"Width": "Width",
"Height": "Height",
"Aspect ratio": "Aspect ratio",
"Fixed height": "Fixed height",
"Show background": "Show background",
"Show padding": "Show padding"
} }

View File

@ -88,5 +88,12 @@
"Show border": "显示边框", "Show border": "显示边框",
"Transformation tip": "一个字段可以应用多次转换,会按照顺序执行,请注意每次转换后的数据类型,拖动可以调整转换顺序。", "Transformation tip": "一个字段可以应用多次转换,会按照顺序执行,请注意每次转换后的数据类型,拖动可以调整转换顺序。",
"Type conversion": "类型转换", "Type conversion": "类型转换",
"Transformer": "转换方法" "Transformer": "转换方法",
"Size": "尺寸",
"Width": "宽",
"Height": "高",
"Aspect ratio": "宽高比",
"Fixed height": "固定高度",
"Show background": "显示背景",
"Show padding": "显示内边距"
} }

View File

@ -53,7 +53,6 @@ export const Mobile = () => {
marginBlock: 18, marginBlock: 18,
borderRadiusBlock: 0, borderRadiusBlock: 0,
boxShadowBlock: 'none', boxShadowBlock: 'none',
borderBottomBlock: '1px solid var(--adm-color-border)',
}, },
}} }}
> >