waterfall.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import { IChartProps } from '../../components/Chart'
  21. import {
  22. decodeMetricName,
  23. getAggregatorLocale
  24. } from '../../components/util'
  25. import {
  26. getDimetionAxisOption,
  27. getMetricAxisOption,
  28. getLabelOption,
  29. getLegendOption,
  30. getGridPositions
  31. } from './util'
  32. import { EChartOption } from 'echarts'
  33. import { getFormattedValue } from '../../components/Config/Format'
  34. const defaultTheme = require('assets/json/echartsThemes/default.project.json')
  35. const defaultThemeColors = defaultTheme.theme.color
  36. export default function (chartProps: IChartProps) {
  37. const {
  38. data,
  39. cols,
  40. metrics,
  41. chartStyles
  42. } = chartProps
  43. const {
  44. spec,
  45. label,
  46. xAxis,
  47. yAxis,
  48. splitLine
  49. } = chartStyles
  50. const {
  51. showVerticalLine,
  52. verticalLineColor,
  53. verticalLineSize,
  54. verticalLineStyle,
  55. showHorizontalLine,
  56. horizontalLineColor,
  57. horizontalLineSize,
  58. horizontalLineStyle
  59. } = splitLine
  60. const labelOption = {
  61. label: getLabelOption('waterfall', label, metrics)
  62. }
  63. const xAxisData = data.map((d) => d[cols[0].name] || '')
  64. let sourceData = []
  65. const series = []
  66. metrics.forEach((m) => {
  67. const metricName = `${m.agg}(${decodeMetricName(m.name)})`
  68. sourceData = data.map((d) => d[metricName])
  69. const baseData = []
  70. const seriesBaseData = [...data]
  71. const ascendOrder = []
  72. const discendOrder = []
  73. sourceData.forEach((a, index) => {
  74. a = parseFloat(a)
  75. if (index > 0) {
  76. const result = a - parseFloat(sourceData[index - 1])
  77. if (result >= 0) {
  78. ascendOrder.push(result)
  79. discendOrder.push('-')
  80. baseData.push(parseFloat(sourceData[index - 1]))
  81. } else {
  82. ascendOrder.push('-')
  83. discendOrder.push(Math.abs(result))
  84. baseData.push(parseFloat(sourceData[index - 1]) - Math.abs(result))
  85. }
  86. return result
  87. } else {
  88. ascendOrder.push(a)
  89. discendOrder.push('-')
  90. baseData.push(0)
  91. return a
  92. }
  93. })
  94. const totalAscend = ascendOrder.reduce((sum, val) => typeof val === 'number' ? sum + val : sum + 0, 0)
  95. const totalDiscendOrder = discendOrder.reduce((sum, val) => typeof val === 'number' ? sum + val : sum + 0, 0)
  96. const difference = totalAscend - totalDiscendOrder
  97. xAxisData.push('累计')
  98. baseData.push('-')
  99. if (difference > 0) {
  100. ascendOrder.push(difference)
  101. discendOrder.push('-')
  102. } else {
  103. discendOrder.push(Math.abs(difference))
  104. ascendOrder.push('-')
  105. }
  106. const baseDataObj = {
  107. name: `[${getAggregatorLocale(m.agg)}] ${decodeMetricName(m.name)}`,
  108. type: 'bar',
  109. sampling: 'average',
  110. stack: 'stack',
  111. data: baseData,
  112. itemStyle: {
  113. normal: {
  114. barBorderColor: 'rgba(0,0,0,0)',
  115. color: 'rgba(0,0,0,0)'
  116. // opacity: interactIndex === undefined ? 1 : 0.25
  117. },
  118. emphasis: {
  119. barBorderColor: 'rgba(0,0,0,0)',
  120. color: 'rgba(0,0,0,0)'
  121. }
  122. }
  123. }
  124. const ascendOrderObj = {
  125. name: '升',
  126. type: 'bar',
  127. sampling: 'average',
  128. stack: 'stack',
  129. data: ascendOrder,
  130. itemStyle: {
  131. // normal: {
  132. // opacity: interactIndex === undefined ? 1 : 0.25
  133. // }
  134. },
  135. ...labelOption
  136. }
  137. const discendOrderObj = {
  138. name: '降',
  139. type: 'bar',
  140. sampling: 'average',
  141. stack: 'stack',
  142. data: discendOrder,
  143. itemStyle: {
  144. // normal: {
  145. // opacity: interactIndex === undefined ? 1 : 0.25
  146. // }
  147. },
  148. ...labelOption
  149. }
  150. series.push(baseDataObj)
  151. series.push(ascendOrderObj)
  152. series.push(discendOrderObj)
  153. })
  154. const seriesNames = series.map((s) => s.name)
  155. const xAxisSplitLineConfig = {
  156. showLine: showVerticalLine,
  157. lineColor: verticalLineColor,
  158. lineSize: verticalLineSize,
  159. lineStyle: verticalLineStyle
  160. }
  161. const yAxisSplitLineConfig = {
  162. showLine: showHorizontalLine,
  163. lineColor: horizontalLineColor,
  164. lineSize: horizontalLineSize,
  165. lineStyle: horizontalLineStyle
  166. }
  167. const tooltip: EChartOption.Tooltip = {
  168. trigger: 'axis',
  169. formatter (param: EChartOption.Tooltip.Format[]) {
  170. let color
  171. const text = param.map((pa, index) => {
  172. const data = !index ? parseFloat(sourceData[pa.dataIndex]) : pa.data
  173. if (typeof data === 'number') {
  174. color = pa.color
  175. }
  176. const formattedValue = getFormattedValue(data, metrics[0].format)
  177. return `${pa.seriesName}: ${formattedValue}`
  178. })
  179. const xAxis = param[0]['axisValue']
  180. if (xAxis === '累计') {
  181. return ''
  182. } else {
  183. text.unshift(xAxis as string)
  184. if (color) {
  185. text[0] = `<span class="widget-tooltip-circle" style="background: ${color}"></span>` + text[0]
  186. }
  187. return text.join('<br/>')
  188. }
  189. }
  190. }
  191. return {
  192. xAxis: getDimetionAxisOption(xAxis, xAxisSplitLineConfig, xAxisData),
  193. yAxis: getMetricAxisOption(yAxis, yAxisSplitLineConfig, metrics.map((m) => decodeMetricName(m.name)).join(` / `)),
  194. series,
  195. tooltip,
  196. grid: getGridPositions({ showLegend: false }, seriesNames, '', false, yAxis, xAxis, xAxisData)
  197. }
  198. }