Files
rustfs-console/composables/useEcharts.ts
T
2025-04-13 11:43:08 +08:00

125 lines
2.8 KiB
TypeScript

// 系列类型的定义后缀都为 SeriesOption
import type {
BarSeriesOption,
LineSeriesOption,
PieSeriesOption,
RadarSeriesOption,
} from 'echarts/charts'
// 组件类型的定义后缀都为 ComponentOption
import { BarChart, LineChart, PieChart, RadarChart } from 'echarts/charts'
import type {
DatasetComponentOption,
GridComponentOption,
LegendComponentOption,
TitleComponentOption,
ToolboxComponentOption,
TooltipComponentOption,
} from 'echarts/components'
import {
DatasetComponent, // 数据集组件
GridComponent,
LegendComponent,
TitleComponent,
ToolboxComponent,
TooltipComponent,
TransformComponent, // 内置数据转换器组件 (filter, sort)
} from 'echarts/components'
import * as echarts from 'echarts/core'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { useTemplateRef } from 'vue'
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
export type ECOption = echarts.ComposeOption<
| BarSeriesOption
| PieSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| LegendComponentOption
| DatasetComponentOption
| ToolboxComponentOption
| RadarSeriesOption
>
// 注册必须的组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
DatasetComponent,
TransformComponent,
BarChart,
PieChart,
LineChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
ToolboxComponent,
RadarChart,
])
/**
* Echarts hooks函数
* @description 按需引入图表组件,没注册的组件需要先引入
*/
export function useEcharts(ref: string, chartOptions: Ref<ECOption>) {
const el = useTemplateRef<HTMLLIElement>(ref)
const { system, store } = useColorMode()
let chart: echarts.ECharts | null = null
const { width, height } = useElementSize(el)
const isRendered = () => Boolean(el && chart)
async function render() {
// 宽或高不存在时不渲染
if (!width || !height)
return
const chartTheme = store.value == 'auto' ? system.value : store.value
await nextTick()
if (el) {
chart = echarts.init(el.value, chartTheme)
update(chartOptions.value)
}
}
async function update(updateOptions: ECOption) {
if (isRendered()) {
chart!.setOption({ backgroundColor: 'transparent', ...updateOptions })
}
}
function destroy() {
chart?.dispose()
chart = null
}
watch([width, height], async ([newWidth, newHeight]) => {
if (isRendered() && newWidth && newHeight)
chart?.resize()
})
watch(chartOptions, (newValue) => {
update(newValue)
})
onMounted(() => {
render()
})
onUnmounted(() => {
destroy()
})
return {
destroy,
update,
}
}