Files
yudao-dev/src/views/home/grossMarginComponents/monthlyRelatedMetrics.vue

225 lines
6.5 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 style="flex: 1">
<Container :name="title" icon="cockpitItemIcon" size="operatingRevenueBg" topSize="middle">
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%;">
<div class="topItem-container" style="display: flex; gap: 8px; width: 100%;">
<!-- 累计指标1 -->
<div class="dashboard left" @click="handleDashboardClick('/operatingRevenue/operatingRevenueBase')">
<div style='position: relative;'>
<div class="title">
营业收入·万元
</div>
</div>
<div style='font-size: 16px;text-align: right;padding-right: 5px;'>
<span>完成率:<span style='color: #0B58FF;'>{{ytdIncomeData.rate}}%</span></span>
<span style='display: inline-block;margin-left: 10px;'>差值:<span :style="{color:ytdIncomeData.flag>0?'#30B590':'#FF9423'}" >{{ytdIncomeData.diff}}</span></span>
</div>
<div class="chart-wrap">
<operatingSingleBar :detailData="ytdIncomeData"></operatingSingleBar>
</div>
</div>
<!-- 累计指标2 -->
<div class="dashboard right" @click="handleDashboardClick('/fullCostAnalysis/fullCostAnalysisBase')">
<div style='position: relative;'>
<div class="title">
全成本·/
</div>
</div>
<div style='font-size: 16px;text-align: right;padding-right: 5px;'>
<span>完成率:<span style='color: #0B58FF;'>{{ytdCostData.rate}}%</span></span>
<span style='display: inline-block;margin-left: 10px;'>差值:<span :style="{color:ytdCostData.flag>0?'#30B590':'#FF9423'}" >{{ytdCostData.diff}}</span></span>
</div>
<div class="chart-wrap">
<operatingSingleBar :detailData="ytdCostData"></operatingSingleBar>
</div>
</div>
</div>
</div>
</Container>
</div>
</template>
<script>
import Container from './container.vue'
import operatingSingleBar from './operatingSingleBar.vue'
import { pushNavigation, saveNavigationState } from '@/utils/navigationReturnState';
export default {
name: 'yearRelatedMetrics',
components: { Container, operatingSingleBar },
props: {
monthAnalysis: {
type: Array,
// 正确写法:默认值通过 factory 函数返回(才能调用 default()
default: () => [
{ title: "营业收入", budget: 0, real: 0, rate: 0, diff: 0 },
{ title: "累计全成本", budget: 0, real: 0, rate: 0, diff: 0 }
]
},
dateData: { // 接收父组件传递的设备数据数组
type: Object,
default: () => { } // 默认空数组,避免报错
},
factory: {
type: [String, Number],
default: ''
},
title: {
type: String,
default: ''
}
},
data() {
return {
ytdIncomeData: { title: "营业收入", budget: 0, real: 0, rate: 0, diff: 0, flag: 0 },
ytdCostData: { title: "累计全成本", budget: 0, real: 0, rate: 0, diff: 0, flag: 0 }
}
},
watch: {
monthAnalysis: {
handler(newVal) {
this.updateChart(newVal)
},
deep: true,
immediate: true
}
},
mounted() {
this.updateChart(this.monthAnalysis)
},
methods: {
handleDashboardClick(path) {
const toPage = path.split('/').pop();
// 保存当前页面状态并入栈
const currentPath = this.$route.path;
const state = {
dateData: {
startTime: this.dateData.startTime,
endTime: this.dateData.endTime
},
factory: this.$route.query.factory || this.factory,
toPage
};
pushNavigation(currentPath, state);
saveNavigationState(currentPath, state);
// query 仅支持字符串,时间范围用 startTime/endTime 传递
this.$router.push({
path: path,
query: {
factory: this.$route.query.factory ? this.$route.query.factory : this.factory,
startTime: this.dateData && this.dateData.startTime != null ? String(this.dateData.startTime) : '',
endTime: this.dateData && this.dateData.endTime != null ? String(this.dateData.endTime) : ''
}
})
},
updateChart(data) {
// 数据兜底确保是数组且长度≥2否则取 props 默认值
const validData = Array.isArray(data) && data.length >= 2
? data
: this.$props.monthAnalysis; // 直接取 props 默认值
// 按 title 匹配目标项(不依赖数组顺序,兼容后端数据结构顺序变化)
const list = Array.isArray(validData) ? validData : []
// 营业收入:精确匹配
const incomeItem = list.find(item => item && item.title === '营业收入')
|| { title: "营业收入", budget: 0, real: 0, rate: 0, diff: 0 };
const costItem = list.find(item => item && item.title === '全成本')
|| { title: "全成本", budget: 0, real: 0, rate: 0, diff: 0 };
// 整合flag字段
this.ytdIncomeData = {
...incomeItem,
flag: incomeItem.rate > 100 ? 1 : 0
};
this.ytdCostData = {
...costItem,
flag: costItem.rate > 100 ? 1 : 0
};
}
}
}
</script>
<style lang='scss' scoped>
// 样式与之前一致,无需修改
.scroll-container {
max-height: 210px;
overflow-y: auto;
overflow-x: hidden;
padding: 10px 0;
&::-webkit-scrollbar {
display: none;
}
scrollbar-width: none;
-ms-overflow-style: none;
}
.topItem-container {
display: flex;
justify-content: space-between;
}
.dashboard {
flex: 1;
min-width: 300px;
height: 205px;
background: #F9FCFF;
padding: 16px 0 0 10px;
margin: 0 4px;
.title {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 2px;
text-align: left;
}
.chart-wrap {
width: 100%;
height: calc(100% - 42px);
}
.number {
display: flex;
align-items: center;
gap: 30px;
height: 32px;
font-family: YouSheBiaoTiHei;
font-size: 32px;
color: #0B58FF;
line-height: 32px;
letter-spacing: 2px;
text-align: left;
}
.mom {
width: 97px;
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
z-index: 1000;
}
}
.dashboard.left {
margin-left: 0;
}
.dashboard.right {
margin-right: 0;
}
</style>