2025-05-19 11:55:58 +08:00

154 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div ref="chartRef" :style="{ height, width }"></div>
</template>
<script>
import { ref, reactive, watchEffect } from 'vue';
import { cloneDeep } from 'lodash';
import { useEcharts } from '@/hooks/useEcharts';
export default {
name: 'CustomEchartLine',
props: {
chartData: {
type: Array,
default: () => [],
required: true,
},
option: {
type: Object,
default: () => ({}),
},
type: {
type: String,
default: 'line',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: 'calc(100vh - 78px)',
},
},
emits: ['click'],
setup(props, { emit }) {
const chartRef = ref(null);
const { setOptions, getInstance, startAutoPlay } = useEcharts(chartRef);
const option = reactive({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
label: {
show: true,
backgroundColor: '#333',
},
},
},
legend: {
top: 30,
},
grid: {
top: 60,
},
xAxis: {
type: 'category',
data: [],
},
yAxis: {
type: 'value',
},
series: [],
});
watchEffect(() => {
props.chartData && initCharts();
});
function hexToRGBA(hex, alpha = 1) {
let hexCode = hex.replace('#', '');
if (hexCode.length === 3) {
hexCode = hexCode
.split('')
.map((char) => char + char)
.join('');
}
const r = parseInt(hexCode.slice(0, 2), 16);
const g = parseInt(hexCode.slice(2, 4), 16);
const b = parseInt(hexCode.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
function setAreaStyle(color) {
return {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: hexToRGBA(color, 1),
},
{
offset: 1,
color: hexToRGBA(color, 0.2),
},
],
},
};
}
function initCharts() {
if (props.option) {
Object.assign(option, cloneDeep(props.option));
}
let typeArr = Array.from(new Set(props.chartData.map((item) => item.type)));
let xAxisData = Array.from(new Set(props.chartData.map((item) => item.name)));
// 1. 优先使用外部传入的series配置如果存在
const externalSeries = props.option?.series || [];
option.series = typeArr.map((type, index) => {
// 2. 合并外部配置按type匹配
const externalConfig = externalSeries.find((s) => s.name === type) || {};
// 3. 动态生成数据
const data = xAxisData.map((x) => {
const item = props.chartData.find((item) => item.type === type && item.name === x);
return item ? item.value : null;
});
// 4. 合并配置(外部配置优先,内部生成配置补充)
return {
type: props.type, // 默认类型
name: type, // 必须字段
data, // 动态生成的数据
smooth: true, // 默认平滑
...externalConfig, // 外部配置覆盖内部默认值
// 特殊处理areaStyle保留您的颜色逻辑
areaStyle: externalConfig.areaStyle || (props.option?.color ? setAreaStyle(props.option.color[index]) : undefined),
};
});
option.xAxis.data = xAxisData;
// console.log(option.series);
setOptions(option);
startAutoPlay({
interval: 2000,
seriesIndex: 0,
showTooltip: true,
});
// getInstance()?.off('click', onClick);
// getInstance()?.on('click', onClick);
}
function onClick(params) {
emit('click', params);
}
return { chartRef };
},
};
</script>