diff --git a/src/assets/area.png b/src/assets/area.png new file mode 100644 index 0000000..b427d58 Binary files /dev/null and b/src/assets/area.png differ diff --git a/src/assets/chart copy.png b/src/assets/chart copy.png new file mode 100644 index 0000000..59f1858 Binary files /dev/null and b/src/assets/chart copy.png differ diff --git a/src/assets/line.png b/src/assets/line.png new file mode 100644 index 0000000..fada705 Binary files /dev/null and b/src/assets/line.png differ diff --git a/src/assets/pie.png b/src/assets/pie.png new file mode 100644 index 0000000..f6b1c10 Binary files /dev/null and b/src/assets/pie.png differ diff --git a/src/components/BasicShop/VisualComponents/Area/index.less b/src/components/BasicShop/VisualComponents/Area/index.less new file mode 100644 index 0000000..57dc736 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Area/index.less @@ -0,0 +1,13 @@ +.chartWrap { + position: relative; + width: 100%; + .chartTitle { + text-align: center; + } + img { + width: 100%; + } + canvas { + width: 100%; + } +} diff --git a/src/components/BasicShop/VisualComponents/Area/index.tsx b/src/components/BasicShop/VisualComponents/Area/index.tsx new file mode 100644 index 0000000..e31732c --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Area/index.tsx @@ -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 ( +
+
+ {title} +
+ {isTpl ? dooring chart : } +
+ ); +}; + +export default memo(XLine); diff --git a/src/components/BasicShop/VisualComponents/Area/schema.ts b/src/components/BasicShop/VisualComponents/Area/schema.ts new file mode 100644 index 0000000..b21ce90 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Area/schema.ts @@ -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; diff --git a/src/components/BasicShop/VisualComponents/Area/template.ts b/src/components/BasicShop/VisualComponents/Area/template.ts new file mode 100644 index 0000000..3c0cd4d --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Area/template.ts @@ -0,0 +1,5 @@ +const template = { + type: 'Area', + h: 108, +}; +export default template; diff --git a/src/components/BasicShop/VisualComponents/Line/index.less b/src/components/BasicShop/VisualComponents/Line/index.less new file mode 100644 index 0000000..57dc736 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Line/index.less @@ -0,0 +1,13 @@ +.chartWrap { + position: relative; + width: 100%; + .chartTitle { + text-align: center; + } + img { + width: 100%; + } + canvas { + width: 100%; + } +} diff --git a/src/components/BasicShop/VisualComponents/Line/index.tsx b/src/components/BasicShop/VisualComponents/Line/index.tsx new file mode 100644 index 0000000..e9e4e82 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Line/index.tsx @@ -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 ( +
+
+ {title} +
+ {isTpl ? dooring chart : } +
+ ); +}; + +export default memo(XLine); diff --git a/src/components/BasicShop/VisualComponents/Line/schema.ts b/src/components/BasicShop/VisualComponents/Line/schema.ts new file mode 100644 index 0000000..f4f8f6c --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Line/schema.ts @@ -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; diff --git a/src/components/BasicShop/VisualComponents/Line/template.ts b/src/components/BasicShop/VisualComponents/Line/template.ts new file mode 100644 index 0000000..cbb7b93 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Line/template.ts @@ -0,0 +1,5 @@ +const template = { + type: 'Line', + h: 104, +}; +export default template; diff --git a/src/components/BasicShop/VisualComponents/Pie/index.less b/src/components/BasicShop/VisualComponents/Pie/index.less new file mode 100644 index 0000000..57dc736 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Pie/index.less @@ -0,0 +1,13 @@ +.chartWrap { + position: relative; + width: 100%; + .chartTitle { + text-align: center; + } + img { + width: 100%; + } + canvas { + width: 100%; + } +} diff --git a/src/components/BasicShop/VisualComponents/Pie/index.tsx b/src/components/BasicShop/VisualComponents/Pie/index.tsx new file mode 100644 index 0000000..3afc5a8 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Pie/index.tsx @@ -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 ( +
+
+ {title} +
+ {isTpl ? dooring chart : } +
+ ); +}; + +export default memo(XLine); diff --git a/src/components/BasicShop/VisualComponents/Pie/schema.ts b/src/components/BasicShop/VisualComponents/Pie/schema.ts new file mode 100644 index 0000000..30305ad --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Pie/schema.ts @@ -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; diff --git a/src/components/BasicShop/VisualComponents/Pie/template.ts b/src/components/BasicShop/VisualComponents/Pie/template.ts new file mode 100644 index 0000000..5562765 --- /dev/null +++ b/src/components/BasicShop/VisualComponents/Pie/template.ts @@ -0,0 +1,5 @@ +const template = { + type: 'Pie', + h: 106, +}; +export default template; diff --git a/src/components/BasicShop/VisualComponents/schema.ts b/src/components/BasicShop/VisualComponents/schema.ts index 93370ae..7156a36 100644 --- a/src/components/BasicShop/VisualComponents/schema.ts +++ b/src/components/BasicShop/VisualComponents/schema.ts @@ -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; diff --git a/src/components/BasicShop/VisualComponents/template.ts b/src/components/BasicShop/VisualComponents/template.ts index d0068f6..06284e8 100644 --- a/src/components/BasicShop/VisualComponents/template.ts +++ b/src/components/BasicShop/VisualComponents/template.ts @@ -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' }; diff --git a/src/components/PanelComponents/Table/index.tsx b/src/components/PanelComponents/Table/index.tsx index 8984620..8221a8b 100644 --- a/src/components/PanelComponents/Table/index.tsx +++ b/src/components/PanelComponents/Table/index.tsx @@ -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 { this.state = { dataSource: dataSource, - count: 2, visible: false, }; } @@ -159,16 +159,16 @@ class EditableTable extends React.Component { }; 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); };