办学质量监测教学评价系统
shenrongliang
2025-06-13 11d86cc6c26bb4f709e407acadf4805c2024e79f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import type { EChartsOption } from 'echarts';
 
import type { Ref } from 'vue';
 
import type { Nullable } from '@vben/types';
 
import type EchartsUI from './echarts-ui.vue';
 
import { computed, nextTick, watch } from 'vue';
 
import { usePreferences } from '@vben/preferences';
 
import {
  tryOnUnmounted,
  useDebounceFn,
  useResizeObserver,
  useTimeoutFn,
  useWindowSize,
} from '@vueuse/core';
 
import echarts from './echarts';
 
type EchartsUIType = typeof EchartsUI | undefined;
 
type EchartsThemeType = 'dark' | 'light' | null;
 
function useEcharts(chartRef: Ref<EchartsUIType>) {
  let chartInstance: echarts.ECharts | null = null;
  let cacheOptions: EChartsOption = {};
 
  const { isDark } = usePreferences();
  const { height, width } = useWindowSize();
  const resizeHandler: () => void = useDebounceFn(resize, 200);
 
  const getOptions = computed((): EChartsOption => {
    if (!isDark.value) {
      return {};
    }
 
    return {
      backgroundColor: 'transparent',
    };
  });
 
  const initCharts = (t?: EchartsThemeType) => {
    const el = chartRef?.value?.$el;
    if (!el) {
      return;
    }
    chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null);
 
    return chartInstance;
  };
 
  const renderEcharts = (
    options: EChartsOption,
    clear = true,
  ): Promise<Nullable<echarts.ECharts>> => {
    cacheOptions = options;
    const currentOptions = {
      ...options,
      ...getOptions.value,
    };
    return new Promise((resolve) => {
      if (chartRef.value?.offsetHeight === 0) {
        useTimeoutFn(async () => {
          resolve(await renderEcharts(currentOptions));
        }, 30);
        return;
      }
      nextTick(() => {
        useTimeoutFn(() => {
          if (!chartInstance) {
            const instance = initCharts();
            if (!instance) return;
          }
          clear && chartInstance?.clear();
          chartInstance?.setOption(currentOptions);
          resolve(chartInstance);
        }, 30);
      });
    });
  };
 
  function resize(withAnimation = true) {
    chartInstance?.resize({
      animation: withAnimation
        ? {
            duration: 300,
            easing: 'quadraticIn',
          }
        : undefined,
    });
  }
 
  watch([width, height], () => {
    resizeHandler?.();
  });
 
  useResizeObserver(chartRef as never, resizeHandler);
 
  watch(isDark, () => {
    if (chartInstance) {
      chartInstance.dispose();
      initCharts();
      renderEcharts(cacheOptions);
      resize();
    }
  });
 
  tryOnUnmounted(() => {
    // 销毁实例,释放资源
    chartInstance?.dispose();
  });
  return {
    renderEcharts,
    resize,
    getChartInstance: () => chartInstance,
  };
}
 
export { useEcharts };
 
export type { EchartsUIType };