From 31ec63f0419895876cbaba99637a884a32d33d0d Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 01 九月 2021 10:31:45 +0800
Subject: [PATCH] 2021-09-01

---
 src/tabviews/zshare/chartcomponent/index.jsx |  847 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 728 insertions(+), 119 deletions(-)

diff --git a/src/tabviews/zshare/chartcomponent/index.jsx b/src/tabviews/zshare/chartcomponent/index.jsx
index f9d9167..231654d 100644
--- a/src/tabviews/zshare/chartcomponent/index.jsx
+++ b/src/tabviews/zshare/chartcomponent/index.jsx
@@ -3,30 +3,108 @@
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
+import { Spin, Empty, Select } from 'antd'
 
-import zhCN from '@/locales/zh-CN/model.js'
-import enUS from '@/locales/en-US/model.js'
+import asyncComponent from './asyncButtonComponent'
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/main.js'
+import enUS from '@/locales/en-US/main.js'
 import './index.scss'
+
+const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton'))
+const ExcelInButton = asyncComponent(() => import('@/tabviews/zshare/actionList/excelInbutton'))
 
 class LineChart extends Component {
   static propTpyes = {
-    plot: PropTypes.object,
-    data: PropTypes.array,
-    config: PropTypes.object
+    BID: PropTypes.any,              // 鐖剁骇Id
+    Tab: PropTypes.any,              // 鏍囩淇℃伅
+    plot: PropTypes.object,          // 鍥炬爣璁剧疆淇℃伅
+    data: PropTypes.array,           // 鍥捐〃浼犲叆鏁版嵁
+    loading: PropTypes.bool,         // 鏁版嵁鍔犺浇涓�
+    config: PropTypes.object,        // 椤甸潰閰嶇疆淇℃伅
   }
 
   state = {
-    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, // 瀛楀吀
+    empty: true,               // 鍥捐〃鏁版嵁涓虹┖
+    actions: [],               // 鍥捐〃缁戝畾鐨勬寜閽粍
+    chartId: Utils.getuuid(),  // 鍥捐〃Id
+    chartData: [],             // 鍥捐〃鏁版嵁
+    chartFields: [],           // 缁熻鍥捐〃鐢熸垚瀛楁闆�
+    selectFields: [],          // 缁熻鍥捐〃閫夋嫨瀛楁
+    percentFields: []          // 璁剧疆涓虹櫨鍒嗘瘮鐨勫瓧娈碉紝tooltip鏃跺鍔�%
   }
 
+  /**
+   * @description 鏍¢獙鍥捐〃鐨勬寜閽粍锛屽鏋滀负缁熻鍥捐〃锛岃绠楀浘琛ㄥ瓧娈�
+   */
   componentDidMount () {
-    this.viewrender()
+    const { plot, data, config } = this.props
+    let _state = {}
+    let actions = []
+    let percentFields = []
+
+    config.action.forEach(item => {
+      if (!plot.actions || plot.actions.length === 0) return
+      if (!(item.OpenType === 'excelOut' || (item.OpenType === 'excelIn' && item.Ot === 'notRequired'))) return
+      if (plot.actions.includes(item.uuid)) {
+        actions.push(fromJS(item).toJS())
+      }
+    })
+
+    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
+      _state.actions = actions
+
+      let _column = config.columns.filter(col => plot.InfoValue === col.field)[0]
+
+      if (_column && _column.format === 'percent') {
+        percentFields.push(plot.InfoValue)
+        _state.percentFields = percentFields
+      }
+
+      this.setState(_state, () => {
+        this.viewrender()
+      })
+    } else {
+      if (plot.chartType === 'line' || plot.chartType === 'bar') {
+        try {
+          plot.Yaxis.forEach(yaxis => {
+            let _column = config.columns.filter(col => yaxis === col.field)[0]
+            if (_column && _column.format === 'percent') {
+              percentFields.push(_column.label)
+            }
+          })
+        } catch (e) {
+          console.warn('Incorrect percentage setting')
+        }
+      }
+      this.setState({ actions, percentFields }, () => {
+        this.viewrender()
+      })
+    }
   }
 
