فهرست منبع

feat: 新增`组件-瀑布流demo`

xiaoxian521 1 سال پیش
والد
کامیت
4e3d752fb6

+ 1 - 0
build/optimize.ts

@@ -36,6 +36,7 @@ const include = [
   "element-resize-detector",
   "@amap/amap-jsapi-loader",
   "el-table-infinite-scroll",
+  "vue-waterfall-plugin-next",
   "@wangeditor/editor-for-vue",
   "vuedraggable/src/vuedraggable"
 ];

+ 1 - 0
locales/en.yaml

@@ -39,6 +39,7 @@ menus:
   hsdialog: Dialog Components
   hsmessage: Message Tips Components
   hsvideo: Video Components
+  hswaterfall: Waterfall Components
   hsmap: Map Components
   hsdraggable: Draggable Components
   hssplitPane: Split Pane

+ 1 - 0
locales/zh-CN.yaml

@@ -39,6 +39,7 @@ menus:
   hsdialog: 函数式弹框组件
   hsmessage: 消息提示组件
   hsvideo: 视频组件
+  hswaterfall: 瀑布流组件
   hsmap: 地图组件
   hsdraggable: 拖拽组件
   hssplitPane: 切割面板

+ 1 - 0
package.json

@@ -72,6 +72,7 @@
     "vue-router": "^4.2.0",
     "vue-types": "^5.0.2",
     "vue-virtual-scroller": "2.0.0-beta.7",
+    "vue-waterfall-plugin-next": "^2.2.1",
     "vue3-danmaku": "1.4.0-beta.1",
     "vuedraggable": "^4.1.0",
     "xgplayer": "^3.0.2",

+ 29 - 0
pnpm-lock.yaml

@@ -108,6 +108,7 @@ specifiers:
   vue-tsc: ^1.6.5
   vue-types: ^5.0.2
   vue-virtual-scroller: 2.0.0-beta.7
+  vue-waterfall-plugin-next: ^2.2.1
   vue3-danmaku: 1.4.0-beta.1
   vuedraggable: ^4.1.0
   xgplayer: ^3.0.2
@@ -157,6 +158,7 @@ dependencies:
   vue-router: 4.2.0_vue@3.3.2
   vue-types: 5.0.2_vue@3.3.2
   vue-virtual-scroller: 2.0.0-beta.7_vue@3.3.2
+  vue-waterfall-plugin-next: 2.2.1_vue@3.3.2
   vue3-danmaku: 1.4.0-beta.1_vue@3.3.2
   vuedraggable: 4.1.0_vue@3.3.2
   xgplayer: 3.0.2
@@ -11966,6 +11968,33 @@ packages:
       vue-resize: 2.0.0-alpha.1_vue@3.3.2
     dev: false
 
+  /vue-waterfall-plugin-next/2.2.0_vue@3.3.2:
+    resolution:
+      {
+        integrity: sha512-rhrTdAlBnMWWt6737L+E08A7itgK3wHTy1NsSDgR9EPiBPuHYlth8jL2/hp2gIMAS4XUxJBtitfNUyK5qynkEA==
+      }
+    dependencies:
+      animate.css: 4.1.1
+      element-plus: 2.3.4_vue@3.3.2
+    transitivePeerDependencies:
+      - "@vue/composition-api"
+      - vue
+    dev: false
+
+  /vue-waterfall-plugin-next/2.2.1_vue@3.3.2:
+    resolution:
+      {
+        integrity: sha512-wEPT9D9VLTPWxGKrIusBxj9JVyXyXU6RLEqKIm3mJt/DeaTUvKu0sZjLOKK9UztkcJV2LaRALwRoCDOOKbLsiw==
+      }
+    dependencies:
+      animate.css: 4.1.1
+      element-plus: 2.3.4_vue@3.3.2
+      vue-waterfall-plugin-next: 2.2.0_vue@3.3.2
+    transitivePeerDependencies:
+      - "@vue/composition-api"
+      - vue
+    dev: false
+
   /vue/3.3.2:
     resolution:
       {

+ 9 - 0
src/router/modules/components.ts

@@ -31,6 +31,15 @@ export default {
         title: $t("menus.hsmessage")
       }
     },
