feat: 新增组件-瀑布流demo

This commit is contained in:
xiaoxian521 2023-05-14 16:38:29 +08:00
parent 799a5140e3
commit 4e3d752fb6
10 changed files with 231 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

29
pnpm-lock.yaml generated
View File

@ -108,6 +108,7 @@ specifiers:
vue-tsc: ^1.6.5 vue-tsc: ^1.6.5
vue-types: ^5.0.2 vue-types: ^5.0.2
vue-virtual-scroller: 2.0.0-beta.7 vue-virtual-scroller: 2.0.0-beta.7
vue-waterfall-plugin-next: ^2.2.1
vue3-danmaku: 1.4.0-beta.1 vue3-danmaku: 1.4.0-beta.1
vuedraggable: ^4.1.0 vuedraggable: ^4.1.0
xgplayer: ^3.0.2 xgplayer: ^3.0.2
@ -157,6 +158,7 @@ dependencies:
vue-router: 4.2.0_vue@3.3.2 vue-router: 4.2.0_vue@3.3.2
vue-types: 5.0.2_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-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 vue3-danmaku: 1.4.0-beta.1_vue@3.3.2
vuedraggable: 4.1.0_vue@3.3.2 vuedraggable: 4.1.0_vue@3.3.2
xgplayer: 3.0.2 xgplayer: 3.0.2
@ -11966,6 +11968,33 @@ packages:
vue-resize: 2.0.0-alpha.1_vue@3.3.2 vue-resize: 2.0.0-alpha.1_vue@3.3.2
dev: false 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: /vue/3.3.2:
resolution: resolution:
{ {

View File

@ -31,6 +31,15 @@ export default {
title: $t("menus.hsmessage") 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", path: "/components/video",
name: "Video", name: "Video",

View File

@ -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
};
});
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB