Appearance
BizMediaWall 媒体墙
瀑布流媒体墙:CSS columns 卡片墙(图片 / 视频封面)+ 悬浮层(标题 / 标签(可点)/ 下载 / 删除)+ 内置灯箱(键盘 ←→ 翻页、Esc 关闭、视频直放)+ 底部加载更多。素材中心、活动相册、案例展示墙——动作类事件全部外抛,数据由业务层维护。
基础用法
品牌主视觉
#VI #主图
banner 素材
#运营
详情页配图
#详情
社媒传播图
#社媒 #活动
海报延展
#海报
包装示意
#包装
图片瀑布流 + 悬浮层(标题 / 标签 / 操作)。
<script setup lang="ts">
/** 场景:基础——图片瀑布流 + 悬浮层(占位图采用 picsum 固定尺寸) */
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const items: BizMediaItem[] = [
{ id: 'm1', url: 'https://picsum.photos/seed/bizwall1/400/560', type: 'image', title: '品牌主视觉', tags: ['VI', '主图'] },
{ id: 'm2', url: 'https://picsum.photos/seed/bizwall2/400/300', type: 'image', title: 'banner 素材', tags: ['运营'] },
{ id: 'm3', url: 'https://picsum.photos/seed/bizwall3/400/420', type: 'image', title: '详情页配图', tags: ['详情'] },
{ id: 'm4', url: 'https://picsum.photos/seed/bizwall4/400/360', type: 'image', title: '社媒传播图', tags: ['社媒', '活动'] },
{ id: 'm5', url: 'https://picsum.photos/seed/bizwall5/400/500', type: 'image', title: '海报延展', tags: ['海报'] },
{ id: 'm6', url: 'https://picsum.photos/seed/bizwall6/400/330', type: 'image', title: '包装示意', tags: ['包装'] },
]
</script>
<template>
<BizMediaWall :items="items" />
</template>
显示代码
灯箱预览
案例图 1
案例图 2
案例图 3
案例图 4
案例图 5
点击任意卡片进入灯箱:← → 键翻页,Esc 关闭
点击卡片进灯箱:←→ 键盘翻页、Esc 关闭、计数显示。
<script setup lang="ts">
/** 场景:灯箱预览——键盘 ←→ / Esc */
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const items: BizMediaItem[] = Array.from({ length: 5 }, (_, i) => ({
id: `lb${i}`,
url: `https://picsum.photos/seed/lightbox${i}/500/380`,
type: 'image' as const,
title: `案例图 ${i + 1}`,
}))
</script>
<template>
<div>
<BizMediaWall :items="items" :columns="5" />
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
点击任意卡片进入灯箱:← → 键翻页,Esc 关闭
</p>
</div>
</template>
显示代码
视频混排
产品演示(灯箱播放)
#演示
配套宣传图
客户案例视频
#案例
type=video 以封面占位,灯箱内直接播放。<script setup lang="ts">
/** 场景:视频混排(封面占位,灯箱内播放) */
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const items: BizMediaItem[] = [
{
id: 'v1',
url: 'https://www.w3schools.com/html/mov_bbb.mp4',
type: 'video',
title: '产品演示(灯箱播放)',
cover: 'https://picsum.photos/seed/videocover1/400/240',
tags: ['演示'],
},
{ id: 'i1', url: 'https://picsum.photos/seed/miximg1/400/500', type: 'image', title: '配套宣传图' },
{
id: 'v2',
url: 'https://www.w3schools.com/html/movie.mp4',
type: 'video',
title: '客户案例视频',
cover: 'https://picsum.photos/seed/videocover2/400/300',
tags: ['案例'],
},
]
</script>
<template>
<BizMediaWall :items="items" :columns="3" />
</template>
显示代码
加载更多
素材 1
素材 2
素材 3
素材 4
素材 5
素材 6
has-more + load-more 事件分页追加。<script setup lang="ts">
/** 场景:加载更多——has-more 分页追加 */
import { ref } from 'vue'
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const page = ref(1)
const loading = ref(false)
const items = ref<BizMediaItem[]>(
Array.from({ length: 6 }, (_, i) => ({
id: `p1-${i}`,
url: `https://picsum.photos/seed/more1-${i}/400/${340 + i * 40}`,
type: 'image' as const,
title: `素材 ${i + 1}`,
})),
)
const loadMore = (): void => {
loading.value = true
setTimeout(() => {
const next = Array.from({ length: 6 }, (_, i) => ({
id: `p${page.value + 1}-${i}`,
url: `https://picsum.photos/seed/more${page.value + 1}-${i}/400/${300 + i * 50}`,
type: 'image' as const,
title: `素材 ${page.value * 6 + i + 1}`,
}))
items.value = [...items.value, ...next]
page.value += 1
loading.value = false
}, 800)
}
</script>
<template>
<BizMediaWall :items="items" :has-more="page < 3" :loading="loading" @load-more="loadMore" />
</template>
显示代码
事件
物料 A
#秋季
物料 B
#双11
download / remove / tag-click / item-click 事件日志。
<script setup lang="ts">
/** 场景:事件日志 */
import { ref } from 'vue'
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const logs = ref<string[]>([])
const log = (msg: string): void => {
logs.value.unshift(msg)
if (logs.value.length > 5) logs.value.pop()
}
const items: BizMediaItem[] = [
{ id: 'e1', url: 'https://picsum.photos/seed/event1/400/340', type: 'image', title: '物料 A', tags: ['秋季'] },
{ id: 'e2', url: 'https://picsum.photos/seed/event2/400/420', type: 'image', title: '物料 B', tags: ['双11'] },
]
</script>
<template>
<div>
<BizMediaWall
:items="items"
:columns="2"
@item-click="(i: BizMediaItem) => log(`item-click:${i.title}`)"
@download="(i: BizMediaItem) => log(`download:${i.title}`)"
@remove="(i: BizMediaItem) => log(`remove:${i.title}`)"
@tag-click="(t: string, i: BizMediaItem) => log(`tag-click:#${t}(${i.title})`)"
/>
<p v-for="(item, i) in logs" :key="i" style="margin: 6px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
{{ item }}
</p>
</div>
</template>
显示代码
布局参数
图 1
图 2
图 3
图 4
图 5
图 6
图 7
图 8
图 9
columns 列数与 gap 间隙调整(窄屏自动换列)。<script setup lang="ts">
/** 场景:列数与间隙调整 */
import { ref } from 'vue'
import { ElRadioButton, ElRadioGroup } from 'element-plus'
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const columns = ref(3)
const items: BizMediaItem[] = Array.from({ length: 9 }, (_, i) => ({
id: `c${i}`,
url: `https://picsum.photos/seed/col${i}/400/${300 + ((i * 47) % 200)}`,
type: 'image' as const,
title: `图 ${i + 1}`,
}))
</script>
<template>
<div>
<ElRadioGroup v-model="columns" size="small" style="margin-bottom: 10px">
<ElRadioButton :value="2">2 列</ElRadioButton>
<ElRadioButton :value="3">3 列</ElRadioButton>
<ElRadioButton :value="4">4 列</ElRadioButton>
</ElRadioGroup>
<BizMediaWall :items="items" :columns="columns" :gap="14" />
</div>
</template>
显示代码
关闭灯箱
资质文件(外链预览)
合同扫描件
验收照片
previewable=false:点击交给业务层(外链预览 / 权限校验等)。<script setup lang="ts">
/** 场景:关闭灯箱——previewable=false,item-click 业务接管预览 */
import { ElMessage } from 'element-plus'
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const items: BizMediaItem[] = [
{ id: 'n1', url: 'https://picsum.photos/seed/nopreview1/400/300', type: 'image', title: '资质文件(外链预览)' },
{ id: 'n2', url: 'https://picsum.photos/seed/nopreview2/400/420', type: 'image', title: '合同扫描件' },
{ id: 'n3', url: 'https://picsum.photos/seed/nopreview3/400/360', type: 'image', title: '验收照片' },
]
const onItemClick = (item: BizMediaItem): void => {
ElMessage.info(`业务层接管预览:${item.title}`)
}
</script>
<template>
<BizMediaWall :items="items" :columns="3" :previewable="false" @item-click="onItemClick" />
</template>
显示代码
瀑布流混排
素材 1(竖版)
素材 2(横版)
素材 3(横版)
素材 4(竖版)
素材 5(横版)
素材 6(竖版)
素材 7(横版)
素材 8(竖版)
横竖版图片混合:CSS columns 自然错落排布,
gap=14 间隙调整。<script setup lang="ts">
/** 场景:混合宽高比瀑布流——不同比例图片自然错落 + gap 调整 */
import { BizMediaWall } from 'vue3-ep-biz-lib'
import type { BizMediaItem } from 'vue3-ep-biz-lib'
const ratios = [[400, 620], [400, 280], [400, 400], [400, 520], [400, 320], [400, 560], [400, 360], [400, 480]]
const items: BizMediaItem[] = ratios.map(([w, h], i) => ({
id: `mix${i}`,
url: `https://picsum.photos/seed/mixratio${i}/${w}/${h}`,
type: 'image' as const,
title: `素材 ${i + 1}(${h > w ? '竖版' : '横版'})`,
}))
</script>
<template>
<BizMediaWall :items="items" :columns="4" :gap="14" />
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| items | BizMediaItem[] | [] | 媒体列表(id / url / type / title / cover / tags / meta) |
| columns | number | 4 | 列数 |
| gap | number | 10 | 卡片间隙 px |
| previewable | boolean | true | 点击进灯箱 |
| show-actions | boolean | true | 悬浮操作(下载 / 删除) |
| has-more | boolean | false | 底部加载更多入口 |
| loading | boolean | false | 加载更多 loading |
| empty-text | string | '暂无媒体内容' | 空态文案 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| item-click | (item) | 卡片点击(未开 previewable 时的业务预览时机) |
| download | (item) | 悬浮下载 |
| remove | (item) | 悬浮删除(业务回写 items) |
| tag-click | (tag, item) | 标签点击 |
| load-more | — | 加载更多 |
Expose
| 名称 | 类型 | 说明 |
|---|---|---|
| open | (id: string) => void | 打开指定项灯箱 |
| close | () => void | 关闭灯箱 |