mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
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:
parent
fe2a679132
commit
de1994521a
@ -14,6 +14,7 @@ import { ChartDataProvider } from './ChartDataProvider';
|
||||
import { ChartRenderer, ChartRendererProvider } from '../renderer';
|
||||
import { ChartFilterBlockProvider, ChartFilterBlockDesigner } from '../filter';
|
||||
import { ChartFilterProvider } from '../filter/FilterProvider';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
export const ChartV2Block: React.FC = (props) => {
|
||||
const [initialVisible, setInitialVisible] = useState(false);
|
||||
@ -24,12 +25,25 @@ export const ChartV2Block: React.FC = (props) => {
|
||||
>
|
||||
<SchemaComponentOptions
|
||||
components={{ ChartRenderer, ChartRendererProvider, ChartFilterBlockProvider, ChartFilterBlockDesigner }}
|
||||
>
|
||||
<div
|
||||
className={css`
|
||||
.ant-nb-card-item {
|
||||
.ant-card {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
.nb-grid-warp > button:last-child {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<ChartDataProvider>
|
||||
<ChartFilterProvider>
|
||||
<ChartConfigProvider>{props.children}</ChartConfigProvider>
|
||||
</ChartFilterProvider>
|
||||
</ChartDataProvider>
|
||||
</div>
|
||||
</SchemaComponentOptions>
|
||||
</SchemaInitializerContext.Provider>
|
||||
);
|
||||
|
@ -12,15 +12,65 @@ import {
|
||||
SchemaSettingsBlockTitleItem,
|
||||
SchemaSettingsDivider,
|
||||
SchemaSettingsRemove,
|
||||
SchemaSettingsSelectItem,
|
||||
SchemaSettingsSwitchItem,
|
||||
useDesignable,
|
||||
useToken,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
|
||||
export const ChartV2BlockDesigner: React.FC = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { dn } = useDesignable();
|
||||
const { token } = useToken();
|
||||
|
||||
return (
|
||||
<GeneralSchemaDesigner title={t('Charts')} showDataSource={false}>
|
||||
<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 />
|
||||
<SchemaSettingsRemove
|
||||
removeParentsIfNoChildren
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
useACLRoleContext,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
useToken,
|
||||
} from '@nocobase/client';
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { ChartConfigContext } from '../configure';
|
||||
@ -103,6 +104,7 @@ export const chartInitializers = new CompatibleSchemaInitializer(
|
||||
export const ChartV2BlockInitializer: React.FC = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
const { insert } = useSchemaInitializer();
|
||||
const { token } = useToken();
|
||||
return (
|
||||
<SchemaInitializerItem
|
||||
{...itemConfig}
|
||||
@ -113,6 +115,9 @@ export const ChartV2BlockInitializer: React.FC = () => {
|
||||
'x-component': 'CardItem',
|
||||
'x-component-props': {
|
||||
name: 'charts',
|
||||
bodyStyle: {
|
||||
padding: `${token.paddingLG}px ${token.paddingLG}px 0`,
|
||||
},
|
||||
},
|
||||
'x-designer': 'ChartV2BlockDesigner',
|
||||
properties: {
|
||||
|
@ -11,25 +11,38 @@ import React, { useContext, useEffect, useRef } from 'react';
|
||||
import { ChartRendererContext } from '../../renderer';
|
||||
|
||||
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 chartRef = useRef(null);
|
||||
const [height, setHeight] = React.useState<number>(0);
|
||||
useEffect(() => {
|
||||
const el = chartRef.current;
|
||||
if (!el || service.loading === true || props.height) {
|
||||
if (!el || service.loading === true || fixedHeight) {
|
||||
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) => {
|
||||
entries.forEach((entry) => {
|
||||
if (ratio) {
|
||||
setHeight(entry.contentRect.width * ratio);
|
||||
return;
|
||||
}
|
||||
setHeight(entry.contentRect.height);
|
||||
});
|
||||
});
|
||||
observer.observe(el);
|
||||
return () => observer.disconnect();
|
||||
}, [service.loading, props.height]);
|
||||
}, [service.loading, fixedHeight, size.type, size.ratio?.width, size.ratio?.height]);
|
||||
return (
|
||||
<div ref={chartRef} style={height ? { height: `${props.height || height}px` } : {}}>
|
||||
<Component {...props} {...(height ? { height: props.height || height } : {})} />
|
||||
<div ref={chartRef} style={height ? { height: `${fixedHeight || height}px` } : {}}>
|
||||
<Component {...props} {...(height ? { height: fixedHeight || height } : {})} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -9,10 +9,95 @@
|
||||
|
||||
import config, { FieldConfigProps } from '../configs';
|
||||
const { booleanField } = config;
|
||||
import { lang } from '../../locale';
|
||||
|
||||
export default {
|
||||
isStack: (props: FieldConfigProps) => booleanField({ name: 'isStack', title: 'isStack', ...props }),
|
||||
smooth: (props: FieldConfigProps) => booleanField({ name: 'smooth', title: 'smooth', ...props }),
|
||||
isPercent: (props: FieldConfigProps) => booleanField({ name: 'isPercent', title: 'isPercent', ...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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ export class G2PlotChart extends Chart {
|
||||
name,
|
||||
title,
|
||||
Component: getAntChart(Component),
|
||||
config: ['xField', 'yField', 'seriesField', ...(config || [])],
|
||||
config: ['xField', 'yField', 'seriesField', 'size', ...(config || [])],
|
||||
});
|
||||
this.addConfigs(configs);
|
||||
}
|
||||
|
@ -147,11 +147,9 @@ export const ChartRendererProvider: React.FC<ChartRendererProps> = (props) => {
|
||||
return (
|
||||
<CollectionManagerProvider dataSource={dataSource}>
|
||||
<MaybeCollectionProvider collection={collection}>
|
||||
<ConfigProvider card={{ style: { boxShadow: 'none' } }}>
|
||||
<ChartRendererContext.Provider value={{ dataSource, collection, config, transform, service, query }}>
|
||||
{props.children}
|
||||
</ChartRendererContext.Provider>
|
||||
</ConfigProvider>
|
||||
</MaybeCollectionProvider>
|
||||
</CollectionManagerProvider>
|
||||
);
|
||||
|
@ -87,5 +87,12 @@
|
||||
"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.",
|
||||
"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"
|
||||
}
|
||||
|
@ -88,5 +88,12 @@
|
||||
"Show border": "显示边框",
|
||||
"Transformation tip": "一个字段可以应用多次转换,会按照顺序执行,请注意每次转换后的数据类型,拖动可以调整转换顺序。",
|
||||
"Type conversion": "类型转换",
|
||||
"Transformer": "转换方法"
|
||||
"Transformer": "转换方法",
|
||||
"Size": "尺寸",
|
||||
"Width": "宽",
|
||||
"Height": "高",
|
||||
"Aspect ratio": "宽高比",
|
||||
"Fixed height": "固定高度",
|
||||
"Show background": "显示背景",
|
||||
"Show padding": "显示内边距"
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ export const Mobile = () => {
|
||||
marginBlock: 18,
|
||||
borderRadiusBlock: 0,
|
||||
boxShadowBlock: 'none',
|
||||
borderBottomBlock: '1px solid var(--adm-color-border)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user