import type { EChartsOption } from "echarts"; import { computed, watch, ref } from "vue"; import { omit, defaultsDeep } from "lodash-es"; import { useRequest } from "vue-hooks-plus"; import { DataSourceType } from "../chartEnum"; import { message } from "ant-design-vue"; import { cllJsCode } from "../utils"; export const useChartOptions = (chartProps: Record) => { const dataSource = chartProps.dataSource || {}; const xAxis = ref(); const yAxis = ref(); const series = ref(dataSource?.data?.series); const server = computed(() => { return async () => await fetch(chartProps.dataSource.url, { method: chartProps.dataSource.method, }) .then((res) => res.json()); }); // 请求数据 const { run, refresh, cancel, data, loading } = useRequest(server.value, { defaultParams: chartProps.dataSource.params, manual: true, pollingInterval: (chartProps.dataSource?.refreshTime || 0) * 1000, // 刷新时间 onError: (error) => { console.error(error); message.error(chartProps.dataSource.url + "请求失败"); } }); /* 初始请求 */ if (chartProps.dataSource.sourceType === DataSourceType.API) { run(); } watch( () => data.value, async (val) => { if (val && chartProps.dataSource.sourceType === DataSourceType.API) { let res = val; if(chartProps.dataSource.dataProcess) { res = await cllJsCode(chartProps.dataSource.dataProcess, JSON.stringify(val)); } xAxis.value = res.xAxis || { data: res.xData }; yAxis.value = res.yAxis || { data: res.yData }; series.value = res.series; } }, { deep: true, } ); watch( () => [ chartProps.dataSource.sourceType, chartProps.dataSource.method ], () => { if (chartProps.dataSource.sourceType === DataSourceType.API) { refresh(); } else { cancel(); const dataSource = chartProps.dataSource || {}; const { xData, yData, series } = dataSource?.data || {}; if(xData) { xAxis.value = { data: xData }; } if(yData) { yAxis.value = { data: yData }; } series.value = series; } }, { deep: true, } ); const options = computed((): EChartsOption => { const opt = omit(chartProps, [ "width", "height", "dataSource", ]) as EChartsOption; // 通用标签 const label = opt?.label || {}; const result = defaultsDeep( { xAxis: xAxis.value, yAxis: yAxis.value, series: (series.value as any[])?.map((item: any) => { // 每个类型的图,可以单独设置series.类型 const customSet = opt.series?.[item.type] || {}; // TODO 动态计算上下左右距离 return { ...label, ...item, ...customSet } }), }, opt ); console.log('option result:', result) return result; }); return { options, loading, }; };