import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Chart } from '@antv/g2'
|
import { connect } from 'react-redux'
|
import DataSet, { DataView } from '@antv/data-set'
|
import { Spin, Empty, notification } from 'antd'
|
import moment from 'moment'
|
|
import Api from '@/api'
|
import Utils from '@/utils/utils.js'
|
import { modifyTabview } from '@/store/action'
|
import { chartColors } from '@/utils/option.js'
|
import asyncComponent from '@/utils/asyncComponent'
|
import UtilsDM from '@/utils/utils-datamanage.js'
|
import MKEmitter from '@/utils/events.js'
|
import './index.scss'
|
|
const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
|
|
class PieChart extends Component {
|
static propTpyes = {
|
BID: PropTypes.any, // 父级Id
|
data: PropTypes.array, // 统一查询数据
|
config: PropTypes.object, // 组件配置信息
|
mainSearch: PropTypes.any, // 外层搜索条件
|
menuType: PropTypes.any, // 菜单类型
|
}
|
|
state = {
|
BID: '', // 上级ID
|
config: null, // 图表配置信息
|
empty: true, // 图表数据为空
|
loading: false, // 数据加载状态
|
chartId: Utils.getuuid(), // 图表Id
|
title: '', // 组件标题
|
sync: false, // 是否统一请求数据
|
plot: null, // 图表设置
|
data: null, // 数据
|
search: null, // 搜索条件
|
}
|
|
UNSAFE_componentWillMount () {
|
const { config, data, initdata, BID } = this.props
|
let _config = fromJS(config).toJS()
|
|
let _data = null
|
let _sync = config.setting.sync === 'true'
|
|
if (config.setting.sync === 'true' && data) {
|
_data = data[config.dataName] || []
|
_sync = false
|
} else if (config.setting.sync === 'true' && initdata) {
|
_data = initdata || []
|
_sync = false
|
}
|
|
let height = config.plot.height || 400
|
if (config.plot.title || config.search.length > 0) {
|
_config.plot.height = height - 75
|
} else {
|
_config.plot.height = height - 30
|
}
|
|
_config.style.height = height
|
|
let decimal = 0
|
_config.columns.forEach(col => {
|
if (_config.plot.Yaxis === col.field && /Decimal/ig.test(col.datatype)) {
|
decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '')
|
}
|
})
|
|
_config.plot.$decimal = decimal
|
|
this.setState({
|
config: _config,
|
data: _data,
|
BID: BID || '',
|
arr_field: _config.columns.map(col => col.field).join(','),
|
plot: _config.plot,
|
sync: _sync,
|
title: config.plot.title,
|
search: Utils.initMainSearch(config.search)
|
}, () => {
|
if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
|
this.loadData()
|
} 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 (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
|
if (config.setting.syncRefresh === 'true') {
|
this.setState({}, () => {
|
this.loadData()
|
})
|
}
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
componentDidMount () {
|
MKEmitter.addListener('reloadData', this.reloadData)
|
MKEmitter.addListener('resetSelectLine', this.resetParentParam)
|
this.handleTimer()
|
}
|
|
/**
|
* @description 组件销毁,清除state更新,清除快捷键设置
|
*/
|
componentWillUnmount () {
|
clearTimeout(this.timer)
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('reloadData', this.reloadData)
|
MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
|
}
|
|
handleTimer = () => {
|
const { config } = this.state
|
|
if (!config.timer) return
|
|
const _change = { '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
|
}
|
|
_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) {
|
this.setState({timer})
|
this.timer = setTimeout(() => {
|
this.timerTask()
|
}, timer)
|
}
|
})
|
}
|
|
timerTask = () => {
|
const { timer } = this.state
|
if (!timer) return
|
|
this.loadData(true)
|
|
this.timer = setTimeout(() => {
|
this.timerTask()
|
}, timer)
|
}
|
|
reloadData = (menuId) => {
|
const { config } = this.state
|
|
if (config.uuid !== menuId) return
|
|
this.loadData()
|
}
|
|
resetParentParam = (MenuID, id) => {
|
const { config } = this.state
|
|
if (!config.setting.supModule || config.setting.supModule !== MenuID) return
|
if (id !== this.state.BID) {
|
this.setState({ BID: id }, () => {
|
this.loadData()
|
})
|
}
|
}
|
|
handleData = () => {
|
let _element = document.getElementById(this.state.chartId)
|
if (_element) {
|
_element.innerHTML = ''
|
}
|
this.pierender()
|
}
|
|
async loadData (hastimer) {
|
const { mainSearch, menuType } = this.props
|
const { config, arr_field, search, BID } = this.state
|
|
if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
|
this.setState({
|
data: []
|
}, () => {
|
this.handleData()
|
})
|
return
|
}
|
|
let searches = fromJS(search).toJS()
|
if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
|
let keys = searches.map(item => item.key)
|
mainSearch.forEach(item => {
|
if (!keys.includes(item.key)) {
|
searches.push(item)
|
}
|
})
|
}
|
|
let requireFields = searches.filter(item => item.required && (!item.value || item.value.length === 0))
|
if (requireFields.length > 0) {
|
this.setState({
|
loading: false
|
})
|
return
|
}
|
|
if (!hastimer) {
|
this.setState({
|
loading: true
|
})
|
}
|
|
let _orderBy = config.setting.order || ''
|
let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType)
|
|
let result = await Api.genericInterface(param)
|
if (result.status) {
|
this.setState({
|
data: result.data,
|
loading: false
|
}, () => {
|
this.handleData()
|
})
|
} else {
|
this.setState({
|
loading: false,
|
timer: null
|
})
|
notification.error({
|
top: 92,
|
message: result.message,
|
duration: 10
|
})
|
}
|
}
|
|
/**
|
* @description 图表数据预处理
|
* 1、通过显示列进行数据类型转换
|
* 2、重复数据:取平均值、累计、去重
|
* 3、柱状图数据补齐
|
*/
|
getdata = () => {
|
const { data, plot } = this.state
|
|
if (!data) {
|
this.setState({empty: true})
|
return []
|
}
|
|
let _data = []
|
let _cdata = fromJS(data).toJS()
|
|
if (plot.repeat === 'average') {
|
let _mdata = new Map()
|
_cdata.forEach(item => {
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
} else if (!item[plot.Xaxis]) {
|
return
|
}
|
|
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++
|
_item[plot.Yaxis] += item[plot.Yaxis]
|
_mdata.set(item[plot.Xaxis], _item)
|
}
|
})
|
|
_data = [..._mdata.values()]
|
_data = _data.map(item => {
|
item[plot.Yaxis] = item[plot.Yaxis] / item.$count
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
|
return item
|
})
|
} else if (plot.repeat === 'cumsum') {
|
let _mdata = new Map()
|
_cdata.forEach(item => {
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
} else if (!item[plot.Xaxis]) {
|
return
|
}
|
|
if (!_mdata.has(item[plot.Xaxis])) {
|
_mdata.set(item[plot.Xaxis], item)
|
} else {
|
let _item = _mdata.get(item[plot.Xaxis])
|
_item[plot.Yaxis] += item[plot.Yaxis]
|
_mdata.set(item[plot.Xaxis], _item)
|
}
|
})
|
|
_data = [..._mdata.values()]
|
_data = _data.map(item => {
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
return item
|
})
|
} else { // plot.repeat === 'unrepeat'
|
let _mdata = new Map()
|
_cdata.forEach(item => {
|
if (!item[plot.Xaxis] || _mdata.has(item[plot.Xaxis])) {
|
return
|
}
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
}
|
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
|
_mdata.set(item[plot.Xaxis], item)
|
})
|
|
_data = [..._mdata.values()]
|
}
|
|
this.setState({empty: _data.length === 0})
|
|
return _data
|
}
|
|
getnestdata = () => {
|
const { data, plot } = this.state
|
|
if (!data) {
|
this.setState({empty: true})
|
return []
|
}
|
|
let _data = []
|
let _cdata = fromJS(data).toJS()
|
|
if (plot.repeat === 'average') {
|
let _mdata = new Map()
|
let map = new Map()
|
let sort = 1
|
_cdata.forEach(item => {
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
} else if (!item[plot.Xaxis] || !item[plot.type]) {
|
return
|
}
|
|
let sign = item[plot.type] + item[plot.Xaxis]
|
|
if (!_mdata.has(sign)) {
|
let _sort = sort
|
if (map.has(item.type)) {
|
_sort = map.get(item.type)
|
} else {
|
map.set(item.type, _sort)
|
sort++
|
}
|
|
item.$count = 1
|
item.$sort = _sort
|
_mdata.set(sign, item)
|
} else {
|
let _item = _mdata.get(sign)
|
_item.$count++
|
_item[plot.Yaxis] += item[plot.Yaxis]
|
_mdata.set(sign, _item)
|
}
|
})
|
|
_data = [..._mdata.values()]
|
_data = _data.map(item => {
|
item[plot.Yaxis] = item[plot.Yaxis] / item.$count
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
|
return item
|
})
|
} else if (plot.repeat === 'cumsum') {
|
let _mdata = new Map()
|
let map = new Map()
|
let sort = 1
|
_cdata.forEach(item => {
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
} else if (!item[plot.Xaxis] || !item[plot.type]) {
|
return
|
}
|
|
let sign = item[plot.type] + item[plot.Xaxis]
|
|
if (!_mdata.has(sign)) {
|
let _sort = sort
|
if (map.has(item.type)) {
|
_sort = map.get(item.type)
|
} else {
|
map.set(item.type, _sort)
|
sort++
|
}
|
|
item.$sort = _sort
|
_mdata.set(sign, item)
|
} else {
|
let _item = _mdata.get(sign)
|
_item[plot.Yaxis] += item[plot.Yaxis]
|
_mdata.set(sign, _item)
|
}
|
})
|
|
_data = [..._mdata.values()]
|
_data = _data.map(item => {
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
return item
|
})
|
} else { // plot.repeat === 'unrepeat'
|
let _mdata = new Map()
|
let map = new Map()
|
let sort = 1
|
_cdata.forEach(item => {
|
let sign = item[plot.type] + item[plot.Xaxis]
|
if (!item[plot.Xaxis] || !item[plot.type] || _mdata.has(sign)) {
|
return
|
}
|
|
if (typeof(item[plot.Yaxis]) !== 'number') {
|
item[plot.Yaxis] = parseFloat(item[plot.Yaxis])
|
if (isNaN(item[plot.Yaxis])) {
|
return
|
}
|
}
|
|
let _sort = sort
|
if (map.has(item.type)) {
|
_sort = map.get(item.type)
|
} else {
|
map.set(item.type, _sort)
|
sort++
|
}
|
|
item.$sort = _sort
|
item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal)
|
|
_mdata.set(sign, item)
|
})
|
|
_data = [..._mdata.values()]
|
}
|
|
this.setState({empty: _data.length === 0})
|
|
return _data
|
}
|
|
nestrender = () => {
|
const { plot, chartId } = this.state
|
|
let X_axis = plot.Xaxis
|
let Y_axis = plot.Yaxis
|
let type = plot.type
|
let color = plot.color
|
|
let _data = this.getnestdata()
|
|
const dvx = new DataView().source(_data)
|
|
dvx.transform({
|
type: 'sort-by',
|
fields: ['$sort']
|
})
|
|
let data = dvx.rows
|
|
// 通过 DataSet 计算百分比
|
const dv = new DataView()
|
dv.source(data).transform({
|
type: 'percent',
|
field: Y_axis,
|
dimension: type,
|
as: '$percent'
|
})
|
|
const dv1 = new DataView()
|
dv1.source(data).transform({
|
type: 'percent',
|
field: Y_axis,
|
dimension: X_axis,
|
as: '$percent',
|
})
|
|
const chart = new Chart({
|
container: chartId,
|
autoFit: true,
|
height: plot.height,
|
padding: 0,
|
})
|
|
chart.data(dv.rows)
|
|
if (plot.show !== 'value') {
|
chart.scale('percent', {
|
formatter: (val) => {
|
val = val * 100 + '%'
|
return val
|
}
|
})
|
|
Y_axis = '$percent'
|
}
|
let radius = plot.radius / 100
|
let innerRadius = plot.innerRadius / 100
|
|
chart.coordinate('theta', {
|
innerRadius: innerRadius,
|
radius: innerRadius + (radius - innerRadius) / 2,
|
})
|
chart.tooltip({
|
showTitle: false,
|
showMarkers: false,
|
})
|
chart.legend(false)
|
let chart1 = chart
|
.interval()
|
.adjust('stack')
|
.position(Y_axis)
|
.color(type)
|
.tooltip(`${type}*${Y_axis}`, (type, percent) => {
|
if (plot.show !== 'value') {
|
percent = (percent * 100).toFixed(2) + '%'
|
}
|
return {
|
name: type,
|
value: percent,
|
}
|
})
|
.style({
|
lineWidth: 1,
|
stroke: '#fff',
|
})
|
|
if (plot.label !== 'false') {
|
chart1.label(type, {
|
offset: -10,
|
})
|
}
|
|
const outterView = chart.createView()
|
|
outterView.data(dv1.rows)
|
|
if (plot.show !== 'value') {
|
outterView.scale('percent', {
|
formatter: (val) => {
|
val = val * 100 + '%'
|
return val
|
}
|
})
|
}
|
outterView.coordinate('theta', {
|
innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius,
|
radius: radius
|
})
|
let chart2 = outterView
|
.interval()
|
.adjust('stack')
|
.position(Y_axis)
|
.color(X_axis)
|
.tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
|
if (plot.show !== 'value') {
|
value = (value * 100).toFixed(2) + '%'
|
}
|
return {
|
name: name,
|
value: value
|
}
|
})
|
.style({
|
lineWidth: 1,
|
stroke: '#fff',
|
})
|
|
if (plot.label !== 'false') {
|
if (plot.label === 'inner') {
|
chart2.label(Y_axis, {
|
offset: -30,
|
content: (data) => {
|
let _label = ''
|
let _val = ''
|
if (plot.show !== 'value') {
|
_val = `${(data[Y_axis] * 100).toFixed(2)}%`
|
} else {
|
_val = `${data[Y_axis]}`
|
}
|
if (plot.label === 'inner') {
|
_label = _val
|
} else {
|
_label = `${data[X_axis]}: ${_val}`
|
}
|
return _label
|
},
|
style: {
|
textAlign: 'center',
|
fontSize: 16,
|
shadowBlur: 2,
|
shadowColor: 'rgba(0, 0, 0, .45)',
|
fill: '#fff',
|
}
|
})
|
} else {
|
chart2.label(Y_axis, {
|
layout: { type: 'pie-spider' },
|
labelHeight: 20,
|
content: (data) => {
|
let _label = ''
|
let _val = ''
|
if (plot.show !== 'value') {
|
_val = `${(data[Y_axis] * 100).toFixed(2)}%`
|
} else {
|
_val = `${data[Y_axis]}`
|
}
|
if (plot.label === 'inner') {
|
_label = _val
|
} else {
|
_label = `${data[X_axis]}: ${_val}`
|
}
|
return _label
|
},
|
labelLine: {
|
style: {
|
lineWidth: 0.5,
|
},
|
},
|
style: {
|
fill: color
|
}
|
})
|
}
|
}
|
|
chart.interaction('element-highlight')
|
|
chart.render()
|
}
|
|
/**
|
* @description 饼图渲染
|
*/
|
pierender = () => {
|
const { plot, chartId } = this.state
|
|
if (plot.shape === 'nest') {
|
this.nestrender()
|
return
|
}
|
|
let color = plot.color
|
|
let X_axis = plot.Xaxis
|
let Y_axis = plot.Yaxis
|
|
let data = this.getdata()
|
|
const ds = new DataSet()
|
const dv = ds.createView().source(data)
|
|
const chart = new Chart({
|
container: chartId,
|
autoFit: true,
|
height: plot.height
|
})
|
|
if (plot.shape !== 'nightingale' && plot.show !== 'value') {
|
dv.transform({
|
type: 'percent',
|
field: Y_axis,
|
dimension: X_axis,
|
as: 'percent'
|
})
|
|
chart.scale('percent', {
|
formatter: (val) => {
|
val = val * 100 + '%'
|
return val
|
}
|
})
|
|
Y_axis = 'percent' // 显示百分比
|
}
|
|
chart.data(dv.rows)
|
|
if (plot.shape === 'nightingale') {
|
chart.coordinate('polar', {
|
innerRadius: plot.innerRadius ? (plot.innerRadius / 100) : 0,
|
radius: plot.radius ? (plot.radius / 100) : 0.75,
|
})
|
} else {
|
chart.coordinate('theta', {
|
innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
|
radius: plot.radius ? (plot.radius / 100) : 0.75,
|
})
|
}
|
|
if (!plot.legend || plot.legend === 'hidden') {
|
chart.legend(false)
|
} else if (plot.shape === 'nightingale') {
|
chart.legend(X_axis, {
|
position: plot.legend,
|
itemName: {
|
style: { fill: color }
|
}
|
})
|
} else {
|
chart.legend({
|
position: plot.legend,
|
itemName: {
|
style: { fill: color }
|
}
|
})
|
}
|
|
if (plot.tooltip !== 'true') {
|
chart.tooltip(false)
|
} else {
|
chart.tooltip({
|
showTitle: false,
|
showMarkers: false
|
})
|
}
|
|
let colors = new Map()
|
let colorIndex = 0
|
|
if (plot.colors && plot.colors.length > 0) {
|
plot.colors.forEach(item => {
|
if (!colors.has(item.label)) {
|
colors.set(item.label, item.color)
|
}
|
})
|
}
|
|
if (plot.shape !== 'nightingale') {
|
let _chart = chart
|
.interval()
|
.adjust('stack')
|
.position(Y_axis)
|
.tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
|
if (plot.show !== 'value') {
|
value = (value * 100).toFixed(2) + '%'
|
}
|
return {
|
name: name,
|
value: value
|
}
|
})
|
if (plot.colors && plot.colors.length > 0) {
|
let limit = chartColors.length
|
_chart.color(X_axis, (type) => {
|
if (colors.get(type)) {
|
return colors.get(type)
|
} else {
|
colors.set(type, chartColors[colorIndex % limit])
|
colorIndex++
|
}
|
})
|
} else {
|
_chart.color(X_axis)
|
}
|
if (plot.label !== 'false') {
|
if (plot.label === 'inner') {
|
_chart.label(Y_axis, {
|
offset: -30,
|
content: (data) => {
|
let _val = ''
|
if (plot.show !== 'value') {
|
_val = `${(data[Y_axis] * 100).toFixed(2)}%`
|
} else {
|
_val = `${data[Y_axis]}`
|
}
|
return _val
|
},
|
style: {
|
textAlign: 'center',
|
fontSize: 16,
|
shadowBlur: 2,
|
shadowColor: 'rgba(0, 0, 0, .45)',
|
fill: '#fff',
|
}
|
})
|
} else {
|
_chart.label(Y_axis, {
|
layout: { type: 'pie-spider' },
|
labelHeight: 20,
|
content: (data) => {
|
let _val = ''
|
if (plot.show !== 'value') {
|
_val = `${(data[Y_axis] * 100).toFixed(2)}%`
|
} else {
|
_val = `${data[Y_axis]}`
|
}
|
|
return `${data[X_axis]}: ${_val}`
|
},
|
labelLine: {
|
style: {
|
lineWidth: 0.5,
|
},
|
},
|
style: {
|
fill: color
|
}
|
})
|
}
|
}
|
chart.interaction('element-active')
|
} else {
|
chart.axis(false)
|
chart.interaction('element-highlight')
|
let _chart = chart
|
.interval()
|
.position(`${X_axis}*${Y_axis}`)
|
|
if (plot.colors && plot.colors.length > 0) {
|
let limit = chartColors.length
|
_chart.color(X_axis, (type) => {
|
if (colors.get(type)) {
|
return colors.get(type)
|
} else {
|
colors.set(type, chartColors[colorIndex % limit])
|
colorIndex++
|
}
|
})
|
} else {
|
_chart.color(X_axis)
|
}
|
if (plot.label !== 'false') {
|
let _label = {}
|
if (plot.label === 'inner') {
|
_label.offset = -15
|
} else {
|
_label.style = {
|
fill: color
|
}
|
}
|
|
_chart.label(X_axis, _label)
|
.style({
|
lineWidth: 1,
|
stroke: '#fff',
|
})
|
}
|
}
|
|
if (plot.linkmenu && plot.linkmenu.length > 0) {
|
let menu_id = plot.linkmenu.slice(-1)[0]
|
let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
|
|
chart.on('element:dblclick', (ev) => {
|
if (!menu) {
|
notification.warning({
|
top: 92,
|
message: '菜单已删除或没有访问权限!',
|
duration: 5
|
})
|
return
|
}
|
|
try {
|
let data = ev.data.data
|
let primaryId = ''
|
if (this.state.config.setting.primaryKey && data) {
|
primaryId = data[this.state.config.setting.primaryKey] || ''
|
}
|
|
let newtab = {
|
...menu,
|
selected: true,
|
param: {
|
$BID: primaryId
|
}
|
}
|
|
let tabs = this.props.tabviews.filter(tab => {
|
tab.selected = false
|
return tab.MenuID !== newtab.MenuID
|
})
|
|
if (this.props.tabviews.length > tabs.length) {
|
this.props.modifyTabview(fromJS(tabs).toJS())
|
}
|
|
this.setState({}, () => {
|
tabs.push(newtab)
|
this.props.modifyTabview(tabs)
|
})
|
} catch {
|
console.warn('菜单打开失败!')
|
}
|
})
|
}
|
|
chart.render()
|
}
|
|
refreshSearch = (list) => {
|
this.setState({search: list}, () => {
|
this.loadData()
|
})
|
}
|
|
render() {
|
const { config, loading, empty, BID } = this.state
|
|
return (
|
<div className="custom-pie-chart-plot-box" style={config.style}>
|
{loading ?
|
<div className="loading-mask">
|
<div className="ant-spin-blur"></div>
|
<Spin />
|
</div> : null
|
}
|
<NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} />
|
<div className="canvas-wrap">
|
<div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 30}} id={this.state.chartId}></div>
|
</div>
|
{empty ? <Empty description={false}/> : null}
|
</div>
|
)
|
}
|
}
|
|
const mapStateToProps = (state) => {
|
return {
|
tabviews: state.tabviews,
|
permMenus: state.permMenus,
|
}
|
}
|
|
const mapDispatchToProps = (dispatch) => {
|
return {
|
modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews))
|
}
|
}
|
|
export default connect(mapStateToProps, mapDispatchToProps)(PieChart)
|