+    {
+      path: "/components/waterfall",
+      name: "Waterfall",
+      component: () => import("@/views/components/waterfall/index.vue"),
+      meta: {
+        title: $t("menus.hswaterfall"),
+        extraIcon: "IF-pure-iconfont-new svg"
+      }
+    },
     {
       path: "/components/video",
       name: "Video",

+ 38 - 0
src/views/components/waterfall/api.ts

@@ -0,0 +1,38 @@
+export function randomID(length = 6) {
+  return Number(
+    Math.random().toString().substr(3, length) + Date.now()
+  ).toString(36);
+}
+
+const COLORS = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C", "#909399"];
+
+function getRandomNum(min: number, max: number) {
+  return Math.floor(Math.random() * (max - min + 1)) + min;
+}
+
+function randomColor() {
+  return COLORS[getRandomNum(0, 4)];
+}
+
+const website = "https://www.getphotoblanket.com";
+
+export const getList = ({ page = 1, pageSize = 20 }) => {
+  const url = `${website}/products.json?page=${page}&limit=${pageSize}`;
+  return fetch(url)
+    .then(res => res.json())
+    .then(res => res.products)
+    .then(res => {
+      return res.map((item: any) => {
+        return {
+          id: randomID(),
+          star: false,
+          price: item.variants[0].price,
+          src: {
+            original: item.images[0].src
+          },
+          backgroundColor: randomColor(),
+          name: item.title
+        };
+      });
+    });
+};

BIN
src/views/components/waterfall/error.png


+ 151 - 0
src/views/components/waterfall/index.vue

@@ -0,0 +1,151 @@
+<script setup lang="ts">
+import { getList } from "./api";
+import error from "./error.png";
+import loading from "./loading.png";
+import { onMounted, reactive, ref } from "vue";
+import "vue-waterfall-plugin-next/dist/style.css";
+import backTop from "@/assets/svg/back_top.svg?component";
+import { LazyImg, Waterfall } from "vue-waterfall-plugin-next";
+
+const options = reactive({
+  // 唯一key值
+  rowKey: "id",
+  // 卡片之间的间隙
+  gutter: 10,
+  // 是否有周围的gutter
+  hasAroundGutter: true,
+  // 卡片在PC上的宽度
+  width: 320,
+  // 自定义行显示个数,主要用于对移动端的适配
+  breakpoints: {
+    1200: {
+      // 当屏幕宽度小于等于1200
+      rowPerView: 4
+    },
+    800: {
+      // 当屏幕宽度小于等于800
+      rowPerView: 3
+    },
+    500: {
+      // 当屏幕宽度小于等于500
+      rowPerView: 2
+    }
+  },
+  // 动画效果
+  animationEffect: "animate__fadeInUp",
+  // 动画时间
+  animationDuration: 1000,
+  // 动画延迟
+  animationDelay: 300,
+  // 背景色
+  // backgroundColor: "#2C2E3A",
+  // 图片字段选择器,如果层级较深,使用 xxx.xxx.xxx 方式
+  imgSelector: "src.original",
+  // 加载配置
+  loadProps: {
+    loading,
+    error
+  },
+  // 是否懒加载
+  lazyload: true
+});
+
+const page = ref(1);
+const list = ref([]);
+const pageSize = ref();
+
+/** 加载更多 */
+function handleLoadMore() {
+  getList({
+    page: page.value,
+    pageSize: pageSize.value
+  }).then(res => {
+    list.value.push(...res);
+    page.value += 1;
+  });
+}
+
+function handleDelete(item, index) {
+  list.value.splice(index, 1);
+}
+
+function handleClick(item) {
+  console.log(item);
+}
+
+onMounted(() => {
+  handleLoadMore();
+});
+</script>
+
+<template>
+  <el-card shadow="never" class="!h-[85vh]">
+    <template #header>
+      <div class="card-header">
+        <span class="font-medium">
+          瀑布流组件,采用开源的
+          <el-link
+            href="https://github.com/heikaimu/vue3-waterfall-plugin"
+            target="_blank"
+            style="margin: 0 4px 5px; font-size: 16px"
+          >
+            vue-waterfall-plugin-next
+          </el-link>
+        </span>
+      </div>
+    </template>
+    <el-scrollbar height="78vh" class="content">
+      <Waterfall :list="list" v-bind="options">
+        <template #item="{ item, url, index }">
+          <div
+            class="bg-gray-900 rounded-lg shadow-md overflow-hidden transition-all duration-300 ease-linear hover:shadow-lg hover:shadow-gray-600 group"
+            @click="handleClick(item)"
+          >
+            <div class="overflow-hidden">
+              <LazyImg
+                :url="url"
+                class="cursor-pointer transition-all duration-300 ease-linear group-hover:scale-105"
+              />
+            </div>
+            <div class="px-4 pt-2 pb-4 border-t border-t-gray-800">
+              <h4 class="pb-4 text-gray-50 group-hover:text-yellow-300">
+                {{ item.name }}
+              </h4>
+              <div
+                class="pt-3 flex justify-between items-center border-t border-t-gray-600 border-opacity-50"
+              >
+                <div class="text-gray-50">$ {{ item.price }}</div>
+                <div>
+                  <button
+                    class="px-3 h-7 rounded-full bg-red-500 text-sm text-white shadow-lg transition-all duration-300 hover:bg-red-600"
+                    @click.stop="handleDelete(item, index)"
+                  >
+                    删除
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </template>
+      </Waterfall>
+
+      <div class="flex justify-center py-10">
+        <button
+          class="px-5 py-2 rounded-full bg-gray-700 text-md text-white cursor-pointer hover:bg-gray-800 transition-all duration-300"
+          @click="handleLoadMore"
+        >
+          加载更多
+        </button>
+      </div>
+
+      <el-backtop
+        title="回到顶部"
+        :right="35"
+        :visibility-height="400"
+        target=".content .el-scrollbar__wrap"
+      >
+        <backTop />
+      </el-backtop>
+    </el-scrollbar>
+  </el-card>
+</template>

BIN
src/views/components/waterfall/loading.png