index.jsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { defineComponent, onMounted, ref, computed, watch, toRefs, onBeforeUnmount } from 'vue'
  2. import * as echarts from 'echarts'
  3. import { sensor } from '@cip/utils/sensor'
  4. import { NAME, GROUP, VALUE, OPTION, CONFIG_ERROR, BAR_OPTION } from './const'
  5. import { Encode } from './method'
  6. import { generateProps, generateEmits } from '../helper/component-util'
  7. import { componentScheme } from './component.scheme'
  8. import './index.less'
  9. /**
  10. * 组件提供默认option, 也支持自定义
  11. * dataset为数据集,传入时需要指定绑定字段,默认为name,value;当存在多维数据时需要指定group
  12. * dataset example
  13. * [
  14. * { name: '邮件营销', value: 120, group: '周一' },
  15. { name: '邮件营销', value: 110, group: '周二' },
  16. { name: '邮件营销', value: 99, group: '周三' },
  17. { name: '联盟广告', value: 11, group: '周一' },
  18. { name: '联盟广告', value: 21, group: '周二' },
  19. { name: '联盟广告', value: 31, group: '周三' },
  20. { name: '视频广告', value: 91, group: '周一' },
  21. { name: '视频广告', value: 41, group: '周二' },
  22. { name: '视频广告', value: 41, group: '周三' }
  23. ]
  24. */
  25. export default defineComponent({
  26. name: 'CipCharts',
  27. props: generateProps(componentScheme),
  28. emits: generateEmits(componentScheme),
  29. setup (props, { emit }) {
  30. const chartRef = ref()
  31. let charts = null
  32. let observe = null
  33. const { dataset, options, bindProps } = toRefs(props)
  34. const groupData = computed(() => {
  35. const key = bindProps.value.group ?? GROUP
  36. return dataset.value.reduce((result, current) => {
  37. const _isArray = Array.isArray(result[current[key]])
  38. if (_isArray) result[current[key]].push(current)
  39. else result[current[key]] = [current]
  40. return result
  41. }, {})
  42. })
  43. // 判断是否存在group
  44. const isSingleGroup = computed(() => {
  45. return Object.keys(groupData.value)[0] === 'undefined'
  46. })
  47. // 获取dataset
  48. const _dataset = computed(() => {
  49. const keys = Object.keys(groupData.value)
  50. const _name = bindProps.value.name
  51. const _value = bindProps.value.value
  52. if (isSingleGroup.value) return dataset.value.map(item => ({ ...item, [VALUE]: item[_value], name: item[_name] }))
  53. const result = keys.map(currentKey => {
  54. const currentData = groupData.value[currentKey].reduce((obj, item) => {
  55. obj[item[_name]] = item[_value]
  56. return obj
  57. }, {})
  58. return {
  59. name: currentKey,
  60. ...currentData
  61. }
  62. })
  63. return result
  64. })
  65. // 获取dimensions
  66. const dimensions = computed(() => {
  67. const groups = [...new Set(dataset.value.map(item => item[bindProps.value.name]))]
  68. return (groups?.length && !isSingleGroup.value) ? [NAME, ...groups] : [NAME, VALUE]
  69. })
  70. // 判断series是否存在,不存在则给默认值;series中如何存在data,则data的优先级高
  71. const series = computed(() => {
  72. const EncodeInstance = new Encode(props.bindProps)
  73. if (options.value.series?.length) return EncodeInstance.checkEncode(options.value.series)
  74. else {
  75. const generateSeries = Array.from({ length: dimensions.value.length - 1 }).map(() => ({
  76. ...BAR_OPTION
  77. }))
  78. return generateSeries.length > 1 ? generateSeries : EncodeInstance.checkEncode(generateSeries)
  79. }
  80. })
  81. // 处理option数据
  82. const chartsOption = computed(() => {
  83. return Object.assign({},
  84. OPTION,
  85. options.value,
  86. isHasDataset.value ? {} : {
  87. dataset: {
  88. dimensions: dimensions.value,
  89. source: _dataset.value
  90. }
  91. }, { series: series.value })
  92. })
  93. // 判断option中是否存在dataset, 存在在则使用option配置
  94. const isHasDataset = computed(() => {
  95. return 'dataset' in options.value
  96. })
  97. // 图表resize
  98. const bindResize = () => {
  99. observe = sensor(chartRef.value)
  100. observe.bind(() => {
  101. charts && charts.resize()
  102. })
  103. }
  104. // 组合echats的options
  105. onMounted(() => {
  106. charts = echarts.init(chartRef.value)
  107. try {
  108. charts.setOption(chartsOption.value)
  109. bindResize()
  110. emit('chart-init', charts)
  111. } catch (error) {
  112. console.error(CONFIG_ERROR)
  113. }
  114. })
  115. // 销毁实例
  116. onBeforeUnmount(() => {
  117. if (observe) {
  118. observe.destroy()
  119. }
  120. if (charts) {
  121. charts.dispose()
  122. charts = null
  123. }
  124. })
  125. watch([options, dataset], () => {
  126. try {
  127. charts.clear()
  128. charts.setOption(chartsOption.value)
  129. } catch (error) {
  130. console.error(CONFIG_ERROR)
  131. }
  132. }, {
  133. deep: true
  134. })
  135. return () => <div ref={chartRef} class="cip-chart-wrapper"></div>
  136. }
  137. })