261 lines
6.9 KiB
Vue
261 lines
6.9 KiB
Vue
<template>
|
||
<div class="coreBar">
|
||
<div class="barTop">
|
||
<div class="barTop-left" style="display: flex;">
|
||
<div class="title">财务指标趋势</div>
|
||
<div class="legend">
|
||
<span class="legend-item target">预算</span>
|
||
<span class="legend-item real">实际</span>
|
||
</div>
|
||
</div>
|
||
<div class="button-group">
|
||
<div style="width: 59px;" class="item-button" :class="{ active: activeButton === 0 }" @click="activeButton = 0">
|
||
营业收入
|
||
</div>
|
||
<div class="button-line lineOne" v-if="activeButton !== 0 && activeButton !== 1"></div>
|
||
|
||
<div style="width: 75px;" class="item-button" :class="{ active: activeButton === 1 }" @click="activeButton = 1">
|
||
经营性利润
|
||
</div>
|
||
<div class="button-line lineTwo" v-if="activeButton !== 1 && activeButton !== 2"></div>
|
||
|
||
<div class="item-button" :class="{ active: activeButton === 2 }" @click="activeButton = 2">
|
||
利润总额
|
||
</div>
|
||
<div class="button-line lineThree" v-if="activeButton !== 2 && activeButton !== 3"></div>
|
||
|
||
<div class="item-button" :class="{ active: activeButton === 3 }" @click="activeButton = 3">
|
||
毛利率
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="lineBottom" style="height: 210px; width: 100%">
|
||
<!-- 传递当前选中的 series 数据和 xAxis 数据给子组件 -->
|
||
<coreLineChart style="height: 210px; width: 680px" :chart-series="currentSeries" :x-axis-data="xAxisData"
|
||
:dateData="dateData" />
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import coreLineChart from './coresBar.vue';
|
||
import * as echarts from 'echarts';
|
||
|
||
export default {
|
||
name: "Container",
|
||
components: { coreLineChart },
|
||
props: {
|
||
line: { // 接收父组件传递的 line 数据
|
||
type: Object,
|
||
default: () => ({})
|
||
},
|
||
dateData: { // 接收父组件传递的 line 数据
|
||
type: Object,
|
||
default: () => ({})
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
activeButton: 0, // 初始激活第一个按钮(索引0)
|
||
// 定义按钮与 line 数据中 key 的映射关系
|
||
buttonToDataKey: [
|
||
'营业收入',
|
||
'经营性利润', // 注意:数据中的 key 是“经营收入”,按钮显示的是“经营性利润”
|
||
'利润总额',
|
||
'毛利率'
|
||
]
|
||
};
|
||
},
|
||
computed: {
|
||
// 根据当前激活的按钮,动态生成对应的 series 数据
|
||
currentSeries() {
|
||
|
||
const dataKey = this.buttonToDataKey[this.activeButton];
|
||
const chartData = this.line[dataKey];
|
||
console.log('this.line[dataKey', this.buttonToDataKey[this.activeButton]);
|
||
|
||
if (!chartData) {
|
||
return [];
|
||
}
|
||
|
||
// 提取目标和实际数据的值
|
||
const targetDataValues = Object.values(chartData.target || {});
|
||
const realDataValues = Object.values(chartData.real || {});
|
||
console.log('realDataValues', realDataValues);
|
||
|
||
return [
|
||
{
|
||
name: '预算',
|
||
type: 'line',
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: { color: 'rgba(91, 230, 190, 1)' },
|
||
itemStyle: { color: 'rgba(91, 230, 190, 1)', borderColor: 'rgba(91, 230, 190, 1)', borderWidth: 2 },
|
||
areaStyle: {
|
||
opacity: 0.3,
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: 'rgba(91, 230, 190, 0.4)' },
|
||
{ offset: 1, color: 'rgba(91, 230, 190, 0)' },
|
||
]),
|
||
},
|
||
data: targetDataValues
|
||
},
|
||
{
|
||
name: '实际',
|
||
type: 'line',
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: { color: 'rgba(255, 132, 0, 1)' },
|
||
itemStyle: { color: 'rgba(255, 132, 0, 1)', borderColor: 'rgba(255, 132, 0, 1)', borderWidth: 2 },
|
||
areaStyle: {
|
||
opacity: 0.3,
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: 'rgba(255, 132, 0, 0.4)' },
|
||
{ offset: 1, color: 'rgba(255, 132, 0, 0)' },
|
||
]),
|
||
},
|
||
data: realDataValues
|
||
}
|
||
];
|
||
},
|
||
// 提取 x 轴数据(日期)
|
||
xAxisData() {
|
||
const dataKey = this.buttonToDataKey[this.activeButton];
|
||
const chartData = this.line[dataKey];
|
||
// 使用 'target' 的键作为 x 轴,如果 'target' 不存在,则使用 'real' 的键
|
||
if (chartData && chartData.target) {
|
||
return Object.keys(chartData.target);
|
||
} else if (chartData && chartData.real) {
|
||
return Object.keys(chartData.real);
|
||
}
|
||
return [];
|
||
}
|
||
},
|
||
methods: {}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
/* 原有样式保持不变 */
|
||
.coreBar {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 12px;
|
||
|
||
.barTop {
|
||
display: flex;
|
||
gap: 8px;
|
||
justify-content: space-between;
|
||
|
||
.title {
|
||
height: 18px;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 18px;
|
||
color: #000000;
|
||
line-height: 18px;
|
||
letter-spacing: 1px;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
|
||
.legend {
|
||
display: flex;
|
||
gap: 24px;
|
||
margin-left: 30px;
|
||
|
||
.legend-item {
|
||
position: relative;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-size: 14px;
|
||
color: rgba(0, 0, 0, 0.8);
|
||
|
||
&::before {
|
||
content: "";
|
||
position: absolute;
|
||
left: -13px;
|
||
top: 30%;
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
&::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: -16px;
|
||
top: 38%;
|
||
width: 12px;
|
||
height: 2px;
|
||
}
|
||
}
|
||
|
||
.target::before,
|
||
.target::after {
|
||
background-color: rgba(91, 230, 190, 1);
|
||
}
|
||
|
||
.real::before,
|
||
.real::after {
|
||
background-color: rgba(255, 132, 0, 1);
|
||
}
|
||
}
|
||
|
||
.button-group {
|
||
display: flex;
|
||
position: relative;
|
||
gap: 2px;
|
||
width: 252px;
|
||
align-items: center;
|
||
height: 24px;
|
||
background: #ecf4fe;
|
||
border-radius: 12px;
|
||
|
||
.button-line {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 14px;
|
||
border: 1px solid rgba(11, 88, 255, 0.25);
|
||
}
|
||
|
||
.lineOne {
|
||
top: 5px;
|
||
left: 59px;
|
||
}
|
||
|
||
.lineTwo {
|
||
top: 5px;
|
||
left: 134px;
|
||
}
|
||
|
||
.lineThree {
|
||
top: 5px;
|
||
left: 193px;
|
||
}
|
||
|
||
.item-button {
|
||
cursor: pointer;
|
||
width: 54px;
|
||
height: 24px;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 12px;
|
||
color: #0b58ff;
|
||
line-height: 24px;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
|
||
.item-button.active {
|
||
width: 54px;
|
||
height: 24px;
|
||
background: #3071ff;
|
||
border-radius: 12px;
|
||
color: #ffffff;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|