automated_uniapp/uni_modules/cool-fixtures/components/fix-menus/fix-menus.vue
2025-01-09 16:40:44 +08:00

209 lines
4.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<fix-base-style
:styleSpacing="styleSpacing"
:styleColor="styleColor"
:position="position"
:index="index"
>
<view class="fix-menus">
<swiper
class="inner"
:style="{
height: height,
}"
:circular="false"
:indicator-dots="false"
@change="changeCurrent"
>
<swiper-item v-for="(item, index) in tabs" :key="index">
<view
class="row"
:class="[`is-${style.rowNum}`]"
v-for="(row, r) in item"
:key="r"
>
<view
class="item"
v-for="(col, c) in row"
:key="c"
@click="toPath(col.link)"
>
<view
:class="[`is-${style.shape}`, `is-${col.mode}`]"
:style="{ backgroundColor: col.backgroundColor }"
class="icon-box"
>
<cl-image :src="col.icon" mode="aspectFill" class="icon">
</cl-image>
</view>
<span
v-if="col.mode == 'mode-1'"
class="text"
:style="{ color: col.color }"
>{{ col.text }}</span
>
</view>
</view>
</swiper-item>
</swiper>
<!-- 自定义指示器 -->
<view class="custom-indicator">
<view
v-for="(item, index) in tabs"
:key="index"
class="custom-indicator-dot"
:class="{ active: current === index }"
></view>
</view>
</view>
</fix-base-style>
</template>
<script lang="ts" setup name="fix-menus">
import { computed, ref, type PropType } from "vue";
import type { Form } from "../../types/form";
import { baseProps } from "../../hooks";
const emits = defineEmits(["jump"]);
const props = defineProps({
style: {
type: Object,
default: () => {
return {
shape: "round",
pageNum: 1,
rowNum: 3,
};
},
},
list: {
type: Array as PropType<Form.Menu[]>,
default: () => [],
},
index: {
type: Number,
default: 0,
},
...baseProps,
});
const current = ref(0);
function changeCurrent(event: any) {
current.value = event.detail.current;
}
const height = computed(() => {
return 180 * props.style.pageNum + "rpx";
});
const tabs = computed(() => {
return paginateArray(props.list, props.style.pageNum, props.style.rowNum);
});
// 解决 每页1行 每行3个 的问题
function paginateArray(data: Form.Menu[], pageNum: number, rowNum: number) {
const result: any[] = [];
const totalItems = data.length;
let pageIndex = 0;
while (pageIndex < totalItems) {
const page: any[] = [];
for (let i = 0; i < pageNum && pageIndex < totalItems; i++) {
const row: any[] = [];
for (let j = 0; j < rowNum && pageIndex < totalItems; j++) {
row.push(data[pageIndex]);
pageIndex++;
}
page.push(row);
}
result.push(page);
}
return result;
}
function toPath(link: Form.Link) {
emits("jump", link);
}
</script>
<style lang="scss" scoped>
.fix-menus {
width: 100%;
padding-bottom: 20rpx;
.inner {
height: 100%;
padding: 10rpx;
box-sizing: border-box;
.row {
margin-bottom: 20rpx;
.item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 160rpx;
box-sizing: border-box;
.is-round {
border-radius: 40rpx;
}
.is-mode-2 {
width: 120rpx !important;
height: 120rpx !important;
}
.icon-box {
width: 80rpx;
height: 80rpx;
overflow: hidden;
.icon {
width: 100%;
height: 100%;
}
}
.text {
font-size: 26rpx;
margin-top: 12rpx;
}
}
}
.row:last-child {
margin-bottom: 0;
}
.is-3 {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 每行3列每列宽度相等 */
gap: 20rpx; /* 间距 */
}
.is-4 {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 每行3列每列宽度相等 */
gap: 20rpx; /* 间距 */
}
.is-5 {
display: grid;
grid-template-columns: repeat(5, 1fr); /* 每行3列每列宽度相等 */
gap: 20rpx; /* 间距 */
}
}
}
.custom-indicator {
display: flex;
justify-content: center;
}
.custom-indicator-dot {
width: 12rpx;
height: 12rpx;
background-color: #686580;
border-radius: 50%; /* 默认圆形 */
margin: 0 10rpx;
transition: all 0.3s ease; /* 过渡效果 */
}
.custom-indicator-dot.active {
width: 40rpx; /* 激活状态变成长方形 */
height: 12rpx;
background: var(--btn-color) !important;
border-radius: 20rpx; /* 调整边角的圆度 */
transition: all 0.5s ease; /* 激活状态有更慢的动画过渡 */
}
</style>