| | |
| | | import { is, fromJS } from 'immutable' |
| | | import { Chart } from '@antv/g2' |
| | | import { Spin, Empty, notification } from 'antd' |
| | | import { DownloadOutlined } from '@ant-design/icons' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncBtnComponent from './asyncButtonComponent' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import NormalHeader from '@/tabviews/custom/components/share/normalheader' |
| | | import './index.scss' |
| | | |
| | | const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) |
| | | const ExcelOutButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) |
| | | const ExcelInButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/excelInbutton')) |
| | | |
| | |
| | | plot: null, // 图表设置 |
| | | data: null, // 数据 |
| | | search: null, // 搜索条件 |
| | | chart: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | _sync = false |
| | | } |
| | | |
| | | let height = config.plot.height || 400 |
| | | if (config.plot.title || config.search.length > 0) { |
| | | _config.plot.height = height - 70 |
| | | } else { |
| | | _config.plot.height = height - 25 |
| | | } |
| | | |
| | | _config.style.height = height |
| | | _config.style.height = config.plot.height || 400 |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | |
| | | search: Utils.initMainSearch(config.search), |
| | | }, () => { |
| | | if (config.setting.sync !== 'true' && config.setting.onload === 'true') { |
| | | this.loadData() |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | }, _config.setting.delay || 0) |
| | | } else if (config.setting.sync === 'true' && _data) { |
| | | this.handleData() |
| | | } |
| | |
| | | |
| | | if (!config.timer) return |
| | | |
| | | const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } |
| | | 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 (config.uuid !== menuId) return |
| | | |
| | | this.loadData() // 数据刷新 |
| | | let supModule = config.setting.supModule |
| | | |
| | | if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== config.setting.supModule) { |
| | | MKEmitter.emit('reloadData', btn.syncComponentId) // 同级标签刷新 |
| | | btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId) |
| | | |
| | | if (!btn.syncComponentId || btn.syncComponentId !== supModule) { |
| | | if (position === 'mainline' || position === 'popclose') { // 刷新源组件时,附带刷新上级行与当前组件 |
| | | if (supModule && BID) { |
| | | MKEmitter.emit('reloadData', supModule, BID) |
| | | } else { |
| | | this.loadData() |
| | | } |
| | | } else { |
| | | this.loadData() |
| | | } |
| | | } |
| | | |
| | | if (position === 'mainline' && config.setting.supModule) { // 主表行刷新 |
| | | MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty')) |
| | | if (position === 'popclose') { // 执行启动弹窗的按钮所选择的刷新项 |
| | | btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId) |
| | | } |
| | | } |
| | | |
| | |
| | | const { config } = this.state |
| | | |
| | | if (!config.setting.supModule || config.setting.supModule !== MenuID) return |
| | | if (id !== this.state.BID) { |
| | | if (id !== this.state.BID || id !== '') { |
| | | this.setState({ BID: id }, () => { |
| | | this.loadData() |
| | | }) |
| | |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | let reset = true |
| | | |
| | | if (hastimer && is(fromJS(result.data), fromJS(this.state.data))) { |
| | | reset = false |
| | | } |
| | | |
| | | this.setState({ |
| | | data: result.data, |
| | | empty: false, |
| | | loading: false |
| | | }, () => { |
| | | if (!reset) return |
| | | this.handleData() |
| | | }) |
| | | } else { |
| | |
| | | const chart = new Chart({ |
| | | container: chartId, |
| | | autoFit: true, |
| | | height: plot.height |
| | | height: this.wrap.offsetHeight - 25 |
| | | }) |
| | | |
| | | chart.data(data); |
| | |
| | | }) |
| | | } |
| | | chart.render() |
| | | |
| | | this.setState({chart}) |
| | | } |
| | | |
| | | refreshSearch = (list) => { |
| | |
| | | }) |
| | | } |
| | | |
| | | downloadImage = () => { |
| | | const { chart, config } = this.state |
| | | const link = document.createElement('a'); |
| | | const filename = `${config.name}${moment().format('YYYY-MM-DD HH_mm_ss')}.png`; |
| | | const canvas = chart.getCanvas(); |
| | | canvas.get('timeline').stopAllAnimations(); |
| | | |
| | | setTimeout(() => { |
| | | const canvas = chart.getCanvas(); |
| | | const canvasDom = canvas.get('el'); |
| | | const dataURL = canvasDom.toDataURL('image/png'); |
| | | |
| | | if (window.Blob && window.URL) { |
| | | const arr = dataURL.split(','); |
| | | const mime = arr[0].match(/:(.*?);/)[1]; |
| | | const bstr = atob(arr[1]); |
| | | let n = bstr.length; |
| | | const u8arr = new Uint8Array(n); |
| | | while (n--) { |
| | | u8arr[n] = bstr.charCodeAt(n); |
| | | } |
| | | const blobObj = new Blob([u8arr], { type: mime }); |
| | | if (window.navigator.msSaveBlob) { |
| | | window.navigator.msSaveBlob(blobObj, filename); |
| | | } else { |
| | | link.addEventListener('click', () => { |
| | | link.download = filename; |
| | | link.href = window.URL.createObjectURL(blobObj); |
| | | }); |
| | | } |
| | | } |
| | | const e = document.createEvent('MouseEvents'); |
| | | e.initEvent('click', false, false); |
| | | link.dispatchEvent(e); |
| | | }, 16); |
| | | } |
| | | |
| | | render() { |
| | | const { config, loading, empty, BID } = this.state |
| | | |
| | | let style = {...config.style} |
| | | if (empty && config.plot.empty === 'hidden') { |
| | | style.opacity = 0 |
| | | style.position = 'absolute' |
| | | style.zIndex = -1 |
| | | style.width = '100%' |
| | | } |
| | | |
| | | return ( |
| | | <div className="custom-scatter-plot-box" style={config.style}> |
| | | <div className="custom-scatter-plot-box" id={'anchor' + config.uuid} style={style}> |
| | | {loading ? |
| | | <div className="loading-mask"> |
| | | <div className="ant-spin-blur"></div> |
| | |
| | | </div> : null |
| | | } |
| | | <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} /> |
| | | <div className="canvas-wrap"> |
| | | <div className="chart-action"> |
| | | <div className="canvas-wrap" ref={ref => this.wrap = ref}> |
| | | {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 => { |
| | | if (item.OpenType === 'excelOut') { |
| | | return ( |
| | |
| | | } |
| | | })} |
| | | </div> |
| | | <div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 25}} id={this.state.chartId}></div> |
| | | <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div> |
| | | </div> |
| | | {empty ? <Empty description={false}/> : null} |
| | | </div> |