Files
yudao-dev/src/views/home/components/financeCostsBottomBar.vue
‘937886381’ 51e66cf6e1 修改
2026-01-06 17:09:52 +08:00

261 lines
6.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 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>