Skip to content

Timeline 时间线

可视化地呈现时间流信息。

ts
import { createApp } from 'vue'
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'

const app = createApp()
app.use(ElTimeline)
app.use(ElTimelineItem)

基础用法

Timeline 可拆分成多个按照时间戳排列的活动,时间戳是其区分于其他控件的重要特征,使用时注意与 Steps 步骤条等区分。

<template>
  <el-timeline>
    <el-timeline-item
      v-for="activity in activities"
      :key="activity.content"
      :timestamp="activity.timestamp"
    >
      {{ activity.content }}
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'


const activities = [
  { content: '创建成功', timestamp: '2024-01-01' },
  { content: '通过审核', timestamp: '2024-01-02' },
  { content: '活动按期开始', timestamp: '2024-01-03' },
]
</script>

自定义节点样式

可根据实际场景自定义节点尺寸、颜色,或直接使用图标。

<template>
  <el-timeline>
    <el-timeline-item
      v-for="(activity, index) in activities"
      :key="index"
      :type="activity.type"
      :color="activity.color"
      :size="activity.size"
      :hollow="activity.hollow"
      :timestamp="activity.timestamp"
    >
      {{ activity.content }}
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'


const activities = [
  { content: '默认节点', timestamp: '2024-04-12 20:46' },
  { content: '主节点', timestamp: '2024-04-03 20:46', type: 'primary' },
  { content: '成功节点', timestamp: '2024-04-03 20:46', type: 'success' },
  { content: '警告节点', timestamp: '2024-04-03 20:46', type: 'warning' },
  { content: '危险节点', timestamp: '2024-04-03 20:46', type: 'danger' },
  { content: '信息节点', timestamp: '2024-04-03 20:46', type: 'info' },
  { content: '自定义颜色', timestamp: '2024-04-03 20:46', color: '#0bbd87' },
  { content: '大尺寸', timestamp: '2024-04-03 20:46', size: 'large' },
  { content: '空心节点', timestamp: '2024-04-03 20:46', hollow: true },
]
</script>

内容框

节点内容可放入卡片等内容容器,适合展示标题、说明和处理人等信息。

<template>
  <el-timeline>
    <el-timeline-item
      v-for="item in items"
      :key="item.title"
      :timestamp="item.time"
      placement="top"
    >
      <el-card>
        <h4>{{ item.title }}</h4>
        <p>{{ item.description }}</p>
      </el-card>
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Card as ElCard, Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'

const items = [
  {
    title: '节点名称',
    time: '2026-01-01',
    description: '事件简要描述',
  },
  {
    title: '节点名称',
    time: '2026-01-02',
    description: '事件简要描述',
  },
  {
    title: '节点名称',
    time: '2026-01-03',
    description: '事件简要描述',
  },
]
</script>

图标节点

通过 icon 属性或 dot 插槽可以替换默认节点图标。

<template>
  <el-timeline>
    <el-timeline-item timestamp="2024-04-01" placement="top">
      <el-card>
        <h4>更新 DHdesign 设计规范 v2.0</h4>
        <p>提交者:Tom,提交时间:2024-04-01 20:46</p>
      </el-card>
    </el-timeline-item>
    <el-timeline-item
      timestamp="2024-04-03"
      placement="top"
      type="primary"
      :icon="MoreFilled"
    >
      <el-card>
        <h4>评审设计稿</h4>
        <p>提交者:Tom,提交时间:2024-04-03 20:46</p>
      </el-card>
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem, Card as ElCard } from '@szhn/dh-design-pc'
import { MoreFilled } from '@szhn/dh-design-pc/icons'

</script>

时间图标节点

当节点需要表达时间属性时,可使用时间图标替换默认圆点。

<template>
  <el-timeline class="timeline-time-icon-demo">
    <el-timeline-item v-for="item in items" :key="item.date">
      <template #dot>
        <span class="timeline-time-icon-demo__dot">
          <svg viewBox="0 0 16 16" aria-hidden="true">
            <circle cx="8" cy="8" r="6" />
            <path d="M8 4.5V8l2.5 1.5" />
          </svg>
        </span>
      </template>
      <div class="timeline-time-icon-demo__title">{{ item.title }}</div>
      <div class="timeline-time-icon-demo__date">{{ item.date }}</div>
      <div class="timeline-time-icon-demo__desc">{{ item.description }}</div>
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'

