293 lines
6.8 KiB
Vue
293 lines
6.8 KiB
Vue
<template>
|
||
<div style="flex: 1">
|
||
<Container name="累计数据对比" icon="cockpitItemIcon" size="operatingLarge" topSize="large">
|
||
<!-- 1. 移除 .kpi-content 的固定高度,改为自适应 -->
|
||
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%; gap: 16px">
|
||
<div class="left" style="
|
||
height: 380px;
|
||
display: flex;
|
||
width: 348px;
|
||
background-color: rgba(249, 252, 255, 1);
|
||
flex-direction: column;
|
||
">
|
||
<div style="
|
||
font-weight: 400;
|
||
font-size: 18px;
|
||
color: #000000;
|
||
line-height: 18px;
|
||
letter-spacing: 1px;
|
||
font-style: normal;
|
||
padding: 16px 0 0 16px;
|
||
">
|
||
集团情况
|
||
</div>
|
||
<operatingTopBar :chartData="groupData" />
|
||
</div>
|
||
<div class="right" style="
|
||
height: 380px;
|
||
display: flex;
|
||
width: 1220px;
|
||
background-color: rgba(249, 252, 255, 1);
|
||
">
|
||
<!-- <top-item /> -->
|
||
<operatingBar :dateData="dateData" :chartData="chartData" @sort-change="sortChange" />
|
||
</div>
|
||
</div>
|
||
</Container>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Container from "../components/container.vue";
|
||
import operatingBar from "./operatingBar.vue";
|
||
import operatingTopBar from "./operatingTopBar.vue";
|
||
|
||
export default {
|
||
name: "ProductionStatus",
|
||
components: { Container, operatingBar, operatingTopBar },
|
||
props: {
|
||
totalData: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
required: true, // 标记为必填,避免空数据导致异常
|
||
},
|
||
dateData: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
chartData: null, // 工厂图表数据
|
||
groupData: {}, // 集团(凯盛新能)数据
|
||
};
|
||
},
|
||
watch: {
|
||
totalData: {
|
||
handler() {
|
||
this.processChartData();
|
||
},
|
||
immediate: true,
|
||
deep: true,
|
||
},
|
||
},
|
||
methods: {
|
||
// 透传排序变化事件给父组件
|
||
sortChange(value) {
|
||
this.$emit('sort-change', value);
|
||
},
|
||
|
||
/**
|
||
* 判断完成率对应的flag值(<100为0,≥100为1)
|
||
* @param {number} rate 完成率(原始值,如80代表80%)
|
||
* @returns {0|1} flag值
|
||
*/
|
||
getRateFlag(rate, real, target) {
|
||
if (isNaN(rate) || rate === null || rate === undefined) return 0;
|
||
|
||
// 1. 完成率 >= 100 => 达标
|
||
if (rate >= 100) return 1;
|
||
|
||
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
|
||
if (rate === 0 && target === 0) return 1;
|
||
|
||
// 其他情况 => 未达标
|
||
return 0;
|
||
},
|
||
|
||
/**
|
||
* 核心处理函数:解析thisMonData,组装集团和工厂数据
|
||
*/
|
||
processChartData() {
|
||
// 1. 处理集团数据(凯盛新能)
|
||
const ksxnData = this.totalData['凯盛新能'] || {
|
||
completeRate: 0,
|
||
diff: 0,
|
||
real: 0,
|
||
target: 0,
|
||
thb: 0
|
||
};
|
||
this.groupData = {
|
||
locations: ['凯盛新能'],
|
||
targets: [ksxnData.target],
|
||
diff: [ksxnData.diff],
|
||
reals: [ksxnData.real],
|
||
rate: [ksxnData.completeRate],
|
||
flags: [this.getRateFlag(ksxnData.completeRate, ksxnData.real, ksxnData.target)],
|
||
thb: [ksxnData.thb] // 新增thb字段(如果子组件需要)
|
||
};
|
||
|
||
// 2. 处理工厂数据(排除凯盛新能)
|
||
const factoryKeys = Object.keys(this.totalData).filter(key => key !== '凯盛新能');
|
||
const factoryDataList = factoryKeys.map(key => this.totalData[key]);
|
||
|
||
// 3. 组装工厂chartData(格式与集团一致,适配子组件)
|
||
this.chartData = {
|
||
locations: factoryKeys, // 工厂名称数组
|
||
targets: factoryDataList.map(item => item.target || 0), // 预算值
|
||
diff: factoryDataList.map(item => item.diff || 0), // 差值
|
||
reals: factoryDataList.map(item => item.real || 0), // 实际值
|
||
rates: factoryDataList.map(item => item.completeRate || 0), // 完成率
|
||
flags: factoryDataList.map(item => this.getRateFlag(item.completeRate, item.real, item.target)), // 完成率标识
|
||
thb: factoryDataList.map(item => item.thb || 0) // thb字段
|
||
};
|
||
|
||
console.log('组装后的集团数据:', this.groupData);
|
||
console.log('组装后的工厂数据:', this.chartData);
|
||
},
|
||
},
|
||
};
|
||
</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>
|
||
/* 全局 tooltip 样式 */
|
||
.production-status-chart-tooltip {
|
||
background: #0a2b4f77 !important;
|
||
border: none !important;
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
|
||
.production-status-chart-tooltip * {
|
||
color: #fff !important;
|
||
}
|
||
</style>
|