手撸的一个阶段编辑的组件

element-ui + vue2

效果如下

为自己点赞

<template>
  <div class="stage-container">
    <el-popover
      v-for="(stage) in stageList" :key="stage.id"
      width="200"
      trigger="hover"
    >
      <div slot="reference" :class="stageState(stage)" class="stage">
        <div class="stage-title">{{ stage.name }}</div>
        <div :class="stageState(stage)" class="stage-side stage-left"/>
        <div :class="stageState(stage)" class="stage-side stage-right"/>
      </div>
      <div class="label-list">
        <div v-for="(label) in stage.labels" :key="label.id">
          <el-link :underline="false" :type="labelState(label)" class="label" @click="selectLabel(label)">{{ label.name }}</el-link>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script>
import { customerStages } from '@/api/admin/crm'
export default {
  props: {
    stageId: Number,
    stageLabelId: Number
  },
  data() {
    return {
      stageList: []
    }
  },
  computed: {
    stageState() {
      return stage => {
        if (!this.currentStage.order) {
          return 'not-active'
        }
        return stage.order > this.currentStage.order ? 'not-active' : ''
      }
    },
    labelState() {
      return label => {
        return this.stageLabelId == label.id ? 'primary' : 'info'
      }
    },
    currentStage() {
      for (const stage of this.stageList) {
        if (stage.id == this.stageId) {
          return stage
        }
      }
      return {}
    }
  },
  async mounted() {
    const res = await customerStages()
    this.stageList = res.data
  },
  methods: {
    selectLabel(label) {
      this.$emit('selectLabel', label)
    }
  }
}
</script>

<style lang="scss">
.stage-container {
  margin-left: 50px;
  display: flex;
}

.stage-side {
  height: 38px;
  width: 38px;
  top: 0px;
  position: absolute;
  transform: rotate(45deg) scale(0.707);
  &.stage-left {
    z-index: 5;
    left: -19px;
    background-color: white;
  }
  &.stage-right {
    z-index: 10;
    right: -18px;
    background-color: $xr-color-primary;
  }
  &.not-active {
    background-color: white;
    border-top: 2px solid $xr-color-primary;
    border-right: 2px solid $xr-color-primary;
    top: -2px;
  }
}

.stage {
  color: #fff;
  position: relative;
  padding: 10px 20px 10px 37px;
  margin: 28px 2px;
  height: 38px;
  background-color: $xr-color-primary;
  cursor: pointer;
  &.not-active {
    color: $xr-color-primary;
    background-color: white;
    border-top: 2px solid $xr-color-primary;
    border-bottom: 2px solid $xr-color-primary;
  }
}

.label {
  padding: 5px;
  font-size: 13px;
  width: 100%;
}
</style>