<template>
|
<div class="timeline-wrapper">
|
<div v-for="(stage, stageIndex) in processList" :key="stage.id || stageIndex" class="stage-group">
|
<!-- 大节点 Stage Node -->
|
<!-- <div class="stage-node">-->
|
<!-- <div class="stage-icon" :class="{ reached: 1 === 1 }">-->
|
<!-- <el-icon v-if="1 === 1"><Check /></el-icon>-->
|
<!-- <span v-else class="stage-index">{{ stageIndex + 1 }}</span>-->
|
<!-- </div>-->
|
<!-- <span class="stage-name" :class="{ reached: true }">{{ stage.newStatusName || stage.statusName || '-' }}</span>-->
|
<!-- </div>-->
|
|
<!-- 小节点 Child Nodes -->
|
<div class="child-list">
|
<template v-for="(record, recordIndex) in getStageRecords(stage)" :key="record.id || recordIndex">
|
<div class="child-node">
|
<div class="child-left">
|
<span class="child-status">
|
{{
|
record.operateContent ||
|
record.operationContent ||
|
record.disposeContent ||
|
record.content ||
|
record.remark ||
|
stage.operateContent ||
|
'-'
|
}}
|
</span>
|
</div>
|
<div class="child-dot"></div>
|
<div class="child-right">
|
<span class="child-operator">
|
{{
|
record.operateUserName ||
|
record.operatorName ||
|
record.operateUser ||
|
record.operator ||
|
record.userName ||
|
stage.operateUserName ||
|
'-'
|
}}
|
</span>
|
<span class="child-time">
|
{{ record.operateTime || record.createTime || record.updateTime || stage.operateTime || '-' }}
|
</span>
|
</div>
|
</div>
|
</template>
|
<!-- 连接线 -->
|
<div class="connector-line" :class="{ reached: 1 === 1 }"></div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { Check } from '@element-plus/icons-vue'
|
|
const props = defineProps({
|
processList: {
|
type: Array,
|
default: () => [],
|
},
|
})
|
|
// 获取状态对应的事件记录
|
function getStageRecords(stage) {
|
if (Array.isArray(stage.child) && stage.child.length) return stage.child
|
if (Array.isArray(stage.children) && stage.children.length) return stage.children
|
if (Array.isArray(stage.records) && stage.records.length) return stage.records
|
return [stage]
|
}
|
</script>
|
|
<style scoped lang="scss">
|
.timeline-wrapper {
|
padding-left: 100px;
|
position: relative;
|
|
.stage-group {
|
position: relative;
|
}
|
|
// 大节点 - Stage Node
|
.stage-node {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
|
.stage-icon {
|
width: 28px;
|
height: 28px;
|
border-radius: 50%;
|
background: #dbdde2;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
color: #fff;
|
font-size: 14px;
|
font-weight: 600;
|
flex-shrink: 0;
|
position: relative;
|
z-index: 2;
|
|
&.reached {
|
background: #1a1a2e;
|
}
|
|
.el-icon {
|
font-size: 16px;
|
}
|
|
.stage-index {
|
font-size: 12px;
|
color: #4e5969;
|
}
|
}
|
|
.stage-name {
|
width: 70px;
|
text-align: right;
|
position: absolute;
|
left: -80px;
|
font-family: Roboto, Roboto;
|
font-weight: bold;
|
font-size: 16px;
|
color: rgba(0, 0, 0, 0.45);
|
|
&.reached {
|
color: #4c34ff;
|
}
|
}
|
}
|
|
// 小节点 - Child Nodes
|
.child-list {
|
position: relative;
|
left: -92px;
|
min-height: 80px;
|
overflow: visible;
|
|
// 连接线
|
.connector-line {
|
position: absolute;
|
left: 105px;
|
width: 1px;
|
height: calc(100% - 5px);
|
top: 50%;
|
transform: translateY(-50%);
|
background: #cccccc;
|
z-index: 1;
|
|
&.reached {
|
background: #4c34ff;
|
}
|
}
|
}
|
|
.child-node {
|
display: flex;
|
align-items: flex-start;
|
position: relative;
|
padding: 40px 0;
|
|
&:last-child::before {
|
bottom: 50%;
|
}
|
|
.child-left {
|
width: 100px;
|
flex-shrink: 0;
|
text-align: right;
|
padding-right: 20px;
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 14px;
|
color: rgba(0, 0, 0, 0.85);
|
|
.child-status {
|
white-space: normal;
|
overflow-wrap: anywhere;
|
}
|
}
|
|
.child-dot {
|
width: 12px;
|
height: 12px;
|
border-radius: 50%;
|
background: #1a1a2e;
|
flex-shrink: 0;
|
position: relative;
|
z-index: 2;
|
margin-top: 4px;
|
}
|
|
.child-right {
|
flex: 1;
|
min-width: 0;
|
padding-left: 12px;
|
display: flex;
|
flex-direction: column;
|
gap: 2px;
|
position: relative;
|
|
.child-operator {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 14px;
|
color: rgba(0, 0, 0, 0.85);
|
white-space: nowrap;
|
}
|
|
.child-time {
|
position: absolute;
|
top: 30px;
|
white-space: nowrap;
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 14px;
|
color: rgba(0, 0, 0, 0.45);
|
}
|
}
|
}
|
}
|
</style>
|