【功能修复】修复装修菜单导航背景图片问题

pull/76/head
卢越 2024-08-12 13:57:25 +08:00
parent be5db900a0
commit e13eedc2c2
1 changed files with 307 additions and 326 deletions

View File

@ -1,363 +1,344 @@
<!-- 装修基础组件菜单导航金刚区 --> <!-- 装修基础组件菜单导航金刚区 -->
<template> <template>
<!-- 包裹层 --> <!-- 包裹层 -->
<view <view class="ui-swiper" :class="[props.mode, props.ui]"
class="ui-swiper" :style="[bgStyle, { height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]">
:class="[props.mode, props.bg, props.ui]" <!-- 轮播 -->
:style="[{ height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]" <swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay" :interval="props.interval"
> :duration="props.duration" :style="[{ height: swiperHeight + 'rpx' }]" @change="swiperChange">
<!-- 轮播 --> <swiper-item v-for="(arr, index) in menuList" :key="index" :class="{ cur: state.cur == index }">
<swiper <!-- 宫格 -->
:circular="props.circular" <view class="grid-wrap">
:current="state.cur" <view v-for="(item, index) in arr" :key="index"
:autoplay="props.autoplay" class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
:interval="props.interval" :style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" hover-class="ss-hover-btn"
:duration="props.duration" @tap="sheep.$router.go(item.url)">
:style="[{ height: swiperHeight + 'rpx' }]" <view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
@change="swiperChange" <view v-if="item.badge.show" class="tag-box"
> :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
<swiper-item {{ item.badge.text }}
v-for="(arr, index) in menuList" </view>
:key="index" <image v-if="item.iconUrl" class="menu-icon" :style="[
:class="{ cur: state.cur == index }"
>
<!-- 宫格 -->
<view class="grid-wrap">
<view
v-for="(item, index) in arr"
:key="index"
class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]"
hover-class="ss-hover-btn"
@tap="sheep.$router.go(item.url)"
>
<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
<view
v-if="item.badge.show"
class="tag-box"
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
>
{{ item.badge.text }}
</view>
<image
v-if="item.iconUrl"
class="menu-icon"
:style="[
{ {
width: props.iconSize + 'rpx', width: props.iconSize + 'rpx',
height: props.iconSize + 'rpx', height: props.iconSize + 'rpx',
}, },
]" ]" :src="sheep.$url.cdn(item.iconUrl)" mode="aspectFill"></image>
:src="sheep.$url.cdn(item.iconUrl)" <view v-if="data.layout === 'iconText'" class="menu-title"
mode="aspectFill" :style="[{ color: item.titleColor }]">
></image> {{ item.title }}
<view </view>
v-if="data.layout === 'iconText'" </view>
class="menu-title" </view>
:style="[{ color: item.titleColor }]" </view>
> </swiper-item>
{{ item.title }} </swiper>
</view> <!-- 指示点 -->
</view> <template v-if="menuList.length > 1">
</view> <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
</view> <view class="line-box" v-for="(item, index) in menuList.length" :key="index"
</swiper-item> :class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
</swiper> </view>
<!-- 指示点 --> <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
<template v-if="menuList.length > 1"> <view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'"> <view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
<view </view>
class="line-box" </view>
v-for="(item, index) in menuList.length" </template>
:key="index" </view>
:class="[state.cur == index ? 'cur' : '', props.dotCur]"
></view>
</view>
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
<view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
<view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
</view>
</view>
</template>
</view>
</template> </template>
<script setup> <script setup>
/** /**
* 轮播menu * 轮播menu
* *
* @property {Boolean} circular = false - 是否采用衔接滑动即播放到末尾后重新回到开头 * @property {Boolean} circular = false - 是否采用衔接滑动即播放到末尾后重新回到开头
* @property {Boolean} autoplay = true - 是否自动切换 * @property {Boolean} autoplay = true - 是否自动切换
* @property {Number} interval = 5000 - 自动切换时间间隔 * @property {Number} interval = 5000 - 自动切换时间间隔
* @property {Number} duration = 500 - 滑动动画时长,app-nvue不支持 * @property {Number} duration = 500 - 滑动动画时长,app-nvue不支持
* @property {Array} list = [] - 轮播数据 * @property {Array} list = [] - 轮播数据
* @property {String} ui = '' - 样式class * @property {String} ui = '' - 样式class
* @property {String} mode - 模式 * @property {String} mode - 模式
* @property {String} dotStyle - 指示点样式 * @property {String} dotStyle - 指示点样式
* @property {String} dotCur= 'ui-BG-Main' - 当前指示点样式,默认主题色 * @property {String} dotCur= 'ui-BG-Main' - 当前指示点样式,默认主题色
* @property {String} bg - 背景 * @property {String} bg - 背景
* *
* @property {String|Number} col = 4 - 一行数量 * @property {String|Number} col = 4 - 一行数量
* @property {String|Number} row = 1 - 几行 * @property {String|Number} row = 1 - 几行
* @property {String} hasBorder - 是否有边框 * @property {String} hasBorder - 是否有边框
* @property {String} borderColor - 边框颜色 * @property {String} borderColor - 边框颜色
* @property {String} background - 背景 * @property {String} background - 背景
* @property {String} hoverClass - 按压样式类 * @property {String} hoverClass - 按压样式类
* @property {String} hoverStayTime - 动画时间 * @property {String} hoverStayTime - 动画时间
* *
* @property {Array} list - 导航列表 * @property {Array} list - 导航列表
* @property {Number} iconSize - 图标大小 * @property {Number} iconSize - 图标大小
* @property {String} color - 标题颜色 * @property {String} color - 标题颜色
* *
*/ */
import { reactive, computed } from 'vue'; import {
import sheep from '@/sheep'; reactive,
computed
} from 'vue';
import sheep from '@/sheep';
// //
const state = reactive({ const state = reactive({
cur: 0, cur: 0,
}); });
// //
const props = defineProps({ const props = defineProps({
data: { //
type: Object, data: {
default() {}, type: Object,
}, default: () => ({}),
styles: { },
type: Object, //
default() {}, styles: {
}, type: Object,
circular: { default: () => ({}),
type: Boolean, },
default: true, circular: {
}, type: Boolean,
autoplay: { default: true,
type: Boolean, },
default: false, autoplay: {
}, type: Boolean,
interval: { default: false,
type: Number, },
default: 5000, interval: {
}, type: Number,
duration: { default: 5000,
type: Number, },
default: 500, duration: {
}, type: Number,
default: 500,
},
ui: {
type: String,
default: '',
},
mode: {
//default
type: String,
default: 'default',
},
dotStyle: {
type: String,
default: 'long', //default long tag
},
dotCur: {
type: String,
default: 'ui-BG-Main',
},
height: {
type: Number,
default: 300,
},
//
hasBorder: {
type: Boolean,
default: true,
},
//
borderColor: {
type: String,
default: 'red',
},
background: {
type: String,
default: 'blue',
},
hoverClass: {
type: String,
default: 'ss-hover-class', //'none'hover
},
//
col: {
type: [Number, String],
default: 3,
},
iconSize: {
type: Number,
default: 80,
},
color: {
type: String,
default: '#000',
},
});
ui: { //
type: String, const bgStyle = computed(() => {
default: '', console.log(props.styles)
}, // props.styles
mode: { const {
//default bgType,
type: String, bgImg,
default: 'default', bgColor
}, } = props.styles;
dotStyle: {
type: String,
default: 'long', //default long tag
},
dotCur: {
type: String,
default: 'ui-BG-Main',
},
bg: {
type: String,
default: 'bg-none',
},
height: {
type: Number,
default: 300,
},
// // bgType
hasBorder: { return {
type: Boolean, background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
default: true, };
}, });
//
borderColor: {
type: String,
default: 'red',
},
background: {
type: String,
default: 'blue',
},
hoverClass: {
type: String,
default: 'ss-hover-class', //'none'hover
},
//
col: {
type: [Number, String],
default: 3,
},
iconSize: {
type: Number,
default: 80,
},
color: {
type: String,
default: '#000',
},
});
// //
const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column)); const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180)); const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
const windowWidth = sheep.$platform.device.windowWidth; const windowWidth = sheep.$platform.device.windowWidth;
// current change // current change
const swiperChange = (e) => { const swiperChange = (e) => {
state.cur = e.detail.current; state.cur = e.detail.current;
}; };
// //
const splitData = (oArr = [], length = 1) => { const splitData = (oArr = [], length = 1) => {
let arr = []; let arr = [];
let minArr = []; let minArr = [];
oArr.forEach((c) => { oArr.forEach((c) => {
if (minArr.length === length) { if (minArr.length === length) {
minArr = []; minArr = [];
} }
if (minArr.length === 0) { if (minArr.length === 0) {
arr.push(minArr); arr.push(minArr);
} }
minArr.push(c); minArr.push(c);
}); });
return arr; return arr;
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.grid-wrap { .grid-wrap {
width: 100%; width: 100%;
display: flex; display: flex;
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
} }
.menu-box {
position: relative;
z-index: 1;
transform: translate(0, 0);
.tag-box { .menu-box {
position: absolute; position: relative;
z-index: 2; z-index: 1;
top: 0; transform: translate(0, 0);
right: -6rpx;
font-size: 2em;
line-height: 1;
padding: 0.4em 0.6em 0.3em;
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
transform-origin: 100% 0;
border-radius: 200rpx;
white-space: nowrap;
}
.menu-icon { .tag-box {
transform: translate(0, 0); position: absolute;
width: 80rpx; z-index: 2;
height: 80rpx; top: 0;
padding-bottom: 10rpx; right: -6rpx;
} font-size: 2em;
line-height: 1;
padding: 0.4em 0.6em 0.3em;
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
transform-origin: 100% 0;
border-radius: 200rpx;
white-space: nowrap;
}
.menu-title { .menu-icon {
font-size: 24rpx; transform: translate(0, 0);
color: #333; width: 80rpx;
} height: 80rpx;
} padding-bottom: 10rpx;
}
::v-deep(.ui-swiper) { .menu-title {
position: relative; font-size: 24rpx;
z-index: 1; color: #333;
}
}
.ui-swiper-dot { ::v-deep(.ui-swiper) {
position: absolute; position: relative;
width: 100%; z-index: 1;
bottom: 20rpx;
height: 30rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
&.default .line-box { .ui-swiper-dot {
display: inline-flex; position: absolute;
border-radius: 50rpx; width: 100%;
width: 6px; bottom: 20rpx;
height: 6px; height: 30rpx;
border: 2px solid transparent; display: flex;
margin: 0 10rpx; align-items: center;
opacity: 0.3; justify-content: center;
position: relative; z-index: 2;
justify-content: center;
align-items: center;
&.cur { &.default .line-box {
width: 8px; display: inline-flex;
height: 8px; border-radius: 50rpx;
opacity: 1; width: 6px;
border: 0px solid transparent; height: 6px;
} border: 2px solid transparent;
margin: 0 10rpx;
opacity: 0.3;
position: relative;
justify-content: center;
align-items: center;
&.cur::after { &.cur {
content: ''; width: 8px;
border-radius: 50rpx; height: 8px;
width: 4px; opacity: 1;
height: 4px; border: 0px solid transparent;
background-color: #fff; }
}
}
&.long .line-box { &.cur::after {
display: inline-block; content: '';
border-radius: 100rpx; border-radius: 50rpx;
width: 6px; width: 4px;
height: 6px; height: 4px;
margin: 0 10rpx; background-color: #fff;
opacity: 0.3; }
position: relative; }
&.cur { &.long .line-box {
width: 24rpx; display: inline-block;
opacity: 1; border-radius: 100rpx;
} width: 6px;
height: 6px;
margin: 0 10rpx;
opacity: 0.3;
position: relative;
&.cur::after { &.cur {
} width: 24rpx;
} opacity: 1;
}
&.line { &.cur::after {}
bottom: 20rpx; }
.line-box { &.line {
display: inline-block; bottom: 20rpx;
width: 30px;
height: 3px;
opacity: 0.3;
position: relative;
&.cur { .line-box {
opacity: 1; display: inline-block;
} width: 30px;
} height: 3px;
} opacity: 0.3;
position: relative;
&.tag { &.cur {
justify-content: flex-end; opacity: 1;
position: absolute; }
bottom: 20rpx; }
right: 20rpx; }
}
} &.tag {
} justify-content: flex-end;
</style> position: absolute;
bottom: 20rpx;
right: 20rpx;
}
}
}
</style>