一个可以拖拽,收藏的首页快速访达应用页

289 阅读1分钟

在线预览链接:stackblitz.com/edit/vitejs…

记录一次写拖拽应用的代码,功能是实现可拖拽应用,点击收藏点击取消收藏,展示和隐藏,当展示应用时,展开图标隐藏,鼠标经过时展示,当收起应用时就一直展示展开三角形。

图片示例

image.png 代码演示:

<template>
  <div class="FinderPage">
    <div class="Finde_collect">
      <div class="Finde_collect_body">
        <div
          class="Finde_collect_body_hover"
          @click="collectState = !collectState"
        >
          <!-- 向右箭头,下方不页面展示时显示 -->

          <div v-if="!collectState" class="arrow-right" />

          <!-- 向下箭头,下方页面展示时 鼠标经过 显示 -->
          <div v-if="collectState" class="arrow-right_hover" />

          <div class="collectBtn">星标应用</div>
        </div>

        <div style="color: #bdbdc3">
          {{ collectItems.length }}
        </div>
      </div>

      <div v-if="collectState">
        <div
          v-for="(item, index) in collectItems"
          :key="item.id"
          :class="[{ 'gray-bg': item.isDragging }, 'block']"
          draggable="true"
          @dragend="handleDragEnd(index)"
          @dragover.prevent
          @dragstart="handleDragStart(index)"
          @drop="handleDrop(index)"
        >
          <div class="body_div">
            <div class="bgc_circle" :style="{ 'background-color': item.bgc }">
              <i>图标</i>
            </div>

            <div class="body_div_title">
              {{ item.content }}
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="Finde_all">
      <div class="Finde_collect_body">
        <div class="Finde_collect_body_hover" @click="allState = !allState">
          <!-- 向右箭头,下方不页面展示时显示 -->
          <div v-if="!allState" class="arrow-right" />

          <!-- 向下箭头,下方页面展示时 鼠标经过 显示 -->
          <div v-if="allState" class="arrow-right_hover" />

          <div class="collectBtn">全部应用</div>
        </div>

        <div style="color: #bdbdc3">
          {{ items.length }}
        </div>
      </div>

      <div v-if="allState">
        <div
          v-for="(item, index) in items"
          :key="item.id"
          :class="[{ 'gray-bg': item.isDragging }, 'block']"
          draggable="true"
          @dragend="handleDragEnd(index)"
          @dragover.prevent
          @dragstart="handleDragStart(index)"
          @drop="handleDrop(index)"
        >
          <div class="body_div">
            <ElTooltip
              v-if="item.status === 0"
              class="box-item"
              placement="bottom"
            >
              <template #content> 收藏 </template>

              <template #default>
                <Icon
                  class="star"
                  icon="ic:twotone-star-border"
                  @click="handleCircleClick(index)"
                />
              </template>
            </ElTooltip>

            <ElTooltip
              v-if="item.status !== 0"
              class="box-item"
              effect="dark"
              placement="bottom"
            >
              <template #content> 取消收藏 </template>

              <template #default>
                <Icon
                  class="star"
                  icon="material-symbols:star-rate-rounded"
                  @click="handleCircleClick(index)"
                />
              </template>
            </ElTooltip>

            <div class="bgc_circle" :style="{ 'background-color': item.bgc }">
              <i>图标</i>
            </div>

            <div class="body_div_title">
              {{ item.content }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed } from "vue";
const collectState = ref(true);
const allState = ref(true);
const items = ref([
  {
    id: 1,
    content: "会议室预约",
    isDragging: false,
    status: 0,
    bgc: "#9c27b0",
  },
  {
    id: 2,
    content: "在线访问",
    isDragging: false,
    status: 0,
    bgc: "#ff9800",
  },
  {
    id: 3,
    content: "快速访问",
    isDragging: false,
    status: 1,
    bgc: "#2196f3",
  },
  {
    id: 4,
    content: "历史访问",
    isDragging: false,
    status: 0,
    bgc: "#d48825",
  },
]);

// 根据 status 分类
const collectItems = computed(() =>
  items.value.filter((item) => item.status === 1)
);
let dragIndex = null;

const handleDragStart = (index) => {
  dragIndex = index;
  items.value[index].isDragging = true;
};

const handleDrop = (index) => {
  const dragItem = items.value[dragIndex];
  items.value.splice(dragIndex, 1);
  items.value.splice(index, 0, dragItem);
};

const handleDragEnd = (index) => {
  items.value.forEach((item) => {
    item.isDragging = false;
  });
  console.log(items.value, "拖动结束时");
};
const handleCircleClick = (index) => {
  if (items.value[index].status === 0) {
    items.value[index].status = 1;
  } else {
    items.value[index].status = 0;
  }
};

// 点击图标进行跳转
const handleRouterLink = ({ name }) => {
  // 跳转
};
</script>

<style scoped lang="scss">
.FinderPage {
  height: 80%;
  padding: 30px 60px 0px 60px;
  background-color: #ffffff;
  .Finde_collect_body {
    display: flex;
    align-items: center;
    margin-bottom: 10px;

    .Finde_collect_body_hover {
      padding-right: 10px;
      margin-right: 5px;
      height: 28px;
      padding-left: 15px;
      border-radius: 5px;
      display: flex;
      align-items: center;
      .arrow-right_hover {
        opacity: 0;
        width: 0;
        height: 0;
        border-left: 5px solid transparent;
        border-right: 5px solid transparent;
        border-top: 5px solid #9d9d9d;
      }
    }
    .Finde_collect_body_hover:hover {
      background-color: #f2f2f2;
      .arrow-right_hover {
        opacity: 1 !important;
      }
    }
    .arrow-right {
      width: 0;
      height: 0;
      border-top: 5px solid transparent;
      border-bottom: 5px solid transparent;
      border-left: 5px solid #9d9d9d;
    }
    .collectBtn {
      padding: 10px 0px;
      padding-left: 8px;
      font-size: 17px;
      font-weight: bolder;
    }
  }

  .block {
    position: relative;
    display: inline-block;
    width: 150px;
    height: 168px;
    padding: 10px 0;
    // background-color: white;
    margin-right: 20px;
    text-align: center;
    vertical-align: middle;
    // line-height: 100px;
    cursor: move;
    border-radius: 15px;
  }
  .star {
    display: none;
    position: absolute;
    top: 10px;
    left: 10px;
    border: none;
  }
  .yellow {
    color: yellow;
  }
  .block:hover {
    background-color: #fafafa;
    transform: translateY(-10px);
    transition: all 0.3s;
    .star {
      display: block !important;
    }
  }

  .body_div_title {
    height: 100%;
  }
  .gray-bg {
    //background-color: gray;
    //margin-top: -2px;
  }
  .bgc_circle {
    position: relative;
    width: 80px;
    height: 80px;
    margin: 0 auto;
    margin-bottom: 20px;
    display: flex;
    //  background-color: rgb(156, 39, 176);
    justify-content: center;
    align-items: center;
    border-radius: 50%;
    cursor: pointer;
  }
}
:deep(.el-tooltip__trigger:focus) {
  outline: none; // 隐藏虚线边框
}

:deep(.el-tooltip__popper:focus, .el-tooltip__popper.is-focused) {
  box-shadow: none; // 隐藏实线边框
}
</style>