提交 | 用户 | 时间
|
820397
|
1 |
<template> |
H |
2 |
<el-carousel |
|
3 |
:height="`${carouselHeight}px`" |
|
4 |
:autoplay="false" |
|
5 |
arrow="hover" |
|
6 |
indicator-position="outside" |
|
7 |
> |
|
8 |
<el-carousel-item v-for="(page, pageIndex) in pages" :key="pageIndex"> |
|
9 |
<div class="flex flex-row flex-wrap"> |
|
10 |
<div |
|
11 |
v-for="(item, index) in page" |
|
12 |
:key="index" |
|
13 |
class="relative flex flex-col items-center justify-center" |
|
14 |
:style="{ width: columnWidth, height: `${rowHeight}px` }" |
|
15 |
> |
|
16 |
<!-- 图标 + 角标 --> |
|
17 |
<div class="relative" :class="`h-${ICON_SIZE}px w-${ICON_SIZE}px`"> |
|
18 |
<!-- 右上角角标 --> |
|
19 |
<span |
|
20 |
v-if="item.badge?.show" |
|
21 |
class="absolute right--10px top--10px z-1 h-20px rounded-10px p-x-6px text-center text-12px leading-20px" |
|
22 |
:style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }" |
|
23 |
> |
|
24 |
{{ item.badge.text }} |
|
25 |
</span> |
|
26 |
<el-image v-if="item.iconUrl" :src="item.iconUrl" class="h-full w-full" /> |
|
27 |
</div> |
|
28 |
<!-- 标题 --> |
|
29 |
<span |
|
30 |
v-if="property.layout === 'iconText'" |
|
31 |
class="text-12px" |
|
32 |
:style="{ |
|
33 |
color: item.titleColor, |
|
34 |
height: `${TITLE_HEIGHT}px`, |
|
35 |
lineHeight: `${TITLE_HEIGHT}px` |
|
36 |
}" |
|
37 |
> |
|
38 |
{{ item.title }} |
|
39 |
</span> |
|
40 |
</div> |
|
41 |
</div> |
|
42 |
</el-carousel-item> |
|
43 |
</el-carousel> |
|
44 |
</template> |
|
45 |
|
|
46 |
<script setup lang="ts"> |
|
47 |
import { MenuSwiperProperty, MenuSwiperItemProperty } from './config' |
|
48 |
/** 菜单导航 */ |
|
49 |
defineOptions({ name: 'MenuSwiper' }) |
|
50 |
const props = defineProps<{ property: MenuSwiperProperty }>() |
|
51 |
// 标题的高度 |
|
52 |
const TITLE_HEIGHT = 20 |
|
53 |
// 图标的高度 |
|
54 |
const ICON_SIZE = 42 |
|
55 |
// 垂直间距:一行上下的间距 |
|
56 |
const SPACE_Y = 16 |
|
57 |
|
|
58 |
// 分页 |
|
59 |
const pages = ref<MenuSwiperItemProperty[][]>([]) |
|
60 |
// 轮播图高度 |
|
61 |
const carouselHeight = ref(0) |
|
62 |
// 行高 |
|
63 |
const rowHeight = ref(0) |
|
64 |
// 列宽 |
|
65 |
const columnWidth = ref('') |
|
66 |
watch( |
|
67 |
() => props.property, |
|
68 |
() => { |
|
69 |
// 计算列宽:每一列的百分比 |
|
70 |
columnWidth.value = `${100 * (1 / props.property.column)}%` |
|
71 |
// 计算行高:图标 + 文字(仅显示图片时为0) + 垂直间距 * 2 |
|
72 |
rowHeight.value = |
|
73 |
(props.property.layout === 'iconText' ? ICON_SIZE + TITLE_HEIGHT : ICON_SIZE) + SPACE_Y * 2 |
|
74 |
// 计算轮播的高度:行数 * 行高 |
|
75 |
carouselHeight.value = props.property.row * rowHeight.value |
|
76 |
|
|
77 |
// 每页数量:行数 * 列数 |
|
78 |
const pageSize = props.property.row * props.property.column |
|
79 |
// 清空分页 |
|
80 |
pages.value = [] |
|
81 |
// 每一页的菜单 |
|
82 |
let pageItems: MenuSwiperItemProperty[] = [] |
|
83 |
for (const item of props.property.list) { |
|
84 |
// 本页满员,新建下一页 |
|
85 |
if (pageItems.length === pageSize) { |
|
86 |
pageItems = [] |
|
87 |
} |
|
88 |
// 增加一页 |
|
89 |
if (pageItems.length === 0) { |
|
90 |
pages.value.push(pageItems) |
|
91 |
} |
|
92 |
// 本页增加一个 |
|
93 |
pageItems.push(item) |
|
94 |
} |
|
95 |
}, |
|
96 |
{ immediate: true, deep: true } |
|
97 |
) |
|
98 |
</script> |
|
99 |
|
|
100 |
<style lang="scss"> |
|
101 |
// 重写指示器样式,与 APP 保持一致 |
|
102 |
:root { |
|
103 |
.el-carousel__indicator { |
|
104 |
padding-top: 0; |
|
105 |
padding-bottom: 0; |
|
106 |
.el-carousel__button { |
|
107 |
--el-carousel-indicator-height: 6px; |
|
108 |
--el-carousel-indicator-width: 6px; |
|
109 |
--el-carousel-indicator-out-color: #ff6000; |
|
110 |
border-radius: 6px; |
|
111 |
} |
|
112 |
} |
|
113 |
.el-carousel__indicator.is-active { |
|
114 |
.el-carousel__button { |
|
115 |
--el-carousel-indicator-width: 12px; |
|
116 |
} |
|
117 |
} |
|
118 |
} |
|
119 |
</style> |