293 lines
6.9 KiB
Vue
293 lines
6.9 KiB
Vue
<template>
|
||
<div style="flex: 1">
|
||
<Container name="数据趋势" icon="cockpitItemIcon" size="opLargeBg" topSize="large">
|
||
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%; gap: 16px">
|
||
<div class="right" style="
|
||
height: 191px;
|
||
display: flex;
|
||
width: 1595px;
|
||
background-color: rgba(249, 252, 255, 1);
|
||
">
|
||
<dataTrendBar @changeItem="handleChange" :chartData="chartData" />
|
||
</div>
|
||
</div>
|
||
</Container>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Container from "../components/container.vue";
|
||
import dataTrendBar from "./dataTrendBar.vue";
|
||
|
||
export default {
|
||
name: "ProductionStatus",
|
||
components: { Container, dataTrendBar },
|
||
props: {
|
||
trend: {
|
||
type: Array,
|
||
// 默认值与实际数据结构一致(12个月)
|
||
default: () => [
|
||
// { title: "2025年01月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年02月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年03月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年04月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年05月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年06月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年07月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年08月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年09月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年10月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年11月", budget: 0, real: 0, rate: 0, diff: 0 },
|
||
// { title: "2025年12月", budget: 0, real: 0, rate: 0, diff: 0 }
|
||
]
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
chartData: {
|
||
months: [], // 月份数组(2025年01月 - 2025年12月)
|
||
rates: [], // 每月完成率(百分比)
|
||
reals: [], // 每月实际值
|
||
budgets: [],// 每月预算值
|
||
diffs: [], // 每月差值
|
||
flags: [] // 每月达标标识(≥100 → 1,<100 → 0)
|
||
}
|
||
};
|
||
},
|
||
watch: {
|
||
trend: {
|
||
handler(newVal) {
|
||
this.processTrendData(newVal);
|
||
},
|
||
immediate: true,
|
||
deep: true,
|
||
},
|
||
},
|
||
mounted() {
|
||
this.processTrendData(this.trend);
|
||
},
|
||
methods: {
|
||
handleChange(value) {
|
||
this.$emit("handleChange", value);
|
||
},
|
||
/**
|
||
* 处理趋势数据(适配12个月的数组结构)
|
||
* @param {Array} trendData - 原始趋势数组(12个月)
|
||
*/
|
||
processTrendData(trendData) {
|
||
// 数据兜底:确保是数组且长度为12
|
||
const validTrend = Array.isArray(trendData) && trendData.length === 12
|
||
? trendData
|
||
: this.$props.trend.default();
|
||
|
||
// 初始化空数组
|
||
const months = [];
|
||
const rates = [];
|
||
const reals = [];
|
||
const budgets = [];
|
||
const diffs = [];
|
||
const flags = [];
|
||
|
||
// 遍历12个月数据
|
||
validTrend.forEach(item => {
|
||
// 基础数据提取(兜底处理)
|
||
const month = item.title ?? '';
|
||
const budget = Number(item.budget) || 0;
|
||
const real = Number(item.real) || 0;
|
||
const rate = Number(item.rate) || 0;
|
||
const diff = Number(item.diff) || 0;
|
||
|
||
// 计算达标标识(≥100 → 1,<100 → 0)
|
||
const flag = this.getRateFlag(rate);
|
||
|
||
// 填充数组
|
||
months.push(month);
|
||
rates.push(Math.round(rate * 100)); // 转为百分比并取整
|
||
reals.push(real);
|
||
budgets.push(budget);
|
||
diffs.push(diff);
|
||
flags.push(flag);
|
||
});
|
||
|
||
// 更新chartData(响应式)
|
||
this.chartData = {
|
||
months,
|
||
rates,
|
||
reals,
|
||
budgets,
|
||
diffs,
|
||
flags
|
||
};
|
||
|
||
console.log('处理后的趋势数据:', this.chartData);
|
||
},
|
||
|
||
/**
|
||
* 计算达标标识
|
||
* @param {Number} rate - 完成率(原始值,如1.2 → 120%)
|
||
* @returns {Number} 1: 达标(≥100%),0: 未达标(<100%)
|
||
*/
|
||
getRateFlag(rate) {
|
||
if (isNaN(rate) || rate === null || rate === undefined) return 0;
|
||
// 原始rate若为小数(如0.8 → 80%,1.1 → 110%),则*100后判断
|
||
const ratePercent = rate;
|
||
return ratePercent >= 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;
|
||
}
|
||
|
||
/* 设备项样式优化 */
|
||
.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>
|