| | |
| | | import { is, fromJS } from 'immutable' |
| | | import { Chart } from '@antv/g2' |
| | | import DataSet from '@antv/data-set' |
| | | import { Spin, Empty, notification } from 'antd' |
| | | import { Spin, Empty } from 'antd' |
| | | import { DownloadOutlined } from '@ant-design/icons' |
| | | import moment from 'moment' |
| | | |
| | |
| | | import Utils from '@/utils/utils.js' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import TimerTask from '@/utils/timer-task.js' |
| | | import NormalHeader from '@/tabviews/custom/components/share/normalheader' |
| | | import './index.scss' |
| | | |
| | | // const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) |
| | | const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) |
| | | const ExcelInButton = asyncComponent(() => import('@/tabviews/zshare/actionList/excelInbutton')) |
| | | |
| | | class LineChart extends Component { |
| | | static propTpyes = { |
| | | data: PropTypes.array, // 统一查询数据 |
| | | config: PropTypes.object, // 组件配置信息 |
| | | mainSearch: PropTypes.any, // 外层搜索条件 |
| | | } |
| | | |
| | | state = { |
| | |
| | | loading: false, // 数据加载状态 |
| | | chartId: Utils.getuuid(), // 图表Id |
| | | transfield: {}, // 字段名称翻译 |
| | | sync: false, // 是否统一请求数据 |
| | | plot: null, // 图表设置 |
| | | data: null, // 数据 |
| | | search: null, // 搜索条件 |
| | | vFields: [], // 数值字段 |
| | | vstFields: null, // 统计数据值字段信息 |
| | | chart: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config, data, initdata } = this.props |
| | | let _config = fromJS(config).toJS() |
| | | let _data = null |
| | | let _sync = config.setting.sync === 'true' |
| | | data = [] |
| | | loaded = false |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | let _config = fromJS(config).toJS() |
| | | let BID = '' |
| | | let BData = '' |
| | | |
| | |
| | | } |
| | | if (BData) { |
| | | BID = BData.$BID || '' |
| | | } |
| | | |
| | | if (config.setting.sync === 'true' && data) { |
| | | _data = data[config.dataName] || [] |
| | | _sync = false |
| | | } else if (config.setting.sync === 'true' && initdata) { |
| | | _data = initdata || [] |
| | | _sync = false |
| | | } |
| | | |
| | | let vFields = [] |
| | |
| | | }) |
| | | } |
| | | |
| | | _config.style.height = config.plot.height || 400 |
| | | _config.plot.height = Utils.getHeight(_config.plot.height) |
| | | _config.style.height = 'auto' |
| | | _config.style.minHeight = _config.plot.height + 30 |
| | | |
| | | if (_config.plot.correction) { |
| | | delete _config.plot.correction // 数据修正(已弃用) |
| | | _config.plot.barSize = 35 |
| | | } |
| | | |
| | | if (!_config.plot.legend || _config.plot.legend === 'hidden') { |
| | | _config.plot.legend = false |
| | | } |
| | | |
| | | if (_config.plot.title) { |
| | | _config.style.minHeight = _config.style.minHeight + 45 |
| | | } |
| | | |
| | | let transfield = {} |
| | | _config.columns.forEach(col => { |
| | |
| | | |
| | | if (_config.plot.mutilBar !== 'overlap' && Bar_axis.length > 1) { |
| | | _config.plot.Bar_axis = Bar_axis |
| | | } |
| | | |
| | | if (_config.plot.Bar_axis && _config.plot.Bar_axis.length) { |
| | | let label = _config.plot.label |
| | | |
| | | if (label === 'false') { |
| | | _config.plot.customs.forEach(item => { |
| | | if (!Bar_axis.includes(item.type)) return |
| | | if (item.label === 'true') { |
| | | label = 'true' |
| | | } |
| | | }) |
| | | } else { |
| | | let reset = true |
| | | _config.plot.customs.forEach(item => { |
| | | if (!Bar_axis.includes(item.type)) return |
| | | if (item.label === 'true') { |
| | | reset = false |
| | | } |
| | | }) |
| | | if (reset) { |
| | | label = 'false' |
| | | } |
| | | } |
| | | |
| | | _config.plot.$label = label |
| | | } |
| | | |
| | | if (_config.plot.zoomYaxis === 'adjust' && _config.plot.mutilBar === 'stack') { |
| | | if (_config.plot.Bar_axis) { |
| | | _config.plot.zoomFields = _config.plot.Yaxis.filter(cell => !_config.plot.Bar_axis.includes(cell)) |
| | | } |
| | | } |
| | | } else { |
| | | _config.plot.enabled = 'false' |
| | |
| | | |
| | | let xc = {label: { |
| | | formatter: (val) => { |
| | | if (!val || /^\s*$/.test(val)) return val |
| | | if (!val || /^\s+$/.test(val)) return val |
| | | let _val = `${val}` |
| | | if (_val.length <= limit) return val |
| | | return _val.substring(0, limit) + '...' |
| | |
| | | style: { fill: _config.plot.color } |
| | | }} |
| | | let yc = {label: { style: { fill: _config.plot.color } }} |
| | | |
| | | if (_config.plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (_config.plot.y_line === 'show') { |
| | | if (_config.plot.tick === 'hidden') { |
| | | xc.tickLine = null |
| | | } |
| | | if (_config.plot.x_line === 'hidden') { |
| | | xc.line = null |
| | | } |
| | | if (_config.plot.y_line === 'hidden') { |
| | | yc.line = null |
| | | } else { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (_config.plot.x_label === 'hidden') { |
| | | xc.label = null |
| | | } |
| | | if (_config.plot.y_label === 'hidden') { |
| | | yc.label = null |
| | | } |
| | | |
| | | if (_config.plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: _config.plot.lineColor }} |
| | | xc.line = { style: { stroke: _config.plot.lineColor } } |
| | | if (xc.tickLine !== null) { |
| | | xc.tickLine = {style: { stroke: _config.plot.lineColor }} |
| | | } |
| | | if (xc.line !== null) { |
| | | xc.line = { style: { stroke: _config.plot.lineColor } } |
| | | } |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: _config.plot.lineColor } }} |
| | | } |
| | |
| | | }) |
| | | } |
| | | |
| | | if (_config.setting.sync === 'true') { |
| | | _config.setting.onload = 'false' |
| | | |
| | | if (window.GLOB.SyncData.has(_config.dataName)) { |
| | | this.data = window.GLOB.SyncData.get(_config.dataName) || [] |
| | | |
| | | if (_config.$cache) { |
| | | Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID) |
| | | } |
| | | |
| | | _config.setting.sync = 'false' |
| | | |
| | | this.loaded = true |
| | | |
| | | window.GLOB.SyncData.delete(_config.dataName) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | data: _data, |
| | | BID: BID || '', |
| | | vFields: vFields, |
| | | vstFields: vstFields, |
| | | arr_field: _config.columns.map(col => col.field).join(','), |
| | | plot: _config.plot, |
| | | sync: _sync, |
| | | search: Utils.initMainSearch(config.search), |
| | | search: _config.$searches, |
| | | transfield |
| | | }, () => { |
| | | if (config.setting.sync !== 'true' && config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | }, _config.setting.delay || 0) |
| | | } else if (config.setting.sync === 'true' && _data) { |
| | | this.handleData() |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 图表数据更新,刷新内容 |
| | | */ |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | const { sync, config } = this.state |
| | | |
| | | if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | let _data = [] |
| | | if (nextProps.data && nextProps.data[config.dataName]) { |
| | | _data = nextProps.data[config.dataName] || [] |
| | | } |
| | | |
| | | this.setState({sync: false, data: _data}, () => { |
| | | this.handleData() |
| | | }) |
| | | } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { |
| | | this.setState({}, () => { |
| | | this.loadData() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | } |
| | | |
| | | componentDidMount () { |
| | | const { config } = this.state |
| | | |
| | | MKEmitter.addListener('reloadData', this.reloadData) |
| | | MKEmitter.addListener('resetSelectLine', this.resetParentParam) |
| | | MKEmitter.addListener('queryModuleParam', this.queryModuleParam) |
| | | MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) |
| | | this.handleTimer() |
| | | |
| | | if (config.setting.useMSearch) { |
| | | MKEmitter.addListener('searchRefresh', this.searchRefresh) |
| | | } |
| | | |
| | | if (config.setting.sync === 'true') { |
| | | MKEmitter.addListener('transferSyncData', this.transferSyncData) |
| | | } |
| | | |
| | | if (config.timer) { |
| | | this.timer = new TimerTask() |
| | | this.timer.init(config.uuid, config.timer, config.timerRepeats, () => { |
| | | this.loadData('timer') |
| | | }) |
| | | } |
| | | |
| | | this.initExec() |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | clearTimeout(this.timer) |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('reloadData', this.reloadData) |
| | | MKEmitter.removeListener('searchRefresh', this.searchRefresh) |
| | | MKEmitter.removeListener('resetSelectLine', this.resetParentParam) |
| | | MKEmitter.removeListener('transferSyncData', this.transferSyncData) |
| | | MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) |
| | | MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) |
| | | |
| | | this.timer && this.timer.stop() |
| | | } |
| | | |
| | | handleTimer = () => { |
| | | initExec = () => { |
| | | const { config, BID } = this.state |
| | | |
| | | if (config.$cache) { |
| | | if (config.$time) { |
| | | if (!this.loaded) { |
| | | Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => { |
| | | if (!res.valid && config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData('init') |
| | | }, config.setting.delay || 0) |
| | | } |
| | | |
| | | if (!res.data || this.loaded) return |
| | | |
| | | this.data = res.data |
| | | this.handleData() |
| | | }) |
| | | } else { |
| | | this.handleData() |
| | | } |
| | | } else { |
| | | if (!this.loaded) { |
| | | Api.getLCacheConfig(config.uuid, 0, BID).then(res => { |
| | | if (!res.data || this.loaded) return |
| | | |
| | | this.data = res.data |
| | | this.handleData() |
| | | }) |
| | | } |
| | | |
| | | if (config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData('init') |
| | | }, config.setting.delay || 0) |
| | | } else if (this.loaded) { |
| | | this.handleData() |
| | | } |
| | | } |
| | | } else if (config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | }, config.setting.delay || 0) |
| | | } else if (this.loaded) { |
| | | this.handleData() |
| | | } |
| | | } |
| | | |
| | | transferSyncData = (syncId) => { |
| | | const { config, BID } = this.state |
| | | |
| | | if (config.$syncId !== syncId) return |
| | | |
| | | let _data = window.GLOB.SyncData.get(config.dataName) || [] |
| | | |
| | | if (config.$cache) { |
| | | Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID) |
| | | } |
| | | |
| | | this.data = _data |
| | | this.handleData() |
| | | |
| | | this.loaded = true |
| | | |
| | | window.GLOB.SyncData.delete(config.dataName) |
| | | |
| | | MKEmitter.removeListener('transferSyncData', this.transferSyncData) |
| | | } |
| | | |
| | | searchRefresh = (searchId) => { |
| | | const { config } = this.state |
| | | |
| | | if (!config.timer) return |
| | | |
| | | const _change = { '5s': 5000, '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } |
| | | |
| | | let timer = _change[config.timer] |
| | | |
| | | if (!timer) return |
| | | |
| | | let _param = { |
| | | func: 's_get_timers_role', |
| | | LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`, |
| | | timer_type: config.timer, |
| | | component_id: config.uuid |
| | | } |
| | | if (config.$searchId !== searchId) return |
| | | |
| | | _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') // 时间戳 |
| | | _param.LText = Utils.formatOptions(_param.LText) // 关键字符替换,base64加密 |
| | | _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) // md5密钥 |
| | | |
| | | Api.getSystemConfig(_param).then(result => { |
| | | if (!result.status) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (result.run_type) { |
| | | let repeats = config.timerRepeats || 0 |
| | | this.setState({timer, repeats}) |
| | | this.timer = setTimeout(() => { |
| | | this.timerTask(repeats) |
| | | }, timer) |
| | | } |
| | | this.setState({}, () => { |
| | | this.loadData() |
| | | }) |
| | | } |
| | | |
| | | timerTask = (times) => { |
| | | const { timer, repeats } = this.state |
| | | if (!timer) return |
| | | |
| | | this.loadData(true) |
| | | |
| | | if (repeats) { |
| | | times = times - 1 |
| | | if (times <= 0) { |
| | | clearTimeout(this.timer) |
| | | return |
| | | } |
| | | } |
| | | this.timer = setTimeout(() => { |
| | | this.timerTask(times) |
| | | }, timer) |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | if (config.uuid !== menuId) return |
| | | |
| | | if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件 |
| | | MKEmitter.emit('reloadData', config.setting.supModule, BID) |
| | | if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) { |
| | | MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID) |
| | | } else { |
| | | this.loadData() |
| | | } |
| | | |
| | | if (position === 'popclose') { // 执行启动弹窗的按钮所选择的刷新项 |
| | | btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId) |
| | | } |
| | | } |
| | | |
| | |
| | | /** |
| | | * @description 导出Excel时,获取页面搜索排序等参数 |
| | | */ |
| | | queryModuleParam = (menuId, btnId) => { |
| | | const { mainSearch } = this.props |
| | | const { arr_field, config, search } = this.state |
| | | queryModuleParam = (menuId, callback) => { |
| | | const { config, search } = this.state |
| | | |
| | | if (config.uuid !== menuId) return |
| | | |
| | | let searches = search ? fromJS(search).toJS() : [] |
| | | if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 主表搜索条件 |
| | | let keys = searches.map(item => item.key.toLowerCase()) |
| | | if (config.setting.useMSearch) { // 主表搜索条件 |
| | | let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || [] |
| | | let keys = config.$s_keys || [] |
| | | mainSearch.forEach(item => { |
| | | if (!keys.includes(item.key.toLowerCase())) { |
| | | searches.push(item) |
| | | } |
| | | if (keys.includes(item.key.toLowerCase())) return |
| | | |
| | | searches.push(item) |
| | | }) |
| | | } |
| | | |
| | | MKEmitter.emit('returnModuleParam', config.uuid, btnId, { |
| | | arr_field: arr_field, |
| | | callback({ |
| | | orderBy: config.setting.order || '', |
| | | search: searches, |
| | | menuName: config.name |
| | |
| | | /** |
| | | * @description 数据加载 |
| | | */ |
| | | async loadData (hastimer) { |
| | | const { mainSearch } = this.props |
| | | const { config, arr_field, BID, search } = this.state |
| | | async loadData (type) { |
| | | const { config, BID, search } = this.state |
| | | |
| | | if (config.setting.supModule && !BID) { // BID 不存在时,不做查询 |
| | | this.setState({ |
| | | data: [] |
| | | }, () => { |
| | | if (!is(fromJS(this.data), fromJS([]))) { |
| | | this.data = [] |
| | | this.handleData() |
| | | }) |
| | | } |
| | | this.loaded = true |
| | | return |
| | | } |
| | | |
| | | let searches = search ? fromJS(search).toJS() : [] |
| | | if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 主表搜索条件 |
| | | let keys = searches.map(item => item.key) |
| | | if (config.setting.useMSearch) { // 主表搜索条件 |
| | | let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || [] |
| | | let keys = config.$s_keys || [] |
| | | mainSearch.forEach(item => { |
| | | if (!keys.includes(item.key)) { |
| | | searches.push(item) |
| | | } |
| | | if (keys.includes(item.key.toLowerCase())) return |
| | | |
| | | searches.push(item) |
| | | }) |
| | | } |
| | | |
| | | let requireFields = searches.filter(item => item.required && item.value === '') |
| | | if (requireFields.length > 0) { |
| | | if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) { |
| | | return |
| | | } |
| | | |
| | | if (!hastimer) { |
| | | if (type !== 'timer') { |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | } |
| | | |
| | | let _orderBy = config.setting.order || '' |
| | | let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID) |
| | | let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID) |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | let reset = true |
| | | |
| | | if (hastimer && is(fromJS(result.data), fromJS(this.state.data))) { |
| | | reset = false |
| | | if (config.$cache && type === 'init') { |
| | | Api.writeCacheConfig(config.uuid, result.data || [], BID) |
| | | } |
| | | |
| | | this.loaded = true |
| | | |
| | | this.setState({ |
| | | data: result.data, |
| | | loading: false |
| | | }, () => { |
| | | if (!reset) return |
| | | this.handleData() |
| | | }) |
| | | |
| | | if (!is(fromJS(this.data), fromJS(result.data || []))) { |
| | | this.data = result.data || [] |
| | | this.handleData() |
| | | } |
| | | |
| | | if (config.timer && config.clearField && result.data && result.data[0]) { |
| | | let vals = (config.clearValue || '').split(',') |
| | | if (vals.includes(result.data[0][config.clearField])) { |
| | | this.timer && this.timer.stop() |
| | | } |
| | | } |
| | | |
| | | UtilsDM.querySuccess(result) |
| | | } else { |
| | | this.setState({ |
| | | loading: false, |
| | | timer: null |
| | | loading: false |
| | | }) |
| | | notification.error({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 10 |
| | | }) |
| | | this.timer && this.timer.stop() |
| | | |
| | | UtilsDM.queryFail(result) |
| | | } |
| | | } |
| | | |
| | |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 100) |
| | | } |
| | | |
| | | /** |
| | | * @description 图表数据预处理 |
| | | * 1、通过显示列进行数据类型转换 |
| | | * 2、重复数据:取平均值、累计、去重 |
| | | * 3、柱状图数据补齐 |
| | | */ |
| | | getdata = () => { |
| | | const { data, plot, vFields, config } = this.state |
| | | const { plot, vFields, config } = this.state |
| | | |
| | | if (!data || data.length === 0) { |
| | | if (this.data.length === 0) { |
| | | this.setState({empty: true}) |
| | | return [] |
| | | } else { |
| | | this.setState({empty: false}) |
| | | } |
| | | |
| | | let _data = [] |
| | | let _cdata = fromJS(data).toJS() |
| | | return fromJS(this.data).toJS().map(item => { |
| | | // dodge is not support linear attribute, please use category attribute! 时间格式 |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } else { |
| | | item[plot.Xaxis] = '' + item[plot.Xaxis] |
| | | } |
| | | |
| | | if (plot.repeat === 'average') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.Xaxis] && item[plot.Xaxis] !== 0) return |
| | | |
| | | 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 |
| | | } |
| | | 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.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | }) |
| | | |
| | | // dodge is not support linear attribute, please use category attribute! 时间格式 |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } else { |
| | | item[plot.Xaxis] = '' + item[plot.Xaxis] |
| | | } |
| | | if (col.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | |
| | | if (!_mdata.has(item[plot.Xaxis])) { |
| | | item.$count = 1 |
| | | _mdata.set(item[plot.Xaxis], item) |
| | | } else { |
| | | let _item = _mdata.get(item[plot.Xaxis]) |
| | | _item.$count++ |
| | | vFields.forEach(col => { |
| | | _item[col.field] += item[col.field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | | item[col.field] = +item[col.field] |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | 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] |
| | | }) |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | return item |
| | | }) |
| | | } else if (plot.repeat === 'cumsum') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.Xaxis] && item[plot.Xaxis] !== 0) return |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | |
| | | 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.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | }) |
| | | |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } else { |
| | | item[plot.Xaxis] = '' + item[plot.Xaxis] |
| | | } |
| | | |
| | | if (!_mdata.has(item[plot.Xaxis])) { |
| | | _mdata.set(item[plot.Xaxis], item) |
| | | } else { |
| | | let _item = _mdata.get(item[plot.Xaxis]) |
| | | vFields.forEach(col => { |
| | | _item[col.field] += item[col.field] |
| | | }) |
| | | _mdata.set(item[plot.Xaxis], _item) |
| | | } |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | _data = _data.map(item => { |
| | | vFields.forEach(col => { |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | | item[col.field] = +item[col.field] |
| | | }) |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | return item |
| | | }) |
| | | } else { // plot.repeat === 'unrepeat' |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.Xaxis] && item[plot.Xaxis] !== 0) return |
| | | |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } else { |
| | | item[plot.Xaxis] = '' + item[plot.Xaxis] |
| | | } |
| | | |
| | | if (!_mdata.has(item[plot.Xaxis])) { |
| | | 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.show === 'percent') { |
| | | item[col.field] = item[col.field] * 100 |
| | | } |
| | | item[col.field] = item[col.field].toFixed(col.decimal) |
| | | item[col.field] = +item[col.field] |
| | | }) |
| | | |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | _mdata.set(item[plot.Xaxis], item) |
| | | } |
| | | }) |
| | | |
| | | _data = [..._mdata.values()] |
| | | } |
| | | |
| | | this.setState({empty: _data.length === 0}) |
| | | return _data |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 统计数据预处理 |
| | | */ |
| | | getStaticMsg = () => { |
| | | const { plot, vstFields, data } = this.state |
| | | const { plot, vstFields } = this.state |
| | | |
| | | let percent = false |
| | | let decimal = vstFields ? vstFields.decimal : 0 |
| | | |
| | | if (plot.show === 'percent') { |
| | | percent = true |
| | | } |
| | | |
| | | if (!data || data.length === 0) { |
| | | if (this.data.length === 0) { |
| | | this.setState({empty: true}) |
| | | return [] |
| | | } else { |
| | | this.setState({empty: false}) |
| | | } |
| | | |
| | | let _data = [] |
| | | let _cdata = fromJS(data).toJS() |
| | | let decimal = vstFields ? vstFields.decimal : 0 |
| | | |
| | | if (plot.repeat === 'average') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | return fromJS(this.data).toJS().map(item => { |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } |
| | | |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(item[plot.InfoValue]) |
| | | if (isNaN(item[plot.InfoValue])) { |
| | | item[plot.InfoValue] = 0 |
| | | } |
| | | } |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(item[plot.InfoValue]) |
| | | if (isNaN(item[plot.InfoValue])) { |
| | | item[plot.InfoValue] = 0 |
| | | } |
| | | } |
| | | if (percent) { |
| | | item[plot.InfoValue] = item[plot.InfoValue] * 100 |
| | | } |
| | | if (plot.show === '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) |
| | | } |
| | | }) |
| | | item[plot.InfoValue] = item[plot.InfoValue].toFixed(decimal) |
| | | item[plot.InfoValue] = +item[plot.InfoValue] |
| | | |
| | | _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 |
| | | |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(item[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 |
| | | |
| | | if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { |
| | | item[plot.Xaxis] = ' ' + item[plot.Xaxis] |
| | | } |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | | if (!_mdata.has(item.$uuid)) { |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | | item[plot.InfoValue] = parseFloat(item[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()] |
| | | } |
| | | |
| | | this.setState({empty: _data.length === 0}) |
| | | |
| | | return _data |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | /** |
| | |
| | | const chart = new Chart({ |
| | | container: this.state.chartId, |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25 |
| | | height: plot.height |
| | | }) |
| | | |
| | | chart.data(_data) |
| | |
| | | chart.axis(plot.Xaxis, plot.$xc) |
| | | chart.axis(_valfield, plot.$yc) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .shape(plot.shape || 'smooth') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label(_valfield, (value) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | return null |
| | | } |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | style: { |
| | | fill: plot.color |
| | | } |
| | |
| | | */ |
| | | customrender = (data) => { |
| | | const { plot, transfield } = this.state |
| | | |
| | | let max = 0 |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | data.forEach(item => { |
| | | if (plot.zoomFields) { |
| | | plot.zoomFields.forEach(f => { |
| | | if (item[f] > max) { |
| | | max = item[f] |
| | | } |
| | | }) |
| | | let sum = 0 |
| | | plot.Bar_axis.forEach(f => { |
| | | sum += item[f] |
| | | }) |
| | | if (sum > max) { |
| | | max = sum |
| | | } |
| | | } else { |
| | | plot.Yaxis.forEach(f => { |
| | | if (item[f] > max) { |
| | | max = item[f] |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | if (!isNaN(max)) { |
| | | max = Math.ceil(max) |
| | | let s = max > 10 ? Math.pow(10, (max + '').length - 2) : 1 |
| | | max = Math.ceil(max / s) * s |
| | | } else { |
| | | max = 0 |
| | | } |
| | | } |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | |
| | | const chart = new Chart({ |
| | | container: this.state.chartId, |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25 |
| | | height: plot.height |
| | | }) |
| | | |
| | | // 坐标轴格式化 |
| | |
| | | }) |
| | | } |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (plot.min || plot.min === 0) { |
| | | c.min = plot.min |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (plot.min || plot.min === 0) { |
| | | c.min = plot.min |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | c.min = c.min || 0 |
| | | } |
| | | } |
| | | view1.scale('value', c) |
| | | view1.axis('value', plot.$yc) |
| | | |
| | | view1.legend(false) |
| | | if (plot.legend) { |
| | | view1.legend(false) |
| | | } |
| | | |
| | | let colorIndex = 0 |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | if (plot.mutilBar !== 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: key, |
| | | value: value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | if (plot.$label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | if (plot.$label !== 'true' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | if (plot.$label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | lablecfg.style.fill = plot.$colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (plot.adjust === 'stack') { |
| | | } else if (plot.mutilBar === 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | if (plot.$label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | if (plot.$label !== 'true' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | if (plot.$label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | lablecfg.style.fill = plot.$colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | |
| | | } |
| | | |
| | | view2.data(dv.rows) |
| | | view2.legend(false) |
| | | |
| | | if (plot.legend && plot.Bar_axis) { |
| | | view2.legend(false) |
| | | } |
| | | |
| | | plot.customs.forEach(item => { |
| | | if (item.chartType === 'bar' && !plot.Bar_axis) { |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | } |
| | | } |
| | | |
| | | view2.scale(item.name, c) |
| | |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: item.name, |
| | | value: item.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | if (plot.label !== 'true' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && item.color) { |
| | | lablecfg.style.fill = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | } |
| | | } |
| | | |
| | | view2.scale(item.name, c) |
| | |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | return { |
| | | name: item.name, |
| | | value: item.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | | if (item.label === 'true') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | return null |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | |
| | | if (item.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | style: { |
| | | fill: plot.color |
| | | } |
| | |
| | | let _valfield = 'value' |
| | | let _typefield = 'key' |
| | | let colorIndex = 0 |
| | | let barcolors = {} |
| | | |
| | | if (plot.datatype === 'statistics') { |
| | | _valfield = plot.InfoValue |
| | |
| | | if (plot.enabled === 'true') { |
| | | this.customrender(data) |
| | | return |
| | | } |
| | | |
| | | if (plot.barcolors && plot.barcolors.length > 0 && plot.Yaxis.length === 1) { |
| | | data.forEach((item, i) => { |
| | | if (plot.barcolors[i]) { |
| | | barcolors[item[plot.Xaxis]] = plot.barcolors[i].color |
| | | } |
| | | }) |
| | | } else { |
| | | barcolors = null |
| | | } |
| | | |
| | | const ds = new DataSet() |
| | |
| | | const chart = new Chart({ |
| | | container: this.state.chartId, |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25 |
| | | height: plot.height |
| | | }) |
| | | |
| | | chart.data(_data) |
| | |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | c.min = c.min || 0 |
| | | } |
| | | chart.scale(_valfield, c) |
| | | |
| | | chart.axis(plot.Xaxis, plot.$xc) |
| | | chart.axis(_valfield, plot.$yc) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | | if (plot.$colors) { |
| | | let limit = chartColors.length |
| | | _chart.color(_typefield, (key) => { |
| | | if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | |
| | | if (barcolors) { |
| | | _chart.color(`${_typefield}*${plot.Xaxis}`, (key, label) => { |
| | | if (barcolors[label]) { |
| | | return barcolors[label] |
| | | } else if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color(`${_typefield}`, (key) => { |
| | | if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } |
| | | } else { |
| | | _chart.color(_typefield) |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label(`${_valfield}*${_typefield}`, (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | if (plot.label !== 'true' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | | if (plot.$colors) { |
| | | let limit = chartColors.length |
| | | _chart.color(_typefield, (key) => { |
| | | if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | if (barcolors) { |
| | | _chart.color(`${_typefield}*${plot.Xaxis}`, (key, label) => { |
| | | if (barcolors[label]) { |
| | | return barcolors[label] |
| | | } else if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color(`${_typefield}`, (key) => { |
| | | if (plot.$colors.has(key)) { |
| | | return plot.$colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } |
| | | } else { |
| | | _chart.color(_typefield) |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label(`${_valfield}*${_typefield}`, (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | if (plot.label !== 'true' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.labelUnit) { |
| | | val = val + plot.labelUnit |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | |
| | | chart.on('element:click', (ev) => { |
| | | let data = ev.data.data |
| | | |
| | | MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data) |
| | | |
| | | if (plot.click === 'menus') { |
| | | let menu = null |
| | | |
| | | if (plot.menus && plot.menus.length > 0) { |
| | | let s = data[plot.menuType] || '' |
| | | let s = data[plot.menuType] + '' |
| | | plot.menus.forEach(m => { |
| | | if (s !== m.sign) return |
| | | menu = m |
| | |
| | | } |
| | | if (!menu || !menu.MenuID) return |
| | | |
| | | menu.type = menu.tabType |
| | | |
| | | let newtab = { |
| | | ...menu, |
| | | MenuID: menu.MenuID, |
| | | MenuName: menu.MenuName, |
| | | MenuNo: menu.MenuNo || '', |
| | | type: menu.tabType, |
| | | param: {} |
| | | } |
| | | |
| | | if (plot.joint === 'true') { |
| | | newtab.param.$BID = data.$$uuid || '' |
| | | |
| | | Object.keys(data).forEach(key => { |
| | | if (/^\$/.test(key)) return |
| | | newtab.param[key] = data[key] |
| | | }) |
| | | } |
| | | |
| | | if (['linkage_navigation', 'linkage', 'menu_board'].includes(window.GLOB.navBar)) { |
| | | MKEmitter.emit('modifyTabs', newtab, 'replace') |
| | | } else { |
| | | MKEmitter.emit('modifyTabs', newtab, 'plus', true) |
| | | MKEmitter.emit('modifyTabs', newtab, true) |
| | | } else if (plot.click === 'menu') { |
| | | let menuId = plot.menu.slice(-1)[0] |
| | | let menu = null |
| | | |
| | | if (window.GLOB.mkThdMenus.has(menuId)) { |
| | | menu = {...window.GLOB.mkThdMenus.get(menuId)} |
| | | } else if (plot.MenuID) { |
| | | menu = { |
| | | MenuID: plot.MenuID, |
| | | MenuName: plot.MenuName, |
| | | type: plot.tabType |
| | | } |
| | | } |
| | | } else if (plot.click === 'menu' && plot.MenuID) { |
| | | let menu = { |
| | | MenuID: plot.MenuID, |
| | | MenuName: plot.MenuName, |
| | | MenuNo: plot.MenuNo, |
| | | type: plot.tabType |
| | | } |
| | | |
| | | if (!menu) return |
| | | |
| | | let newtab = { |
| | | ...menu, |
| | | param: {} |
| | | } |
| | | menu.param = {} |
| | | |
| | | if (plot.joint === 'true') { |
| | | newtab.param.$BID = data.$$uuid || '' |
| | | menu.param.$BID = data.$$uuid || '' |
| | | |
| | | Object.keys(data).forEach(key => { |
| | | if (/^\$/.test(key)) return |
| | | menu.param[key] = data[key] |
| | | }) |
| | | } |
| | | |
| | | if (['linkage_navigation', 'linkage', 'menu_board'].includes(window.GLOB.navBar)) { |
| | | MKEmitter.emit('modifyTabs', newtab, 'replace') |
| | | } else { |
| | | MKEmitter.emit('modifyTabs', newtab, 'plus', true) |
| | | } |
| | | MKEmitter.emit('modifyTabs', menu, true) |
| | | } else { |
| | | MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data) |
| | | } |
| | | }) |
| | | |
| | |
| | | </div> : null |
| | | } |
| | | <NormalHeader config={config} BID={BID} refresh={this.refreshSearch} /> |
| | | <div className="canvas-wrap" ref={ref => this.wrap = ref}> |
| | | <div className="canvas-wrap"> |
| | | {config.plot.download === 'enable' && this.state.chart && !empty ? <DownloadOutlined onClick={this.downloadImage} className="system-color download"/> : null} |
| | | <div className={'chart-action' + (config.plot.download === 'enable' ? ' downable' : '')}> |
| | | {config.action.map(item => { |