| | |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, // 字典 |
| | | config: true, // 图表配置信息 |
| | | empty: true, // 图表数据为空 |
| | | loading: false, // 数据加载状态 |
| | | chartId: Utils.getuuid(), // 图表Id |
| | | title: '', // 组件标题 |
| | | sync: false, // 是否统一请求数据 |
| | | plot: null, // 图表设置 |
| | | data: null, // 数据 |
| | | search: null, // 搜索条件 |
| | | vFields: [], // 数值字段 |
| | | vstFields: null, // 统计数据值字段信息 |
| | | chartData: [], // 图表数据 |
| | | chartFields: [], // 统计图表生成字段集 |
| | | selectFields: [], // 统计图表选择字段 |
| | |
| | | _sync = false |
| | | } |
| | | |
| | | let vFields = [] |
| | | let percentFields = [] |
| | | let vstFields = null |
| | | |
| | | if (_config.plot.datatype === 'statistics') { |
| | | let _column = _config.columns.filter(col => _config.plot.InfoValue === col.field)[0] |
| | | if (_column) { |
| | | let decimal = 0 |
| | | |
| | | if (/Decimal/ig.test(_column.datatype)) { |
| | | decimal = +_column.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') |
| | | } |
| | | |
| | | vstFields = { |
| | | label: _column.label, |
| | | field: _column.field, |
| | | show: _config.plot.show, |
| | | decimal |
| | | } |
| | | } |
| | | } else { |
| | | let _vFields = _config.plot.Yaxis && typeof(_config.plot.Yaxis) === 'string' ? [_config.plot.Yaxis] : _config.plot.Yaxis |
| | | _config.columns.forEach(col => { |
| | | if (_vFields.includes(col.field)) { |
| | | let decimal = 0 |
| | | if (/Decimal/ig.test(col.datatype)) { |
| | | decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') |
| | | } |
| | | vFields.push({ |
| | | label: col.label, |
| | | field: col.field, |
| | | show: _config.plot.show, |
| | | decimal |
| | | }) |
| | | |
| | | if (_config.plot.show === 'percent') { |
| | | percentFields.push(col.label) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | data: _data, |
| | | vFields: vFields, |
| | | vstFields: vstFields, |
| | | percentFields: percentFields, |
| | | arr_field: _config.columns.map(col => col.field).join(','), |
| | | plot: _config.plot, |
| | | sync: _sync, |
| | |
| | | }, () => { |
| | | if (config.setting.sync !== 'true') { |
| | | this.loadData() |
| | | } else if (config.setting.sync === 'true' && _data) { |
| | | this.handleData() |
| | | } else if (config.setting.sync === 'true') { |
| | | if (!_data) { |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | } else { |
| | | this.handleData() |
| | | } |
| | | } |
| | | }) |
| | | } |
| | |
| | | * @description 校验图表的按钮组,如果为统计图表,计算图表字段 |
| | | */ |
| | | componentDidMount () { |
| | | // const { plot, data, config } = this.props |
| | | // let _state = {} |
| | | // let percentFields = [] |
| | | |
| | | // if (plot.datatype === 'statistics' && (plot.chartType === 'line' || plot.chartType === 'bar')) { |
| | | // let result = this.getStaticMsg(data) |
| | | // _state.chartData = result.data |
| | | // _state.chartFields = result.chartFields |
| | | // _state.selectFields = result.selectFields |
| | | |
| | | // let _column = config.columns.filter(col => plot.InfoValue === col.field)[0] |
| | | |
| | | // if (_column && _column.format === 'percent') { |
| | | // percentFields.push(plot.InfoValue) |
| | | // _state.percentFields = percentFields |
| | | // } |
| | | |
| | | // this.setState(_state, () => { |
| | | // this.viewrender() |
| | | // }) |
| | | // } else { |
| | | // if (plot.chartType === 'line' || plot.chartType === 'bar') { |
| | | // try { |
| | | // plot.Yaxis.forEach(yaxis => { |
| | | // let _column = config.columns.filter(col => yaxis === col.field)[0] |
| | | // if (_column && _column.format === 'percent') { |
| | | // percentFields.push(_column.label) |
| | | // } |
| | | // }) |
| | | // } catch { |
| | | // console.warn('Incorrect percentage setting') |
| | | // } |
| | | // } |
| | | // this.setState({ percentFields }, () => { |
| | | // this.viewrender() |
| | | // }) |
| | | // } |
| | | } |
| | | |
| | | /** |
| | |
| | | _data = nextProps.data[config.dataName] || [] |
| | | } |
| | | |
| | | this.setState({sync: false, data: _data}, () => { |
| | | this.setState({sync: false, loading: false, data: _data}, () => { |
| | | this.handleData() |
| | | }) |
| | | } |
| | |
| | | } |
| | | this.viewrender() |
| | | }) |
| | | } else { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | } |
| | | } |
| | | |
| | |
| | | * 3、柱状图数据补齐 |
| | | */ |
| | | getdata = () => { |
| | | const { data, plot, config } = this.props |
| | | let vFields = plot.Yaxis && typeof(plot.Yaxis) === 'string' ? [plot.Yaxis] : plot.Yaxis |
| | | let _columns = config.columns.filter(col => vFields.includes(col.field)) |
| | | const { data, plot, vFields } = this.state |
| | | |
| | | if (!data) { |
| | | this.setState({empty: true}) |
| | |
| | | if (plot.repeat === 'average') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | if (typeof(item[col.field]) !== 'number') { |
| | | item[col.field] = parseFloat(item[col.field]) |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } |
| | | if (col.format === 'percent') { |
| | | if (col.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | }) |
| | |
| | | } else if (item[plot.Xaxis]) { |
| | | let _item = _mdata.get(item[plot.Xaxis]) |
| | | _item.$count++ |
| | | vFields.forEach(field => { |
| | | _item[field] += item[field] |
| | | vFields.forEach(col => { |
| | | _item[col.field] += item[col.field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | item[col.field] = item[col.field] / item.$count |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | | item[col.field] = +item[col.field] |
| | |
| | | } else if (plot.repeat === 'cumsum') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | if (typeof(item[col.field]) !== 'number') { |
| | | item[col.field] = parseFloat(item[col.field]) |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } |
| | | if (col.format === 'percent') { |
| | | if (col.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | }) |
| | |
| | | _mdata.set(item[plot.Xaxis], item) |
| | | } else if (item[plot.Xaxis]) { |
| | | let _item = _mdata.get(item[plot.Xaxis]) |
| | | vFields.forEach(field => { |
| | | _item[field] += item[field] |
| | | vFields.forEach(col => { |
| | | _item[col.field] += item[col.field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | | item[col.field] = +item[col.field] |
| | | }) |
| | |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | if (typeof(item[col.field]) !== 'number') { |
| | | item[col.field] = parseFloat(item[col.field]) |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } |
| | | if (col.format === 'percent') { |
| | | if (col.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | |
| | | let _val = Array( i + 2 ).join(' ') |
| | | let _cell = {} |
| | | _cell[plot.Xaxis] = _val |
| | | _columns.forEach(col => { |
| | | vFields.forEach(col => { |
| | | _cell[col.field] = '' |
| | | }) |
| | | |
| | |
| | | * @description 统计数据预处理,动态生成统计字段并进行数据转换 |
| | | */ |
| | | getStaticMsg = (data) => { |
| | | const { plot, config } = this.props |
| | | const { plot, vstFields } = this.state |
| | | |
| | | let _column = config.columns.filter(col => plot.InfoValue === col.field)[0] |
| | | let percent = false |
| | | let decimal = 0 |
| | | if (_column && _column.format === 'percent') { |
| | | |
| | | if (plot.show === 'percent') { |
| | | percent = true |
| | | } |
| | | if (_column) { |
| | | decimal = _column.decimal |
| | | if (vstFields) { |
| | | decimal = vstFields.decimal |
| | | } |
| | | |
| | | if (!data) { |
| | |
| | | * @description 获取统计图表展示数据,通过选择类型筛选 |
| | | */ |
| | | getStaticData = () => { |
| | | const { plot } = this.props |
| | | const { chartData, chartFields, selectFields } = this.state |
| | | const { plot, chartData, chartFields, selectFields } = this.state |
| | | |
| | | let _data = [] |
| | | if (selectFields.length === chartFields.length) { |
| | |
| | | * @description 图表渲染分组 |
| | | */ |
| | | viewrender = () => { |
| | | const { plot } = this.props |
| | | const { plot } = this.state |
| | | |
| | | if (plot.chartType === 'line') { |
| | | this.linerender() |
| | |
| | | * @description 折线图渲染 |
| | | */ |
| | | linerender = () => { |
| | | const { plot, config } = this.props |
| | | const { percentFields } = this.state |
| | | const { plot, config, percentFields } = this.state |
| | | |
| | | let _data = [] |
| | | let _valfield = 'value' |
| | |
| | | _valfield = plot.InfoValue |
| | | _typefield = plot.InfoType |
| | | |
| | | if (percentFields.length > 0) { |
| | | if (plot.show === 'percent') { |
| | | ispercent = true |
| | | } |
| | | |
| | |
| | | formatter: (val) => { |
| | | if (!val || /^\s*$/.test(val)) return val |
| | | let _val = `${val}` |
| | | if (_val.length <= 10) return val |
| | | return _val.substring(0, 7) + '...' |
| | | if (_val.length <= 11) return val |
| | | return _val.substring(0, 8) + '...' |
| | | } |
| | | } |
| | | }) |
| | |
| | | * @description 自定义渲染 |
| | | */ |
| | | customrender = (data, transfield) => { |
| | | const { plot } = this.props |
| | | const { percentFields } = this.state |
| | | const { plot, percentFields } = this.state |
| | | |
| | | let barfields = [] |
| | | let fields = [] |
| | |
| | | formatter: (val) => { |
| | | if (!val || /^\s*$/.test(val)) return val |
| | | let _val = `${val}` |
| | | if (_val.length <= 10) return val |
| | | return _val.substring(0, 7) + '...' |
| | | if (_val.length <= 11) return val |
| | | return _val.substring(0, 8) + '...' |
| | | } |
| | | } |
| | | }) |
| | |
| | | * @description 柱状图渲染 |
| | | */ |
| | | barrender = () => { |
| | | const { plot, config } = this.props |
| | | const { percentFields } = this.state |
| | | const { plot, config, percentFields } = this.state |
| | | |
| | | let _data = [] |
| | | let _valfield = 'value' |
| | |
| | | _valfield = plot.InfoValue |
| | | _typefield = plot.InfoType |
| | | |
| | | if (percentFields.length > 0) { |
| | | if (plot.show === 'percent') { |
| | | ispercent = true |
| | | } |
| | | |
| | |
| | | |
| | | // dodge is not support linear attribute, please use category attribute! 时间格式 |
| | | if (_data[0] && _data[0][plot.Xaxis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(_data[0][plot.Xaxis])) { |
| | | for (let i = 1; i < 12; i++) { |
| | | if (_data[i] && _data[i][plot.Xaxis] === _data[0][plot.Xaxis]) { |
| | | _data[i][plot.Xaxis] += ' ' |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | _data[0][plot.Xaxis] += ' ' |
| | | } |
| | | |
| | |
| | | formatter: (val) => { |
| | | if (!val || /^\s*$/.test(val)) return val |
| | | let _val = `${val}` |
| | | if (_val.length <= 10) return val |
| | | return _val.substring(0, 7) + '...' |
| | | if (_val.length <= 11) return val |
| | | return _val.substring(0, 8) + '...' |
| | | } |
| | | } |
| | | }) |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { loading, config, BID, Tab } = this.props |
| | | const { title, plot, empty, chartFields, selectFields } = this.state |
| | | const { BID } = this.props |
| | | const { config, loading, title, plot, empty, chartFields, selectFields } = this.state |
| | | |
| | | return ( |
| | | <div className="custom-line-chart-plot-box"> |
| | | <searchLine /> |
| | | {/* <searchLine /> */} |
| | | {title ? <p className="chart-title">{title}</p> : null} |
| | | {loading ? |
| | | <div className="loading-mask"> |
| | |
| | | <ExcelOutButton |
| | | key={item.uuid} |
| | | BID={BID} |
| | | Tab={Tab} |
| | | btn={item} |
| | | show="icon" |
| | | setting={config.setting} |
| | |
| | | <ExcelInButton |
| | | key={item.uuid} |
| | | BID={BID} |
| | | Tab={Tab} |
| | | btn={item} |
| | | show="icon" |
| | | setting={config.setting} |