BarAndLine.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <template>
  2. <div v-if="spinning" class="spinning">
  3. <a-spin :spinning="true" />
  4. </div>
  5. <div v-if="!spinning" ref="chartRef" :style="{ height, width }"></div>
  6. </template>
  7. <script lang="ts">
  8. import { defineComponent, PropType, ref, Ref, reactive, watchEffect, watch, nextTick } from 'vue';
  9. import { useECharts } from '/@/hooks/web/useECharts';
  10. import { toEchartsData } from '/@/utils/ventutil';
  11. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  12. import EchartsUtil from '/@/utils/echartsUtil';
  13. import { object } from 'vue-types';
  14. export default defineComponent({
  15. name: 'BarAndLine',
  16. props: {
  17. chartsColumns: {
  18. type: Array,
  19. default: () => [],
  20. },
  21. chartsColumnsType: {
  22. type: String,
  23. },
  24. chartsType: {
  25. type: String,
  26. default: 'listMonitor',
  27. },
  28. dataSource: {
  29. type: Array,
  30. default: () => [],
  31. },
  32. option: {
  33. type: Object,
  34. default: () => ({}),
  35. },
  36. xAxisPropType: {
  37. type: String,
  38. required: true,
  39. },
  40. width: {
  41. type: String as PropType<string>,
  42. default: '100%',
  43. },
  44. height: {
  45. type: String as PropType<string>,
  46. default: 'calc(100vh - 78px)',
  47. },
  48. },
  49. emits: ['refresh'],
  50. setup(props, { emit }) {
  51. const spinning = ref<boolean>(true);
  52. const chartRef = ref<HTMLDivElement | null>(null);
  53. const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>);
  54. const chartData = props.chartsColumnsType ? getTableHeaderColumns(props.chartsColumnsType) : [];
  55. let chartsColumns = props.chartsColumns.length > 0 ? props.chartsColumns : chartData;
  56. const option = reactive({
  57. name: '',
  58. color: ['#7B68EE', '#0000CD', '#6495ED', '#00BFFF', '#AFEEEE', '#008080', '#00FA9A', '#2E8B57', '#FAFAD2', '#DAA520'],
  59. tooltip: null,
  60. grid: null,
  61. toolbox: {
  62. feature: {
  63. saveAsImage: {
  64. iconStyle: {
  65. normal: {
  66. borderColor: '#ffffff',
  67. },
  68. },
  69. show: true,
  70. },
  71. },
  72. },
  73. dataZoom: null,
  74. legend: null,
  75. timeline: null,
  76. xAxis: null,
  77. yAxis: null,
  78. series: null,
  79. });
  80. let optionUtil;
  81. watchEffect(() => {
  82. props.dataSource && props.dataSource.length > 0 && option.series && initCharts();
  83. });
  84. watch([() => props.chartsType, () => props.chartsColumns], ([newChartsType, newChartsColumns]) => {
  85. spinning.value = true;
  86. chartsColumns = newChartsColumns;
  87. optionUtil.initChartOption(newChartsType, newChartsColumns);
  88. spinning.value = false;
  89. initCharts(true);
  90. emit('refresh');
  91. });
  92. function initChartsOption() {
  93. optionUtil = new EchartsUtil(Object.assign(option, props.option));
  94. optionUtil.initChartOption(props.chartsType, chartsColumns);
  95. }
  96. initChartsOption();
  97. function initCharts(isRefresh = false) {
  98. //轴数据
  99. if (option.series && option.series.length === chartsColumns.length) {
  100. let xAxisData = props.dataSource.map((item) => item[props.xAxisPropType]);
  101. [...chartsColumns].forEach((propType: any, index) => {
  102. option.series[index].data = props.dataSource.map((item) => item[propType.dataIndex] || 0);
  103. });
  104. option.xAxis[0].data = xAxisData;
  105. setOptions(option, isRefresh);
  106. }
  107. }
  108. setTimeout(() => {
  109. spinning.value = false;
  110. }, 1000);
  111. return { chartRef, spinning };
  112. },
  113. });
  114. </script>
  115. <style lang="less" scoped>
  116. .spinning {
  117. display: flex;
  118. width: 100%;
  119. height: 100%;
  120. justify-content: center;
  121. align-items: center;
  122. }
  123. </style>