266 lines
6.6 KiB
Vue
266 lines
6.6 KiB
Vue
<template>
|
||
<div style="">
|
||
<Container name="利润主要影响因素·万元" icon="cockpitItemIcon" size="profitMiddleBasic" topSize="KFAPTopTitle">
|
||
<div class="kpi-content" style="padding: 14px 16px; display: flex;width: 100%;">
|
||
<div class="left" style="width: 382px;">
|
||
<top-item :itemList="targetItemList" />
|
||
</div>
|
||
<div class="bottom"
|
||
style="height: 227px; margin-left: 16px; display: flex; width: 100%;background-color: rgba(249, 252, 255, 1);">
|
||
<KFAPMiddleBar :chartData="{
|
||
allPlaceNames, incomeValueData, profitListData, costValueData, costCompletedData
|
||
}" />
|
||
</div>
|
||
</div>
|
||
</Container>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Container from './container.vue'
|
||
import topItem from './profit-item-middle.vue'
|
||
import KFAPMiddleBar from './KFAPMiddleBar.vue'
|
||
|
||
export default {
|
||
name: 'ProductionStatus',
|
||
components: { Container, topItem, KFAPMiddleBar },
|
||
props: {
|
||
middleChartData: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
middleItemData: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
parentItemList: [
|
||
{ name: "营业收入", targetValue: 0, value: 0, proportion: 0, route: 'operatingRevenue' },
|
||
{ name: "成本", targetValue: 0, value: 0, proportion: 0, route: 'cost/cost' },
|
||
]
|
||
}
|
||
},
|
||
computed: {
|
||
allPlaceNames() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.middleChartData.map(item => this.cleanPlaceName(item.name)).filter(Boolean)
|
||
},
|
||
PlaceNames() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.middleChartData.map(item => item.name).filter(Boolean);
|
||
},
|
||
profitListData() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.PlaceNames.map(place => {
|
||
const target = this.middleChartData.find(item => item.name === place);
|
||
console.log('target?.profit', target?.profit);
|
||
|
||
return target?.profit || 0;
|
||
});
|
||
},
|
||
incomeValueData() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.PlaceNames.map(place => {
|
||
const target = this.middleChartData.find(item => item.name === place);
|
||
return target?.income || 0;
|
||
});
|
||
},
|
||
costValueData() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.PlaceNames.map(place => {
|
||
const target = this.middleChartData.find(item => item.name === place);
|
||
return target?.cost || 0;
|
||
});
|
||
},
|
||
|
||
costCompletedData() {
|
||
if (!Array.isArray(this.middleChartData)) return [];
|
||
return this.PlaceNames.map(place => {
|
||
const target = this.middleChartData.find(item => item.name === place);
|
||
return target?.costCompleted || 0;
|
||
});
|
||
},
|
||
|
||
targetItemList() {
|
||
// 基于 parentItemList 的名称,匹配 productAndSaleData 中对应名称的数据
|
||
return this.parentItemList.map(parentItem => {
|
||
// 按名称精准匹配(name 完全一致才关联)
|
||
const productItem = this.middleItemData.find(
|
||
item => item.name === parentItem.name
|
||
) || {};
|
||
|
||
// 优先使用匹配到的 productItem 数据,缺失则用 parentItem 的默认值(0)
|
||
return {
|
||
name: parentItem.name, // 保留原名称(销量、产量等)
|
||
targetValue: productItem.targetValue ?? parentItem.targetValue ?? 0,
|
||
value: productItem.value ?? parentItem.value ?? 0,
|
||
proportion: productItem.proportion ?? parentItem.proportion ?? 0,
|
||
completed: productItem.completed ?? parentItem.completed ?? 1,
|
||
route: parentItem.route // 路由沿用 parentItem 的配置
|
||
};
|
||
});
|
||
}
|
||
},
|
||
methods: {
|
||
cleanPlaceName(place) {
|
||
return place?.replace('分公司', '') || ''; // 匹配“分公司”并替换为空,兼容null/undefined
|
||
},
|
||
// // 唯一的地名提取方法(定义在 methods 中,确保是函数)
|
||
// extractPlace(item) {
|
||
// if (!item?.name) return ''; // 处理空值,避免报错
|
||
// const match = item.name.match(/(.+?)(基地|利润总额|营业收入|成本)/);
|
||
// return match ? match[1] : item.name;
|
||
// }
|
||
}
|
||
}
|
||
</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;
|
||
}
|
||
|
||
.proBarInfo {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 8px 27px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.proBarInfoEqInfo {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.slot {
|
||
width: 21px;
|
||
height: 23px;
|
||
background: rgba(0, 106, 205, 0.22);
|
||
backdrop-filter: blur(1.5px);
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
color: #68B5FF;
|
||
line-height: 23px;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
|
||
.eq-name {
|
||
margin-left: 8px;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
color: #FFFFFF;
|
||
line-height: 18px;
|
||
letter-spacing: 1px;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
|
||
.eqStatus {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
color: #FFFFFF;
|
||
line-height: 18px;
|
||
text-align: right;
|
||
font-style: normal;
|
||
}
|
||
|
||
.splitLine {
|
||
width: 1px;
|
||
height: 14px;
|
||
border: 1px solid #ADADAD;
|
||
margin: 0 8px;
|
||
}
|
||
|
||
.yield {
|
||
height: 18px;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
color: #00FFFF;
|
||
line-height: 18px;
|
||
text-align: right;
|
||
font-style: normal;
|
||
}
|
||
|
||
.proBarInfoEqInfoLeft {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.proBarInfoEqInfoRight {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.proBarWrapper {
|
||
position: relative;
|
||
height: 10px;
|
||
margin-top: 6px;
|
||
border-radius: 5px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.proBarLine {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(65deg, rgba(82, 82, 82, 0) 0%, #ACACAC 100%);
|
||
opacity: 0.2;
|
||
}
|
||
|
||
.proBarLineTop {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
height: 100%;
|
||
background: linear-gradient(65deg, rgba(53, 223, 247, 0) 0%, rgba(54, 220, 246, 0.92) 92%, #36F6E5 100%, #37ACF5 100%);
|
||
border-radius: 5px;
|
||
transition: width 0.3s ease;
|
||
}
|
||
|
||
.chartImgBottom {
|
||
position: absolute;
|
||
bottom: 45px;
|
||
left: 58px;
|
||
}
|
||
|
||
.line {
|
||
display: inline-block;
|
||
position: absolute;
|
||
left: 57px;
|
||
bottom: 42px;
|
||
width: 1px;
|
||
height: 20px;
|
||
background-color: #00E8FF;
|
||
}
|
||
</style>
|
||
|
||
<style>
|
||
.production-status-chart-tooltip {
|
||
background: #0a2b4f77 !important;
|
||
border: none !important;
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
|
||
.production-status-chart-tooltip * {
|
||
color: #fff !important;
|
||
}
|
||
</style>
|