+  /**
+   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
+   */
   UNSAFE_componentWillReceiveProps (nextProps) {
+    const { plot } = this.props
     if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      this.setState({}, () => {
-        let _element = document.getElementById(this.props.plot.uuid)
+      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 = ''
         }
@@ -35,13 +113,25 @@
     }
   }
 
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 鍥捐〃鏁版嵁棰勫鐞�
+   * 1銆侀�氳繃鏄剧ず鍒楄繘琛屾暟鎹被鍨嬭浆鎹�
+   * 2銆侀噸澶嶆暟鎹細鍙栧钩鍧囧�笺�佺疮璁°�佸幓閲�
+   * 3銆佹煴鐘跺浘鏁版嵁琛ラ綈
+   */
   getdata = () => {
     const { data, plot, config } = this.props
-    
     let vFields = plot.Yaxis && typeof(plot.Yaxis) === 'string' ? [plot.Yaxis] : plot.Yaxis
     let _columns = config.columns.filter(col => vFields.includes(col.field))
 
-    if (!data) return []
+    if (!data) {
+      this.setState({empty: true})
+      return []
+    }
 
     let _data = []
     let _cdata = fromJS(data).toJS()
@@ -70,6 +160,7 @@
           vFields.forEach(field => {
             _item[field] += item[field]
           })
+          _mdata.set(item[plot.Xaxis], _item)
         }
       })
 
@@ -104,6 +195,7 @@
           vFields.forEach(field => {
             _item[field] += item[field]
           })
+          _mdata.set(item[plot.Xaxis], _item)
         }
       })
 
@@ -139,9 +231,167 @@
       _data = [..._mdata.values()]
     }
 
+    this.setState({empty: _data.length === 0})
     return _data
   }
 
+  /**
+   * @description 缁熻鏁版嵁棰勫鐞嗭紝鍔ㄦ�佺敓鎴愮粺璁″瓧娈靛苟杩涜鏁版嵁杞崲
+   */
+  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(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)) {
+          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(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
+        _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(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()]
+    }
+
+    _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}
+  }
+
+  /**
+   * @description 鑾峰彇缁熻鍥捐〃灞曠ず鏁版嵁锛岄�氳繃閫夋嫨绫诲瀷绛涢��
+   */
+  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
+  }
+
+  /**
+   * @description 鍥捐〃娓叉煋鍒嗙粍
+   */
   viewrender = () => {
     const { plot } = this.props
 
@@ -154,57 +404,94 @@
     }
   }
 
+  /**
+   * @description 鎶樼嚎鍥炬覆鏌�
+   */
   linerender = () => {
     const { plot, config } = this.props
+    const { percentFields } = this.state
 
-    let transfield = {}
-    config.columns.forEach(col => {
-      if (col.field) {
-        transfield[col.field] = col.label
+    let _data = []
+    let _valfield = 'value'
+    let _typefield = 'key'
+    let ispercent = false
+
+    if (plot.datatype === 'statistics') {
+      _valfield = plot.InfoValue
+      _typefield = plot.InfoType
+
+      if (percentFields.length > 0) {
+        ispercent = true
       }
-    })
-    // const colors = ['#f49d37', '#f03838', '#35d1d1', '#5be56b', '#4e7af0', '#ebcc21']
-    let X_axis = plot.Xaxis
-    let Y_axis = plot.Yaxis
 
-    let data = this.getdata()
-
-    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({
-      container: plot.uuid,
+      container: this.state.chartId,
       autoFit: true,
       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', {
-      nice: true
+    chart.scale(_valfield, {
+      nice: true,
+      range: [0, 0.93]
+    })
+
+    // 鍧愭爣杞存牸寮忓寲
+    chart.axis(plot.Xaxis, {
+      label: {
+        formatter: (val) => {
+          if (!val || /^\s*$/.test(val)) return val
+          let _val = `${val}`
+          if (_val.length <= 11) return val
+          return _val.substring(0, 8) + '...'
+        }
+      }
     })
 
     if (!plot.legend || plot.legend === 'hidden') {
@@ -236,19 +523,25 @@
 
     let _chart = chart
       .line()
-      .position(`${X_axis}*value`)
-      .color('key')
+      .position(`${plot.Xaxis}*${_valfield}`)
+      .color(_typefield)
       .shape(plot.shape || 'smooth')
+      .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => {
+        return {
+          name: type,
+          value: percentFields.includes(type) || ispercent ? value + '%' : value
+        }
+      })
 
     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')
     }
@@ -256,57 +549,92 @@
     chart.render()
   }
 
-  barrender = () => {
-    const { plot, config } = this.props
+  /**
+   * @description 鑷畾涔夋覆鏌�
+   */
+  customrender = (data, transfield) => {
+    const { plot } = this.props
+    const { percentFields } = this.state
 
-    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: plot.uuid,
+      container: this.state.chartId,
       autoFit: true,
       height: plot.height || 400
     })
 
     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]
+      })
+    }
+    
+    // 鍧愭爣杞存牸寮忓寲
+    chart.axis(plot.Xaxis, {
+      label: {
+        formatter: (val) => {
+          if (!val || /^\s*$/.test(val)) return val
+          let _val = `${val}`
+          if (_val.length <= 11) return val
+          return _val.substring(0, 8) + '...'
+        }
+      }
     })
 
     if (!plot.legend || plot.legend === 'hidden') {
       chart.legend(false)
     } else {
       chart.legend({
-        position: plot.legend
+        custom: true,
+        position: plot.legend,
+        items: legends,
       })
     }
 