const items = [
  { title: '节点名称', date: '2026-01-01', description: '事件简要描述' },
  { title: '节点名称', date: '2026-01-01', description: '事件简要描述' },
  { title: '节点名称', date: '2026-01-01', description: '事件简要描述' },
  { title: '节点名称', date: '2026-01-01', description: '事件简要描述' },
]
</script>

<style scoped>
.timeline-time-icon-demo {
  padding-left: 0;
}

.timeline-time-icon-demo :deep(.el-timeline-item) {
  padding-bottom: 28px;
}

.timeline-time-icon-demo :deep(.el-timeline-item__dot) {
  top: 5px;
  left: 0;
  width: 16px;
  height: 16px;
  color: var(--dh-color-text-disabled);
  background-color: var(--dh-color-surface);
  border: 0;
}

.timeline-time-icon-demo :deep(.el-timeline-item__tail) {
  top: 31px;
  left: 7px;
  height: calc(100% - 31px);
}

.timeline-time-icon-demo :deep(.el-timeline-item__wrapper) {
  padding-left: 28px;
}

.timeline-time-icon-demo__dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  color: var(--dh-color-text-disabled);
  background-color: var(--dh-color-surface);
}

.timeline-time-icon-demo__dot svg {
  width: 16px;
  height: 16px;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.5;
}

.timeline-time-icon-demo__title {
  color: var(--dh-color-text-primary);
  font-size: var(--dh-font-size-base);
  font-weight: var(--dh-font-weight-medium);
  line-height: var(--dh-line-height-base);
}

.timeline-time-icon-demo__date {
  margin-top: 2px;
  color: var(--dh-color-text-placeholder);
  font-size: var(--dh-font-size-sm);
  line-height: var(--dh-line-height-sm);
}

.timeline-time-icon-demo__desc {
  margin-top: 12px;
  padding: 10px 16px;
  color: var(--dh-color-text-secondary);
  font-size: var(--dh-font-size-sm);
  line-height: var(--dh-line-height-sm);
  background-color: var(--dh-color-surface-soft);
  border-radius: var(--dh-radius-base);
}
</style>

时间戳位置

通过 placement 属性设置时间戳位置,可选 topbottom(默认)。

<template>
  <el-timeline>
    <el-timeline-item
      v-for="(activity, index) in activities"
      :key="index"
      :timestamp="activity.timestamp"
      placement="top"
    >
      {{ activity.content }}
    </el-timeline-item>
  </el-timeline>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'


const activities = [
  { content: '需求评审', timestamp: '2024-01-01 09:00' },
  { content: '技术设计', timestamp: '2024-01-02 10:30' },
  { content: '开发联调', timestamp: '2024-01-05 18:00' },
  { content: '正式上线', timestamp: '2024-01-10 14:20' },
]
</script>

布局方式

Timeline 默认纵向展示。需要横向展示时,可基于时间线节点结构增加横向样式。

<template>
  <div class="timeline-layout-demo">
    <section>
      <h4>纵向布局</h4>
      <el-timeline>
        <el-timeline-item
          v-for="item in items"
          :key="`vertical-${item.time}`"
          :timestamp="item.time"
        >
          {{ item.title }}
        </el-timeline-item>
      </el-timeline>
    </section>

    <section>
      <h4>横向展示</h4>
      <div class="dh-timeline-horizontal-wrap">
        <el-timeline class="dh-timeline-horizontal">
          <el-timeline-item
            v-for="item in items"
            :key="`horizontal-${item.time}`"
            :timestamp="item.time"
          >
            {{ item.title }}
          </el-timeline-item>
        </el-timeline>
      </div>
    </section>
  </div>
</template>

<script lang="ts" setup>
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem } from '@szhn/dh-design-pc'

