| | |
| | | MenuNo: 's_custom_scriptM', |
| | | MenuName: '自定义函数', |
| | | text: '自定义函数' |
| | | }, { |
| | | src: '', |
| | | PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, |
| | | type: 'ManageTable', |
| | | MenuID: '1590458676585agbbr63t6ihighg2i1g', |
| | | MenuNo: 'LdropdownmenuNewM', |
| | | MenuName: '通用下拉菜单', |
| | | text: '通用下拉菜单' |
| | | }] |
| | | }, { |
| | | MenuID: 'systemManageViewInterface', |
| | |
| | | MenuNo: 'sModularM', |
| | | MenuName: '系统模块', |
| | | text: '系统模块' |
| | | }, { |
| | | src: '', |
| | | PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, |
| | | type: 'ManageTable', |
| | | MenuID: '1578479100252lfbp29v1kafk4s4q4ig', |
| | | MenuNo: 'BDLanguagePacksM', |
| | | MenuName: '语言包', |
| | | text: '语言包' |
| | | }, { |
| | | src: '', |
| | | systems: ['official', 'local', 'SSO', 'cloud'], |
| | | PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, |
| | | type: 'ManageTable', |
| | | MenuID: '1577971621421tg4v0i1ur8873k7e0ob', |
| | | MenuNo: 'sSystemParametersM', |
| | | MenuName: '接口地址', |
| | | text: '接口地址' |
| | | }, { |
| | | src: '', |
| | | systems: ['official', 'local', 'SSO', 'cloud'], |
| | | PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, |
| | | type: 'ManageTable', |
| | | MenuID: '1577929944419lgc5h3hepum765e2k7u', |
| | | MenuNo: 'sProcExcepM', |
| | | MenuName: '报错日志', |
| | | text: '报错日志' |
| | | }, { |
| | | src: '', |
| | | PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, |
| | | type: 'ManageTable', |
| | | MenuID: '1588493493409k9guqp067d31lu7blsv', |
| | | MenuNo: 's_job_stepM', |
| | | MenuName: '计划任务', |
| | | text: '计划任务' |
| | | }] |
| | | }] |
| | | } |
| | |
| | | .ant-table-fixed-left, .ant-table-fixed-right { |
| | | z-index: 1; |
| | | } |
| | | .chart-view { |
| | | > .chart-view { |
| | | position: relative; |
| | | >.ant-tabs { |
| | | .ant-tabs-bar { |
| | |
| | | display: none!important; |
| | | } |
| | | .ant-tabs-tab { |
| | | padding: 5px 5px; |
| | | padding: 6px 5px; |
| | | margin-right: 5px; |
| | | } |
| | | } |
| | |
| | | } |
| | | .chart-title { |
| | | position: relative; |
| | | // top: -20px; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | margin: 0 20px; |
| | | padding: 10px 5px 5px; |
| | | // border-bottom: 1px solid #e8e8e8; |
| | | margin: 0px 0px 0px 20px; |
| | | padding: 5px 10px; |
| | | float: left; |
| | | max-width: 50%; |
| | | } |
| | | .chart-table.chart-title { |
| | | position: absolute; |
| | | top: 0px; |
| | | } |
| | | .canvas { |
| | | clear: both; |
| | | } |
| | | } |
| | | } |
| | | .commontable.pick-control { |
| | |
| | | padding: 10px 0px 5px; |
| | | } |
| | | } |
| | | >.chart-view >.ant-tabs { |
| | | > .chart-view { |
| | | position: relative; |
| | | top: -10px; |
| | | .ant-tabs-bar .ant-tabs-nav-scroll { |
| | | text-align: right; |
| | | padding-right: 0px; |
| | | >.ant-tabs { |
| | | .ant-tabs-bar { |
| | | position: relative; |
| | | z-index: 1; |
| | | top: -10px; |
| | | margin: 0; |
| | | border: 0; |
| | | .ant-tabs-nav-scroll { |
| | | text-align: right; |
| | | padding-right: 0px; |
| | | .ant-tabs-ink-bar { |
| | | display: none!important; |
| | | } |
| | | .ant-tabs-tab { |
| | | padding: 6px 5px; |
| | | margin-right: 5px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .chart-title { |
| | | position: relative; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | margin: 0; |
| | | padding: 5px 10px; |
| | | float: left; |
| | | max-width: 50%; |
| | | } |
| | | .chart-table.chart-title { |
| | | position: absolute; |
| | | top: 0px; |
| | | } |
| | | .canvas { |
| | | clear: both; |
| | | } |
| | | } |
| | | |
| | |
| | | import { is, fromJS } from 'immutable' |
| | | import { Chart } from '@antv/g2' |
| | | import DataSet from '@antv/data-set' |
| | | import { Spin, Empty } from 'antd' |
| | | import { Spin, Empty, Select } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | state = { |
| | | dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, |
| | | empty: true, |
| | | chartId: Utils.getuuid() |
| | | chartId: Utils.getuuid(), |
| | | chartData: [], |
| | | chartFields: [], |
| | | selectFields: [] |
| | | } |
| | | |
| | | componentDidMount () { |
| | | this.viewrender() |
| | | const { plot, data } = this.props |
| | | |
| | | let _state = {} |
| | | |
| | | 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 |
| | | |
| | | this.setState(_state, () => { |
| | | this.viewrender() |
| | | }) |
| | | } else { |
| | | this.viewrender() |
| | | } |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | const { plot } = this.props |
| | | if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | this.setState({}, () => { |
| | | let _state = {} |
| | | |
| | | if (plot.datatype === 'statistics' && (plot.chartType === 'line' || plot.chartType === 'bar')) { |
| | | let result = this.getStaticMsg(nextProps.data) |
| | | _state.chartData = result.data |
| | | _state.chartFields = result.chartFields |
| | | _state.selectFields = result.selectFields |
| | | } |
| | | |
| | | this.setState(_state, () => { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | |
| | | vFields.forEach(field => { |
| | | _item[field] += item[field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | | }) |
| | | |
| | |
| | | vFields.forEach(field => { |
| | | _item[field] += item[field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | | }) |
| | | |
| | |
| | | _data = [..._mdata.values()] |
| | | } |
| | | |
| | | if (plot.correction && plot.chartType === 'bar' && plot.enabled !== 'true' && _data.length > 0 && _data.length < plot.correction) { |
| | | if (plot.customs && plot.customs.filter(cell => cell.chartType !== 'bar').length === 0) { |
| | | let _num = plot.correction - _data.length |
| | | for (let i = 0; i < _num; i++) { |
| | | let _val = Array( i + 2 ).join(' ') |
| | | let _cell = {} |
| | | _cell[plot.Xaxis] = _val |
| | | _columns.forEach(col => { |
| | | _cell[col.field] = '' |
| | | }) |
| | | |
| | | _data.push(_cell) |
| | | } |
| | | } |
| | | } |
| | | |
| | | this.setState({empty: _data.length === 0}) |
| | | return _data |
| | | } |
| | | |
| | | getStaticMsg = (data) => { |
| | | const { plot, config } = this.props |
| | | |
| | | let _column = config.columns.filter(col => plot.InfoValue === col.field)[0] |
| | | let percent = false |
| | | let decimal = 0 |
| | | if (_column && _column.format === 'percent') { |
| | | percent = true |
| | | } |
| | | if (_column) { |
| | | decimal = _column.decimal |
| | | } |
| | | |
| | | if (!data) { |
| | | this.setState({empty: true}) |
| | | return {data: [], chartFields: [], selectFields: []} |
| | | } |
| | | |
| | | let _data = [] |
| | | let _cdata = fromJS(data).toJS() |
| | | let _chartFields = [] |
| | | let _selectFields = [] |
| | | |
| | | if (plot.repeat === 'average') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(plot.InfoValue) |
| | | if (isNaN(item[plot.InfoValue])) { |
| | | item[plot.InfoValue] = 0 |
| | | } |
| | | } |
| | | if (percent) { |
| | | item[plot.InfoValue] = item[plot.InfoValue] * 100 |
| | | } |
| | | |
| | | if (!_mdata.has(item.$uuid)) { |
| | | item.$count = 1 |
| | | _mdata.set(item.$uuid, item) |
| | | } else { |
| | | let _item = _mdata.get(item.$uuid) |
| | | _item.$count++ |
| | | _item[plot.InfoValue] += item[plot.InfoValue] |
| | | _mdata.set(item.$uuid, _item) |
| | | } |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | item[plot.InfoValue] = item[plot.InfoValue] / item.$count |
| | | item[plot.InfoValue] = item[plot.InfoValue].toFixed(decimal) |
| | | item[plot.InfoValue] = +item[plot.InfoValue] |
| | | |
| | | return item |
| | | }) |
| | | } else if (plot.repeat === 'cumsum') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(plot.InfoValue) |
| | | if (isNaN(item[plot.InfoValue])) { |
| | | item[plot.InfoValue] = 0 |
| | | } |
| | | } |
| | | if (percent) { |
| | | item[plot.InfoValue] = item[plot.InfoValue] * 100 |
| | | } |
| | | |
| | | if (!_mdata.has(item.$uuid)) { |
| | | _mdata.set(item.$uuid, item) |
| | | } else { |
| | | let _item = _mdata.get(item.$uuid) |
| | | _item[plot.InfoValue] += item[plot.InfoValue] |
| | | _mdata.set(item.$uuid, _item) |
| | | } |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | item[plot.InfoValue] = item[plot.InfoValue].toFixed(decimal) |
| | | item[plot.InfoValue] = +item[plot.InfoValue] |
| | | |
| | | return item |
| | | }) |
| | | } else { // plot.repeat === 'unrepeat' |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | | if (!_mdata.has(item.$uuid)) { |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(plot.InfoValue) |
| | | if (isNaN(item[plot.InfoValue])) { |
| | | item[plot.InfoValue] = 0 |
| | | } |
| | | } |
| | | if (percent) { |
| | | item[plot.InfoValue] = item[plot.InfoValue] * 100 |
| | | } |
| | | |
| | | item[plot.InfoValue] = item[plot.InfoValue].toFixed(decimal) |
| | | item[plot.InfoValue] = +item[plot.InfoValue] |
| | | |
| | | _mdata.set(item.$uuid, item) |
| | | } |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | } |
| | | |
| | | _chartFields = Array.from(new Set(_chartFields)) |
| | | |
| | | if (plot.InfoDefNumber >= _chartFields.length) { |
| | | _selectFields = _chartFields |
| | | } else { |
| | | _selectFields = _chartFields.slice(0, plot.InfoDefNumber) |
| | | } |
| | | |
| | | return {data: _data, chartFields: _chartFields, selectFields: _selectFields} |
| | | } |
| | | |
| | | getStaticData = () => { |
| | | const { plot } = this.props |
| | | const { chartData, chartFields, selectFields } = this.state |
| | | |
| | | let _data = [] |
| | | if (selectFields.length === chartFields.length) { |
| | | _data = chartData |
| | | } else { |
| | | _data = chartData.filter(item => selectFields.includes(item[plot.InfoType])) |
| | | } |
| | | |
| | | this.setState({empty: _data.length === 0}) |
| | | return _data |
| | | } |
| | |
| | | linerender = () => { |
| | | const { plot, config } = this.props |
| | | |
| | | let transfield = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | // const colors = ['#f49d37', '#f03838', '#35d1d1', '#5be56b', '#4e7af0', '#ebcc21'] |
| | | let X_axis = plot.Xaxis |
| | | let Y_axis = plot.Yaxis |
| | | let _data = [] |
| | | let _valfield = 'value' |
| | | let _typefield = 'key' |
| | | |
| | | let data = this.getdata() |
| | | if (plot.datatype === 'statistics') { |
| | | _valfield = plot.InfoValue |
| | | _typefield = plot.InfoType |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', // key字段 |
| | | value: 'value', // value字段 |
| | | // retains: [], // 保留字段集,默认为除 fields 以外的所有字段 |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | _data = this.getStaticData() |
| | | } else { |
| | | let transfield = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | let data = this.getdata() |
| | | |
| | | if (plot.enabled === 'true') { |
| | | this.customrender(data, transfield) |
| | | return |
| | | } |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...plot.Yaxis], |
| | | key: 'key', // key字段 |
| | | value: _valfield, // value字段 |
| | | // retains: [], // 保留字段集,默认为除 fields 以外的所有字段 |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | _data = dv.rows |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | chart.data(_data) |
| | | |
| | | if (plot.coordinate !== 'polar') { |
| | | chart.scale(X_axis, { |
| | | chart.scale(plot.Xaxis, { |
| | | range: [0, 1] |
| | | }) |
| | | } |
| | | chart.scale('value', { |
| | | chart.scale(_valfield, { |
| | | nice: true |
| | | }) |
| | | |
| | |
| | | |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .color(_typefield) |
| | | .shape(plot.shape || 'smooth') |
| | | |
| | | if (plot.label === 'true') { |
| | | _chart.label('value') |
| | | _chart.label(_valfield) |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .color(_typefield) |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | |
| | | chart.render() |
| | | } |
| | | |
| | | barrender = () => { |
| | | const { plot, config } = this.props |
| | | customrender = (data, transfield) => { |
| | | const { plot } = this.props |
| | | |
| | | let transfield = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | let barfields = [] |
| | | let fields = [] |
| | | let legends = [] |
| | | |
| | | plot.customs.forEach(item => { |
| | | item.name = transfield[item.field] || item.field |
| | | if (item.axis === 'left') { |
| | | item.index = 0 |
| | | } else if (item.axis === 'right') { |
| | | item.index = 1 |
| | | } else { |
| | | item.index = 2 |
| | | } |
| | | }) |
| | | let X_axis = plot.Xaxis |
| | | let Y_axis = plot.Yaxis |
| | | |
| | | let data = this.getdata() |
| | | if (item.chartType === 'bar') { |
| | | barfields.push(item.field) |
| | | fields.unshift(item) |
| | | } else { |
| | | fields.push(item) |
| | | } |
| | | |
| | | legends.push({ |
| | | value: item.name, |
| | | name: item.name, |
| | | marker: { symbol: item.chartType === 'bar' ? 'square' : 'hyphen', style: { stroke: item.color,fill: item.color, r: 5, lineWidth: 2 } } |
| | | }) |
| | | }) |
| | | |
| | | fields.sort((a, b) => a.index - b.index) |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | type: 'map', |
| | | callback(row) { |
| | | fields.forEach(line => { |
| | | row[line.name] = row[line.field] |
| | | }) |
| | | return row |
| | | } |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: this.state.chartId, |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | // dodge is not support linear attribute, please use category attribute! 时间格式 |
| | | if (dv.rows[0] && dv.rows[0][X_axis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(dv.rows[0][X_axis])) { |
| | | dv.rows[0][X_axis] += ' ' |
| | | } |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | chart.scale('value', { |
| | | nice: true |
| | | }) |
| | | if (plot.coordinate !== 'polar' && barfields.length === 0) { |
| | | chart.scale(plot.Xaxis, { |
| | | range: [0, 1] |
| | | }) |
| | | } else { |
| | | chart.scale(plot.Xaxis, { |
| | | range: [0.05, 0.95] |
| | | }) |
| | | } |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | custom: true, |
| | | position: plot.legend, |
| | | items: legends, |
| | | }) |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | fields.forEach((item, i) => { |
| | | if (i === 0) { |
| | | chart.axis(item.name, { |
| | | grid: {}, |
| | | title: {}, |
| | | label: {} |
| | | }) |
| | | } else if (i === 1 && item.axis !== 'unset') { |
| | | chart.axis(item.name, { |
| | | grid: null, |
| | | title: {}, |
| | | label: {} |
| | | }) |
| | | } else { |
| | | chart.axis(item.name, { |
| | | grid: null, |
| | | title: null, |
| | | label: null |
| | | }) |
| | | } |
| | | |
| | | if (item.chartType === 'bar') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | |
| | | if (item.label === 'true') { |
| | | _chart.label(item.name) |
| | | } |
| | | } else if (item.chartType === 'line') { |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | |
| | | if (item.label === 'true') { |
| | | _chart.label(item.name) |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | } |
| | | }) |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | | barrender = () => { |
| | | const { plot, config } = this.props |
| | | |
| | | let _data = [] |
| | | let _valfield = 'value' |
| | | let _typefield = 'key' |
| | | |
| | | if (plot.datatype === 'statistics') { |
| | | _valfield = plot.InfoValue |
| | | _typefield = plot.InfoType |
| | | |
| | | _data = this.getStaticData() |
| | | } else { |
| | | let transfield = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | let data = this.getdata() |
| | | |
| | | if (plot.enabled === 'true') { |
| | | this.customrender(data, transfield) |
| | | return |
| | | } |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...plot.Yaxis], |
| | | key: 'key', |
| | | value: _valfield |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | _data = dv.rows |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: this.state.chartId, |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | // 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])) { |
| | | _data[0][plot.Xaxis] += ' ' |
| | | } |
| | | |
| | | chart.data(_data) |
| | | |
| | | chart.scale(_valfield, { |
| | | nice: true |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | showMarkers: false, |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .color(_typefield) |
| | | .adjust([ |
| | | { |
| | | type: 'dodge', |
| | |
| | | } else if (plot.adjust === 'stack') { |
| | | chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .color(_typefield) |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | } |
| | |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | let X_axis = plot.Xaxis |
| | | let Y_axis = plot.Yaxis |
| | | |
| | | let data = this.getdata() |
| | | |
| | |
| | | if (plot.pieshow !== 'value') { |
| | | dv.transform({ |
| | | type: 'percent', |
| | | field: Y_axis, |
| | | dimension: X_axis, |
| | | field: plot.Yaxis, |
| | | dimension: plot.Xaxis, |
| | | as: 'percent' |
| | | }) |
| | | } |
| | |
| | | .interval() |
| | | .adjust('stack') |
| | | .position('percent') |
| | | .color(X_axis) |
| | | .tooltip(X_axis + '*percent', (item, percent) => { |
| | | .color(plot.Xaxis) |
| | | .tooltip(plot.Xaxis + '*percent', (item, percent) => { |
| | | percent = (percent * 100).toFixed(2) + '%' |
| | | return { |
| | | name: item, |
| | |
| | | if (plot.label === 'true') { |
| | | let setting = { |
| | | content: (data) => { |
| | | return `${data[X_axis]}: ${(data.percent * 100).toFixed(2)}%` |
| | | return `${data[plot.Xaxis]}: ${(data.percent * 100).toFixed(2)}%` |
| | | } |
| | | } |
| | | |
| | |
| | | type: 'overlap' |
| | | } |
| | | setting.offset = 0 |
| | | // setting.style = { |
| | | // textAlign: 'center', |
| | | // fontSize: 12, |
| | | // fill: '#535353' |
| | | // } |
| | | } |
| | | |
| | | _chart.label('percent', setting) |
| | |
| | | let _chart = chart |
| | | .interval() |
| | | .adjust('stack') |
| | | .position(Y_axis) |
| | | .color(X_axis) |
| | | .tooltip(X_axis + '*' + Y_axis, (item, value) => { |
| | | .position(plot.Yaxis) |
| | | .color(plot.Xaxis) |
| | | .tooltip(plot.Xaxis + '*' + plot.Yaxis, (item, value) => { |
| | | return { |
| | | name: item, |
| | | value: value |
| | |
| | | if (plot.label === 'true') { |
| | | let setting = { |
| | | content: (data) => { |
| | | return `${data[X_axis]}: ${data[Y_axis]}` |
| | | return `${data[plot.Xaxis]}: ${data[plot.Yaxis]}` |
| | | } |
| | | } |
| | | |
| | |
| | | setting.offset = 0 |
| | | } |
| | | |
| | | _chart.label(Y_axis, setting) |
| | | _chart.label(plot.Yaxis, setting) |
| | | } |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | | handleChange = (val) => { |
| | | this.setState({selectFields: val}, () => { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { plot, loading } = this.props |
| | | const { empty } = this.state |
| | | const { empty, chartFields, selectFields } = this.state |
| | | |
| | | return ( |
| | | <div className="line-chart-plot-box"> |
| | |
| | | <Spin /> |
| | | </div> : null |
| | | } |
| | | {plot.datatype === 'statistics' && chartFields.length > 0 ? <Select |
| | | mode="multiple" |
| | | showSearch |
| | | showArrow={true} |
| | | value={selectFields} |
| | | onChange={this.handleChange} |
| | | maxTagCount={0} |
| | | maxTagPlaceholder={(option) => <div className="type-label">{option.join('、')}</div>} |
| | | > |
| | | {chartFields.map((item, i) => <Select.Option key={i} value={item}>{item}</Select.Option>)} |
| | | </Select> : null} |
| | | <div className={'canvas' + (empty ? ' empty' : '')} style={{minHeight: plot.height ? plot.height : 400}} id={this.state.chartId}></div> |
| | | {empty ? <Empty description={false}/> : null} |
| | | </div> |
| | |
| | | .chart-title + .loading-mask { |
| | | top: 40px; |
| | | } |
| | | > .ant-select { |
| | | width: 150px; |
| | | float: right; |
| | | .ant-select-selection { |
| | | min-height: 24px; |
| | | height: 28px; |
| | | li { |
| | | background: unset; |
| | | border: 0; |
| | | width: 99%; |
| | | padding: 0; |
| | | margin-right: 0; |
| | | cursor: pointer; |
| | | |
| | | .type-label { |
| | | overflow: hidden; |
| | | word-break: break-word; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | } |
| | | } |
| | | li + li { |
| | | width: 1%; |
| | | opacity: 0; |
| | | } |
| | | } |
| | | } |
| | | .g2-tooltip-list{ |
| | | display: none; |
| | | } |
| | | .g2-tooltip-title + .g2-tooltip-list{ |
| | | display: block; |
| | | } |
| | | } |
| | | |
| | | .subtable .ant-col-24 .line-chart-plot-box { |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Drawer, Form, Button, Col, Row, Select, Icon, Radio, Tooltip, Input, InputNumber } from 'antd' |
| | | import { Drawer, Form, Button, Col, Row, Select, Icon, Radio, Tooltip, Input, InputNumber, Cascader } from 'antd' |
| | | |
| | | import { getChartOptionForm } from '@/templates/zshare/formconfig' |
| | | import { minkeColorSystem, colorTransform } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class LineChartDrawerForm extends Component { |
| | |
| | | view: 'normal', |
| | | visible: false, |
| | | plot: null, |
| | | formlist: null |
| | | formlist: null, |
| | | datatype: null, |
| | | fieldName: null, |
| | | colorOptions: fromJS(minkeColorSystem).toJS().map(option => { |
| | | option.children = option.children.map(cell => { |
| | | let _cell = {} |
| | | _cell.label = <div className={'background ' + cell.value}>{cell.value}</div> |
| | | _cell.value = colorTransform[cell.value] |
| | | |
| | | return _cell |
| | | }) |
| | | return option |
| | | }), |
| | | shapeOptions: [ |
| | | { |
| | | value: 'line', |
| | | label: '折线', |
| | | children: [ |
| | | { value: 'smooth', label: 'smooth' }, |
| | | { value: 'line', label: 'line' }, |
| | | { value: 'dot', label: 'dot' }, |
| | | { value: 'dash', label: 'dash' }, |
| | | { value: 'hv', label: 'hv' }, |
| | | { value: 'vh', label: 'vh' }, |
| | | { value: 'hvh', label: 'hvh' }, |
| | | { value: 'vhv', label: 'vhv' } |
| | | ] |
| | | }, |
| | | { |
| | | value: 'bar', |
| | | label: '柱形', |
| | | children: [ |
| | | { value: 'rect', label: 'rect' }, |
| | | { value: 'hollow-rect', label: 'hollow-rect' }, |
| | | { value: 'line', label: 'line' }, |
| | | { value: 'tick', label: 'tick' }, |
| | | { value: 'funnel', label: 'funnel' }, |
| | | { value: 'pyramid', label: 'pyramid' } |
| | | ], |
| | | } |
| | | ] |
| | | } |
| | | |
| | | showDrawer = () => { |
| | | const { config, plot } = this.props |
| | | |
| | | let datatype = null |
| | | if (['line', 'bar'].includes(plot.chartType)) { |
| | | datatype = plot.datatype || 'query' |
| | | } |
| | | |
| | | let fieldName = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | fieldName[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | view: 'normal', |
| | | datatype: datatype, |
| | | fieldName: fieldName, |
| | | enabled: plot.enabled || 'false', |
| | | plot: fromJS(plot).toJS(), |
| | | formlist: getChartOptionForm(plot, config.columns, config.setting) |
| | | }) |
| | | } |
| | | |
| | | onSubmit = () => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.plotchange(values) |
| | | } |
| | | }) |
| | | } |
| | | |
| | |
| | | |
| | | if (key === 'datatype') { |
| | | this.setState({ |
| | | datatype: val, |
| | | formlist: formlist.map(item => { |
| | | if (['Yaxis'].includes(item.key)) { |
| | | item.hidden = val === 'statistics' |
| | |
| | | return fields |
| | | } |
| | | |
| | | getCustomFields = () => { |
| | | const { getFieldDecorator } = this.props.form |
| | | const { plot, fieldName, enabled, colorOptions, shapeOptions } = this.state |
| | | const fields = [] |
| | | |
| | | fields.push(<Col span={12} key="enabled"> |
| | | <Form.Item label="是否启用" style={{marginBottom: 10}}> |
| | | {getFieldDecorator('enabled', { |
| | | initialValue: plot.enabled || 'false' |
| | | })( |
| | | <Radio.Group onChange={this.enabledChange}> |
| | | <Radio value="true">是</Radio> |
| | | <Radio value="false">否</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col>) |
| | | |
| | | plot.customs.forEach((item, i) => { |
| | | fields.push(<Col span={24} key={'field' + i}> |
| | | <p className="field-title">{fieldName[item.field]}</p> |
| | | </Col>) |
| | | fields.push(<Col span={12} key={'shape' + i}> |
| | | <Form.Item label="形状"> |
| | | {getFieldDecorator(item.field + '$shape', { |
| | | initialValue: item.$shape, |
| | | rules: [ |
| | | { |
| | | required: enabled === 'true', |
| | | message: this.props.dict['form.required.select'] + '形状!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader |
| | | disabled={enabled === 'false'} |
| | | options={shapeOptions} |
| | | placeholder="" |
| | | displayRender={(label, selectedOptions) => selectedOptions[0] ? selectedOptions[0].label + ' / ' + selectedOptions[1].value : ''} |
| | | /> |
| | | )} |
| | | </Form.Item> |
| | | </Col>) |
| | | fields.push(<Col span={12} key={'color' + i}> |
| | | <Form.Item label="颜色"> |
| | | {getFieldDecorator(item.field + '$color', { |
| | | initialValue: item.$color, |
| | | rules: [ |
| | | { |
| | | required: enabled === 'true', |
| | | message: this.props.dict['form.required.select'] + '颜色!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader |
| | | disabled={enabled === 'false'} |
| | | options={colorOptions} |
| | | placeholder="" |
| | | getPopupContainer={() => document.getElementById('chart-custom-drawer-form')} |
| | | displayRender={(label, selectedOptions) => selectedOptions[0] ? <div style={{background: selectedOptions[1].value, width: '20px', height: '20px'}}></div> : ''} |
| | | /> |
| | | )} |
| | | </Form.Item> |
| | | </Col>) |
| | | fields.push(<Col span={12} key={'axis' + i}> |
| | | <Form.Item label="坐标轴"> |
| | | {getFieldDecorator(item.field + '$axis', { |
| | | initialValue: item.axis |
| | | })( |
| | | <Radio.Group disabled={enabled === 'false'} onChange={this.axisChange}> |
| | | <Radio value="left">左侧</Radio> |
| | | <Radio value="right">右侧</Radio> |
| | | <Radio value="unset">不显示</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col>) |
| | | fields.push(<Col span={12} key={'label' + i}> |
| | | <Form.Item label="标注-值"> |
| | | {getFieldDecorator(item.field + '$label', { |
| | | initialValue: item.label |
| | | })( |
| | | <Radio.Group disabled={enabled === 'false'}> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col>) |
| | | }) |
| | | |
| | | return fields |
| | | } |
| | | |
| | | axisChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | let fieldvalue = {} |
| | | |
| | | plot.customs.forEach(item => { |
| | | if (this.props.form.getFieldValue(item.field + '$axis') === val) { |
| | | fieldvalue[item.field + '$axis'] = 'unset' |
| | | } |
| | | }) |
| | | |
| | | this.props.form.setFieldsValue(fieldvalue) |
| | | } |
| | | |
| | | enabledChange = (e) => { |
| | | let val = e.target.value |
| | | |
| | | this.setState({enabled: val}) |
| | | } |
| | | |
| | | onSubmit = () => { |
| | | const { plot, view, datatype } = this.state |
| | | |
| | | if (view !== 'custom') { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _plot = {...plot, ...values} |
| | | |
| | | if (datatype === 'query') { |
| | | if (_plot.enabled === 'true') { |
| | | if (_plot.customs.map(_cell => _cell.field).sort().toString() !== _plot.Yaxis.sort().toString()) { |
| | | _plot.customs = null |
| | | _plot.enabled = 'false' |
| | | } |
| | | } |
| | | } else { |
| | | _plot.customs = null |
| | | _plot.enabled = 'false' |
| | | } |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | | visible: false |
| | | }) |
| | | |
| | | this.props.plotchange(_plot) |
| | | } |
| | | }) |
| | | } else { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _plot = {...plot, enabled: values.enabled} |
| | | |
| | | if (_plot.enabled === 'true') { |
| | | _plot.customs = _plot.Yaxis.map(field => { |
| | | let _item = {field: field} |
| | | |
| | | _item.$shape = values[field + '$shape'] |
| | | _item.chartType = _item.$shape[0] |
| | | _item.shape = _item.$shape[1] |
| | | |
| | | _item.$color = values[field + '$color'] |
| | | _item.color = _item.$color[1] |
| | | |
| | | _item.axis = values[field + '$axis'] |
| | | |
| | | _item.label = values[field + '$label'] |
| | | |
| | | return _item |
| | | }) |
| | | } else { |
| | | _plot.customs = null |
| | | } |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | | visible: false |
| | | }) |
| | | |
| | | this.props.plotchange(_plot) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | changeView = () => { |
| | | let _view = this.state.view === 'normal' ? 'custom' : 'normal' |
| | | const { config } = this.props |
| | | const { plot, view } = this.state |
| | | let _view = view === 'normal' ? 'custom' : 'normal' |
| | | |
| | | if (_view === 'custom') { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _plot = {...this.state.plot, ...values} |
| | | let _plot = {...plot, ...values} |
| | | |
| | | if (_plot.enabled !== 'true') { |
| | | _plot.enabled = 'false' |
| | | _plot.customs = _plot.Yaxis.map((field, i) => { |
| | | let _item = {field: field} |
| | | _item.$shape = [_plot.chartType, _plot.shape] |
| | | _item.$color = [] |
| | | _item.axis = i === 0 ? 'left' : 'unset' |
| | | _item.label = _plot.label |
| | | |
| | | return _item |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _values = {enabled: values.enabled} |
| | | |
| | | if (values.enabled === 'true') { |
| | | let _customs = [] |
| | | plot.Yaxis.forEach(field => { |
| | | let _item = {field: field} |
| | | |
| | | _item.$shape = values[field + '$shape'] |
| | | _item.chartType = _item.$shape[0] |
| | | _item.shape = _item.$shape[1] |
| | | |
| | | _item.$color = values[field + '$color'] |
| | | _item.color = _item.$color[1] |
| | | |
| | | _item.axis = values[field + '$axis'] |
| | | _item.label = values[field + '$label'] |
| | | |
| | | _customs.push(_item) |
| | | }) |
| | | |
| | | _values.customs = _customs |
| | | } else { |
| | | _values.customs = null |
| | | } |
| | | |
| | | let _plot = {...plot, ..._values} |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | | view: _view, |
| | | formlist: getChartOptionForm(_plot, config.columns, config.setting) |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | this.setState({view: _view}) |
| | | } |
| | | |
| | | render() { |
| | | const { view } = this.state |
| | | const { view, datatype } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | visible={this.state.visible} |
| | | bodyStyle={{ paddingBottom: 80 }} |
| | | > |
| | | {view !== 'custom' ? <Form {...formItemLayout}> |
| | | {view !== 'custom' ? <Form {...formItemLayout} className="base-setting"> |
| | | <Row gutter={16}>{this.getFields()}</Row> |
| | | {/* <Row gutter={16}> |
| | | {datatype === 'query' ? <Row gutter={16}> |
| | | <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>自定义设置<Icon style={{marginLeft: 5}} type="right" /></Button> |
| | | </Row> */} |
| | | </Row> : null} |
| | | </Form> : null} |
| | | {/* <Form {...formItemLayout}> |
| | | {view === 'custom' ? <Form {...formItemLayout} id="chart-custom-drawer-form" className="mingke-table"> |
| | | <Row gutter={16} style={{minHeight: 'calc(100vh - 180px)'}}>{this.getCustomFields()}</Row> |
| | | <Row gutter={16}> |
| | | <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>自定义设置<Icon style={{marginLeft: 5}} type="right" /></Button> |
| | | <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}><Icon style={{marginRight: 5}} type="left" />基本设置</Button> |
| | | </Row> |
| | | </Form> */} |
| | | </Form> : null} |
| | | <div |
| | | style={{ |
| | | position: 'absolute', |
| | |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | .field-title { |
| | | padding-left: 15px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | color: rgb(24, 144, 255); |
| | | } |
| | | |
| | | .base-setting { |
| | | .ant-col-12:nth-child(2n + 1) { |
| | | clear: left; |
| | | } |
| | | } |
| | | } |
| | |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | // const colors = ['#f49d37', '#f03838', '#35d1d1', '#5be56b', '#4e7af0', '#ebcc21'] |
| | | |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || ['y'] |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | if (plot.enabled !== 'true') { |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', // key字段 |
| | | value: 'value', // value字段 |
| | | // retains: [], // 保留字段集,默认为除 fields 以外的所有字段 |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: plot.uuid, |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | if (plot.coordinate !== 'polar') { |
| | | chart.scale(X_axis, { |
| | | range: [0, 1] |
| | | }) |
| | | } |
| | | chart.scale('value', { |
| | | nice: true |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .shape(plot.shape || 'smooth') |
| | | |
| | | if (plot.label === 'true') { |
| | | _chart.label('value') |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | chart.render() |
| | | } else { |
| | | this.customrender(data, transfield) |
| | | } |
| | | } |
| | | |
| | | customrender = (data, transfield) => { |
| | | const { plot } = this.props |
| | | |
| | | let barfields = [] |
| | | let fields = [] |
| | | let legends = [] |
| | | |
| | | plot.customs.forEach(item => { |
| | | item.name = transfield[item.field] || item.field |
| | | if (item.axis === 'left') { |
| | | item.index = 0 |
| | | } else if (item.axis === 'right') { |
| | | item.index = 1 |
| | | } else { |
| | | item.index = 2 |
| | | } |
| | | |
| | | if (item.chartType === 'bar') { |
| | | barfields.push(item.field) |
| | | fields.unshift(item) |
| | | } else { |
| | | fields.push(item) |
| | | } |
| | | |
| | | legends.push({ |
| | | value: item.name, |
| | | name: item.name, |
| | | marker: { symbol: item.chartType === 'bar' ? 'square' : 'hyphen', style: { stroke: item.color,fill: item.color, r: 5, lineWidth: 2 } } |
| | | }) |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | fields.sort((a, b) => a.index - b.index) |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | fields.forEach(line => { |
| | | row[line.name] = row[line.field] |
| | | }) |
| | | return row |
| | | } |
| | | }) |
| | | |
| | | const chart = new Chart({ |
| | | container: plot.uuid, |
| | | autoFit: true, |
| | |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | if (plot.coordinate !== 'polar') { |
| | | chart.scale(X_axis, { |
| | | if (plot.coordinate !== 'polar' && barfields.length === 0) { |
| | | chart.scale(plot.Xaxis, { |
| | | range: [0, 1] |
| | | }) |
| | | } |
| | | chart.scale('value', { |
| | | nice: true |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | custom: true, |
| | | position: plot.legend, |
| | | items: legends, |
| | | }) |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .shape(plot.shape || 'smooth') |
| | | chart.scale({ |
| | | nice: true |
| | | }) |
| | | |
| | | if (plot.label === 'true') { |
| | | _chart.label('value') |
| | | } |
| | | fields.forEach((item, i) => { |
| | | if (i === 0) { |
| | | chart.axis(item.name, { |
| | | grid: {}, |
| | | title: {}, |
| | | label: {} |
| | | }) |
| | | } else if (i === 1 && item.axis !== 'unset') { |
| | | chart.axis(item.name, { |
| | | grid: null, |
| | | title: {}, |
| | | label: {} |
| | | }) |
| | | } else { |
| | | chart.axis(item.name, { |
| | | grid: null, |
| | | title: null, |
| | | label: null |
| | | }) |
| | | } |
| | | |
| | | if (item.chartType === 'bar') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | |
| | | // chart.interaction('element-active') |
| | | // chart.removeInteraction('legend-filter') // 自定义图例,移除默认的分类图例筛选交互 |
| | | if (item.label === 'true') { |
| | | _chart.label(item.name) |
| | | } |
| | | } else if (item.chartType === 'line') { |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | |
| | | if (item.label === 'true') { |
| | | _chart.label(item.name) |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | } |
| | | }) |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: plot.uuid, |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | chart.scale('value', { |
| | | nice: true |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | if (plot.enabled !== 'true') { |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: plot.uuid, |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | chart.scale('value', { |
| | | nice: true |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .adjust([ |
| | | { |
| | | type: 'dodge', |
| | | marginRatio: 0 |
| | | } |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | |
| | | if (plot.label === 'true') { |
| | | _chart.label('value') |
| | | } |
| | | } else if (plot.adjust === 'stack') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | |
| | | if (plot.label === 'true') { |
| | | _chart.label('value') |
| | | } |
| | | } |
| | | |
| | | chart.render() |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend |
| | | }) |
| | | this.customrender(data, transfield) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .adjust([ |
| | | { |
| | | type: 'dodge', |
| | | marginRatio: 0 |
| | | } |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | } else if (plot.adjust === 'stack') { |
| | | chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | | pierender = () => { |
| | |
| | | chart.render() |
| | | } |
| | | |
| | | plotChange = (values) => { |
| | | const { plot, config } = this.props |
| | | let _plot = {...plot, ...values} |
| | | plotChange = (_plot) => { |
| | | const { config } = this.props |
| | | |
| | | if (_plot.datatype === 'statistics') { |
| | | _plot.Yaxis = [_plot.InfoValue] |
| | | } |
| | | |
| | | let _charts = fromJS(config.charts).toJS() |
| | | |
| | | _charts = _charts.map(item => { |
| | |
| | | |
| | | return ( |
| | | <div className="line-chart-edit-box" style={{minHeight: plot.height ? plot.height + 50 : 450}}> |
| | | <p className="chart-title">{plot.title}</p> |
| | | {plot.title ? <p className="chart-title">{plot.title}</p> : null} |
| | | <div className="canvas" id={plot.uuid}></div> |
| | | <ChartCompileForm |
| | | plot={plot} |
| | |
| | | margin-bottom: 30px; |
| | | |
| | | .canvas { |
| | | margin: 0 20px; |
| | | margin: 40px 20px 0px; |
| | | border: 1px solid #e8e8e8; |
| | | padding: 15px; |
| | | padding: 25px 15px; |
| | | } |
| | | |
| | | .chart-title + .canvas { |
| | | margin-top: 0; |
| | | } |
| | | } |
| | |
| | | chartType: 'line', |
| | | icon: 'line-chart', |
| | | Hide: 'false', |
| | | blacklist: [] |
| | | blacklist: [], |
| | | correction: 7 |
| | | } |
| | | } |
| | | |
| | |
| | | originField: this.props.card, |
| | | signType: 'background', |
| | | selectIcon: '', |
| | | options: minkeColorSystem, |
| | | options: JSON.parse(JSON.stringify(minkeColorSystem)), |
| | | icons: minkeIconSystem.direction |
| | | } |
| | | |
| | |
| | | this.setState({ |
| | | editItem: null |
| | | }) |
| | | this.props.form.setFieldsValue({ |
| | | field: '', |
| | | }) |
| | | if (this.state.contrastType !== 'static') { |
| | | this.props.form.setFieldsValue({contrastField: ''}) |
| | | } else { |
| | | this.props.form.setFieldsValue({contrastValue: ''}) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | |
| | | })( |
| | | <Select onChange={this.changeIcon} getPopupContainer={() => document.getElementById('model-mark-form-box')}> |
| | | {icons.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {/* <Select.Option value="arrow-up"><Icon type="arrow-up" /></Select.Option> |
| | | <Select.Option value="arrow-down"><Icon type="arrow-down" /></Select.Option> |
| | | <Select.Option value="arrow-left"><Icon type="arrow-left" /></Select.Option> |
| | | <Select.Option value="arrow-right"><Icon type="arrow-right" /></Select.Option> |
| | | <Select.Option value="check-circle"><Icon type="check-circle" /></Select.Option> |
| | | <Select.Option value="close-circle"><Icon type="close-circle" /></Select.Option> |
| | | <Select.Option value="clock-circle"><Icon type="clock-circle" /></Select.Option> |
| | | <Select.Option value="pause-circle"><Icon type="pause-circle" /></Select.Option> |
| | | <Select.Option value="stop"><Icon type="stop" /></Select.Option> |
| | | <Select.Option value="question-circle"><Icon type="question-circle" /></Select.Option> |
| | | <Select.Option value="exclamation-circle"><Icon type="exclamation-circle" /></Select.Option> |
| | | <Select.Option value="check-square"><Icon type="check-square" /></Select.Option> |
| | | <Select.Option value="warning"><Icon type="warning" /></Select.Option> |
| | | <Select.Option value="minus-circle"><Icon type="minus-circle" /></Select.Option> |
| | | <Select.Option value="issues-close"><Icon type="issues-close" /></Select.Option> |
| | | <Select.Option value="question"><Icon type="question" /></Select.Option> |
| | | <Select.Option value="fall"><Icon type="fall" /></Select.Option> |
| | | <Select.Option value="rise"><Icon type="rise" /></Select.Option> |
| | | <Select.Option value="link"><Icon type="link" /></Select.Option> */} |
| | | {/* <Select.Option value="link"></Select.Option> */} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | |
| | | { |
| | | type: 'radio', |
| | | key: 'label', |
| | | label: '文本标签', |
| | | label: '标注-值', |
| | | initVal: card.label || (card.chartType === 'pie' ? 'true' : 'false'), |
| | | required: false, |
| | | forbid: !['pie', 'line'].includes(card.chartType), |
| | | forbid: !['pie', 'bar', 'line'].includes(card.chartType), |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | |
| | | forbid: !['line', 'bar'].includes(card.chartType), |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true |
| | | }, |
| | | }, { |
| | | type: 'number', |
| | | key: 'correction', |
| | | label: '数据修正', |
| | | tooltip: '当数据项少于设置值时,系统会自动修正(避免柱形图过宽),在自定义中,设置为折线图时失效。', |
| | | min: 5, |
| | | max: 30, |
| | | decimal: 0, |
| | | initVal: card.correction, |
| | | forbid: !['bar'].includes(card.chartType), |
| | | required: false |
| | | } |
| | | ] |
| | | } |
| | | |
| | |
| | | text: '白底紫框' |
| | | }] |
| | | |
| | | export const colorTransform = { |
| | | 'dust-red-1': '#fff1f0', |
| | | 'dust-red-2': '#ffccc7', |
| | | 'dust-red-3': '#ffa39e', |
| | | 'dust-red-4': '#ff7875', |
| | | 'dust-red-5': '#ff4d4f', |
| | | 'dust-red-6': '#f5222d', |
| | | 'dust-red-7': '#cf1322', |
| | | 'dust-red-8': '#a8071a', |
| | | 'dust-red-9': '#820014', |
| | | 'dust-red-10': '#5c0011', |
| | | 'volcano-1': '#fff2e8', |
| | | 'volcano-2': '#ffd8bf', |
| | | 'volcano-3': '#ffbb96', |
| | | 'volcano-4': '#ff9c6e', |
| | | 'volcano-5': '#ff7a45', |
| | | 'volcano-6': '#fa541c', |
| | | 'volcano-7': '#d4380d', |
| | | 'volcano-8': '#ad2102', |
| | | 'volcano-9': '#871400', |
| | | 'volcano-10': '#610b00', |
| | | 'orange-1': '#fff7e6', |
| | | 'orange-2': '#ffe7ba', |
| | | 'orange-3': '#ffd591', |
| | | 'orange-4': '#ffc069', |
| | | 'orange-5': '#ffa940', |
| | | 'orange-6': '#fa8c16', |
| | | 'orange-7': '#d46b08', |
| | | 'orange-8': '#ad4e00', |
| | | 'orange-9': '#873800', |
| | | 'orange-10': '#612500', |
| | | 'gold-1': '#fffbe6', |
| | | 'gold-2': '#fff1b8', |
| | | 'gold-3': '#ffe58f', |
| | | 'gold-4': '#ffd666', |
| | | 'gold-5': '#ffc53d', |
| | | 'gold-6': '#faad14', |
| | | 'gold-7': '#d48806', |
| | | 'gold-8': '#ad6800', |
| | | 'gold-9': '#874d00', |
| | | 'gold-10': '#613400', |
| | | 'yellow-1': '#feffe6', |
| | | 'yellow-2': '#ffffb8', |
| | | 'yellow-3': '#fffb8f', |
| | | 'yellow-4': '#fff566', |
| | | 'yellow-5': '#ffec3d', |
| | | 'yellow-6': '#fadb14', |
| | | 'yellow-7': '#d4b106', |
| | | 'yellow-8': '#ad8b00', |
| | | 'yellow-9': '#876800', |
| | | 'yellow-10': '#614700', |
| | | 'lime-1': '#fcffe6', |
| | | 'lime-2': '#f4ffb8', |
| | | 'lime-3': '#eaff8f', |
| | | 'lime-4': '#d3f261', |
| | | 'lime-5': '#bae637', |
| | | 'lime-6': '#a0d911', |
| | | 'lime-7': '#7cb305', |
| | | 'lime-8': '#5b8c00', |
| | | 'lime-9': '#3f6600', |
| | | 'lime-10': '#254000', |
| | | 'green-1': '#f6ffed', |
| | | 'green-2': '#d9f7be', |
| | | 'green-3': '#b7eb8f', |
| | | 'green-4': '#95de64', |
| | | 'green-5': '#73d13d', |
| | | 'green-6': '#52c41a', |
| | | 'green-7': '#389e0d', |
| | | 'green-8': '#237804', |
| | | 'green-9': '#135200', |
| | | 'green-10': '#092b00', |
| | | 'cyan-1': '#e6fffb', |
| | | 'cyan-2': '#b5f5ec', |
| | | 'cyan-3': '#87e8de', |
| | | 'cyan-4': '#5cdbd3', |
| | | 'cyan-5': '#36cfc9', |
| | | 'cyan-6': '#13c2c2', |
| | | 'cyan-7': '#08979c', |
| | | 'cyan-8': '#006d75', |
| | | 'cyan-9': '#00474f', |
| | | 'cyan-10': '#002329', |
| | | 'blue-1': '#e6f7ff', |
| | | 'blue-2': '#bae7ff', |
| | | 'blue-3': '#91d5ff', |
| | | 'blue-4': '#69c0ff', |
| | | 'blue-5': '#40a9ff', |
| | | 'blue-6': '#1890ff', |
| | | 'blue-7': '#096dd9', |
| | | 'blue-8': '#0050b3', |
| | | 'blue-9': '#003a8c', |
| | | 'blue-10': '#002766', |
| | | 'geekblue-1': '#f0f5ff', |
| | | 'geekblue-2': '#d6e4ff', |
| | | 'geekblue-3': '#adc6ff', |
| | | 'geekblue-4': '#85a5ff', |
| | | 'geekblue-5': '#597ef7', |
| | | 'geekblue-6': '#2f54eb', |
| | | 'geekblue-7': '#1d39c4', |
| | | 'geekblue-8': '#10239e', |
| | | 'geekblue-9': '#061178', |
| | | 'geekblue-10': '#030852', |
| | | 'purple-1': '#f9f0ff', |
| | | 'purple-2': '#efdbff', |
| | | 'purple-3': '#d3adf7', |
| | | 'purple-4': '#b37feb', |
| | | 'purple-5': '#9254de', |
| | | 'purple-6': '#722ed1', |
| | | 'purple-7': '#531dab', |
| | | 'purple-8': '#391085', |
| | | 'purple-9': '#22075e', |
| | | 'purple-10': '#120338', |
| | | 'magenta-1': '#fff0f6', |
| | | 'magenta-2': '#ffd6e7', |
| | | 'magenta-3': '#ffadd2', |
| | | 'magenta-4': '#ff85c0', |
| | | 'magenta-5': '#f759ab', |
| | | 'magenta-6': '#eb2f96', |
| | | 'magenta-7': '#c41d7f', |
| | | 'magenta-8': '#9e1068', |
| | | 'magenta-9': '#780650', |
| | | 'magenta-10': '#520339', |
| | | 'gray-1': '#f5f5f5', |
| | | 'gray-2': '#f0f0f0', |
| | | 'gray-3': '#d9d9d9', |
| | | 'gray-4': '#bfbfbf', |
| | | 'gray-5': '#8c8c8c', |
| | | 'gray-6': '#595959', |
| | | 'gray-7': '#434343', |
| | | 'gray-8': '#262626', |
| | | 'gray-9': '#1f1f1f', |
| | | 'gray-10': '#141414', |
| | | } |
| | | |
| | | export const minkeColorSystem = [ |
| | | { |
| | | value: 'DustRed', |