组件代码
<template>
<!-- 蛇形流程图-->
<div class="snakeFlowchart ">
<div style="width: 100%; display: flex; position: relative; margin-top: 20px">
<!--左侧曲线-->
<div :style="`width:${sideWidth}vw ; margin-left: 30px`">
<div>
<span :style="`margin-top:${ItemHeight/2}px ; opacity: 0`" class="headerRadio"></span>
<div v-if="experienceData.length > Index">
<span
v-for="(num, index) in leftRows"
:key="index"
class="hingelisHeard"
:style="`height:${ItemHeight}px ; margin-top:${ItemHeight}px; ;border: ${LineWidth}px ${LineType} ${LineColor};`"
></span>
</div>
</div>
</div>
<!--中间流程项-->
<div style="width: 96%">
<div
style="display: flex"
v-for="(item, index) in experienceData"
:key="index"
>
<div style="display: flex ;justify-content: flex-start;" v-if="(index + 1) % 2 !== 0">
<div
class="timeline"
v-for="(v, i) in DisplayProcessing(experienceData, index + 1)"
:key="i"
:style="(i + 1) % Index !== 0 ? `width:${ItemWidth}vw ; height:${ItemHeight}px` : `width: ${IconWidth}vw;height:${ItemHeight}px`"
>
<div class="NodesItem">
<div class="timeNodes">
<div class="timeContent">
{{v.content }}
</div>
<div class="nodeTimes">
{{v.createTime }}
</div>
</div>
</div>
<div class="Nodes " :style="{width:`${IconWidth}vw`,height:`${IconWidth}vw`, backgroundColor:(v.last ?CurrentItemColor:DoneItemColor)}">
</div>
<div
class="border"
v-if="
(i + 1) % Index != 0 &&
i != DisplayProcessing(experienceData, index + 1).length - 1
"
>
<div class="borderTime " :style="`border-bottom:${LineWidth}px ${LineType} ${LineColor}`"></div>
</div>
</div>
</div>
<div style="display: flex ;justify-content: flex-end;" v-else>
<div
class="timeline2"
v-for="(v, i) in DisplayProcessing(experienceData, index + 1)"
:key="i"
:style="
i + 1 === 1 &&
DisplayProcessing(experienceData, index + 1).length !== 1
? `width: ${IconWidth}vw;height:${ItemHeight}px`
: `width:${ItemWidth}vw;height:${ItemHeight}px`
"
>
<div class="Nodes " :style="{width:`${IconWidth}vw`,height:`${IconWidth}vw`, backgroundColor:(v.last ?CurrentItemColor:DoneItemColor)}">
</div>
<div class="border" v-if="i !== 0">
<div class="borderTime" :style="`border-bottom:${LineWidth}px ${LineType} ${LineColor}`"></div>
</div>
<div class="NodesItem">
<div class="timeNodes">
<div class="timeContent">
{{v.content }}
</div>
<div class="nodeTimes">
{{v.createTime }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--右侧曲线-->
<div :style="`width:${sideWidth}vw ; margin-right: 30px`">
<div>
<span class="hingelis" :style="`margin-top: ${ItemHeight/2}px;height:${ItemHeight}px; border: ${LineWidth}px ${LineType} ${LineColor};`" v-if="experienceData.length > Index"></span>
<div v-if="experienceData.length > Index * 2">
<span
class="hingelis"
v-for="(num, index) in rightRows"
:key="index"
></span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
// 流程数据
chartData: {
type: Array,
default: () => {
return [];
},
},
//每行几条数据
Index: {
type: Number,
default: 5,
},
// 行高
ItemHeight: {
type: String,
default: '80',
},
// 线宽度
LineWidth:{
type: Number,
default: 1
},
// 线样式(实线/虚线)
LineType:{
type: String,
default: 'dashed',
},
// 线颜色
LineColor:{
type: String,
default: '#a0a0a5',
},
//已完成流程颜色
DoneItemColor: {
type: String,
default: '#a0a0a5',
},
// 当前流程颜色
CurrentItemColor:{
type: String,
default: '#10bc28',
},
//小球大小
IconWidth:{
type: String,
default: '0.85',
}
},
data() {
return {
// 流程数据
experienceData: this.chartData,
leftRows: 0,
rightRows: 0,
leftShow: false,
rightShow: false,
// 宽度
ItemWidth:"19.4",
// 拐弯位置宽度
sideWidth:'',
};
},
watch: {
chartData: {
handler(newVal) {
//时间线数据
this.experienceData = newVal;
let rows = Math.ceil(newVal.length / this.Index);
this.leftRows = rows === 2 ? 0 : rows % 2 === 0 ? parseInt(rows / 2) - 1 : parseInt(rows / 2);
this.rightRows = rows === 4 ? 1 : rows % 2 === 0 ? parseInt(rows / 2) % 2 === 0 ? parseInt(rows / 2) >= 4
? parseInt(rows / 2) - 1
: parseInt(rows / 2)
: parseInt(rows / 2) - 1
: parseInt(rows / 2) - 1;
this.leftShow = rows % 2 === 0;
this.rightShow = rows === 1 ? false : rows % 2 === 1;
},
immediate: true,
},
},
mounted() {
this.initWidth()
},
methods: {
// 初始化宽度
initWidth(){
let p = document.querySelector(".snakeFlowchart").parentNode;
// 1VW宽度
let VW = window.innerWidth/100
// 中间流程部分占8成,算出每一段长度
this.ItemWidth= ((Number(p.clientWidth))*0.70/VW)/(this.Index-1)
console.log(this.ItemWidth)
// 两边拐弯部分共占2成
this.sideWidth = ((Number(p.clientWidth))*0.30/VW)/2
},
// 计算数据排列
DisplayProcessing(Arg, Num) {
//数据循环处理
let arr = Arg.slice(this.Index * (Num - 1), this.Index * Num);
arr = Num % 2 === 0 ? arr.reverse() : arr;
return arr;
},
},
};
</script>
<style scoped lang="scss">
.timeline {
width: 21.4vw;
display: flex;
align-items: center;
}
.timeline2 {
width: 21.4vw;;
display: flex;
align-items: center;
justify-content: flex-end;
}
.border {
width: 100%;
justify-content: center;
align-items: center;
display: flex;
.borderTime {
width: 100%;
}
}
.NodesItem{
display: flex;
flex-direction: column;
align-items: center;
width: 0.85vw;
margin-top: 1.85vw;
}
.Nodes {
position: absolute;
justify-content: center;
align-items: center;
display: flex;
border-radius: 50%;
background-color: #a0a0a5;
}
.timeNodes {
position: relative;
top: 5px;
.timeContent{
position: relative;
text-align: center;
width: 8vw;
font-size: 12px;
}
.nodeTimes{
position: absolute;
text-align: center;
width: 8vw;
font-size: 12px;
}
}
.hingelis {
content: "";
display: block;
width: 100%;
border-radius: 0 35px 35px 0px;
border-left: 0px !important;
}
.hingelisHeard {
content: "";
display: block;
width: 100%;
border-radius: 35px 0px 0px 35px;
border-right: 0px !important;
}
.headerRadio {
display: block;
width: 100%;
border-bottom: 1px solid #cccccc;
position: relative;
}
</style>
父组件引用
<template>
<div class="app-container">
<el-card class="box-card">
<SnakeFlowchart v-if="FlowData.length > 0" :chartData="FlowData" :Index="5"/>
</el-card>
</div>
</template>
<script>
import SnakeFlowchart from "@/components/SnakeFlowchart/index.vue";
export default {
components: { SnakeFlowchart },
name: 'process-track',
props: {
},
data() {
return {
FlowData: [
{
id: 7204928,
content: "步骤1",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: null,
createTime: "2024-01-03",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤2",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-01-04",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤3",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-01-05",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤4",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤5",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤6",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤7",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤8",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤9",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 0
},
{
id: 7204929,
content: "步骤10",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 1
},
{
id: 7204929,
content: "步骤15",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 2
},
{
id: 7204929,
content: "步骤16",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 2
},
{
id: 7204929,
content: "步骤17",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 2
},
{
id: 7204929,
content: "步骤20",
smallClass: "UpdateOutBoundAgingPlanning",
bigClass: "SCFXD",
createTime: "2024-03-01",
createUser: "Mia",
outBoundAgingPlanningId: 1342,
status: 2,
last:true
}
]
}
},
}
</script>
<style scoped>
</style>