Pārlūkot izejas kodu

feat: 首页活动分类图标网格支持左右滑动分页

- 把固定的 4 列 wrap 网格改为 swiper,每页 4×2=8 个分类
- 超过 8 个分类时自动分页,底部加圆形指示点
- 新增 typeGridPages(computed)按 8 个一组切片
- gridIndex 跟踪当前页;重新加载分类时重置回 0
- getTypeList 取消 .slice(0,8),所有配过 icon 的分类都会展示
Developer 5 dienas atpakaļ
vecāks
revīzija
3587ff12fa
1 mainītis faili ar 56 papildinājumiem un 11 dzēšanām
  1. 56 11
      pages/home.vue

+ 56 - 11
pages/home.vue

@@ -38,11 +38,20 @@
 				<view class="c-box-title-right adfac" @click="toTurnPage('/pagesHome/allActivity',false)">更多 <up-icon name="arrow-right" size="30rpx" style="margin-left: 10rpx;"></up-icon></view>
 			</view>
 			<view class="c-box-typegrid" v-if="typeGrid.length">
-				<view class="typegrid-item adffc" v-for="(item,index) in typeGrid" :key="item.id" :style="{'margin-right':(index+1)%4===0?'0':'20rpx'}" @click="changeType(item,index)">
-					<view class="typegrid-circle">
-						<image v-if="item.iconUrl" :src="item.iconUrl" mode="aspectFit"></image>
-					</view>
-					<view class="typegrid-name">{{item.name}}</view>
+				<swiper class="typegrid-swiper" :current="gridIndex" @change="e => gridIndex = e.detail.current" :duration="200" :circular="false" :disable-touch="false">
+					<swiper-item v-for="(page, pi) in typeGridPages" :key="pi">
+						<view class="typegrid-page">
+							<view class="typegrid-item adffc" v-for="(item, idx) in page" :key="item.id" @click="changeType(item)">
+								<view class="typegrid-circle">
+									<image v-if="item.iconUrl" :src="item.iconUrl" mode="aspectFit"></image>
+								</view>
+								<view class="typegrid-name">{{item.name}}</view>
+							</view>
+						</view>
+					</swiper-item>
+				</swiper>
+				<view class="typegrid-dots adf" v-if="typeGridPages.length > 1">
+					<view class="typegrid-dot" v-for="(_, i) in typeGridPages" :key="i" :class="{'active': i === gridIndex}"></view>
 				</view>
 			</view>
 			<view class="c-box-list" v-if="activityList.length">
@@ -66,7 +75,7 @@
 	import CusSearch from '@/components/CusSearch/index.vue'
 	import NonprofitActivety from '@/components/pages/nonprofitActivety/index.vue'
 	import PageEmpty from '@/components/pageEmpty/index.vue'
-	import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
+	import { ref, computed, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
 	const { proxy } = getCurrentInstance()
 	import { useUserStore } from '@/common/stores/user';
 	const userStore = useUserStore();
@@ -117,6 +126,7 @@
 	const bannarOrigin = ref([])
 	const current = ref(0)
 	const typeGrid = ref([])
+	const gridIndex = ref(0)
 	const isOver = ref(false)
 	const activityList = ref([])
 	// 进入页面默认查全部(categoryId 为空),点图标网格才切到具体分类
@@ -126,6 +136,17 @@
 		categoryId:'',
 		userId:''
 	})
+
+	// 图标网格分页:每页 8 个(4 列 × 2 行),超过则分多页
+	const TYPEGRID_PAGE_SIZE = 8
+	const typeGridPages = computed(() => {
+		const pages = []
+		const list = typeGrid.value || []
+		for (let i = 0; i < list.length; i += TYPEGRID_PAGE_SIZE) {
+			pages.push(list.slice(i, i + TYPEGRID_PAGE_SIZE))
+		}
+		return pages
+	})
 	
 	const toSearch = (keyword) => {
 		if (!keyword) return
@@ -177,8 +198,9 @@
 	const getTypeList = () => {
 		proxy.$api.get('/core/activity/category/list').then(({data:res})=>{
 			if(res.code!==0) return proxy.$showToast(res.msg)
-			// icon 网格:取配过 icon 的前 8 个分类;空 grid 时不展示
-			typeGrid.value = res.data.filter(d=>d.iconUrl).slice(0,8).map(d=>({id:d.id,name:d.categoryName,iconUrl:d.iconUrl,bgImageUrl:d.bgImageUrl||''}));
+			// icon 网格:取所有配过 icon 的分类;超过 8 个会自动分页
+			typeGrid.value = res.data.filter(d=>d.iconUrl).map(d=>({id:d.id,name:d.categoryName,iconUrl:d.iconUrl,bgImageUrl:d.bgImageUrl||''}));
+			gridIndex.value = 0
 		})
 	}
 	
@@ -320,13 +342,21 @@
 			}
 			&-typegrid{
 				width: 100%;
-				display: flex;
-				flex-wrap: wrap;
 				margin-top: 36rpx;
 				padding: 0 0;
 				box-sizing: border-box;
+				.typegrid-swiper{
+					width: 100%;
+					height: 320rpx;
+				}
+				.typegrid-page{
+					width: 100%;
+					height: 100%;
+					display: flex;
+					flex-wrap: wrap;
+				}
 				.typegrid-item{
-					width: calc((100% - 60rpx) / 4);
+					width: 25%;
 					margin-bottom: 28rpx;
 					align-items: center;
 					.typegrid-circle{
@@ -350,6 +380,21 @@
 						text-align: center;
 					}
 				}
+				.typegrid-dots{
+					width: 100%;
+					justify-content: center;
+					margin-top: 4rpx;
+					.typegrid-dot{
+						width: 12rpx;
+						height: 12rpx;
+						border-radius: 50%;
+						background: #E2E5E9;
+						margin: 0 6rpx;
+						&.active{
+							background: #00AE57;
+						}
+					}
+				}
 			}
 			&-list{
 				width: 100%;