251 lines
5.3 KiB
Vue
251 lines
5.3 KiB
Vue
<template>
|
||
<div class="supply-chart-container">
|
||
<!-- 柱状图 -->
|
||
<EChart :options="barOption" :height="height" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { EChartsOption } from 'echarts'
|
||
// @ts-ignore
|
||
import EChart from '@/components/Echart/src/Echart.vue'
|
||
import { computed, watch } from 'vue'
|
||
|
||
defineOptions({ name: 'BarChart' })
|
||
|
||
interface ChartDataItem {
|
||
category: string
|
||
monthlyStandard: number
|
||
perCapita: number
|
||
}
|
||
|
||
interface CardData {
|
||
inProgress: number
|
||
toWarehouse: number
|
||
outWarehouse: number
|
||
}
|
||
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
width?: number
|
||
height?: string
|
||
data?: ChartDataItem[]
|
||
cardData?: CardData
|
||
}>(),
|
||
{
|
||
width: 400,
|
||
height: '300px',
|
||
data: () => [],
|
||
cardData: () => ({
|
||
inProgress: 5,
|
||
toWarehouse: 5,
|
||
outWarehouse: 5
|
||
})
|
||
}
|
||
)
|
||
|
||
// 创建图表配置
|
||
const createChartOption = (): EChartsOption => {
|
||
const categories = props.data.map((item) => item.category)
|
||
const monthlyStandardData = props.data.map((item) => item.monthlyStandard)
|
||
const perCapitaData = props.data.map((item) => item.perCapita)
|
||
|
||
// 创建底色数据(最大值50)
|
||
const maxValue = 50
|
||
const monthlyStandardBgData = categories.map((_, index) => maxValue - monthlyStandardData[index])
|
||
const perCapitaBgData = categories.map((_, index) => maxValue - perCapitaData[index])
|
||
|
||
return {
|
||
backgroundColor: 'transparent',
|
||
grid: {
|
||
left: '10%',
|
||
right: '15%',
|
||
top: '20%',
|
||
bottom: '15%',
|
||
containLabel: false
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
data: categories,
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#38668D50'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
color: '#D8F0FF',
|
||
fontSize: 10,
|
||
interval: 0,
|
||
rotate: 0
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
min: 0,
|
||
max: 50,
|
||
interval: 10,
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
},
|
||
axisLabel: {
|
||
color: '#D8F0FF',
|
||
fontSize: 10
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: '#38668D20',
|
||
type: 'dashed'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['支出', '收入'],
|
||
top: '5%',
|
||
right: '10%',
|
||
textStyle: {
|
||
color: '#6D869A',
|
||
fontSize: 9
|
||
},
|
||
itemWidth: 9,
|
||
itemHeight: 9,
|
||
itemGap: 25
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'shadow'
|
||
},
|
||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||
borderColor: 'rgba(0, 167, 255, 0.5)',
|
||
textStyle: {
|
||
color: '#D8F0FF',
|
||
fontSize: 10
|
||
},
|
||
formatter: function (params: any) {
|
||
let result = params[0].name + '<br/>'
|
||
// 只显示数据系列,不显示底色系列
|
||
params.forEach((param: any) => {
|
||
if (param.seriesName === '支出' || param.seriesName === '收入') {
|
||
result += param.marker + param.seriesName + ': ' + param.value + '<br/>'
|
||
}
|
||
})
|
||
return result
|
||
}
|
||
},
|
||
series: [
|
||
// 支出数据(渐变)- 先绘制,作为底层
|
||
{
|
||
name: '支出',
|
||
type: 'bar',
|
||
stack: 'monthly',
|
||
data: monthlyStandardData,
|
||
itemStyle: {
|
||
color: {
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 0,
|
||
color: '#10A0F2'
|
||
},
|
||
{
|
||
offset: 1,
|
||
color: 'rgba(0, 82, 184, 0)'
|
||
}
|
||
]
|
||
}
|
||
},
|
||
barWidth: '20%',
|
||
barGap: '20%'
|
||
},
|
||
// 支出底色 - 后绘制,堆叠在数据上方
|
||
{
|
||
name: '支出底色',
|
||
type: 'bar',
|
||
stack: 'monthly',
|
||
data: monthlyStandardBgData,
|
||
itemStyle: {
|
||
color: '#38668D70'
|
||
},
|
||
barWidth: '20%',
|
||
barGap: '20%',
|
||
silent: true,
|
||
tooltip: {
|
||
show: false
|
||
}
|
||
},
|
||
// 收入数据(渐变)
|
||
{
|
||
name: '收入',
|
||
type: 'bar',
|
||
stack: 'perCapita',
|
||
data: perCapitaData,
|
||
itemStyle: {
|
||
color: {
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 0,
|
||
color: '#FFA58D'
|
||
},
|
||
{
|
||
offset: 1,
|
||
color: 'rgba(87, 140, 205, 0)'
|
||
}
|
||
]
|
||
}
|
||
},
|
||
barWidth: '20%',
|
||
barGap: '80%'
|
||
},
|
||
{
|
||
name: '收入底色',
|
||
type: 'bar',
|
||
stack: 'perCapita',
|
||
data: perCapitaBgData,
|
||
itemStyle: {
|
||
color: '#38668D70'
|
||
},
|
||
barWidth: '20%',
|
||
barGap: '80%',
|
||
silent: true,
|
||
tooltip: {
|
||
show: false
|
||
}
|
||
}
|
||
]
|
||
}
|
||
}
|
||
|
||
// 柱状图配置
|
||
const barOption = computed(() => createChartOption())
|
||
|
||
// 监听数据变化,更新图表
|
||
watch(
|
||
() => [props.data, props.cardData],
|
||
() => {
|
||
// 数据变化时,computed 会自动更新
|
||
},
|
||
{ deep: true }
|
||
)
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.supply-chart-container {
|
||
width: 100%;
|
||
}
|
||
</style>
|