效果:
封装代码:
<template>
<div style="width: 100%">
<div class="my-steps">
<div class="steps">
<template v-for="(mItem, mIndex) in pageNum">
<div
class="stepMain"
:style="{
'margin-top': mIndex > 0 ? '50px' : '0px',
'justify-content':
mIndex % 2 == 1 ? 'flex-end' : 'flex-start',
}"
>
<template v-for="(item, index) in mStepsData[mIndex]">
<div
class="step"
:style="{
'flex-basis': flexBasis,
}"
>
<div
class="step-pane"
:class="[getActiveClass(item)]"
>
<div class="left">
<el-icon class="step-icon">
<el-icon-success-filled />
</el-icon>
</div>
<div class="right">
<div class="title">
{{ item.title }}
</div>
<div class="description">
{{ item.description }}
</div>
</div>
</div>
<div
class="line"
:class="[
getLineClass(
item,
mStepsData[mIndex].length,
mIndex
),
]"
></div>
</div>
</template>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
stepsData: {
type: Array,
default() {
return [];
},
},
active: {
type: Number,
default: 0,
},
//每行的数量
rowCount: {
type: Number,
default: 5,
},
},
data() {
return {
mStepsData: [],
pageNum: 0,
flexBasis: "",
};
},
computed: {
getActiveClass() {
return (item) => {
return this.active > item.myStepIndex
? "is-finish"
: this.active == item.myStepIndex
? "is-process"
: "";
};
},
getLineClass() {
return (item, len, rowIndex) => {
if (item.colNum == len) {
if (rowIndex + 1 == this.pageNum) {
//如果是最后一行,则不显示连接线
return "none";
}
//最后一列
return "bottom" + item.lineDirection;
} else {
return item.lineDirection;
}
};
},
},
mounted() {
this.init();
},
methods: {
// 初始化数据
init() {
const stepsData = this.stepsData;
if (stepsData && stepsData.length > 0) {
this.pageNum = Math.ceil(stepsData.length / this.rowCount);
this.flexBasis = parseFloat(100.0 / this.rowCount) + "%";
let list = [];
let index = 0;
stepsData.forEach((item) => {
item.myStepIndex = index;
let colNum = (index % this.rowCount) + 1;
item.colNum = colNum;
if (this.mStepsData.length % 2 == 1) {
//连接线的位置
item.lineDirection = "left";
} else {
item.lineDirection = "right";
}
list.push(item);
if (list.length >= this.rowCount) {
if (
this.mStepsData.length > 0 &&
this.mStepsData.length % 2 == 1
) {
list = list.reverse();
}
this.mStepsData.push(JSON.parse(JSON.stringify(list)));
list = [];
}
index++;
});
if (list.length > 0) {
if (
this.mStepsData.length > 0 &&
this.mStepsData.length % 2 == 1
) {
list = list.reverse();
}
this.mStepsData.push(JSON.parse(JSON.stringify(list)));
}
}
},
},
};
</script>
<style scoped lang="scss">
.my-steps {
padding: 10px;
display: flex;
.steps {
width: 100%;
.stepMain {
display: flex;
.step {
color: #b9abb2;
position: relative;
.step-pane {
position: relative;
display: flex;
border: 1px solid #b9abb2;
width: 60%;
padding: 10px;
align-items: center;
gap: 10px;
background: white;
.left {
height: 30px;
display: flex;
.step-icon {
font-size: 30px;
}
}
.right {
}
z-index: 100;
}
.line {
position: absolute;
width: 100%;
height: 3px;
background: #b9abb2;
top: 50%;
z-index: 99;
&.left {
right: 100%;
}
&.bottomright {
/* transform: rotate(90deg); */
width: 3px;
height: 100%;
top: 100%;
left: 50%;
}
&.bottomleft {
/* transform: rotate(90deg); */
width: 3px;
height: 100%;
top: 100%;
left: 10%;
}
&.none {
width: 0px;
height: 0px;
display: none;
}
}
.is-finish {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
& + .line {
background: var(--el-color-primary);
}
}
.is-process {
color: var(--el-text-color-primary);
border-color: var(--el-text-color-primary);
& + .line {
background: var(--el-text-color-primary);
}
}
}
}
}
}
</style>
使用:
<template>
<div style="width: 100%; padding: 20px">
<custom-steps
:steps-data="stepData"
:rowCount="5"
:active="active"
></custom-steps>
</div>
<el-button type="primary" @click="nextStep">下一步骤</el-button>
</template>
<script>
//引入步骤条组件
import customSteps from "@/components/customComp/steps";
export default {
name: "Test",
components: {
customSteps,
},
data() {
return {
active: 0,
stepData: [
{
title: "Step 1",
description: "步骤00",
},
{ title: "Step 2", description: "步骤11" },
{ title: "Step 3", description: "步骤22" },
{ title: "Step 4", description: "步骤33" },
{ title: "Step 5", description: "步骤44" },
{ title: "Step 6", description: "步骤55" },
{ title: "Step 7", description: "步骤66" },
{ title: "Step 8", description: "步骤77" },
{ title: "Step 9", description: "步骤88" },
{ title: "Step 10", description: "步骤99" },
{ title: "Step 11", description: "步骤110" },
{ title: "Step 12", description: "步骤120" },
],
};
},
methods: {
nextStep() {
if (this.active + 1 > this.stepData.length) {
this.active = 0;
} else {
this.active++;
}
},
},
};
</script>