Files
yudao-dev/src/views/home/components/order-bottom-leftItem.vue
‘937886381’ 51e66cf6e1 修改
2026-01-06 17:09:52 +08:00

568 lines
15 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">
<!-- 单独渲染第一个item -->
<div class="item" v-if="itemList.length > 0">
<div class="unit">{{ itemList[0].unit }}</div>
<div class="item-content">
<div class="content-wrapper">
<div class="left">
<div class="number">{{ itemList[0].targetValue }}</div>
<div class="title">预算值</div>
</div>
<div class="line"></div>
<div class="right">
<div class="number" :style="{ color: getColor(itemList[0].currentValue, itemList[0].targetValue) }">
{{ itemList[0].currentValue }}
</div>
<div class="title">实际值</div>
</div>
</div>
<div class="progress-group">
<div class="progress-container">
<!-- 进度条颜色和宽度动态绑定 -->
<div class="progress-bar" :style="{
width: itemList[0].progress + '%',
background: getColor(itemList[0].currentValue, itemList[0].targetValue)
}"></div>
</div>
</div>
<div class="yield" style="display: flex;justify-content: space-between;">
<div class="progress-percent">完成率</div>
<!-- 百分比颜色动态绑定 -->
<div class="progress-percent" :style="{
color: getColor(itemList[0].currentValue, itemList[0].targetValue)
}">
{{ itemList[0].progress }}%
</div>
</div>
</div>
</div>
<!-- 循环渲染剩余的item从索引1开始 -->
<div class="item groupData" style="display: flex;padding: 0;" v-for="(item, index) in itemList.slice(1)"
:key="index">
<!-- 左侧预算值/实际值部分不变 -->
<div class="left" style="display: flex;align-items: start;gap: 4px;padding: 12px 0 0 12px;">
<div class="groupName">{{ item.unit }}</div>
<div class="left-target">
<div class="number">{{ item.targetValue }}</div>
<div class="title">预算值</div>
</div>
<div class="left-real">
<div class="number" :style="{ color: getColor(item.currentValue, item.targetValue) }">
{{ item.currentValue }}
</div>
<div class="title">实际值</div>
</div>
</div>
<div class="cityLine"></div>
<div class="right">
<!-- 顶部完成率部分不变 -->
<div class="groupName" :class="{
'bg-default': item.currentValue < item.targetValue,
'bg-green': item.currentValue >= item.targetValue
}" style="font-size: 12px;display: flex;align-items: center;justify-content: flex-end;">
<div class="title">完成率</div>
<div class="yield" style="font-size: 22px;margin-bottom: 4px;">
{{ item.progress }}
</div>
<div class="unit">%</div>
</div>
<!-- 动态渲染城市进度循环 item.cities -->
<div class="right-city" v-for="(city, cityIdx) in item.cities" :key="cityIdx"
:style="{ marginTop: cityIdx > 0 ? '2px' : '0' }" @click="getTableData(city.num)" style="cursor: pointer;">
<div class="city">{{ city.name }}</div> <!-- 动态城市名 -->
<div class="city-progress-group">
<div class="city-progress-container">
<!-- 动态城市进度条颜色按城市进度判断 -->
<div class="city-progress-bar" :style="{
width: city.progress + '%',
background: getColor(city.completed, city.total) // 用城市已完成/总数判断颜色
}"></div>
</div>
</div>
<div class="city-progress-yield" style="display: flex;justify-content: space-between;">
<!-- 动态比值已完成/总数 -->
<div class="numerator" :style="{ color: getColor(city.completed, city.total) }">
{{ city.completed }}/{{ city.total }}
</div>
<!-- 动态城市完成率 -->
<div class="city-yield" :style="{ color: getColor(city.completed, city.total) }">
{{ city.progress }}%
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Container",
components: {},
props: ["orderOutput"],
data() {
return {
progress: 90, // 进度值基础参数
itemList: [
// {
// unit: "总进度",
// targetValue: 16,
// currentValue: 14.5,
// progress: 90,
// cities: [] // 总进度无需城市数据,留空
// },
// {
// unit: "一组",
// targetValue: 16,
// currentValue: 17,
// progress: 106,
// cities: [
// { name: "桐城", completed: 12, total: 13, progress: 92 },
// { name: "自贡", completed: 15, total: 16, progress: 93 } // 新增城市示例
// ]
// },
// {
// unit: "二组",
// targetValue: 16,
// currentValue: 16,
// progress: 100,
// cities: [
// { name: "蚌埠", completed: 10, total: 12, progress: 83 },
// { name: "合肥", completed: 8, total: 10, progress: 80 }
// ]
// },
// // 其他组同理,按需添加 cities 数据
// {
// unit: "三组",
// targetValue: 16,
// currentValue: 15.2,
// progress: 85,
// cities: [{ name: "宜兴", completed: 9, total: 11, progress: 81 }]
// },
// {
// unit: "四组",
// targetValue: 16,
// currentValue: 18,
// progress: 112,
// cities: [
// { name: "漳州", completed: 14, total: 15, progress: 93 },
// { name: "洛阳", completed: 12, total: 14, progress: 85 }
// ]
// },
// {
// unit: "五组",
// targetValue: 16,
// currentValue: 14,
// progress: 80,
// cities: [{ name: "桐城", completed: 7, total: 9, progress: 77 }]
// }
]
};
},
watch: {
orderOutput: {
handler(newValue, oldValue) {
this.getItemData(newValue)
},
deep: true // 若对象内属性变化需触发,需加 deep: true
}
},
methods: {
getItemData(data) {
this.itemList = [
{
unit: "总进度",
targetValue: data.totalProgress.target,
currentValue: data.totalProgress.real,
progress: data.totalProgress.rate,
cities: [] // 总进度无需城市数据,留空
},
{
unit: "一组",
targetValue: data.group1.target,
currentValue: data.group1.real,
progress: data.group1.rate,
cities: [
{ name: "桐城", completed: data[2].real, total: data[2].target, progress: data[2].rate,num:2 },
{ name: "自贡", completed: data[3].real, total: data[3].target, progress: data[3].rate, num: 3 } // 新增城市示例
]
},
{
unit: "二组",
targetValue: data.group2.target,
currentValue: data.group2.real,
progress: data.group2.rate,
cities: [
{ name: "蚌埠", completed: data[4].real, total: data[4].target, progress: data[4].rate, num: 4 },
{ name: "合肥", completed: data[5].real, total: data[5].target, progress: data[5].rate, num: 5 }
]
},
// 其他组同理,按需添加 cities 数据
{
unit: "三组",
targetValue: data.group3.target,
currentValue: data.group3.real,
progress: data.group3.rate,
cities: [{ name: "江苏凯盛", completed: data[6].real, total: data[6].target, progress: data[6].rate, num: 6 },
{ name: "宜兴", completed: data[7].real, total: data[7].target, progress: data[7].rate, num: 7 }
]
},
{
unit: "四组",
targetValue: data.group4.target,
currentValue: data.group4.real,
progress: data.group4.rate,
cities: [
{ name: "漳州", completed: data[8].real, total: data[8].target, progress: data[8].rate, num: 8 },
{ name: "洛阳", completed: data[9].real, total: data[9].target, progress: data[9].rate, num: 9 }
]
},
{
unit: "五组",
targetValue: data.group5.target,
currentValue: data.group5.real,
progress: data.group5.rate,
cities: [{ name: "秦皇岛", completed: data[10].real, total: data[10].target, progress: data[10].rate, num: 10 },
// { name: "秦皇岛", completed: 7, total: 9, progress: 77 }
]
}
]
},
// 颜色判断核心方法:实际值≥预算值返回绿色,否则返回橙色
getColor(currentValue, targetValue) {
return currentValue >= targetValue
? "rgba(98, 213, 180, 1)"
: "rgba(249, 164, 74, 1)";
},
getTableData(data) {
console.log(data, 'data');
this.$emit('handleShowTable',data)
}
}
};
</script>
<style scoped lang="scss">
/* 第一个item单独样式可选 */
.item:first-of-type {
// background: #f0f7ff; /* 示例背景色 */
}
.coreItem {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.item {
width: 220px;
height: 122px;
background: #f9fcff;
padding: 12px;
box-sizing: border-box;
.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;
}
.groupName {
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;
}
.left-target {
.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;
}
}
.left-real {
.number {
height: 22px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 24px;
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;
}
}
.right {
width: 100%;
.bg-default {
background-image: url("../../../assets/img/order-item-bg.png");
}
// 实际值 >= 预算值:绿色背景图
.bg-green {
background-image: url("../../../assets/img/order-item-greenbg.png");
}
.groupName {
width: 129px;
height: 32px;
// background: url(../../../assets/img/order-item-bg.png) no-repeat;
background-size: 100% 100%;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
color: #000000;
text-align: center;
.title {
margin-top: 10px;
height: 12px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
margin-right: 8px;
color: #000000;
line-height: 12px;
text-align: left;
font-style: normal;
}
.unit {
margin-top: 10px;
margin-right: 14px;
height: 12px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #000000;
line-height: 12px;
text-align: left;
font-style: normal;
}
}
.right-city {
.city {
height: 14px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #575757;
line-height: 14px;
text-align: left;
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;
}
}
}
.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);
}
.cityLine {
width: 1px;
margin-top: 40px;
height: 76px;
background: linear-gradient(to bottom,
rgba(255, 0, 0, 0),
#cbcbcb);
}
.left,
.right {
display: flex;
flex-direction: column;
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: 230px;
height: 10px;
background: #ECEFF7;
border-radius: 8px;
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 8px;
/* 背景色由动态绑定控制,移除固定值 */
}
.city-progress-group {
margin-top: 2px;
display: flex;
align-items: center;
gap: 8px;
}
.city-progress-container {
width: 112px;
height: 10px;
background: #ECEFF7;
border-radius: 8px;
overflow: hidden;
}
.city-progress-bar {
height: 100%;
border-radius: 8px;
opacity: 1;
/* 背景色由动态绑定控制,移除固定值 */
}
.progress-percent {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 1;
/* 颜色由动态绑定控制,此处不设置固定值 */
}
.yield {
margin-top: 3px;
}
.numerator {
/* 颜色由动态绑定控制,此处不设置固定值 */
}
.city-yield {
/* 颜色由动态绑定控制,此处不设置固定值 */
}
}
.groupData {
position: relative;
overflow: hidden;
}
/* 右上角折现边框(主边框) */
// .groupData::before {
// content: "";
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// background-color: #000000;
// clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
// }
/* 右上角折现细节 */
.groupData::after {
content: "";
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 20px;
background: #EFF3F8;
transform: rotate(-45deg) translate(50%, -50%);
transform-origin: top right;
}
</style>