import * as React from 'react'; import {CSSProperties} from 'react'; import {BasicConfig, BasicContainer, BasicContainerPropsInterface} from '../../render/core/Container/types'; import {IsArray, IsBoolean, IsString} from 'class-validator'; import {seriesTypes} from './types'; import componentLoader from '../../render/util/componentLoader'; import {Set} from 'immutable'; import {Spin} from '@native-ads/antd'; const echarts = require('echarts'); import './LineChart.css'; export class LineChartConfig extends BasicConfig { /** * 图表宽度 * @public * @default 500 */ @IsString() width: string; /** * 图表高度 * @public * @default 400 */ @IsString() height: string; /** * 是否展示提示框组件 * @public * @default true */ tooltip: boolean; /** * 图表标题 * @public */ @IsString() title: string; /** * 图例组件 * @public * @default [] */ categories: string[]; /** * 工具栏 * @public * @default true */ @IsBoolean() toolbox: boolean; /** * x轴数据 * @public * @default []; */ xAxisData: string[]; /** * 是否支持缩放 * @public * @default true */ dataZoom: any; /** * 图标数据源 * @public * @default [] */ @IsArray() series: { name: string; data: string[] | number[]; icon?: string; smooth?: boolean; showSymbol?: boolean; areaStyle?: object; itemStyle?: object; }[]; /** * CSS class */ @IsString() className?: string; /** * 内联CSS属性 */ style?: CSSProperties; /** * 是否在加载 */ loading?: boolean; /** * 是否在图标上显示数值 */ chartLabel?: boolean; /** * 图例形状 * @public */ @IsString() icon?: string; /** * legend.data设置了 textStyle icon * @public * @default false */ @IsBoolean() customLegend?: boolean; } export class LineChartPropsInterface extends BasicContainerPropsInterface { info: LineChartConfig; } export default class LineChart extends BasicContainer { DOMElement: any; DOMID: string; isMount: boolean; chart: any; chartOptions: any = { title: { text: '' }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985', fontSize: '12px' } }, textStyle: { fontSize: 12 } }, legend: { type: 'scroll', left: 'auto', right: 'auto', top: 'auto', bottom: 'auto', width: 'auto', height: 'auto', orient: 'horizontal', show: true, data: [], x: 'right' }, toolbox: { show: false, itemSize: 15, itemGap: 5, right: 15, feature: { saveAsImage: {} } }, grid: { left: '0%', right: '0%', bottom: '20%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, data: [''] }, yAxis: { type: 'value', }, dataZoom: [ { id: 'dataZoomX', type: 'slider', xAxisIndex: [0], filterMode: 'filter' } ], series: [] }; constructor(props: LineChartPropsInterface) { super(props); this.DOMID = `RCRE_lineChart_${Math.floor(Math.random() * 1000)}`; } componentDidMount() { setTimeout(() => { let info = this.getPropsInfo(this.props.info, this.props, [], true); if (!(info.series && info.series.length > 0)) { return; } this.chart = echarts.init(this.DOMElement); this.overRideChartOptions(info); this.chart.setOption(this.chartOptions); }); } shouldComponentUpdate() { return true; } componentDidUpdate(prevProps: LineChartPropsInterface) { let info = this.getPropsInfo(this.props.info, this.props, [], true); if (!(info.series && info.series.length > 0)) { return; } if (!this.chart) { this.chart = echarts.init(this.DOMElement); } this.overRideChartOptions(info); this.chart.setOption(this.chartOptions, true); } private overRideChartOptions(info: LineChartConfig) { // title this.chartOptions.title.text = info.title; // tooltip if (info.tooltip === false) { delete this.chartOptions.tooltip; } if (info.categoriesUp) { if (Array.isArray(info.categoriesUp)) { this.chartOptions.xAxis = [ { type: 'category', boundaryGap: false, data: info.categoriesUp }, { type: 'category', boundaryGap: false, data: info.categories } ]; Object.assign(this.chartOptions.xAxis[0], info.xAxis && info.xAxis[0]); Object.assign(this.chartOptions.xAxis[1], info.xAxis && info.xAxis[1]); } } else { if (Array.isArray(info.categories)) { Object.assign(this.chartOptions.xAxis, info.xAxis); this.chartOptions.xAxis.data = info.categories; } } if (info.toolbox === false) { delete this.chartOptions.toolbox; } if (Array.isArray(info.dataZoom)) { this.chartOptions.dataZoom = info.dataZoom; } if (Array.isArray(info.series)) { let legends = Set(); let legendsAgroup: any = []; this.chartOptions.series = info.series.map(item => { let ret: seriesTypes = { name: item.name, type: 'line', data: item.data, smooth: item.smooth || false, showSymbol: item.showSymbol , areaStyle: item.areaStyle || {}, itemStyle: item.itemStyle || {} }; if (info.chartLabel) { ret.label = { normal: { show: true, position: 'top' } }; } if (info.customLegend) { legendsAgroup.push({ name: item.name, icon: item.icon || 'circle', textStyle: info.textStyle || {} }); } else { legends = legends.add(item.name); } return ret; }); Object.assign(this.chartOptions.legend, info.legends); if (info.customLegend) { this.chartOptions.legend.data = legendsAgroup; } else { this.chartOptions.legend.data = legends.toArray(); } Object.assign(this.chartOptions.grid, info.grid); Object.assign(this.chartOptions.yAxis, info.yAxis); Object.assign(this.chartOptions.tooltip, info.tooltip); } } render() { let info = this.getPropsInfo(this.props.info, this.props, [], true); const style = { width: info.width || '100%', height: info.height || 500, ...info.style }; const noDatetyle = { width: info.width || '100%', height: info.noDateheight || 100, border: '1px solid #e9e9e9', textAlign: 'center', lineHeight: (info.noDateheight || 100) + 'px', borderRadius: '4px', color: '#5c6b77' }; const refCallback = (ref: any) => { if (ref) { this.DOMElement = ref; } }; let $loading; if (this.isUnderContainerEnv()) { $loading = this.getValueFromDataStore('$loading') || false; } else { $loading = info.loading; } let childrenElement = (
); let noDateElement = (
暂无数据
); if ((!info.series || info.series.length === 0) && !$loading) { this.chart = null; return noDateElement; } return this.renderChildren(info, childrenElement); } } componentLoader.addComponent('lineChart', LineChart, LineChartPropsInterface);