Files
yudao-dev/src/views/home/components/top-product-item.vue
‘937886381’ 5605eeab06 xiugai
2026-01-06 13:48:11 +08:00

310 lines
7.0 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 class="coreItem">
<div class="item" :class="`item${index + 1}`" @click="handleItemClick(index)" v-for="(item, index) in itemList"
:key="index">
<div class="unit">{{ item.unit }}</div>
<div class="item-content">
<div class="content-wrapper">
<div class="left">
<div class="number">{{ item.target }}</div>
<div class="title">目标值</div>
</div>
<div class="line"></div>
<div class="right">
<!-- 实际值颜色动态绑定 -->
<div class="number" :style="{ color: getColor(index) }">
{{ item.actual }}
</div>
<div class="title">实际值</div>
</div>
</div>
<div class="progress-group">
<div class="progress-container">
<!-- 进度条样式动态绑定 -->
<div class="progress-bar" :style="{
width: `${item.progress}%`,
background: getColor(index)
}"></div>
</div>
<!-- 百分比颜色动态绑定 -->
<div class="progress-percent" :style="{ color: getColor(index) }">
{{ item.progress }}%
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Container",
components: {},
// 接收父组件传递过来的原始 itemList 对象
props: ['rawItemList','dateData'],
data() {
return {
// 组件内部用于渲染的数组
itemList: [],
activeIndex: -1
};
},
// 监听 props 中的 rawItemList 变化
watch: {
rawItemList: {
handler(newVal) {
if (newVal) {
this.itemList = this.transformData(newVal);
}
},
immediate: true, // 组件初始化时立即执行一次
deep: true // 深度监听对象内部变化
}
},
methods: {
/**
* 核心转换函数:将对象转换为组件需要的数组格式
* @param {Object} rawData - 父组件传递的原始数据对象
* @returns {Array} - 转换后的数组
*/
transformData(rawData) {
// 定义一个映射关系,将后端字段名与前端显示信息关联起来
const dataMap = [
{
key: 'processCost',
unit: '制造成本·元/㎡',
route: '/productionCostAnalysis/productionCostAnalysis'
},
{
key: 'rawCost',
unit: '原片成本·元/㎡',
route: '/productionCostAnalysis/originalSheetCost'
},
{
key: 'processCost',
unit: '加工成本·元/㎡',
route: '/productionCostAnalysis/processingCostAnalysis'
},
{
key: 'rawYield',
unit: '原片成品率·%',
route: '/rawSheetYield/rawSheetYield' // 假设这个没有路由
},
{
key: 'ioYield',
unit: '投入产出率·%',
route: '/inputOutputRatio/inputOutputRatio' // 假设这个没有路由
}
];
// 使用 map 方法将 dataMap 数组转换为组件需要的 itemList 数组
return dataMap.map(itemInfo => {
const rawItem = rawData[itemInfo.key] || {};
// 计算进度百分比确保不小于0
const progress = Math.max(0, Math.round((rawItem.rate || 0)));
return {
unit: itemInfo.unit,
route: itemInfo.route,
target: rawItem.target || 0,
actual: rawItem.real || 0,
progress: progress
};
});
},
handleItemClick(index) {
const currentItem = this.itemList[index];
console.log(`点击了第${index + 1}个item:`, currentItem.unit);
this.$emit('item-click', { index, ...currentItem });
this.activeIndex = index;
if (currentItem.route) {
this.$router.push({
path: currentItem.route,
query: {
dateData: this.dateData
}
});
}
},
// 判断颜色的方法
getColor(index) {
const { actual, target, progress } = this.itemList[index];
// 新增条件如果实际值、目标值和进度都为0则显示绿色
if (actual === 0 && target === 0 && progress === 0) {
return "rgba(98, 213, 180, 1)"; // 绿色
}
// 原有的通用判断逻辑
return progress >= 100
? "rgba(98, 213, 180, 1)" // 绿色
: "rgba(249, 164, 74, 1)"; // 橙色
}
}
};
</script>
<style scoped lang="scss">
/* (你的样式代码保持不变) */
.coreItem {
display: flex;
flex-wrap: wrap;
gap: 8px;
box-sizing: border-box;
}
.coreItem> :nth-child(1) {
grid-area: item1;
&:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
}
}
.coreItem> :nth-child(2) {
grid-area: item2;
&:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
}
}
.coreItem> :nth-child(3) {
grid-area: item3;
&:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
}
}
.coreItem> :nth-child(4) {
grid-area: item4;
&:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
}
}
.coreItem> :nth-child(5) {
grid-area: item5;
&:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
}
}
.item {
width: 252px;
height: 110px;
background: #f9fcff;
padding: 12px;
box-sizing: border-box;
cursor: pointer;
transition: all 0.2s ease;
&:active {
transform: scale(0.98);
}
.unit {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
font-style: normal;
margin-bottom: 8px;
}
.item-content {
display: flex;
flex-direction: column;
justify-content: space-between;
height: calc(100% - 26px);
}
.content-wrapper {
display: flex;
align-items: center;
justify-content: space-around;
flex: 1;
}
.line {
width: 1px;
height: 46px;
background: linear-gradient(to bottom,
rgba(255, 0, 0, 0),
#cbcbcb);
}
.left,
.right {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 2px;
flex: 1;
}
.number {
height: 22px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 24px;
color: rgba(103, 103, 103, 0.79);
line-height: 22px;
text-align: center;
font-style: normal;
}
.title {
height: 14px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #868687;
line-height: 14px;
text-align: center;
font-style: normal;
}
.progress-group {
display: flex;
align-items: center;
gap: 8px;
}
.progress-container {
width: 190px;
height: 10px;
background: #ECEFF7;
border-radius: 8px;
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 8px;
transition: width 0.3s ease;
}
.progress-percent {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 1;
}
}
.item1,
.item2,
.item3 {
width: 166px;
}
</style>