mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2025-12-12 01:47:08 +00:00
🆕 新增折线图,面积图,饼图组件
This commit is contained in:
parent
e209d7956e
commit
f780b6bf8d
BIN
src/assets/area.png
Normal file
BIN
src/assets/area.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
src/assets/chart copy.png
Normal file
BIN
src/assets/chart copy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
src/assets/line.png
Normal file
BIN
src/assets/line.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/pie.png
Normal file
BIN
src/assets/pie.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
13
src/components/BasicShop/VisualComponents/Area/index.less
Normal file
13
src/components/BasicShop/VisualComponents/Area/index.less
Normal file
@ -0,0 +1,13 @@
|
||||
.chartWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.chartTitle {
|
||||
text-align: center;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
canvas {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
76
src/components/BasicShop/VisualComponents/Area/index.tsx
Normal file
76
src/components/BasicShop/VisualComponents/Area/index.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import { Chart } from '@antv/f2';
|
||||
import React, { memo, useEffect, useRef } from 'react';
|
||||
// import { uuid } from 'utils/tool';
|
||||
import AreaImg from '@/assets/area.png';
|
||||
|
||||
import styles from './index.less';
|
||||
import { IChartConfig } from './schema';
|
||||
|
||||
interface XChartProps extends IChartConfig {
|
||||
isTpl: boolean;
|
||||
}
|
||||
|
||||
const XLine = (props: XChartProps) => {
|
||||
const { isTpl, data, color, size, paddingTop, title } = props;
|
||||
const chartRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (!isTpl) {
|
||||
const chart = new Chart({
|
||||
el: chartRef.current || undefined,
|
||||
pixelRatio: window.devicePixelRatio, // 指定分辨率
|
||||
});
|
||||
|
||||
// step 2: 处理数据
|
||||
const dataX = data.map(item => ({ ...item, value: Number(item.value), a: '1' }));
|
||||
|
||||
// Step 2: 载入数据源
|
||||
chart.source(dataX, {
|
||||
percent: {
|
||||
formatter: function formatter(val) {
|
||||
return val * 100 + '%';
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
chart.tooltip({
|
||||
showCrosshairs: true,
|
||||
});
|
||||
|
||||
chart.scale({
|
||||
name: {
|
||||
range: [0, 1],
|
||||
},
|
||||
value: {
|
||||
tickCount: 5,
|
||||
min: 0,
|
||||
},
|
||||
});
|
||||
|
||||
chart.axis('name', {
|
||||
label: function label(text, index, total) {
|
||||
const textCfg: any = {};
|
||||
if (index === 0) {
|
||||
textCfg.textAlign = 'left';
|
||||
} else if (index === total - 1) {
|
||||
textCfg.textAlign = 'right';
|
||||
}
|
||||
return textCfg;
|
||||
},
|
||||
});
|
||||
|
||||
chart.area().position('name*value');
|
||||
chart.line().position('name*value');
|
||||
chart.render();
|
||||
}
|
||||
}, [data, isTpl]);
|
||||
return (
|
||||
<div className={styles.chartWrap}>
|
||||
<div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>
|
||||
{title}
|
||||
</div>
|
||||
{isTpl ? <img src={AreaImg} alt="dooring chart" /> : <canvas ref={chartRef}></canvas>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(XLine);
|
||||
82
src/components/BasicShop/VisualComponents/Area/schema.ts
Normal file
82
src/components/BasicShop/VisualComponents/Area/schema.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import {
|
||||
IColorConfigType,
|
||||
INumberConfigType,
|
||||
ITableConfigType,
|
||||
ITextConfigType,
|
||||
TColorDefaultType,
|
||||
TNumberDefaultType,
|
||||
TTableDefaultType,
|
||||
TTextDefaultType,
|
||||
} from '@/components/PanelComponents/FormEditor/types';
|
||||
|
||||
export type TChartEditData = Array<
|
||||
ITextConfigType | INumberConfigType | IColorConfigType | ITableConfigType
|
||||
>;
|
||||
export interface IChartConfig {
|
||||
title: TTextDefaultType;
|
||||
size: TNumberDefaultType;
|
||||
color: TColorDefaultType;
|
||||
paddingTop: TNumberDefaultType;
|
||||
data: TTableDefaultType;
|
||||
}
|
||||
|
||||
export interface IChartSchema {
|
||||
editData: TChartEditData;
|
||||
config: IChartConfig;
|
||||
}
|
||||
|
||||
const Chart: IChartSchema = {
|
||||
editData: [
|
||||
{
|
||||
key: 'title',
|
||||
name: '标题',
|
||||
type: 'Text',
|
||||
},
|
||||
{
|
||||
key: 'size',
|
||||
name: '标题大小',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'color',
|
||||
name: '标题颜色',
|
||||
type: 'Color',
|
||||
},
|
||||
{
|
||||
key: 'paddingTop',
|
||||
name: '上边距',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'data',
|
||||
name: '数据源',
|
||||
type: 'Table',
|
||||
},
|
||||
],
|
||||
config: {
|
||||
title: '面积图',
|
||||
size: 14,
|
||||
color: 'rgba(0,0,0,1)',
|
||||
paddingTop: 10,
|
||||
data: [
|
||||
{
|
||||
name: 'A',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'B',
|
||||
value: 60,
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'D',
|
||||
value: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default Chart;
|
||||
@ -0,0 +1,5 @@
|
||||
const template = {
|
||||
type: 'Area',
|
||||
h: 108,
|
||||
};
|
||||
export default template;
|
||||
13
src/components/BasicShop/VisualComponents/Line/index.less
Normal file
13
src/components/BasicShop/VisualComponents/Line/index.less
Normal file
@ -0,0 +1,13 @@
|
||||
.chartWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.chartTitle {
|
||||
text-align: center;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
canvas {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
73
src/components/BasicShop/VisualComponents/Line/index.tsx
Normal file
73
src/components/BasicShop/VisualComponents/Line/index.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import { Chart } from '@antv/f2';
|
||||
import React, { memo, useEffect, useRef } from 'react';
|
||||
// import { uuid } from 'utils/tool';
|
||||
import LineImg from '@/assets/line.png';
|
||||
|
||||
import styles from './index.less';
|
||||
import { IChartConfig } from './schema';
|
||||
|
||||
interface XChartProps extends IChartConfig {
|
||||
isTpl: boolean;
|
||||
}
|
||||
|
||||
const XLine = (props: XChartProps) => {
|
||||
const { isTpl, data, color, size, paddingTop, title } = props;
|
||||
const chartRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (!isTpl) {
|
||||
const chart = new Chart({
|
||||
el: chartRef.current || undefined,
|
||||
pixelRatio: window.devicePixelRatio, // 指定分辨率
|
||||
});
|
||||
|
||||
// step 2: 处理数据
|
||||
const dataX = data.map(item => ({ ...item, value: Number(item.value) }));
|
||||
|
||||
// Step 2: 载入数据源
|
||||
chart.source(dataX, {
|
||||
value: {
|
||||
tickCount: 5,
|
||||
min: 0,
|
||||
},
|
||||
});
|
||||
|
||||
chart.tooltip({
|
||||
showCrosshairs: true,
|
||||
showItemMarker: false,
|
||||
});
|
||||
|
||||
chart.axis('name', {
|
||||
label: function label(text, index, total) {
|
||||
const textCfg: any = {};
|
||||
if (index === 0) {
|
||||
textCfg.textAlign = 'left';
|
||||
} else if (index === total - 1) {
|
||||
textCfg.textAlign = 'right';
|
||||
}
|
||||
return textCfg;
|
||||
},
|
||||
});
|
||||
|
||||
chart.line().position('name*value');
|
||||
chart
|
||||
.point()
|
||||
.position('name*value')
|
||||
.style({
|
||||
stroke: '#fff',
|
||||
lineWidth: 1,
|
||||
});
|
||||
|
||||
chart.render();
|
||||
}
|
||||
}, [data, isTpl]);
|
||||
return (
|
||||
<div className={styles.chartWrap}>
|
||||
<div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>
|
||||
{title}
|
||||
</div>
|
||||
{isTpl ? <img src={LineImg} alt="dooring chart" /> : <canvas ref={chartRef}></canvas>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(XLine);
|
||||
82
src/components/BasicShop/VisualComponents/Line/schema.ts
Normal file
82
src/components/BasicShop/VisualComponents/Line/schema.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import {
|
||||
IColorConfigType,
|
||||
INumberConfigType,
|
||||
ITableConfigType,
|
||||
ITextConfigType,
|
||||
TColorDefaultType,
|
||||
TNumberDefaultType,
|
||||
TTableDefaultType,
|
||||
TTextDefaultType,
|
||||
} from '@/components/PanelComponents/FormEditor/types';
|
||||
|
||||
export type TChartEditData = Array<
|
||||
ITextConfigType | INumberConfigType | IColorConfigType | ITableConfigType
|
||||
>;
|
||||
export interface IChartConfig {
|
||||
title: TTextDefaultType;
|
||||
size: TNumberDefaultType;
|
||||
color: TColorDefaultType;
|
||||
paddingTop: TNumberDefaultType;
|
||||
data: TTableDefaultType;
|
||||
}
|
||||
|
||||
export interface IChartSchema {
|
||||
editData: TChartEditData;
|
||||
config: IChartConfig;
|
||||
}
|
||||
|
||||
const Chart: IChartSchema = {
|
||||
editData: [
|
||||
{
|
||||
key: 'title',
|
||||
name: '标题',
|
||||
type: 'Text',
|
||||
},
|
||||
{
|
||||
key: 'size',
|
||||
name: '标题大小',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'color',
|
||||
name: '标题颜色',
|
||||
type: 'Color',
|
||||
},
|
||||
{
|
||||
key: 'paddingTop',
|
||||
name: '上边距',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'data',
|
||||
name: '数据源',
|
||||
type: 'Table',
|
||||
},
|
||||
],
|
||||
config: {
|
||||
title: '折线图',
|
||||
size: 14,
|
||||
color: 'rgba(0,0,0,1)',
|
||||
paddingTop: 10,
|
||||
data: [
|
||||
{
|
||||
name: 'A',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'B',
|
||||
value: 60,
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'D',
|
||||
value: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default Chart;
|
||||
@ -0,0 +1,5 @@
|
||||
const template = {
|
||||
type: 'Line',
|
||||
h: 104,
|
||||
};
|
||||
export default template;
|
||||
13
src/components/BasicShop/VisualComponents/Pie/index.less
Normal file
13
src/components/BasicShop/VisualComponents/Pie/index.less
Normal file
@ -0,0 +1,13 @@
|
||||
.chartWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.chartTitle {
|
||||
text-align: center;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
canvas {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
100
src/components/BasicShop/VisualComponents/Pie/index.tsx
Normal file
100
src/components/BasicShop/VisualComponents/Pie/index.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import { Chart } from '@antv/f2';
|
||||
import React, { memo, useEffect, useRef } from 'react';
|
||||
// import { uuid } from 'utils/tool';
|
||||
import PieImg from '@/assets/pie.png';
|
||||
|
||||
import styles from './index.less';
|
||||
import { IChartConfig } from './schema';
|
||||
|
||||
interface XChartProps extends IChartConfig {
|
||||
isTpl: boolean;
|
||||
}
|
||||
|
||||
interface DataMap {
|
||||
[name: string]: number | string;
|
||||
}
|
||||
|
||||
const XLine = (props: XChartProps) => {
|
||||
const { isTpl, data, color, size, paddingTop, title } = props;
|
||||
const chartRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (!isTpl) {
|
||||
const chart = new Chart({
|
||||
el: chartRef.current || undefined,
|
||||
pixelRatio: window.devicePixelRatio, // 指定分辨率
|
||||
});
|
||||
|
||||
// step 2: 处理数据
|
||||
const dataX = data.map(item => ({ ...item, value: Number(item.value), a: '1' }));
|
||||
|
||||
// Step 2: 载入数据源
|
||||
chart.source(dataX, {
|
||||
percent: {
|
||||
formatter: function formatter(val) {
|
||||
return val * 100 + '%';
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 获取数据的map类型,用以展示图例说明
|
||||
const dataMap: DataMap = dataX.reduce((prev: any, cur) => {
|
||||
return prev.name
|
||||
? { [prev.name]: prev.value, ...{ [cur.name]: cur.value } }
|
||||
: { ...prev, ...{ [cur.name]: cur.value } };
|
||||
});
|
||||
|
||||
chart.legend({
|
||||
position: 'right',
|
||||
itemFormatter: function itemFormatter(val) {
|
||||
return val + ' ' + dataMap[val] + '%';
|
||||
},
|
||||
});
|
||||
chart.tooltip(false);
|
||||
chart.coord('polar', {
|
||||
transposed: true,
|
||||
radius: 0.85,
|
||||
});
|
||||
chart.axis(false);
|
||||
chart
|
||||
.interval()
|
||||
.position('a*value')
|
||||
.color('name', [
|
||||
'#1890FF',
|
||||
'#13C2C2',
|
||||
'#2FC25B',
|
||||
'#FACC14',
|
||||
'#00CC99',
|
||||
'#CC3366',
|
||||
'#CC6600',
|
||||
'#CC66CC',
|
||||
'#FF3366',
|
||||
'#0066CC',
|
||||
])
|
||||
.adjust('stack')
|
||||
.style({
|
||||
lineWidth: 1,
|
||||
stroke: '#fff',
|
||||
lineJoin: 'round',
|
||||
lineCap: 'round',
|
||||
})
|
||||
.animate({
|
||||
appear: {
|
||||
duration: 1200,
|
||||
easing: 'bounceOut',
|
||||
},
|
||||
});
|
||||
|
||||
chart.render();
|
||||
}
|
||||
}, [data, isTpl]);
|
||||
return (
|
||||
<div className={styles.chartWrap}>
|
||||
<div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>
|
||||
{title}
|
||||
</div>
|
||||
{isTpl ? <img src={PieImg} alt="dooring chart" /> : <canvas ref={chartRef}></canvas>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(XLine);
|
||||
82
src/components/BasicShop/VisualComponents/Pie/schema.ts
Normal file
82
src/components/BasicShop/VisualComponents/Pie/schema.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import {
|
||||
IColorConfigType,
|
||||
INumberConfigType,
|
||||
ITableConfigType,
|
||||
ITextConfigType,
|
||||
TColorDefaultType,
|
||||
TNumberDefaultType,
|
||||
TTableDefaultType,
|
||||
TTextDefaultType,
|
||||
} from '@/components/PanelComponents/FormEditor/types';
|
||||
|
||||
export type TChartEditData = Array<
|
||||
ITextConfigType | INumberConfigType | IColorConfigType | ITableConfigType
|
||||
>;
|
||||
export interface IChartConfig {
|
||||
title: TTextDefaultType;
|
||||
size: TNumberDefaultType;
|
||||
color: TColorDefaultType;
|
||||
paddingTop: TNumberDefaultType;
|
||||
data: TTableDefaultType;
|
||||
}
|
||||
|
||||
export interface IChartSchema {
|
||||
editData: TChartEditData;
|
||||
config: IChartConfig;
|
||||
}
|
||||
|
||||
const Chart: IChartSchema = {
|
||||
editData: [
|
||||
{
|
||||
key: 'title',
|
||||
name: '标题',
|
||||
type: 'Text',
|
||||
},
|
||||
{
|
||||
key: 'size',
|
||||
name: '标题大小',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'color',
|
||||
name: '标题颜色',
|
||||
type: 'Color',
|
||||
},
|
||||
{
|
||||
key: 'paddingTop',
|
||||
name: '上边距',
|
||||
type: 'Number',
|
||||
},
|
||||
{
|
||||
key: 'data',
|
||||
name: '数据源',
|
||||
type: 'Table',
|
||||
},
|
||||
],
|
||||
config: {
|
||||
title: '饼图',
|
||||
size: 14,
|
||||
color: 'rgba(0,0,0,1)',
|
||||
paddingTop: 10,
|
||||
data: [
|
||||
{
|
||||
name: 'A',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'B',
|
||||
value: 60,
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'D',
|
||||
value: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default Chart;
|
||||
@ -0,0 +1,5 @@
|
||||
const template = {
|
||||
type: 'Pie',
|
||||
h: 106,
|
||||
};
|
||||
export default template;
|
||||
@ -1,8 +1,15 @@
|
||||
import Chart from './Chart/schema';
|
||||
import Line from './Line/schema';
|
||||
import Pie from './Pie/schema';
|
||||
import Area from './Area/schema';
|
||||
import XProgress from './XProgress/schema';
|
||||
|
||||
const visualSchema = {
|
||||
Chart,
|
||||
Line,
|
||||
Pie,
|
||||
Area,
|
||||
XProgress,
|
||||
};
|
||||
|
||||
export default visualSchema;
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import Chart from './Chart/template';
|
||||
import Line from './Line/template';
|
||||
import Pie from './Pie/template';
|
||||
import Area from './Area/template';
|
||||
import XProgress from './XProgress/template';
|
||||
|
||||
const visualTemplate = [Chart, XProgress];
|
||||
const visualTemplate = [Chart, Line, Pie, Area, XProgress];
|
||||
|
||||
const VisualTemplate = visualTemplate.map(v => {
|
||||
return { ...v, category: 'visual' };
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import React, { useContext, useState, useEffect, useRef, memo, RefObject } from 'react';
|
||||
import { Table, Input, Button, Popconfirm, Form, Modal, Upload } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { uuid } from '@/utils/tool';
|
||||
import XLSX from 'xlsx';
|
||||
// 下方样式主要为全局样式,暂时不可删
|
||||
import styles from './index.less';
|
||||
@ -146,7 +147,6 @@ class EditableTable extends React.Component<any, any> {
|
||||
|
||||
this.state = {
|
||||
dataSource: dataSource,
|
||||
count: 2,
|
||||
visible: false,
|
||||
};
|
||||
}
|
||||
@ -159,16 +159,16 @@ class EditableTable extends React.Component<any, any> {
|
||||
};
|
||||
|
||||
handleAdd = () => {
|
||||
const { count, dataSource } = this.state;
|
||||
const { dataSource } = this.state;
|
||||
const uid = uuid(8, 10);
|
||||
const newData = {
|
||||
key: count,
|
||||
name: `dooring ${count}`,
|
||||
key: uid,
|
||||
name: `dooring ${dataSource.length + 1}`,
|
||||
value: 32,
|
||||
};
|
||||
const newDataSource = [...dataSource, newData];
|
||||
this.setState({
|
||||
dataSource: newDataSource,
|
||||
count: count + 1,
|
||||
});
|
||||
this.props.onChange && this.props.onChange(newDataSource);
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user