【Vue】使用html、css实现鱼骨组件

发布于:2024-07-05 ⋅ 阅读:(7) ⋅ 点赞:(0)

组件

<template>
  <div class="context">
    <div class="top">
      <div class="label-context">
        <div class="label" v-for="(item, index) in value" :key="index">
          <div class="label-text" v-if="index % 2 === 0">
            {{ item.label }}
          </div>
          <div class="connect-line-box" v-if="index % 2 === 0">
            <div class="connect-line"><i class="center-line-icon"></i></div>
          </div>
        </div>
      </div>
    </div>
    <div class="center-line">

      <div class="icon-box" v-for="(item, index) in value" :key="index">
        <i class="center-line-icon"></i>
      </div>

    </div>
    <div class="bottom">
      <div class="label-context">
        <div class="label" v-for="(item, index) in value" :key="index">
          <div class="connect-line-box" v-if="index % 2 === 1">
            <div class="connect-line"></div>
          </div>
          <div class="label-text" v-if="index % 2 === 1">
            {{ item.label }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'FishBoneComponent',
  props: {
    value: {
      type: Array,
      default: () => [
        {
          time: '2024-06-13 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
        {
          time: '2024-06-12 15:27:30',
          label: ''
        },
      ]
    }
  },
  mounted() {
    this.value = this.value.sort((a, b) => {
      return new Date(a.time) - new Date(b.time);
    });
    console.log(this.value)
  }
}
</script>
<style lang="scss" scoped>
$center-color: #1890ff;
$text-box-width: 200px;
$text-margin-left: 10px;
$line-height: 40px;
$add-width: 0px;
$line-icon-size: 13px;

.context {
  width: 100%;
  padding: 0.5%;
  height: 100%;
}

.center-line {
  position: absolute;
  height: 2px;
  background-color: $center-color;
  width: 98%;
  display: flex;
  align-items: center;
  justify-content: left;
}

.center-line::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -10px;
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 10px solid $center-color;
  transform: translateY(-50%);
}

.center-line .icon-box:first-child {
  margin-left: $text-margin-left;
  width: $text-box-width/2 + $line-icon-size/2;
  flex-shrink: 0;

  i {
    float: right;
    width: $line-icon-size;
    height: $line-icon-size;
    flex-shrink: 0;
  }
}

.center-line .icon-box:not(:first-child) {
  margin-left: $text-margin-left - $line-icon-size/2;
  width: $text-box-width/2 + $line-icon-size/2;
  flex-shrink: 0;

  i {
    float: right;
    width: $line-icon-size;
    height: $line-icon-size;
    flex-shrink: 0;
  }
}

.center-line-icon {
  width: $line-icon-size;
  height: $line-icon-size;
  background-color: $center-color;
  border-radius: 50%;
}

.top .label-context {
  display: flex;
  flex-direction: row;
  justify-content: normal;
}

.connect-line-box {
  display: flex;
  flex-direction: row;
  text-align: center;
  justify-content: center;
}

.connect-line {
  width: 2px;
  height: $line-height;
  background-color: #1d71fa;
}

.top .label {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  margin-left: $text-margin-left;
}

.label > div {
  width: $text-box-width;
  margin-left: $add-width;
  white-space: normal;
}

.bottom .label-context {
  display: flex;
  flex-direction: row;
  justify-content: normal;
  margin-left: $text-box-width/2;
}

.bottom .label {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  margin-left: $text-margin-left;
}

.label-text {
  padding: 6px;
  background-color: rgb($center-color, 0.08);
  border-radius: 3px;
  color: black;
  font-size: 15px;
}
</style>

测试案例

<template>
  <div class="card">
    <FishBoneComponent :value="data"></FishBoneComponent>
  </div>
</template>

<script>
import FishBoneComponent from "@/views/FishBoneComponent";

export default {
  name: "FishBone",
  components: {FishBoneComponent},
  data(){
    return{
      data: [
        {
          time: '2024-06-13 15:27:30',
          label: '测试测试测试测试测试测试测试测试测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试测试测试测试测试测试测试测试测试测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试测试测试测试测试测试测试测试测试测试测试测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试测试测试测试测试测试测试测试测试测试测试测试测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试'
        },
        {
          time: '2024-06-12 15:27:30',
          label: '测试'
        },
      ]
    }
  }
}
</script>

<style scoped>
.card{
  padding: 8px;
}

.title-box{
  margin-bottom: 8px;
}

.title{
  font-size: 18px;
  font-weight: bold;
  color: #1890ff;
}
</style>

</style>

预览图

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到