feat: Add TokenRecords finance management system
- Created new finance application based on Vue Vben Admin - Implemented transaction management, category management, and loan tracking - Added person management for tracking financial relationships - Integrated budget management and financial analytics - Added data import/export functionality - Implemented responsive design for mobile support - Added comprehensive testing with Playwright 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
147
apps/web-finance/src/components/charts/useChart.ts
Normal file
147
apps/web-finance/src/components/charts/useChart.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import type * as echarts from 'echarts';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, unref, watch } from 'vue';
|
||||
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import * as echartCore from 'echarts/core';
|
||||
import { BarChart, LineChart, PieChart } from 'echarts/charts';
|
||||
import {
|
||||
DataZoomComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
TitleComponent,
|
||||
ToolboxComponent,
|
||||
TooltipComponent,
|
||||
} from 'echarts/components';
|
||||
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
|
||||
// 注册必要的组件
|
||||
echartCore.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent,
|
||||
BarChart,
|
||||
LineChart,
|
||||
PieChart,
|
||||
CanvasRenderer,
|
||||
UniversalTransition,
|
||||
LabelLayout,
|
||||
]);
|
||||
|
||||
export type EChartsOption = echarts.EChartsOption;
|
||||
export type EChartsInstance = echarts.ECharts;
|
||||
|
||||
export interface UseChartOptions {
|
||||
theme?: string | object;
|
||||
initOptions?: echarts.EChartsCoreOption;
|
||||
loading?: boolean;
|
||||
loadingOptions?: object;
|
||||
}
|
||||
|
||||
export function useChart(
|
||||
elRef: Ref<HTMLDivElement | null>,
|
||||
options: UseChartOptions = {},
|
||||
) {
|
||||
const { theme = 'light', initOptions = {}, loading = false, loadingOptions = {} } = options;
|
||||
|
||||
let chartInstance: EChartsInstance | null = null;
|
||||
const cacheOptions = ref<EChartsOption>({});
|
||||
const isDisposed = ref(false);
|
||||
|
||||
// 获取图表实例
|
||||
const getChartInstance = (): EChartsInstance | null => {
|
||||
if (!elRef.value || isDisposed.value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!chartInstance) {
|
||||
chartInstance = echartCore.init(elRef.value, theme, initOptions);
|
||||
}
|
||||
|
||||
return chartInstance;
|
||||
};
|
||||
|
||||
// 设置图表配置
|
||||
const setOptions = (options: EChartsOption, clear = true) => {
|
||||
cacheOptions.value = options;
|
||||
nextTick(() => {
|
||||
if (!isDisposed.value) {
|
||||
const instance = getChartInstance();
|
||||
if (instance) {
|
||||
clear && instance.clear();
|
||||
instance.setOption(options);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取图表配置
|
||||
const getOptions = (): EChartsOption => {
|
||||
return cacheOptions.value;
|
||||
};
|
||||
|
||||
// 调整图表大小
|
||||
const resize = useDebounceFn(() => {
|
||||
const instance = getChartInstance();
|
||||
instance?.resize();
|
||||
}, 200);
|
||||
|
||||
// 销毁图表
|
||||
const dispose = () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose();
|
||||
chartInstance = null;
|
||||
isDisposed.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听 loading 状态
|
||||
watch(
|
||||
() => loading,
|
||||
(val) => {
|
||||
const instance = getChartInstance();
|
||||
if (instance) {
|
||||
if (val) {
|
||||
instance.showLoading(loadingOptions);
|
||||
} else {
|
||||
instance.hideLoading();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 监听元素变化,重新初始化
|
||||
watch(
|
||||
elRef,
|
||||
(el) => {
|
||||
if (el) {
|
||||
isDisposed.value = false;
|
||||
setOptions(cacheOptions.value);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 挂载时初始化
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', resize);
|
||||
});
|
||||
|
||||
// 卸载时清理
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', resize);
|
||||
dispose();
|
||||
});
|
||||
|
||||
return {
|
||||
getInstance: getChartInstance,
|
||||
setOptions,
|
||||
getOptions,
|
||||
resize,
|
||||
dispose,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user