Files
yudao-dev/src/views/home/fullCostAnalysisComponents/operatingLineChart.vue
‘937886381’ b76f3bfd37 修改
2026-01-07 16:47:49 +08:00

293 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 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: {
thisMonData: {
type: Object,
default: () => ({}),
required: true, // 标记为必填,避免空数据导致异常
},
dateData: {
type: Object,
default: () => ({})
},
},
data() {
return {
chartData: null, // 工厂图表数据
groupData: {}, // 集团(凯盛新能)数据
};
},
watch: {
thisMonData: {
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.thisMonData['凯盛新能'] || {
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.thisMonData).filter(key => key !== '凯盛新能');
const factoryDataList = factoryKeys.map(key => this.thisMonData[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>