@@ -329,11 +657,204 @@
       })
     }
 
+    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)
+          .tooltip(`${item.name}`, (value) => {
+            return {
+              name: item.name,
+              value: percentFields.includes(item.name) ? value + '%' : value
+            }
+          })
+
+        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)
+          .tooltip(`${item.name}`, (value) => {
+            return {
+              name: item.name,
+              value: percentFields.includes(item.name) ? value + '%' : value
+            }
+          })
+
+        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()
+  }
+
+  /**
+   * @description 鏌辩姸鍥炬覆鏌�
+   */
+  barrender = () => {
+    const { plot, config } = this.props
+    const { percentFields } = this.state
+
+    let _data = []
+    let _valfield = 'value'
+    let _typefield = 'key'
+    let ispercent = false
+
+    if (plot.datatype === 'statistics') {
+      _valfield = plot.InfoValue
+      _typefield = plot.InfoType
+
+      if (percentFields.length > 0) {
+        ispercent = true
+      }
+
+      _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])) {
+      for (let i = 1; i < 12; i++) {
+        if (_data[i] && _data[i][plot.Xaxis] === _data[0][plot.Xaxis]) {
+          _data[i][plot.Xaxis] += ' '
+        } else {
+          break;
+        }
+      }
+      _data[0][plot.Xaxis] += ' '
+    }
+
+    chart.data(_data)
+
+    chart.scale(_valfield, {
+      nice: true,
+      range: [0, 0.93]
+    })
+
+    // 鍧愭爣杞存牸寮忓寲
+    chart.axis(plot.Xaxis, {
+      label: {
+        formatter: (val) => {
+          if (!val || /^\s*$/.test(val)) return val
+          let _val = `${val}`
+          if (_val.length <= 11) return val
+          return _val.substring(0, 8) + '...'
+        }
+      }
+    })
+
+    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
+      let _chart = chart
         .interval()
-        .position(`${X_axis}*value`)
-        .color('key')
+        .position(`${plot.Xaxis}*${_valfield}`)
+        .size(30)
+        .color(_typefield)
         .adjust([
           {
             type: 'dodge',
@@ -341,18 +862,42 @@
           }
         ])
         .shape(plot.shape || 'rect')
+        .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => {
+          return {
+            name: type,
+            value: percentFields.includes(type) || ispercent ? value + '%' : value
+          }
+        })
+
+      if (plot.label === 'true') {
+        _chart.label(_valfield)
+      }
     } else if (plot.adjust === 'stack') {
-      chart
+      let _chart = chart
         .interval()
-        .position(`${X_axis}*value`)
-        .color('key')
+        .position(`${plot.Xaxis}*${_valfield}`)
+        .size(30)
+        .color(_typefield)
         .adjust('stack')
         .shape(plot.shape || 'rect')
+        .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => {
+          return {
+            name: type,
+            value: percentFields.includes(type) || ispercent ? value + '%' : value
+          }
+        })
+
+      if (plot.label === 'true') {
+        _chart.label(_valfield)
+      }
     }
 
     chart.render()
   }
 
+  /**
+   * @description 楗煎浘娓叉煋
+   */
   pierender = () => {
     const { plot, config } = this.props
 
@@ -362,8 +907,6 @@
         transfield[col.field] = col.label
       }
     })
-    let X_axis = plot.Xaxis
-    let Y_axis = plot.Yaxis
 
     let data = this.getdata()
 