const items = [
  { title: '节点名称', time: '2026-01-01' },
  { title: '节点名称', time: '2026-01-02' },
  { title: '节点名称', time: '2026-01-03' },
  { title: '节点名称', time: '2026-01-04' },
]
</script>

<style scoped>
.timeline-layout-demo {
  display: grid;
  gap: 28px;
}

.timeline-layout-demo h4 {
  margin: 0 0 16px;
  color: var(--dh-color-text-primary);
  font-size: var(--dh-font-size-base);
  font-weight: var(--dh-font-weight-medium);
}

.dh-timeline-horizontal-wrap {
  overflow-x: auto;
  padding-bottom: 4px;
}

.dh-timeline-horizontal {
  display: grid;
  grid-template-columns: repeat(4, minmax(160px, 1fr));
  gap: 0;
  min-width: 640px;
  padding: 12px 0 0;
}

.dh-timeline-horizontal :deep(.el-timeline-item) {
  min-width: 0;
  padding: 0;
}

.dh-timeline-horizontal :deep(.el-timeline-item__tail) {
  top: 7px;
  left: calc(50% + 12px);
  width: calc(100% - 24px);
  height: 0;
  border-left: 0;
  border-top: var(--dh-timeline-line-width) solid var(--dh-timeline-line-color);
}

.dh-timeline-horizontal :deep(.el-timeline-item.is-start .el-timeline-item__tail) {
  left: calc(50% + 12px);
}

.dh-timeline-horizontal :deep(.el-timeline-item:last-child .el-timeline-item__tail) {
  display: none;
}

.dh-timeline-horizontal :deep(.el-timeline-item__node) {
  top: 4px;
  left: calc(50% - 4px);
}

.dh-timeline-horizontal :deep(.el-timeline-item.is-start .el-timeline-item__node--normal),
.dh-timeline-horizontal :deep(.el-timeline-item.is-start .el-timeline-item__node--large),
.dh-timeline-horizontal :deep(.el-timeline-item.is-start .el-timeline-item__node:not(:empty)) {
  left: calc(50% - 4px);
}

.dh-timeline-horizontal :deep(.el-timeline-item__wrapper) {
  top: 0;
  padding-top: 24px;
  padding-left: 0;
  text-align: center;
}

.dh-timeline-horizontal :deep(.el-timeline-item.is-start .el-timeline-item__wrapper) {
  padding-left: 0;
}

.dh-timeline-horizontal :deep(.el-timeline-item__timestamp.is-bottom) {
  margin-top: 2px;
}
</style>

反向

使用 reverse 属性来控制节点的顺序。

<template>
  <div>
    <el-switch v-model="reverse" />
    <span style="margin-left: 8px;">reverse</span>

    <el-timeline style="margin-top: 12px;">
      <el-timeline-item
        v-for="(activity, index) in list"
        :key="index"
        :timestamp="activity.timestamp"
      >
        {{ activity.content }}
      </el-timeline-item>
    </el-timeline>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import { Timeline as ElTimeline, TimelineItem as ElTimelineItem, Switch as ElSwitch } from '@szhn/dh-design-pc'


const reverse = ref(true)

const activities = [
  { content: 'Success', timestamp: '2018-04-11' },
  { content: 'Approved', timestamp: '2018-04-13' },
  { content: 'Success', timestamp: '2018-04-15' },
]

const list = computed(() =>
  reverse.value ? [...activities].reverse() : activities,
)
</script>

API

Timeline Attributes

属性名说明类型默认值
mode时间线与内容的相对位置enum(start / end / alternate / alternate-reversestart
reverse是否反向排序节点booleanfalse

TimelineItem Attributes

属性名说明类型默认值
timestamp时间戳string
hide-timestamp是否隐藏时间戳booleanfalse
center时间戳是否垂直居中booleanfalse
placement时间戳位置enum(top / bottombottom
type节点类型enum(primary / success / warning / danger / info
color节点颜色string
size节点尺寸enum(normal / largenormal
icon节点自定义图标Component
hollow是否空心节点booleanfalse

TimelineItem Slots

插槽名说明
default自定义内容
dot自定义节点

更多细节参见 Element Plus Timeline 文档。