Files
yudao-dev/src/views/home/costComponents/processingCost-Item.vue
‘937886381’ 51e66cf6e1 修改
2026-01-06 17:09:52 +08:00

331 lines
9.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-container" @mousedown="handleMouseDown" @mousemove="handleMouseMove" @mouseup="handleMouseUp"
@mouseleave="handleMouseUp" :style="{ cursor: isDragging ? 'grabbing' : 'grab' }">
<div class="coreItem">
<div class="item" @click="handleRoute(item.route,item.name)" v-for="(item, index) in finalItemList" :key="index">
<div class="item-header">
<div class="unit">{{ item.name }}</div>
</div>
<div class="item-content">
<div class="content-wrapper">
<!-- 预算值 + 分割线 + 实际值 -->
<div class="value-group">
<div class="value-item">
<div class="number">{{ item.targetValue || 0 }}</div>
<div class="title">预算值</div>
</div>
<div class="middle-line"></div>
<div class="value-item">
<!-- 实际值根据 flag 动态绑定颜色 -->
<div class="number" :style="{ color: getColorByFlag(item.flag) }">
{{ item.value || 0 }}
</div>
<div class="title">实际值</div>
</div>
</div>
<!-- 进度条 + 完成率 -->
<div class="progress-yield-group">
<div class="progress-group">
<div class="progress-container">
<div class="progress-bar" :style="{
width: getProportionPercent(item.proportion) + '%',
background: getColorByFlag(item.flag, true)
}"></div>
</div>
</div>
<div class="yield">
<span class="progress-percent" :style="{ color: getColorByFlag(item.flag) }">完成率</span>
<!-- 完成率动态颜色 + 百分比格式 -->
<span class="progress-percent progress-value" :style="{ color: getColorByFlag(item.flag) }">
{{ getProportionPercent(item.proportion) }}%
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Container",
components: {},
props: ["name", "size", "icon", 'processCostViews'],
data() {
return {
itemList: [
{
name: "人工", targetValue: 0, value: 0, proportion: 0, flag: 0,
// route:'cost/rawMaterialCostAnalysis/rawMaterialCostAnalysis'
},
{ name: "燃动力", targetValue: 0, value: 0, proportion: 0, flag: 0, route:'fuelPowerCostAnalysis/fuelPowerCostAnalysis' },
{
name: "包装物", targetValue: 0, value: 0, proportion: 0, flag: 0,
route:'packagingCostAnalysis/packagingCostAnalysis'
},
{
name: "辅料", targetValue: 0, value: 0, proportion: 0, flag: 0,
route: 'packagingCostAnalysis/packagingCostAnalysis'
},
{
name: "制造费用", targetValue: 0, value: 0, proportion: 0, flag: 0,
route:'productionCostsAnalysis/productionCostsAnalysis'
},
],
isDragging: false,
startX: 0,
scrollLeft: 0
};
},
// computed: {
// finalItemList() {
// if (Array.isArray(this.piecesCostViews) && this.piecesCostViews.length > 0) {
// return this.piecesCostViews.map((item) => ({
// flag: item.flag || 0, // 默认 flag 为 0
// proportion: item.proportion || 0, // 默认完成率为 0
// targetValue: item.target ?? 0, // 兼容 null 值,显示为 0
// value: item.value || 0,
// name: item.name
// }));
// } else {
// return this.itemList;
// }
// }
// },
computed: {
finalItemList() {
return this.itemList.map((defaultItem, index) => {
// 核心修复1. 恢复模板名称处理2. 统一大小写和空格处理
const matchedItem = this.processCostViews.find(item => {
const processedIncomingName = (item.name || '').replace(/成本/g, '').trim().toLowerCase();
// 恢复模板名称处理:去除“成本”(如果有的话)、去空格、小写
const processedDefaultName = defaultItem.name.replace(/成本/g, '').trim().toLowerCase();
return processedIncomingName === processedDefaultName;
});
// 移除索引 fallback只匹配名称不按索引赋值避免误匹配
// 无匹配项则完全保留默认值
const targetItem = matchedItem || defaultItem;
return {
name: defaultItem.name, // 固定模板名称
flag: targetItem.flag ?? defaultItem.flag,
proportion: targetItem.proportion ?? defaultItem.proportion,
targetValue: targetItem.target ?? defaultItem.targetValue,
value: targetItem.value ?? defaultItem.value,
route: defaultItem.route
};
});
}
},
methods: {
handleRoute(route, name) {
if (route) {
this.$router.push({
path: route,
query: {
name: name + '成本'
}
})
}
},
// 根据 flag 获取文字/进度条颜色
getColorByFlag(flag, isProgressBar = false) {
const colorMap = {
1: {
text: 'rgba(98, 213, 180, 1)',
progress: 'rgba(98, 213, 180, 1)' // 进度条颜色稍浅
},
0: {
text: 'rgba(255, 132, 0, 1)',
progress: 'rgba(249, 164, 74, 1)' // 进度条颜色稍浅
}
};
const currentFlag = flag === 1 ? 1 : 0;
return isProgressBar ? colorMap[currentFlag].progress : colorMap[currentFlag].text;
},
// 处理 proportion乘以 100 并保留 0 位小数
getProportionPercent(proportion) {
const num = Number(proportion) || 0;
return num; // 四舍五入取整,如需保留小数可改为 toFixed(2)
},
// 拖拽相关方法
handleMouseDown(e) {
this.isDragging = true;
this.startX = e.pageX - this.$el.offsetLeft;
this.scrollLeft = this.$el.scrollLeft;
this.$el.style.userSelect = "none";
},
handleMouseMove(e) {
if (!this.isDragging) return;
e.preventDefault();
const x = e.pageX - this.$el.offsetLeft;
const walk = (x - this.startX) * 1.2;
this.$el.scrollLeft = this.scrollLeft - walk;
},
handleMouseUp() {
this.isDragging = false;
this.$el.style.userSelect = "";
}
}
};
</script>
<style scoped lang="scss">
.coreItem-container {
width: 100%;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
&::-webkit-scrollbar {
height: 0;
width: 0;
}
scrollbar-width: none;
-ms-overflow-style: none;
cursor: grab;
&:active {
cursor: grabbing;
}
}
.coreItem {
display: flex;
gap: 16px;
padding: 0 8px;
width: fit-content;
min-width: 100%;
}
.item {
width: 202px;
height: 180px;
background: #f9fcff;
padding: 10px 20px 0 27px;
box-sizing: border-box;
transition: all 0.3s ease;
&:not(:nth-child(1)):hover {
box-shadow: 0px 4px 12px 2px #B5CDE5;
transform: translateY(-2px);
}
.item-header {
margin-bottom: 11px;
}
.unit {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 16px;
color: #333333;
line-height: 1.2;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-content {
display: flex;
flex-direction: column;
height: calc(100% - 30px);
}
.content-wrapper {
display: flex;
flex-direction: column;
gap: 12px;
flex: 1;
}
.value-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.value-item {
display: flex;
flex-direction: column;
}
.middle-line {
width: 100%;
height: 1px;
background: linear-gradient(to right, #cbcbcb rgba(255, 255, 255, 0));
}
.number {
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 22px;
line-height: 1.2;
text-align: left;
/* 颜色由动态样式控制,移除固定颜色 */
}
.title {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #999999;
line-height: 1.2;
text-align: left;
}
.progress-yield-group {
display: flex;
flex-direction: column;
gap: 0;
}
.progress-group {
display: flex;
align-items: center;
margin-bottom: 4px;
}
.progress-container {
width: 100%;
height: 8px;
background: #F5F7FA;
border-radius: 4px;
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 4px;
transition: width 0.5s ease;
/* 背景色由动态样式控制,移除固定颜色 */
}
.yield {
display: flex;
justify-content: space-between;
margin-top: 0;
}
.progress-percent {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #999999;
line-height: 1;
}
.progress-value {
font-weight: 500;
/* 颜色由动态样式控制,移除固定颜色 */
}
}
</style>