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