@@ -377,14 +920,14 @@
     if (plot.pieshow !== 'value') {
       dv.transform({
         type: 'percent',
-        field: Y_axis,
-        dimension: X_axis,
+        field: plot.Yaxis,
+        dimension: plot.Xaxis,
         as: 'percent'
       })
     }
     
     const chart = new Chart({
-      container: plot.uuid,
+      container: this.state.chartId,
       autoFit: true,
       height: plot.height || 400
     })
@@ -427,8 +970,8 @@
         .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,
@@ -436,36 +979,34 @@
           }
         })
 
-      if (plot.label === 'true') {
-        let setting = {
+      if (plot.label !== 'false') {
+        _chart.label('percent', {
+          layout: { type: 'pie-spider' },
+          labelHeight: 20,
           content: (data) => {
-            return `${data[X_axis]}: ${(data.percent * 100).toFixed(2)}%`
+            let val = data[plot.Xaxis]
+            if (val) {
+              val = `${val}`
+              if (val.length > 10) {
+                val = val.substring(0, 7) + '...'
+              }
+            }
+            return `${val}: ${(data.percent * 100).toFixed(2)}%`
+          },
+          labelLine: {
+            style: {
+              lineWidth: 0.5,
+            },
           }
-        }
-
-        if (plot.labelLayout === 'overlap') {
-          setting.type = 'pie'
-          setting.layout = {
-            type: 'overlap'
-          }
-          setting.offset = 0
-          // setting.style = {
-          //   textAlign: 'center',
-          //   fontSize: 12,
-          //   fill: '#535353'
-          // }
-        }
-
-        _chart.label('percent', setting)
+        })
       }
-      
     } else {
       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
@@ -475,7 +1016,14 @@
       if (plot.label === 'true') {
         let setting = {
           content: (data) => {
-            return `${data[X_axis]}: ${data[Y_axis]}`
+            let val = data[plot.Xaxis]
+            if (val) {
+              val = `${val}`
+              if (val.length > 10) {
+                val = val.substring(0, 7) + '...'
+              }
+            }
+            return `${val}: ${data[plot.Yaxis]}`
           }
         }
 
@@ -487,20 +1035,81 @@
           setting.offset = 0
         }
 
-        _chart.label(Y_axis, setting)
+        _chart.label(plot.Yaxis, setting)
       }
     }
     
     chart.render()
   }
 
+  /**
+   * @description 缁熻鍥捐〃锛岀粺璁$被鍨嬪垏鎹�
+   */
+  handleChange = (val) => {
+    this.setState({selectFields: val}, () => {
+      let _element = document.getElementById(this.state.chartId)
+      if (_element) {
+        _element.innerHTML = ''
+      }
+      this.viewrender()
+    })
+  }
+
   render() {
-    const { plot } = this.props
+    const { plot, loading, config, BID, Tab } = this.props
+    const { empty, chartFields, selectFields, actions } = this.state
 
     return (
-      <div className="line-chart-plot-box" style={{minHeight: plot.height ? plot.height + 50 : 450}}>
+      <div className="line-chart-plot-box">
         {plot.title ? <p className="chart-title">{plot.title}</p> : null}
-        <div className="canvas" id={plot.uuid}></div>
+        {loading ?
+          <div className="loading-mask">
+            <div className="ant-spin-blur"></div>
+            <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-wrap">
+          <div className={'chart-action ' + (plot.title ? 'with-title' : '')}>
+            {actions.map(item => {
+              if (item.OpenType === 'excelOut') {
+                return (
+                  <ExcelOutButton
+                    key={item.uuid}
+                    BID={BID}
+                    Tab={Tab}
+                    btn={item}
+                    show="icon"
+                    setting={config.setting}
+                  />
+                )
+              } else {
+                return (
+                  <ExcelInButton
+                    key={item.uuid}
+                    BID={BID}
+                    Tab={Tab}
+                    btn={item}
+                    show="icon"
+                    setting={config.setting}
+                  />
+                )
+              }
+            })}
+          </div>
+          <div className={'canvas' + (empty ? ' empty' : '')} style={{minHeight: plot.height ? plot.height : 400}} id={this.state.chartId}></div>
+        </div>
+        {empty ? <Empty description={false}/> : null}
       </div>
     )
   }

--
Gitblit v1.8.0