<template>
<div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">{{ params.title || 'ECharts Chart' }}</h5>
</div>
<div class="card-body">
<!-- v-chart is the component from vue-echarts -->
<!-- The 'autoresize' prop is a handy feature of the wrapper -->
<v-chart class="chart" :option="chartOption" autoresize />
</div>
</div>
</template>
<script>
// 1. Import vue-echarts and the core ECharts library
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { PieChart, BarChart, LineChart } from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
} from 'echarts/components';
import VChart from 'vue-echarts';
// 2. Register the ECharts components you plan to use (for tree-shaking)
use([
CanvasRenderer,
PieChart,
BarChart,
LineChart,
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
]);
export default {
components: {
VChart,
},
props: {
// 3. We use the EXACT SAME props as our other widgets
data: { type: Array, required: true },
params: { type: Object, required: true },
},
computed: {
/**
* The "Translator": This computed property builds the ECharts
* configuration object from our simplified `data` and `params` props.
*/
chartOption() {
// Start with a base configuration for a consistent look & feel
let baseOptions = {
title: {
text: this.params.title, // ECharts has a built-in title
left: 'center',
textStyle: {
fontSize: 16,
fontWeight: 'normal'
}
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
show: this.params.showLegend !== false, // Default to true
},
// Main data series configuration
series: this.data.map(seriesItem => ({
// Map our generic API to ECharts' specific keys
name: seriesItem.name,
data: seriesItem.data,
// ECharts often requires a 'type' per series
type: this.params.type || 'bar',
// Default styling for pie charts
radius: this.params.type === 'pie' ? '50%' : undefined,
})),
};
// Add axis configuration for non-pie charts
if (this.params.type !== 'pie' && this.params.categories) {
baseOptions.xAxis = { type: 'category', data: this.params.categories };
baseOptions.yAxis = { type: 'value' };
baseOptions.grid = { left: '3%', right: '4%', bottom: '3%', containLabel: true };
baseOptions.tooltip.trigger = 'axis'; // More suitable for bar/line charts
}
// "Escape Hatch": Just like before, allow for deep, custom overrides.
// This is crucial for accessing advanced ECharts features.
if (this.params.options) {
const merge = (target, source) => {
for (const key in source) {
if (source[key] instanceof Object && key in target) {
Object.assign(source[key], merge(target[key], source[key]))
}
}
Object.assign(target || {}, source)
return target
}
return merge(baseOptions, this.params.options);
}
return baseOptions;
},
},
};
</script>
<style scoped>
/* ECharts needs a defined height on its container to render */
.chart {
height: 100%;
min-height: 300px;
}
</style>